Fix product creation flow for simple products (#4081)

* Fix simple product creation

* Fix simple product creation
This commit is contained in:
Patryk Andrzejewski 2023-08-16 10:40:35 +02:00 committed by GitHub
parent 3c1d84f775
commit 498feff0a2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 91 additions and 11 deletions

View file

@ -233,7 +233,6 @@ export const ProductCreatePage: React.FC<ProductCreatePageProps> = ({
assignReferencesAttributeId,
data.attributes,
);
return (
<DetailPageLayout>
<TopNav href={productListUrl()} title={header} />
@ -275,7 +274,7 @@ export const ProductCreatePage: React.FC<ProductCreatePageProps> = ({
/>
<ProductVariantPrice
ProductVariantChannelListings={data.channelListings}
errors={channelsErrors}
errors={[...errors, ...channelsErrors]}
loading={loading}
onChange={handlers.changeChannelPrice}
/>

View file

@ -9,11 +9,15 @@ import PriceField from "@dashboard/components/PriceField";
import ResponsiveTable from "@dashboard/components/ResponsiveTable";
import Skeleton from "@dashboard/components/Skeleton";
import TableRowLink from "@dashboard/components/TableRowLink";
import { ProductChannelListingErrorFragment } from "@dashboard/graphql";
import {
ProductChannelListingErrorFragment,
ProductErrorFragment,
} from "@dashboard/graphql";
import { renderCollection } from "@dashboard/misc";
import {
getFormChannelError,
getFormChannelErrors,
getFormErrors,
} from "@dashboard/utils/errors";
import getProductErrorMessage from "@dashboard/utils/errors/product";
import { TableBody, TableCell, TableHead } from "@material-ui/core";
@ -23,7 +27,7 @@ import { FormattedMessage, MessageDescriptor, useIntl } from "react-intl";
interface ProductVariantPriceProps {
ProductVariantChannelListings?: ChannelData[];
errors?: ProductChannelListingErrorFragment[];
errors: Array<ProductErrorFragment | ProductChannelListingErrorFragment>;
loading?: boolean;
disabled?: boolean;
onChange?: (
@ -47,7 +51,10 @@ export const ProductVariantPrice: React.FC<
disabledMessage,
} = props;
const intl = useIntl();
const formErrors = getFormChannelErrors(["price", "costPrice"], errors);
const channelErrors = errors.filter(
e => "channels" in e,
) as ProductChannelListingErrorFragment[];
const apiErrors = getFormChannelErrors(["price", "costPrice"], channelErrors);
if (disabled || !ProductVariantChannelListings.length) {
return (
@ -120,12 +127,15 @@ export const ProductVariantPrice: React.FC<
{renderCollection(
ProductVariantChannelListings,
(listing, index) => {
const priceError = getFormChannelError(
formErrors.price,
listing.id,
);
const fieldName = `${listing.id}-channel-price`;
const formErrors = getFormErrors([fieldName], errors);
const priceError =
getFormChannelError(apiErrors.price, listing.id) ||
formErrors[fieldName];
const costPriceError = getFormChannelError(
formErrors.costPrice,
apiErrors.costPrice,
listing.id,
);
@ -142,7 +152,7 @@ export const ProductVariantPrice: React.FC<
id: "b1zuN9",
defaultMessage: "Price",
})}
name={`${listing.id}-channel-price`}
name={fieldName}
value={listing.price || ""}
currencySymbol={listing.currency}
onChange={e =>

View file

@ -0,0 +1,63 @@
import { ProductCreateData } from "../components/ProductCreatePage";
import { validateProductCreateData } from "./validation";
describe("validateProductCreateData", () => {
it("returns errors when there is no productType or name", () => {
// Arrange
const data = { productType: "" } as unknown as ProductCreateData;
// Act
const errors = validateProductCreateData(data);
// Assert
expect(errors).toEqual([
{
__typename: "ProductError",
attributes: [],
code: "REQUIRED",
field: "productType",
message: null,
},
{
__typename: "ProductError",
attributes: [],
code: "REQUIRED",
field: "name",
message: null,
},
]);
});
it("returns errors when there is no prices for channels", () => {
// Arrange
const data = {
productType: "something",
name: "something",
channelListings: [
{ id: "chann-1", price: "" },
{ id: "chann-2", price: "" },
],
} as unknown as ProductCreateData;
// Act
const errors = validateProductCreateData(data);
// Assert
expect(errors).toEqual([
{
__typename: "ProductError",
attributes: [],
code: "REQUIRED",
field: "chann-1-channel-price",
message: null,
},
{
__typename: "ProductError",
attributes: [],
code: "REQUIRED",
field: "chann-2-channel-price",
message: null,
},
]);
});
});

View file

@ -34,6 +34,14 @@ export const validateProductCreateData = (data: ProductCreateData) => {
errors = [...errors, createEmptyRequiredError("name")];
}
if (data.channelListings) {
const emptyPrices = data.channelListings
.filter(channel => channel.price?.length === 0)
.map(({ id }) => createEmptyRequiredError(`${id}-channel-price`));
errors = [...errors, ...emptyPrices];
}
return errors;
};