diff --git a/src/products/views/ProductCreate/ProductCreate.tsx b/src/products/views/ProductCreate/ProductCreate.tsx index a2474630c..ce9893b02 100644 --- a/src/products/views/ProductCreate/ProductCreate.tsx +++ b/src/products/views/ProductCreate/ProductCreate.tsx @@ -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 ( <> diff --git a/src/products/views/ProductCreate/handlers.ts b/src/products/views/ProductCreate/handlers.ts index 024033cb4..96e26f8b5 100644 --- a/src/products/views/ProductCreate/handlers.ts +++ b/src/products/views/ProductCreate/handlers.ts @@ -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>, updateVariantChannels: (options: { variables: ProductVariantChannelListingUpdateVariables; - }) => Promise> + }) => Promise>, + productDelete: (options: { + variables: ProductDeleteVariables; + }) => Promise> ) { 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; };