From b9bccd07f30a6067172ff5eedaf45318db16a3da Mon Sep 17 00:00:00 2001 From: Dawid Tarasiuk Date: Mon, 28 Sep 2020 17:37:55 +0200 Subject: [PATCH] Refactor leave action in product update --- src/components/Form/Form.tsx | 17 +++++- src/hooks/useForm.ts | 18 ++++++- .../ProductUpdatePage/ProductUpdatePage.tsx | 52 +++++++------------ .../views/ProductUpdate/ProductUpdate.tsx | 18 ++----- .../stories/products/ProductUpdatePage.tsx | 1 + 5 files changed, 56 insertions(+), 50 deletions(-) diff --git a/src/components/Form/Form.tsx b/src/components/Form/Form.tsx index 2721f678a..d7ae58fcb 100644 --- a/src/components/Form/Form.tsx +++ b/src/components/Form/Form.tsx @@ -1,12 +1,14 @@ import useForm, { UseFormResult } from "@saleor/hooks/useForm"; import React from "react"; +import LeaveScreenDialog from "../LeaveScreenDialog"; + export interface FormProps { children: (props: UseFormResult) => React.ReactNode; confirmLeave?: boolean; initial?: T; resetOnSubmit?: boolean; - onSubmit?: (data: T) => void; + onSubmit?: (data: T, nextAction: () => void) => void; } function Form(props: FormProps) { @@ -32,7 +34,18 @@ function Form(props: FormProps) { submit(); } - return
{children(renderProps)}
; + return ( +
+ {children(renderProps)} + renderProps.askToLeave(null)} + open={!!renderProps.leaveModal} + confirmButtonState="default" + /> + + ); } Form.displayName = "Form"; diff --git a/src/hooks/useForm.ts b/src/hooks/useForm.ts index 752030949..a08c8971b 100644 --- a/src/hooks/useForm.ts +++ b/src/hooks/useForm.ts @@ -14,6 +14,9 @@ export interface ChangeEvent { export type FormChange = (event: ChangeEvent, cb?: () => void) => void; export interface UseFormResult { + askToLeave: (action: () => void | null) => void; + leaveAction: () => void | null; + leaveModal: boolean; change: FormChange; data: T; hasChanged: boolean; @@ -51,13 +54,15 @@ function handleRefresh( function useForm( initial: T, - onSubmit: (data: T) => void + onSubmit: (data: T, nextAction: () => void) => void ): UseFormResult { const [hasChanged, setChanged] = useState(false); const [data, setData] = useStateFromProps(initial, { mergeFunc: merge, onRefresh: newData => handleRefresh(data, newData, setChanged) }); + const [leaveModal, setLeaveModal] = useState(false); + const [leaveAction, setLeaveAction] = useState<() => void>(null); function toggleValue(event: ChangeEvent, cb?: () => void) { const { name, value } = event.target; @@ -107,17 +112,26 @@ function useForm( } function submit() { - return onSubmit(data); + onSubmit(data, leaveAction); + setLeaveModal(false); } function triggerChange() { setChanged(true); } + function askToLeave(action: () => void | null) { + setLeaveModal(() => !!action); + setLeaveAction(() => action); + } + return { + askToLeave, change, data, hasChanged, + leaveAction, + leaveModal, reset, set, submit, diff --git a/src/products/components/ProductUpdatePage/ProductUpdatePage.tsx b/src/products/components/ProductUpdatePage/ProductUpdatePage.tsx index 48d50cf6c..b263bd57e 100644 --- a/src/products/components/ProductUpdatePage/ProductUpdatePage.tsx +++ b/src/products/components/ProductUpdatePage/ProductUpdatePage.tsx @@ -5,7 +5,6 @@ import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; import Container from "@saleor/components/Container"; import Form from "@saleor/components/Form"; import Grid from "@saleor/components/Grid"; -import LeaveScreenDialog from "@saleor/components/LeaveScreenDialog"; import Metadata from "@saleor/components/Metadata/Metadata"; import PageHeader from "@saleor/components/PageHeader"; import SaveButtonBar from "@saleor/components/SaveButtonBar"; @@ -57,8 +56,6 @@ import ProductStocks, { ProductStockInput } from "../ProductStocks"; import ProductTaxes from "../ProductTaxes"; import ProductVariants from "../ProductVariants"; -export type ProductUpdatePageSubmitNextAction = "warehouse-configure"; - export interface ProductUpdatePageProps extends ListActions { defaultWeightUnit: string; errors: ProductErrorFragment[]; @@ -75,7 +72,6 @@ export interface ProductUpdatePageProps extends ListActions { saveButtonBarState: ConfirmButtonTransitionState; warehouses: WarehouseFragment[]; taxTypes: TaxTypeFragment[]; - submitNextAction?: ProductUpdatePageSubmitNextAction; fetchCategories: (query: string) => void; fetchCollections: (query: string) => void; onVariantsAdd: () => void; @@ -88,13 +84,10 @@ export interface ProductUpdatePageProps extends ListActions { onImageReorder?(event: { oldIndex: number; newIndex: number }); onImageUpload(file: File); onSeoClick?(); - onSubmit?( - data: ProductUpdatePageSubmitData, - nextAction?: ProductUpdatePageSubmitNextAction - ); - onSubmitSkip?(nextAction?: ProductUpdatePageSubmitNextAction); + onSubmit?(data: ProductUpdatePageSubmitData, nextAction?: () => void); onVariantAdd?(); onSetDefaultVariant(); + onWarehouseConfigure(); } export interface ProductUpdatePageSubmitData extends ProductUpdatePageFormData { @@ -131,12 +124,12 @@ export const ProductUpdatePage: React.FC = ({ onImageUpload, onSeoClick, onSubmit, - onSubmitSkip, onVariantAdd, onVariantsAdd, onSetDefaultVariant, onVariantShow, onVariantReorder, + onWarehouseConfigure, isChecked, selected, toggle, @@ -200,11 +193,10 @@ export const ProductUpdatePage: React.FC = ({ value: taxType.taxCode })) || []; - const [modalWithAction, setModalWithAction] = React.useState< - ProductUpdatePageSubmitNextAction - >(null); - - const handleSubmit = (data: ProductUpdatePageFormData) => { + const handleSubmit = ( + data: ProductUpdatePageFormData, + nextAction: () => void + ) => { const metadata = isMetadataModified ? data.metadata : undefined; const privateMetadata = isPrivateMetadataModified ? data.privateMetadata @@ -221,7 +213,7 @@ export const ProductUpdatePage: React.FC = ({ removeStocks: [], updateStocks: [] }, - modalWithAction + nextAction ); } else { const dataStocks = stocks.map(stock => stock.id); @@ -245,15 +237,22 @@ export const ProductUpdatePage: React.FC = ({ !stockDiff.added.some(addedStock => addedStock === stock.id) ) }, - modalWithAction + nextAction ); } - setModalWithAction(null); }; return (
- {({ change, data, hasChanged, submit, triggerChange, toggleValue }) => { + {({ + change, + data, + hasChanged, + submit, + triggerChange, + toggleValue, + askToLeave + }) => { const handleCollectionSelect = createMultiAutocompleteSelectHandler( toggleValue, setSelectedCollections, @@ -393,9 +392,9 @@ export const ProductUpdatePage: React.FC = ({ }} onWarehouseConfigure={() => { if (disabled || !onSubmit || !hasChanged) { - onSubmitSkip("warehouse-configure"); + onWarehouseConfigure(); } else { - setModalWithAction("warehouse-configure"); + askToLeave(onWarehouseConfigure); } }} /> @@ -487,17 +486,6 @@ export const ProductUpdatePage: React.FC = ({ state={saveButtonBarState} disabled={disabled || !hasChanged} /> - { - submit(); - }} - onRejectChanges={() => { - onSubmitSkip("warehouse-configure"); - }} - onClose={() => setModalWithAction(null)} - open={modalWithAction === "warehouse-configure"} - confirmButtonState={saveButtonBarState} - /> ); diff --git a/src/products/views/ProductUpdate/ProductUpdate.tsx b/src/products/views/ProductUpdate/ProductUpdate.tsx index 6321b4e57..6e1225941 100644 --- a/src/products/views/ProductUpdate/ProductUpdate.tsx +++ b/src/products/views/ProductUpdate/ProductUpdate.tsx @@ -38,9 +38,7 @@ import React from "react"; import { FormattedMessage, useIntl } from "react-intl"; import { getMutationState, maybe } from "../../../misc"; -import ProductUpdatePage, { - ProductUpdatePageSubmitNextAction -} from "../../components/ProductUpdatePage"; +import ProductUpdatePage from "../../components/ProductUpdatePage"; import { useProductDetails } from "../../queries"; import { ProductImageCreateVariables } from "../../types/ProductImageCreate"; import { ProductUpdate as ProductUpdateMutationResult } from "../../types/ProductUpdate"; @@ -281,14 +279,6 @@ export const ProductUpdate: React.FC = ({ id, params }) => { null ); - const handleSubmitNextAction = ( - nextAction?: ProductUpdatePageSubmitNextAction - ) => { - if (nextAction === "warehouse-configure") { - navigate(warehouseListPath); - } - }; - return ( <> data.product.name)} /> @@ -316,11 +306,11 @@ export const ProductUpdate: React.FC = ({ id, params }) => { onImageReorder={handleImageReorder} onSubmit={async (data, nextAction) => { const errors = await handleSubmit(data); - if (errors?.length === 0) { - handleSubmitNextAction(nextAction); + if (errors?.length === 0 && nextAction) { + nextAction(); } }} - onSubmitSkip={handleSubmitNextAction} + onWarehouseConfigure={() => navigate(warehouseListPath)} onVariantAdd={handleVariantAdd} onVariantsAdd={() => navigate(productVariantCreatorUrl(id))} onVariantShow={variantId => () => diff --git a/src/storybook/stories/products/ProductUpdatePage.tsx b/src/storybook/stories/products/ProductUpdatePage.tsx index c44841a1b..980d68a84 100644 --- a/src/storybook/stories/products/ProductUpdatePage.tsx +++ b/src/storybook/stories/products/ProductUpdatePage.tsx @@ -39,6 +39,7 @@ const props: ProductUpdatePageProps = { onVariantReorder: () => undefined, onVariantShow: () => undefined, onVariantsAdd: () => undefined, + onWarehouseConfigure: () => undefined, placeholderImage, product, saveButtonBarState: "default",