Merge pull request #842 from mirumee/saleor-1516-do-not-clear-form-on-error

[1516] Create product only when all required fields are valid
This commit is contained in:
Jakub Majorek 2020-11-19 15:40:26 +01:00 committed by GitHub
commit 080f6e5b01
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 67 additions and 22 deletions

View file

@ -10,6 +10,7 @@ import useShop from "@saleor/hooks/useShop";
import ProductCreatePage from "@saleor/products/components/ProductCreatePage";
import {
useProductChannelListingUpdate,
useProductDeleteMutation,
useProductVariantChannelListingUpdate,
useVariantCreateMutation
} from "@saleor/products/mutations";
@ -37,6 +38,9 @@ export const ProductCreateView: React.FC = () => {
const notify = useNotifier();
const shop = useShop();
const intl = useIntl();
const [productCreateComplete, setProductCreateComplete] = React.useState(
false
);
const {
loadMore: loadMoreCategories,
search: searchCategory,
@ -100,14 +104,9 @@ export const ProductCreateView: React.FC = () => {
navigate(productUrl(productId));
};
const [updateChannels, updateChannelsOpts] = useProductChannelListingUpdate({
onCompleted: data => {
const productId = data.productChannelListingUpdate.product.id;
if (productId) {
handleSuccess(productId);
}
}
});
const [updateChannels, updateChannelsOpts] = useProductChannelListingUpdate(
{}
);
const [
updateVariantChannels,
updateVariantChannelsOpts
@ -116,6 +115,7 @@ export const ProductCreateView: React.FC = () => {
const handleBack = () => navigate(productListUrl());
const [productCreate, productCreateOpts] = useProductCreateMutation({});
const [deleteProduct] = useProductDeleteMutation({});
const [
productVariantCreate,
productVariantCreateOpts
@ -133,17 +133,32 @@ export const ProductCreateView: React.FC = () => {
}
});
const handleSubmit = createMetadataCreateHandler(
createHandler(
productTypes,
variables => productCreate({ variables }),
variables => productVariantCreate({ variables }),
updateChannels,
updateVariantChannels
),
updateMetadata,
updatePrivateMetadata
);
const handleSubmit = async data => {
const result = await createMetadataCreateHandler(
createHandler(
productTypes,
variables => productCreate({ variables }),
variables => productVariantCreate({ variables }),
updateChannels,
updateVariantChannels,
deleteProduct
),
updateMetadata,
updatePrivateMetadata
)(data);
if (result) {
setProductCreateComplete(true);
}
};
React.useEffect(() => {
const productId = productCreateOpts.data?.productCreate?.product?.id;
if (productCreateComplete && productId) {
handleSuccess(productId);
}
}, [productCreateComplete]);
return (
<>

View file

@ -9,6 +9,10 @@ import {
ProductCreate,
ProductCreateVariables
} from "@saleor/products/types/ProductCreate";
import {
ProductDelete,
ProductDeleteVariables
} from "@saleor/products/types/ProductDelete";
import {
ProductVariantChannelListingUpdate,
ProductVariantChannelListingUpdateVariables
@ -59,7 +63,10 @@ export function createHandler(
}) => Promise<MutationFetchResult<ProductChannelListingUpdate>>,
updateVariantChannels: (options: {
variables: ProductVariantChannelListingUpdateVariables;
}) => Promise<MutationFetchResult<ProductVariantChannelListingUpdate>>
}) => Promise<MutationFetchResult<ProductVariantChannelListingUpdate>>,
productDelete: (options: {
variables: ProductDeleteVariables;
}) => Promise<MutationFetchResult<ProductDelete>>
) {
return async (formData: ProductCreateData) => {
const productVariables: ProductCreateVariables = {
@ -85,6 +92,7 @@ export function createHandler(
};
const result = await productCreate(productVariables);
let hasErrors = false;
const hasVariants = productTypes.find(
product => product.id === formData.productType.id
@ -98,7 +106,13 @@ export function createHandler(
),
productVariantCreate(getSimpleProductVariables(formData, productId))
]);
const variantErrors = result[1].data.productVariantCreate.errors;
const channelErrors = result[0].data?.productChannelListingUpdate?.errors;
const variantErrors = result[1].data?.productVariantCreate?.errors;
if ([...(channelErrors || []), ...(variantErrors || [])].length > 0) {
hasErrors = true;
}
const variantId = result[1].data.productVariantCreate.productVariant?.id;
if (variantErrors.length === 0 && variantId) {
updateVariantChannels({
@ -113,7 +127,23 @@ export function createHandler(
});
}
} else {
updateChannels(getChannelsVariables(productId, formData.channelListings));
const result = await updateChannels(
getChannelsVariables(productId, formData.channelListings)
);
if (result.data?.productChannelListingUpdate?.errors.length > 0) {
hasErrors = true;
}
}
/*
INFO: This is a stop-gap solution, where we delete products that didn't meet all required data in the create form
A more robust solution would require merging create and update form into one to persist form state across redirects
*/
if (productId && hasErrors) {
productDelete({ variables: { id: productId } });
return null;
}
return productId || null;
};