diff --git a/src/components/VisibilityCard/VisibilityCard.tsx b/src/components/VisibilityCard/VisibilityCard.tsx index 4207baff5..a97754e83 100644 --- a/src/components/VisibilityCard/VisibilityCard.tsx +++ b/src/components/VisibilityCard/VisibilityCard.tsx @@ -241,7 +241,10 @@ export const VisibilityCard: React.FC = props => { const { value } = e.target; if (!value) { onChange({ - target: { name: "availableForPurchase", value: null } + target: { + name: "availableForPurchase", + value: null + } }); } return onChange(e); diff --git a/src/products/mutations.ts b/src/products/mutations.ts index 12d6d4de3..663f6cad1 100644 --- a/src/products/mutations.ts +++ b/src/products/mutations.ts @@ -611,6 +611,11 @@ const productSetAvailabilityForPurchase = gql` productId: $productId startDate: $startDate ) { + product { + id + availableForPurchase + isAvailableForPurchase + } errors: productErrors { ...ProductErrorFragment message diff --git a/src/products/types/ProductSetAvailabilityForPurchase.ts b/src/products/types/ProductSetAvailabilityForPurchase.ts index cc8cb6557..8a5fdeebb 100644 --- a/src/products/types/ProductSetAvailabilityForPurchase.ts +++ b/src/products/types/ProductSetAvailabilityForPurchase.ts @@ -8,6 +8,13 @@ import { ProductErrorCode } from "./../../types/globalTypes"; // GraphQL mutation operation: ProductSetAvailabilityForPurchase // ==================================================== +export interface ProductSetAvailabilityForPurchase_productSetAvailabilityForPurchase_product { + __typename: "Product"; + id: string; + availableForPurchase: any | null; + isAvailableForPurchase: boolean | null; +} + export interface ProductSetAvailabilityForPurchase_productSetAvailabilityForPurchase_errors { __typename: "ProductError"; code: ProductErrorCode; @@ -17,6 +24,7 @@ export interface ProductSetAvailabilityForPurchase_productSetAvailabilityForPurc export interface ProductSetAvailabilityForPurchase_productSetAvailabilityForPurchase { __typename: "ProductSetAvailabilityForPurchase"; + product: ProductSetAvailabilityForPurchase_productSetAvailabilityForPurchase_product | null; errors: ProductSetAvailabilityForPurchase_productSetAvailabilityForPurchase_errors[]; } diff --git a/src/products/utils/handlers.ts b/src/products/utils/handlers.ts index cba4b3018..e6ae599b5 100644 --- a/src/products/utils/handlers.ts +++ b/src/products/utils/handlers.ts @@ -116,3 +116,30 @@ export function createProductTypeSelectHandler( ); }; } + +interface ProductAvailabilityArgs { + availableForPurchase: string | null; + isAvailableForPurchase: boolean; + productId: string; +} + +export function getProductAvailabilityVariables({ + isAvailableForPurchase, + availableForPurchase, + productId +}: ProductAvailabilityArgs) { + const isAvailable = + availableForPurchase && !isAvailableForPurchase + ? true + : isAvailableForPurchase; + + return { + isAvailable, + productId, + startDate: isAvailableForPurchase + ? null + : availableForPurchase !== "" + ? availableForPurchase + : null + }; +} diff --git a/src/products/views/ProductCreate.tsx b/src/products/views/ProductCreate.tsx index 24d06a9da..f59685bff 100644 --- a/src/products/views/ProductCreate.tsx +++ b/src/products/views/ProductCreate.tsx @@ -3,6 +3,7 @@ import { DEFAULT_INITIAL_SEARCH_DATA } from "@saleor/config"; import useNavigator from "@saleor/hooks/useNavigator"; import useNotifier from "@saleor/hooks/useNotifier"; import useShop from "@saleor/hooks/useShop"; +import { getProductAvailabilityVariables } from "@saleor/products/utils/handlers"; import useCategorySearch from "@saleor/searches/useCategorySearch"; import useCollectionSearch from "@saleor/searches/useCollectionSearch"; import useProductTypeSearch from "@saleor/searches/useProductTypeSearch"; @@ -19,7 +20,10 @@ import { decimal, weight } from "../../misc"; import ProductCreatePage, { ProductCreatePageSubmitData } from "../components/ProductCreatePage"; -import { useProductCreateMutation } from "../mutations"; +import { + useProductCreateMutation, + useProductSetAvailabilityForPurchase +} from "../mutations"; import { productListUrl, productUrl } from "../urls"; export const ProductCreateView: React.FC = () => { @@ -59,6 +63,18 @@ export const ProductCreateView: React.FC = () => { const handleBack = () => navigate(productListUrl()); + const [ + setProductAvailability, + productAvailabilityOpts + ] = useProductSetAvailabilityForPurchase({ + onCompleted: data => { + const errors = data?.productSetAvailabilityForPurchase?.errors; + if (errors?.length === 0) { + navigate(productUrl(data.productSetAvailabilityForPurchase.product.id)); + } + } + }); + const [productCreate, productCreateOpts] = useProductCreateMutation({ onCompleted: data => { if (data.productCreate.errors.length === 0) { @@ -68,7 +84,6 @@ export const ProductCreateView: React.FC = () => { defaultMessage: "Product created" }) }); - navigate(productUrl(data.productCreate.product.id)); } } }); @@ -100,11 +115,28 @@ export const ProductCreateView: React.FC = () => { warehouse: stock.id })), trackInventory: formData.trackInventory, + visibleInListings: formData.visibleInListings, weight: weight(formData.weight) } }); - return result.data.productCreate?.product?.id || null; + const productId = result.data.productCreate?.product?.id; + + if (productId) { + const { isAvailableForPurchase, availableForPurchase } = formData; + + const variables = getProductAvailabilityVariables({ + availableForPurchase, + isAvailableForPurchase, + productId + }); + + setProductAvailability({ + variables + }); + } + + return productId || null; }; const handleSubmit = createMetadataCreateHandler( handleCreate, @@ -128,7 +160,7 @@ export const ProductCreateView: React.FC = () => { collections={(searchCollectionOpts.data?.search.edges || []).map( edge => edge.node )} - disabled={productCreateOpts.loading} + disabled={productCreateOpts.loading || productAvailabilityOpts.loading} errors={productCreateOpts.data?.productCreate.errors || []} fetchCategories={searchCategory} fetchCollections={searchCollection} diff --git a/src/products/views/ProductUpdate/ProductUpdate.tsx b/src/products/views/ProductUpdate/ProductUpdate.tsx index d3915ceab..a5f9c4e57 100644 --- a/src/products/views/ProductUpdate/ProductUpdate.tsx +++ b/src/products/views/ProductUpdate/ProductUpdate.tsx @@ -10,6 +10,7 @@ import useBulkActions from "@saleor/hooks/useBulkActions"; import useNavigator from "@saleor/hooks/useNavigator"; import useNotifier from "@saleor/hooks/useNotifier"; import useShop from "@saleor/hooks/useShop"; +import useStateFromProps from "@saleor/hooks/useStateFromProps"; import { commonMessages } from "@saleor/intl"; import { useProductDeleteMutation, @@ -177,6 +178,12 @@ export const ProductUpdate: React.FC = ({ id, params }) => { onCompleted: data => { const errors = data?.productSetAvailabilityForPurchase?.errors; if (errors?.length === 0) { + const updatedProduct = data?.productSetAvailabilityForPurchase?.product; + setProduct(product => ({ + ...product, + availableForPurchase: updatedProduct.availableForPurchase, + isAvailableForPurchase: updatedProduct.isAvailableForPurchase + })); notify({ status: "success", text: intl.formatMessage({ @@ -195,7 +202,7 @@ export const ProductUpdate: React.FC = ({ id, params }) => { const handleBack = () => navigate(productListUrl()); - const product = data?.product; + const [product, setProduct] = useStateFromProps(data?.product); if (product === null) { return ; diff --git a/src/products/views/ProductUpdate/handlers.ts b/src/products/views/ProductUpdate/handlers.ts index f1ac03ad9..1d1cdd56f 100644 --- a/src/products/views/ProductUpdate/handlers.ts +++ b/src/products/views/ProductUpdate/handlers.ts @@ -19,6 +19,7 @@ import { SimpleProductUpdateVariables } from "@saleor/products/types/SimpleProductUpdate"; import { mapFormsetStockToStockInput } from "@saleor/products/utils/data"; +import { getProductAvailabilityVariables } from "@saleor/products/utils/handlers"; import { ReorderEvent } from "@saleor/types"; import { MutationFetchResult } from "react-apollo"; import { arrayMove } from "react-sortable-hoc"; @@ -91,20 +92,13 @@ export function createUpdateHandler( isAvailableForPurchase !== product.isAvailableForPurchase || availableForPurchase !== product.availableForPurchase ) { - const isAvailable = - availableForPurchase && !isAvailableForPurchase - ? true - : isAvailableForPurchase; - - const availabilityResult = await setProductAvailability({ - isAvailable, - productId: product.id, - startDate: isAvailableForPurchase - ? null - : availableForPurchase !== "" - ? availableForPurchase - : null + const variables = getProductAvailabilityVariables({ + availableForPurchase, + isAvailableForPurchase, + productId: product.id }); + + const availabilityResult = await setProductAvailability(variables); errors = [ ...errors, ...availabilityResult.data.productSetAvailabilityForPurchase.errors