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:
commit
080f6e5b01
2 changed files with 67 additions and 22 deletions
|
@ -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 (
|
||||
<>
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue