diff --git a/src/apps/components/CustomAppDetailsPage/CustomAppDetailsPage.tsx b/src/apps/components/CustomAppDetailsPage/CustomAppDetailsPage.tsx index f452257e2..3d84b32e2 100644 --- a/src/apps/components/CustomAppDetailsPage/CustomAppDetailsPage.tsx +++ b/src/apps/components/CustomAppDetailsPage/CustomAppDetailsPage.tsx @@ -42,7 +42,7 @@ export interface CustomAppDetailsPageProps { onTokenDelete: (id: string) => void; onTokenClose: () => void; onTokenCreate: () => void; - onSubmit: (data: CustomAppDetailsPageFormData) => void; + onSubmit: (data: CustomAppDetailsPageFormData) => Promise; onWebhookCreate: () => void; onWebhookRemove: (id: string) => void; navigateToWebhookDetails: (id: string) => () => void; diff --git a/src/apps/views/CustomAppDetails/CustomAppDetails.tsx b/src/apps/views/CustomAppDetails/CustomAppDetails.tsx index da7111e6d..4edd2a465 100644 --- a/src/apps/views/CustomAppDetails/CustomAppDetails.tsx +++ b/src/apps/views/CustomAppDetails/CustomAppDetails.tsx @@ -130,8 +130,8 @@ export const CustomAppDetails: React.FC = ({ onCompleted: onTokenDelete }); - const handleSubmit = (data: CustomAppDetailsPageFormData) => - updateApp({ + const handleSubmit = async (data: CustomAppDetailsPageFormData) => { + const result = await updateApp({ variables: { id, input: { @@ -144,6 +144,9 @@ export const CustomAppDetails: React.FC = ({ } }); + return result.data.appUpdate.errors; + }; + const handleTokenCreate = (name: string) => createToken({ variables: { diff --git a/src/attributes/components/AttributePage/AttributePage.tsx b/src/attributes/components/AttributePage/AttributePage.tsx index 2e4bb018a..611d9bbdb 100644 --- a/src/attributes/components/AttributePage/AttributePage.tsx +++ b/src/attributes/components/AttributePage/AttributePage.tsx @@ -126,7 +126,7 @@ const AttributePage: React.FC = ({ ? data.privateMetadata : undefined; - onSubmit({ + return onSubmit({ ...data, metadata, privateMetadata, diff --git a/src/categories/components/CategoryUpdatePage/CategoryUpdatePage.tsx b/src/categories/components/CategoryUpdatePage/CategoryUpdatePage.tsx index eb0d7280a..ec0df2233 100644 --- a/src/categories/components/CategoryUpdatePage/CategoryUpdatePage.tsx +++ b/src/categories/components/CategoryUpdatePage/CategoryUpdatePage.tsx @@ -61,7 +61,7 @@ export interface CategoryUpdatePageProps }; saveButtonBarState: ConfirmButtonTransitionState; onImageDelete: () => void; - onSubmit: (data: FormData) => void; + onSubmit: (data: FormData) => Promise; onImageUpload(file: File); onNextPage(); onPreviousPage(); @@ -139,7 +139,7 @@ export const CategoryUpdatePage: React.FC = ({ ? data.privateMetadata : undefined; - onSubmit({ + return onSubmit({ ...data, metadata, privateMetadata diff --git a/src/collections/components/CollectionDetailsPage/CollectionDetailsPage.tsx b/src/collections/components/CollectionDetailsPage/CollectionDetailsPage.tsx index d2661ed3a..0b37e6e51 100644 --- a/src/collections/components/CollectionDetailsPage/CollectionDetailsPage.tsx +++ b/src/collections/components/CollectionDetailsPage/CollectionDetailsPage.tsx @@ -81,7 +81,7 @@ const CollectionDetailsPage: React.FC = ({ ? data.privateMetadata : undefined; - onSubmit({ + return onSubmit({ ...data, isPublished: data.isPublished || !!data.publicationDate, metadata, diff --git a/src/customers/components/CustomerDetailsPage/CustomerDetailsPage.tsx b/src/customers/components/CustomerDetailsPage/CustomerDetailsPage.tsx index 44081fc76..216686180 100644 --- a/src/customers/components/CustomerDetailsPage/CustomerDetailsPage.tsx +++ b/src/customers/components/CustomerDetailsPage/CustomerDetailsPage.tsx @@ -33,7 +33,7 @@ export interface CustomerDetailsPageProps { errors: AccountErrorFragment[]; saveButtonBar: ConfirmButtonTransitionState; onBack: () => void; - onSubmit: (data: CustomerDetailsPageFormData) => void; + onSubmit: (data: CustomerDetailsPageFormData) => Promise; onViewAllOrdersClick: () => void; onRowClick: (id: string) => void; onAddressManageClick: () => void; diff --git a/src/customers/views/CustomerDetails.tsx b/src/customers/views/CustomerDetails.tsx index c7227e803..765c471e0 100644 --- a/src/customers/views/CustomerDetails.tsx +++ b/src/customers/views/CustomerDetails.tsx @@ -10,7 +10,9 @@ import { FormattedMessage, useIntl } from "react-intl"; import { maybe } from "../../misc"; import { orderListUrl, orderUrl } from "../../orders/urls"; -import CustomerDetailsPage from "../components/CustomerDetailsPage/CustomerDetailsPage"; +import CustomerDetailsPage, { + CustomerDetailsPageFormData +} from "../components/CustomerDetailsPage/CustomerDetailsPage"; import { TypedRemoveCustomerMutation, TypedUpdateCustomerMutation @@ -76,6 +78,25 @@ export const CustomerDetailsView: React.FC = ({ return ; } + const handleSubmit = async ( + data: CustomerDetailsPageFormData + ) => { + const result = await updateCustomer({ + variables: { + id, + input: { + email: data.email, + firstName: data.firstName, + isActive: data.isActive, + lastName: data.lastName, + note: data.note + } + } + }); + + return result.data.customerUpdate.errors; + }; + return ( <> = ({ } onBack={handleBack} onRowClick={id => navigate(orderUrl(id))} - onSubmit={formData => - updateCustomer({ - variables: { - id, - input: { - email: formData.email, - firstName: formData.firstName, - isActive: formData.isActive, - lastName: formData.lastName, - note: formData.note - } - } - }) - } + onSubmit={handleSubmit} onDelete={() => navigate( customerUrl(id, { diff --git a/src/discounts/components/SaleDetailsPage/SaleDetailsPage.tsx b/src/discounts/components/SaleDetailsPage/SaleDetailsPage.tsx index 46df77189..d831737fc 100644 --- a/src/discounts/components/SaleDetailsPage/SaleDetailsPage.tsx +++ b/src/discounts/components/SaleDetailsPage/SaleDetailsPage.tsx @@ -25,7 +25,7 @@ import SaleSummary from "../SaleSummary"; import SaleType from "../SaleType"; import SaleValue from "../SaleValue"; -export interface FormData { +export interface SaleDetailsPageFormData { endDate: string; endTime: string; hasEndDate: boolean; @@ -70,7 +70,7 @@ export interface SaleDetailsPageProps onProductUnassign: (id: string) => void; onProductClick: (id: string) => () => void; onRemove: () => void; - onSubmit: (data: FormData) => void; + onSubmit: (data: SaleDetailsPageFormData) => void; onTabClick: (index: SaleDetailsPageTab) => void; } @@ -111,7 +111,7 @@ const SaleDetailsPage: React.FC = ({ }) => { const intl = useIntl(); - const initialForm: FormData = { + const initialForm: SaleDetailsPageFormData = { endDate: splitDateTime(maybe(() => sale.endDate, "")).date, endTime: splitDateTime(maybe(() => sale.endDate, "")).time, hasEndDate: maybe(() => !!sale.endDate), diff --git a/src/discounts/components/SaleInfo/SaleInfo.tsx b/src/discounts/components/SaleInfo/SaleInfo.tsx index 94a1baa1e..dad0ffc23 100644 --- a/src/discounts/components/SaleInfo/SaleInfo.tsx +++ b/src/discounts/components/SaleInfo/SaleInfo.tsx @@ -9,10 +9,10 @@ import getDiscountErrorMessage from "@saleor/utils/errors/discounts"; import React from "react"; import { useIntl } from "react-intl"; -import { FormData } from "../SaleDetailsPage"; +import { SaleDetailsPageFormData } from "../SaleDetailsPage"; export interface SaleInfoProps { - data: FormData; + data: SaleDetailsPageFormData; disabled: boolean; errors: DiscountErrorFragment[]; onChange: (event: React.ChangeEvent) => void; @@ -38,7 +38,7 @@ const SaleInfo: React.FC = ({ disabled={disabled} error={!!formErrors.name} helperText={getDiscountErrorMessage(formErrors.name, intl)} - name={"name" as keyof FormData} + name={"name" as keyof SaleDetailsPageFormData} onChange={onChange} label={intl.formatMessage({ defaultMessage: "Name", diff --git a/src/discounts/components/SaleType/SaleType.tsx b/src/discounts/components/SaleType/SaleType.tsx index a5f782f37..ebec25615 100644 --- a/src/discounts/components/SaleType/SaleType.tsx +++ b/src/discounts/components/SaleType/SaleType.tsx @@ -10,10 +10,10 @@ import { SaleType as SaleTypeEnum } from "@saleor/types/globalTypes"; import React from "react"; import { IntlShape, useIntl } from "react-intl"; -import { FormData } from "../SaleDetailsPage"; +import { SaleDetailsPageFormData } from "../SaleDetailsPage"; export interface SaleTypeProps { - data: FormData; + data: SaleDetailsPageFormData; disabled: boolean; onChange: FormChange; } @@ -70,7 +70,7 @@ const SaleType: React.FC = props => { diff --git a/src/discounts/components/SaleValue/SaleValue.tsx b/src/discounts/components/SaleValue/SaleValue.tsx index 34312ac2c..1112365f6 100644 --- a/src/discounts/components/SaleValue/SaleValue.tsx +++ b/src/discounts/components/SaleValue/SaleValue.tsx @@ -10,11 +10,11 @@ import getDiscountErrorMessage from "@saleor/utils/errors/discounts"; import React from "react"; import { useIntl } from "react-intl"; -import { FormData } from "../SaleDetailsPage"; +import { SaleDetailsPageFormData } from "../SaleDetailsPage"; export interface SaleValueProps { currencySymbol: string; - data: FormData; + data: SaleDetailsPageFormData; disabled: boolean; errors: DiscountErrorFragment[]; onChange: FormChange; diff --git a/src/discounts/components/VoucherDates/VoucherDates.tsx b/src/discounts/components/VoucherDates/VoucherDates.tsx index be804c2e6..3589aa142 100644 --- a/src/discounts/components/VoucherDates/VoucherDates.tsx +++ b/src/discounts/components/VoucherDates/VoucherDates.tsx @@ -11,10 +11,10 @@ import getDiscountErrorMessage from "@saleor/utils/errors/discounts"; import React from "react"; import { useIntl } from "react-intl"; -import { FormData } from "../VoucherDetailsPage"; +import { VoucherDetailsPageFormData } from "../VoucherDetailsPage"; interface VoucherDatesProps { - data: FormData; + data: VoucherDetailsPageFormData; defaultCurrency: string; disabled: boolean; errors: DiscountErrorFragment[]; @@ -45,7 +45,7 @@ const VoucherDates = ({ disabled={disabled} error={!!formErrors.startDate} helperText={getDiscountErrorMessage(formErrors.startDate, intl)} - name={"startDate" as keyof FormData} + name={"startDate" as keyof VoucherDetailsPageFormData} onChange={onChange} label={intl.formatMessage(commonMessages.startDate)} value={data.startDate} @@ -59,7 +59,7 @@ const VoucherDates = ({ disabled={disabled} error={!!formErrors.startDate} helperText={getDiscountErrorMessage(formErrors.startDate, intl)} - name={"startTime" as keyof FormData} + name={"startTime" as keyof VoucherDetailsPageFormData} onChange={onChange} label={intl.formatMessage(commonMessages.startHour)} value={data.startTime} @@ -76,7 +76,7 @@ const VoucherDates = ({ defaultMessage: "Set end date", description: "voucher end date, switch button" })} - name={"hasEndDate" as keyof FormData} + name={"hasEndDate" as keyof VoucherDetailsPageFormData} onChange={onChange} /> {data.hasEndDate && ( @@ -85,7 +85,7 @@ const VoucherDates = ({ disabled={disabled} error={!!formErrors.endDate} helperText={getDiscountErrorMessage(formErrors.endDate, intl)} - name={"endDate" as keyof FormData} + name={"endDate" as keyof VoucherDetailsPageFormData} onChange={onChange} label={intl.formatMessage(commonMessages.endDate)} value={data.endDate} @@ -99,7 +99,7 @@ const VoucherDates = ({ disabled={disabled} error={!!formErrors.endDate} helperText={getDiscountErrorMessage(formErrors.endDate, intl)} - name={"endTime" as keyof FormData} + name={"endTime" as keyof VoucherDetailsPageFormData} onChange={onChange} label={intl.formatMessage(commonMessages.endHour)} value={data.endTime} diff --git a/src/discounts/components/VoucherDetailsPage/VoucherDetailsPage.tsx b/src/discounts/components/VoucherDetailsPage/VoucherDetailsPage.tsx index db418d3e6..660a8196c 100644 --- a/src/discounts/components/VoucherDetailsPage/VoucherDetailsPage.tsx +++ b/src/discounts/components/VoucherDetailsPage/VoucherDetailsPage.tsx @@ -47,7 +47,7 @@ export function voucherDetailsPageTab(tab: string): VoucherDetailsPageTab { : VoucherDetailsPageTab.categories; } -export interface FormData { +export interface VoucherDetailsPageFormData { applyOncePerCustomer: boolean; applyOncePerOrder: boolean; code: string; @@ -89,7 +89,7 @@ export interface VoucherDetailsPageProps onProductUnassign: (id: string) => void; onProductClick: (id: string) => () => void; onRemove: () => void; - onSubmit: (data: FormData) => void; + onSubmit: (data: VoucherDetailsPageFormData) => void; onTabClick: (index: VoucherDetailsPageTab) => void; } @@ -141,7 +141,7 @@ const VoucherDetailsPage: React.FC = ({ requirementsPickerInitValue = RequirementsPicker.NONE; } - const initialForm: FormData = { + const initialForm: VoucherDetailsPageFormData = { applyOncePerCustomer: maybe(() => voucher.applyOncePerCustomer, false), applyOncePerOrder: maybe(() => voucher.applyOncePerOrder, false), code: maybe(() => voucher.code, ""), diff --git a/src/discounts/components/VoucherInfo/VoucherInfo.tsx b/src/discounts/components/VoucherInfo/VoucherInfo.tsx index 3b227980f..e773d17a4 100644 --- a/src/discounts/components/VoucherInfo/VoucherInfo.tsx +++ b/src/discounts/components/VoucherInfo/VoucherInfo.tsx @@ -11,10 +11,10 @@ import React from "react"; import { FormattedMessage, useIntl } from "react-intl"; import { generateCode } from "../../../misc"; -import { FormData } from "../VoucherDetailsPage"; +import { VoucherDetailsPageFormData } from "../VoucherDetailsPage"; interface VoucherInfoProps { - data: FormData; + data: VoucherDetailsPageFormData; errors: DiscountErrorFragment[]; disabled: boolean; variant: "create" | "update"; @@ -61,7 +61,7 @@ const VoucherInfo = ({ error={!!formErrors.code} fullWidth helperText={getDiscountErrorMessage(formErrors.code, intl)} - name={"code" as keyof FormData} + name={"code" as keyof VoucherDetailsPageFormData} label={intl.formatMessage({ defaultMessage: "Discount Code" })} diff --git a/src/discounts/components/VoucherLimits/VoucherLimits.tsx b/src/discounts/components/VoucherLimits/VoucherLimits.tsx index 30a377641..35a0bb0c3 100644 --- a/src/discounts/components/VoucherLimits/VoucherLimits.tsx +++ b/src/discounts/components/VoucherLimits/VoucherLimits.tsx @@ -9,10 +9,10 @@ import getDiscountErrorMessage from "@saleor/utils/errors/discounts"; import React from "react"; import { useIntl } from "react-intl"; -import { FormData } from "../VoucherDetailsPage"; +import { VoucherDetailsPageFormData } from "../VoucherDetailsPage"; interface VoucherLimitsProps { - data: FormData; + data: VoucherDetailsPageFormData; defaultCurrency: string; disabled: boolean; errors: DiscountErrorFragment[]; @@ -44,7 +44,7 @@ const VoucherLimits = ({ defaultMessage: "Limit number of times this discount can be used in total" })} - name={"hasUsageLimit" as keyof FormData} + name={"hasUsageLimit" as keyof VoucherDetailsPageFormData} onChange={onChange} /> {data.hasUsageLimit && ( @@ -56,7 +56,7 @@ const VoucherLimits = ({ defaultMessage: "Limit of Uses", description: "voucher" })} - name={"usageLimit" as keyof FormData} + name={"usageLimit" as keyof VoucherDetailsPageFormData} value={data.usageLimit} onChange={onChange} type="number" @@ -72,7 +72,7 @@ const VoucherLimits = ({ defaultMessage: "Limit to one use per customer", description: "limit voucher" })} - name={"applyOncePerCustomer" as keyof FormData} + name={"applyOncePerCustomer" as keyof VoucherDetailsPageFormData} onChange={onChange} /> diff --git a/src/discounts/components/VoucherRequirements/VoucherRequirements.tsx b/src/discounts/components/VoucherRequirements/VoucherRequirements.tsx index da7d8e563..64255c4a0 100644 --- a/src/discounts/components/VoucherRequirements/VoucherRequirements.tsx +++ b/src/discounts/components/VoucherRequirements/VoucherRequirements.tsx @@ -11,10 +11,10 @@ import getDiscountErrorMessage from "@saleor/utils/errors/discounts"; import React from "react"; import { useIntl } from "react-intl"; -import { FormData } from "../VoucherDetailsPage"; +import { VoucherDetailsPageFormData } from "../VoucherDetailsPage"; interface VoucherRequirementsProps { - data: FormData; + data: VoucherDetailsPageFormData; defaultCurrency: string; disabled: boolean; errors: DiscountErrorFragment[]; @@ -73,7 +73,7 @@ const VoucherRequirements = ({ @@ -86,7 +86,7 @@ const VoucherRequirements = ({ error={!!formErrors.minSpent} helperText={getDiscountErrorMessage(formErrors.minSpent, intl)} label={minimalOrderValueText} - name={"minSpent" as keyof FormData} + name={"minSpent" as keyof VoucherDetailsPageFormData} value={data.minSpent} onChange={onChange} fullWidth @@ -100,7 +100,9 @@ const VoucherRequirements = ({ intl )} label={minimalQuantityText} - name={"minCheckoutItemsQuantity" as keyof FormData} + name={ + "minCheckoutItemsQuantity" as keyof VoucherDetailsPageFormData + } value={data.minCheckoutItemsQuantity} onChange={onChange} fullWidth diff --git a/src/discounts/components/VoucherTypes/VoucherTypes.tsx b/src/discounts/components/VoucherTypes/VoucherTypes.tsx index f64e9b4a8..f2e5d7591 100644 --- a/src/discounts/components/VoucherTypes/VoucherTypes.tsx +++ b/src/discounts/components/VoucherTypes/VoucherTypes.tsx @@ -10,10 +10,10 @@ import React from "react"; import { useIntl } from "react-intl"; import { DiscountValueTypeEnum } from "../../../types/globalTypes"; -import { FormData } from "../VoucherDetailsPage"; +import { VoucherDetailsPageFormData } from "../VoucherDetailsPage"; interface VoucherTypesProps { - data: FormData; + data: VoucherDetailsPageFormData; errors: DiscountErrorFragment[]; disabled: boolean; onChange: (event: React.ChangeEvent) => void; @@ -68,7 +68,7 @@ const VoucherTypes = ({ disabled={disabled} error={!!formErrors.discountType} hint={getDiscountErrorMessage(formErrors.discountType, intl)} - name={"discountType" as keyof FormData} + name={"discountType" as keyof VoucherDetailsPageFormData} value={data.discountType} onChange={onChange} /> diff --git a/src/discounts/components/VoucherValue/VoucherValue.tsx b/src/discounts/components/VoucherValue/VoucherValue.tsx index 6c3e1ecf8..b3123cfd5 100644 --- a/src/discounts/components/VoucherValue/VoucherValue.tsx +++ b/src/discounts/components/VoucherValue/VoucherValue.tsx @@ -16,10 +16,10 @@ import { FormattedMessage, useIntl } from "react-intl"; import { DiscountValueTypeEnum } from "../../../types/globalTypes"; import { translateVoucherTypes } from "../../translations"; -import { FormData } from "../VoucherDetailsPage"; +import { VoucherDetailsPageFormData } from "../VoucherDetailsPage"; interface VoucherValueProps { - data: FormData; + data: VoucherDetailsPageFormData; defaultCurrency: string; errors: DiscountErrorFragment[]; disabled: boolean; @@ -74,11 +74,11 @@ const VoucherValue: React.FC = props => { data.discountType === DiscountValueTypeEnum.FIXED ? defaultCurrency : "%", - name: "discountType" as keyof FormData, + name: "discountType" as keyof VoucherDetailsPageFormData, values: null }} helperText={getDiscountErrorMessage(formErrors.discountValue, intl)} - name={"value" as keyof FormData} + name={"value" as keyof VoucherDetailsPageFormData} onChange={onChange} label={intl.formatMessage({ defaultMessage: "Discount Value" @@ -102,7 +102,7 @@ const VoucherValue: React.FC = props => { label={intl.formatMessage({ defaultMessage: "Voucher Specific Information" })} - name={"type" as keyof FormData} + name={"type" as keyof VoucherDetailsPageFormData} value={data.type} onChange={onChange} /> @@ -111,7 +111,7 @@ const VoucherValue: React.FC = props => {
= ({ id, params }) => { } }); + const handleSubmit = async ( + data: SaleDetailsPageFormData + ) => { + const result = await saleUpdate({ + variables: { + id, + input: { + endDate: data.hasEndDate + ? joinDateTime(data.endDate, data.endTime) + : null, + name: data.name, + startDate: joinDateTime( + data.startDate, + data.startTime + ), + type: discountValueTypeEnum(data.type), + value: decimal(data.value) + } + } + }); + + return result.data.saleUpdate.errors; + }; + const { loadNextPage, loadPreviousPage, @@ -244,30 +269,7 @@ export const SaleDetails: React.FC = ({ id, params }) => { activeTab={params.activeTab} onBack={() => navigate(saleListUrl())} onTabClick={changeTab} - onSubmit={formData => - saleUpdate({ - variables: { - id, - input: { - endDate: formData.hasEndDate - ? joinDateTime( - formData.endDate, - formData.endTime - ) - : null, - name: formData.name, - startDate: joinDateTime( - formData.startDate, - formData.startTime - ), - type: discountValueTypeEnum( - formData.type - ), - value: decimal(formData.value) - } - } - }) - } + onSubmit={handleSubmit} onRemove={() => openModal("remove")} saveButtonBarState={saleUpdateOpts.status} categoryListToolbar={ diff --git a/src/discounts/views/VoucherDetails.tsx b/src/discounts/views/VoucherDetails.tsx index 866073fde..f59c90a34 100644 --- a/src/discounts/views/VoucherDetails.tsx +++ b/src/discounts/views/VoucherDetails.tsx @@ -31,6 +31,7 @@ import { } from "../../types/globalTypes"; import DiscountCountrySelectDialog from "../components/DiscountCountrySelectDialog"; import VoucherDetailsPage, { + VoucherDetailsPageFormData, VoucherDetailsPageTab } from "../components/VoucherDetailsPage"; import { @@ -195,6 +196,54 @@ export const VoucherDetails: React.FC = ({ } }); + const handleSubmit = async ( + data: VoucherDetailsPageFormData + ) => { + const result = await voucherUpdate({ + variables: { + id, + input: { + applyOncePerCustomer: data.applyOncePerCustomer, + applyOncePerOrder: data.applyOncePerOrder, + discountValue: + data.discountType.toString() === "SHIPPING" + ? 100 + : decimal(data.value), + discountValueType: + data.discountType.toString() === "SHIPPING" + ? DiscountValueTypeEnum.PERCENTAGE + : data.discountType, + endDate: data.hasEndDate + ? joinDateTime(data.endDate, data.endTime) + : null, + minAmountSpent: + data.requirementsPicker !== + RequirementsPicker.ORDER + ? 0 + : parseFloat(data.minSpent), + minCheckoutItemsQuantity: + data.requirementsPicker !== + RequirementsPicker.ITEM + ? 0 + : parseFloat(data.minCheckoutItemsQuantity), + startDate: joinDateTime( + data.startDate, + data.startTime + ), + type: + data.discountType.toString() === "SHIPPING" + ? VoucherTypeEnum.SHIPPING + : data.type, + usageLimit: data.hasUsageLimit + ? parseInt(data.usageLimit, 10) + : null + } + } + }); + + return result.data.voucherUpdate.errors; + }; + const { loadNextPage, loadPreviousPage, @@ -291,59 +340,7 @@ export const VoucherDetails: React.FC = ({ activeTab={params.activeTab} onBack={() => navigate(voucherListUrl())} onTabClick={changeTab} - onSubmit={formData => - voucherUpdate({ - variables: { - id, - input: { - applyOncePerCustomer: - formData.applyOncePerCustomer, - applyOncePerOrder: - formData.applyOncePerOrder, - discountValue: - formData.discountType.toString() === - "SHIPPING" - ? 100 - : decimal(formData.value), - discountValueType: - formData.discountType.toString() === - "SHIPPING" - ? DiscountValueTypeEnum.PERCENTAGE - : formData.discountType, - endDate: formData.hasEndDate - ? joinDateTime( - formData.endDate, - formData.endTime - ) - : null, - minAmountSpent: - formData.requirementsPicker !== - RequirementsPicker.ORDER - ? 0 - : parseFloat(formData.minSpent), - minCheckoutItemsQuantity: - formData.requirementsPicker !== - RequirementsPicker.ITEM - ? 0 - : parseFloat( - formData.minCheckoutItemsQuantity - ), - startDate: joinDateTime( - formData.startDate, - formData.startTime - ), - type: - formData.discountType.toString() === - "SHIPPING" - ? VoucherTypeEnum.SHIPPING - : formData.type, - usageLimit: formData.hasUsageLimit - ? parseInt(formData.usageLimit, 10) - : null - } - } - }) - } + onSubmit={handleSubmit} onRemove={() => openModal("remove")} saveButtonBarState={voucherUpdateOpts.status} categoryListToolbar={ diff --git a/src/hooks/useAddressValidation.ts b/src/hooks/useAddressValidation.ts index de9f81bad..8a042bed8 100644 --- a/src/hooks/useAddressValidation.ts +++ b/src/hooks/useAddressValidation.ts @@ -5,14 +5,14 @@ import { AccountErrorCode, AddressInput } from "@saleor/types/globalTypes"; import { add, remove } from "@saleor/utils/lists"; import { useState } from "react"; -interface UseAddressValidation { +interface UseAddressValidation { errors: AccountErrorFragment[]; - submit: (data: T & AddressTypeInput) => void; + submit: (data: TInput & AddressTypeInput) => TOutput; } -function useAddressValidation( - onSubmit: (address: T & AddressInput) => void -): UseAddressValidation { +function useAddressValidation( + onSubmit: (address: TInput & AddressInput) => TOutput +): UseAddressValidation { const [validationErrors, setValidationErrors] = useState< AccountErrorFragment[] >([]); @@ -25,7 +25,7 @@ function useAddressValidation( return { errors: validationErrors, - submit: (data: T & AddressTypeInput) => { + submit: (data: TInput & AddressTypeInput) => { try { setValidationErrors( remove( @@ -34,7 +34,7 @@ function useAddressValidation( (a, b) => a.field === b.field ) ); - onSubmit(transformFormToAddress(data)); + return onSubmit(transformFormToAddress(data)); } catch { setValidationErrors(add(countryRequiredError, validationErrors)); } diff --git a/src/hooks/useForm.ts b/src/hooks/useForm.ts index 2f3d54282..46009e8a2 100644 --- a/src/hooks/useForm.ts +++ b/src/hooks/useForm.ts @@ -51,7 +51,7 @@ function handleRefresh( function useForm( initial: T, - onSubmit?: (data: T) => void + onSubmit?: (data: T) => Promise | void ): UseFormResult { const [hasChanged, setChanged] = useState(false); const [data, setData] = useStateFromProps(initial, { @@ -106,9 +106,15 @@ function useForm( })); } - function submit() { + async function submit() { if (typeof onSubmit === "function") { - onSubmit(data); + const result = onSubmit(data); + if (result) { + const errors = await result; + if (errors.length === 0) { + setChanged(false); + } + } } } diff --git a/src/navigation/components/MenuDetailsPage/MenuDetailsPage.tsx b/src/navigation/components/MenuDetailsPage/MenuDetailsPage.tsx index 93c093ff8..576dd0bb9 100644 --- a/src/navigation/components/MenuDetailsPage/MenuDetailsPage.tsx +++ b/src/navigation/components/MenuDetailsPage/MenuDetailsPage.tsx @@ -36,7 +36,7 @@ export interface MenuDetailsPageProps { onItemAdd: () => void; onItemClick: (id: string, type: MenuItemType) => void; onItemEdit: (id: string) => void; - onSubmit: (data: MenuDetailsSubmitData) => Promise; + onSubmit: (data: MenuDetailsSubmitData) => Promise; } const MenuDetailsPage: React.FC = ({ @@ -62,14 +62,16 @@ const MenuDetailsPage: React.FC = ({ ); const handleSubmit = async (data: MenuDetailsFormData) => { - if ( - await onSubmit({ - name: data.name, - operations: treeOperations - }) - ) { + const result = await onSubmit({ + name: data.name, + operations: treeOperations + }); + + if (result) { setTreeOperations([]); } + + return result; }; const handleChange = (operation: TreeOperation) => { diff --git a/src/navigation/views/MenuDetails/index.tsx b/src/navigation/views/MenuDetails/index.tsx index d33d5ddcc..4f9756082 100644 --- a/src/navigation/views/MenuDetails/index.tsx +++ b/src/navigation/views/MenuDetails/index.tsx @@ -141,28 +141,20 @@ const MenuDetails: React.FC = ({ id, params }) => { // that it should clean operation stack if mutations // were successful const handleSubmit = async (data: MenuDetailsSubmitData) => { - try { - const result = await menuUpdate({ - variables: { - id, - moves: getMoves(data), - name: data.name, - removeIds: getRemoveIds(data) - } - }); - if (result) { - if ( - result.data.menuItemBulkDelete.errors.length > 0 || - result.data.menuItemMove.errors.length > 0 || - result.data.menuUpdate.errors.length > 0 - ) { - return false; - } + const result = await menuUpdate({ + variables: { + id, + moves: getMoves(data), + name: data.name, + removeIds: getRemoveIds(data) } - return true; - } catch { - return false; - } + }); + + return [ + ...result.data.menuItemBulkDelete.errors, + ...result.data.menuItemMove.errors, + ...result.data.menuUpdate.errors + ]; }; return ( diff --git a/src/orders/components/OrderDetailsPage/OrderDetailsPage.tsx b/src/orders/components/OrderDetailsPage/OrderDetailsPage.tsx index eb5ad5d68..62c9bf240 100644 --- a/src/orders/components/OrderDetailsPage/OrderDetailsPage.tsx +++ b/src/orders/components/OrderDetailsPage/OrderDetailsPage.tsx @@ -74,7 +74,7 @@ export interface OrderDetailsPageProps extends UserPermissionProps { onInvoiceClick(invoiceId: string); onInvoiceGenerate(); onInvoiceSend(invoiceId: string); - onSubmit(data: MetadataFormData); + onSubmit(data: MetadataFormData): Promise; } const OrderDetailsPage: React.FC = props => { @@ -123,7 +123,7 @@ const OrderDetailsPage: React.FC = props => { ? data.privateMetadata : undefined; - onSubmit({ + return onSubmit({ metadata, privateMetadata }); diff --git a/src/orders/views/OrderDetails/index.tsx b/src/orders/views/OrderDetails/index.tsx index 92b646f42..3b85a4e1b 100644 --- a/src/orders/views/OrderDetails/index.tsx +++ b/src/orders/views/OrderDetails/index.tsx @@ -127,6 +127,8 @@ export const OrderDetails: React.FC = ({ id, params }) => { text: intl.formatMessage(commonMessages.savedChanges) }); } + + return result; }; return ( diff --git a/src/pages/components/PageDetailsPage/PageDetailsPage.tsx b/src/pages/components/PageDetailsPage/PageDetailsPage.tsx index 8350b9b99..db0115c34 100644 --- a/src/pages/components/PageDetailsPage/PageDetailsPage.tsx +++ b/src/pages/components/PageDetailsPage/PageDetailsPage.tsx @@ -27,7 +27,7 @@ import { maybe } from "../../../misc"; import { PageDetails_page } from "../../types/PageDetails"; import PageInfo from "../PageInfo"; -export interface FormData extends MetadataFormData { +export interface PageDetailsPageFormData extends MetadataFormData { content: RawDraftContentState; isPublished: boolean; publicationDate: string; @@ -45,7 +45,7 @@ export interface PageDetailsPageProps { saveButtonBarState: ConfirmButtonTransitionState; onBack: () => void; onRemove: () => void; - onSubmit: (data: FormData) => void; + onSubmit: (data: PageDetailsPageFormData) => void; } const PageDetailsPage: React.FC = ({ @@ -67,7 +67,7 @@ const PageDetailsPage: React.FC = ({ const pageExists = page !== null; - const initialForm: FormData = { + const initialForm: PageDetailsPageFormData = { content: maybe( () => JSON.parse(page.contentJson), convertToRaw(ContentState.createFromText("")) diff --git a/src/pages/components/PageInfo/PageInfo.tsx b/src/pages/components/PageInfo/PageInfo.tsx index c89a2883f..12c2ecdeb 100644 --- a/src/pages/components/PageInfo/PageInfo.tsx +++ b/src/pages/components/PageInfo/PageInfo.tsx @@ -14,10 +14,10 @@ import { useIntl } from "react-intl"; import { maybe } from "../../../misc"; import { PageDetails_page } from "../../types/PageDetails"; -import { FormData } from "../PageDetailsPage"; +import { PageDetailsPageFormData } from "../PageDetailsPage"; export interface PageInfoProps { - data: FormData; + data: PageDetailsPageFormData; disabled: boolean; errors: PageErrorFragment[]; page: PageDetails_page; @@ -56,7 +56,7 @@ const PageInfo: React.FC = props => { defaultMessage: "Title", description: "page title" })} - name={"title" as keyof FormData} + name={"title" as keyof PageDetailsPageFormData} value={data.title} onChange={onChange} /> @@ -70,7 +70,7 @@ const PageInfo: React.FC = props => { defaultMessage: "Content", description: "page content" })} - name={"content" as keyof FormData} + name={"content" as keyof PageDetailsPageFormData} onChange={onChange} /> diff --git a/src/pages/views/PageDetails.tsx b/src/pages/views/PageDetails.tsx index ded216691..7b159d7de 100644 --- a/src/pages/views/PageDetails.tsx +++ b/src/pages/views/PageDetails.tsx @@ -14,7 +14,9 @@ import { FormattedMessage, useIntl } from "react-intl"; import { getStringOrPlaceholder, maybe } from "../../misc"; import { PageInput } from "../../types/globalTypes"; -import PageDetailsPage, { FormData } from "../components/PageDetailsPage"; +import PageDetailsPage, { + PageDetailsPageFormData +} from "../components/PageDetailsPage"; import { TypedPageRemove, TypedPageUpdate } from "../mutations"; import { TypedPageDetailsQuery } from "../queries"; import { PageRemove } from "../types/PageRemove"; @@ -25,7 +27,7 @@ export interface PageDetailsProps { params: PageUrlQueryParams; } -const createPageInput = (data: FormData): PageInput => ({ +const createPageInput = (data: PageDetailsPageFormData): PageInput => ({ contentJson: JSON.stringify(data.content), isPublished: data.isPublished, publicationDate: data.publicationDate, @@ -61,7 +63,7 @@ export const PageDetails: React.FC = ({ id, params }) => { {(pageUpdate, pageUpdateOpts) => ( {pageDetails => { - const handleUpdate = async (data: FormData) => { + const handleUpdate = async (data: PageDetailsPageFormData) => { const result = await pageUpdate({ variables: { id, diff --git a/src/permissionGroups/components/PermissionGroupDetailsPage/PermissionGroupDetailsPage.tsx b/src/permissionGroups/components/PermissionGroupDetailsPage/PermissionGroupDetailsPage.tsx index 996afa327..871a42e26 100644 --- a/src/permissionGroups/components/PermissionGroupDetailsPage/PermissionGroupDetailsPage.tsx +++ b/src/permissionGroups/components/PermissionGroupDetailsPage/PermissionGroupDetailsPage.tsx @@ -56,7 +56,7 @@ export interface PermissionGroupDetailsPageProps onAssign: () => void; onBack: () => void; onUnassign: (ids: string[]) => void; - onSubmit(data: PermissionGroupDetailsPageFormData); + onSubmit: (data: PermissionGroupDetailsPageFormData) => Promise; } const PermissionGroupDetailsPage: React.FC = ({ diff --git a/src/permissionGroups/views/PermissionGroupDetails/PermissionGroupDetails.tsx b/src/permissionGroups/views/PermissionGroupDetails/PermissionGroupDetails.tsx index 6294c993b..7bdd746d1 100644 --- a/src/permissionGroups/views/PermissionGroupDetails/PermissionGroupDetails.tsx +++ b/src/permissionGroups/views/PermissionGroupDetails/PermissionGroupDetails.tsx @@ -21,7 +21,9 @@ import React, { useState } from "react"; import { useIntl } from "react-intl"; import AssignMembersDialog from "../../components/AssignMembersDialog"; -import PermissionGroupDetailsPage from "../../components/PermissionGroupDetailsPage"; +import PermissionGroupDetailsPage, { + PermissionGroupDetailsPageFormData +} from "../../components/PermissionGroupDetailsPage"; import UnassignMembersDialog from "../../components/UnassignMembersDialog"; import { usePermissionGroupUpdate } from "../../mutations"; import { usePermissionGroupDetailsQuery } from "../../queries"; @@ -131,6 +133,21 @@ export const PermissionGroupDetails: React.FC = ({ ); const disabled = loading || !isGroupEditable || permissionsExceeded; + const handleSubmit = async (formData: PermissionGroupDetailsPageFormData) => { + const result = await permissionGroupUpdate({ + variables: { + id, + input: { + name: formData.name, + ...permissionsDiff(data?.permissionGroup, formData), + ...usersDiff(data?.permissionGroup, formData) + } + } + }); + + return result.data.permissionGroupUpdate.errors; + }; + return ( <> = ({ errors={ permissionGroupUpdateResult?.data?.permissionGroupUpdate.errors || [] } - onSubmit={formData => - permissionGroupUpdate({ - variables: { - id, - input: { - name: formData.name, - ...permissionsDiff(data?.permissionGroup, formData), - ...usersDiff(data?.permissionGroup, formData) - } - } - }) - } + onSubmit={handleSubmit} permissions={permissions} saveButtonBarState={permissionGroupUpdateResult.status} disabled={disabled} diff --git a/src/plugins/components/PluginInfo/PluginInfo.tsx b/src/plugins/components/PluginInfo/PluginInfo.tsx index 861c6c8eb..9e8f0ce50 100644 --- a/src/plugins/components/PluginInfo/PluginInfo.tsx +++ b/src/plugins/components/PluginInfo/PluginInfo.tsx @@ -13,10 +13,10 @@ import getPluginErrorMessage from "@saleor/utils/errors/plugins"; import React from "react"; import { FormattedMessage, useIntl } from "react-intl"; -import { FormData } from "../PluginsDetailsPage"; +import { PluginDetailsPageFormData } from "../PluginsDetailsPage"; interface PluginInfoProps { - data: FormData; + data: PluginDetailsPageFormData; description: string; errors: PluginErrorFragment[]; name: string; @@ -83,7 +83,7 @@ const PluginInfo: React.FC = ({ })} ) => void; diff --git a/src/plugins/components/PluginsDetailsPage/PluginsDetailsPage.tsx b/src/plugins/components/PluginsDetailsPage/PluginsDetailsPage.tsx index 329e94871..be1e1d2c7 100644 --- a/src/plugins/components/PluginsDetailsPage/PluginsDetailsPage.tsx +++ b/src/plugins/components/PluginsDetailsPage/PluginsDetailsPage.tsx @@ -23,7 +23,7 @@ import PluginAuthorization from "../PluginAuthorization"; import PluginInfo from "../PluginInfo"; import PluginSettings from "../PluginSettings"; -export interface FormData { +export interface PluginDetailsPageFormData { active: boolean; configuration: ConfigurationItemInput[]; } @@ -36,7 +36,7 @@ export interface PluginsDetailsPageProps { onBack: () => void; onClear: (field: string) => void; onEdit: (field: string) => void; - onSubmit: (data: FormData) => void; + onSubmit: (data: PluginDetailsPageFormData) => void; } const useStyles = makeStyles( @@ -64,7 +64,7 @@ const PluginsDetailsPage: React.FC = props => { const classes = useStyles(props); const intl = useIntl(); - const initialForm: FormData = { + const initialForm: PluginDetailsPageFormData = { active: plugin?.active || false, configuration: plugin?.configuration ?.filter(field => !isSecretField(plugin?.configuration || [], field.name)) diff --git a/src/plugins/views/PluginsDetails.tsx b/src/plugins/views/PluginsDetails.tsx index 74b719024..56cf7f072 100644 --- a/src/plugins/views/PluginsDetails.tsx +++ b/src/plugins/views/PluginsDetails.tsx @@ -9,7 +9,9 @@ import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandl import React from "react"; import { FormattedMessage, useIntl } from "react-intl"; -import PluginsDetailsPage from "../components/PluginsDetailsPage"; +import PluginsDetailsPage, { + PluginDetailsPageFormData +} from "../components/PluginsDetailsPage"; import PluginSecretFieldDialog from "../components/PluginSecretFieldDialog"; import { TypedPluginUpdate } from "../mutations"; import { TypedPluginsDetailsQuery } from "../queries"; @@ -89,6 +91,25 @@ export const PluginsDetails: React.FC = ({ } }); + const handleSubmit = async ( + formData: PluginDetailsPageFormData + ) => { + const result = await pluginUpdate({ + variables: { + id, + input: { + active: formData.active, + configuration: getConfigurationInput( + pluginDetails.data.plugin.configuration, + formData.configuration + ) + } + } + }); + + return result.data.pluginUpdate.errors; + }; + return ( <> @@ -110,20 +131,7 @@ export const PluginsDetails: React.FC = ({ id }) } - onSubmit={formData => - pluginUpdate({ - variables: { - id, - input: { - active: formData.active, - configuration: getConfigurationInput( - pluginDetails.data.plugin.configuration, - formData.configuration - ) - } - } - }) - } + onSubmit={handleSubmit} /> {pluginDetails.data?.plugin?.configuration && ( <> diff --git a/src/productTypes/components/ProductTypeDetailsPage/ProductTypeDetailsPage.tsx b/src/productTypes/components/ProductTypeDetailsPage/ProductTypeDetailsPage.tsx index a4a5391df..810736704 100644 --- a/src/productTypes/components/ProductTypeDetailsPage/ProductTypeDetailsPage.tsx +++ b/src/productTypes/components/ProductTypeDetailsPage/ProductTypeDetailsPage.tsx @@ -61,7 +61,7 @@ export interface ProductTypeDetailsPageProps { onBack: () => void; onDelete: () => void; onHasVariantsToggle: (hasVariants: boolean) => void; - onSubmit: (data: ProductTypeForm) => void; + onSubmit: (data: ProductTypeForm) => Promise; } function handleTaxTypeChange( @@ -141,7 +141,7 @@ const ProductTypeDetailsPage: React.FC = ({ ? data.privateMetadata : undefined; - onSubmit({ + return onSubmit({ ...data, metadata, privateMetadata diff --git a/src/shipping/components/ShippingZoneDetailsPage/ShippingZoneDetailsPage.tsx b/src/shipping/components/ShippingZoneDetailsPage/ShippingZoneDetailsPage.tsx index 31c41233a..18175bf86 100644 --- a/src/shipping/components/ShippingZoneDetailsPage/ShippingZoneDetailsPage.tsx +++ b/src/shipping/components/ShippingZoneDetailsPage/ShippingZoneDetailsPage.tsx @@ -46,7 +46,7 @@ export interface ShippingZoneDetailsPageProps onPriceRateAdd: () => void; onPriceRateEdit: (id: string) => void; onRateRemove: (rateId: string) => void; - onSubmit: (data: FormData) => void; + onSubmit: (data: FormData) => Promise; onWarehouseAdd: () => void; onWeightRateAdd: () => void; onWeightRateEdit: (id: string) => void; diff --git a/src/shipping/views/ShippingZoneDetails/index.tsx b/src/shipping/views/ShippingZoneDetails/index.tsx index 1ebaf32cc..84bc07de1 100644 --- a/src/shipping/views/ShippingZoneDetails/index.tsx +++ b/src/shipping/views/ShippingZoneDetails/index.tsx @@ -148,13 +148,13 @@ const ShippingZoneDetails: React.FC = ({ } }); - const handleSubmit = (submitData: FormData) => { + const handleSubmit = async (submitData: FormData) => { const warehouseDiff = diff( data.shippingZone.warehouses.map(warehouse => warehouse.id), submitData.warehouses ); - updateShippingZone({ + const result = await updateShippingZone({ variables: { id, input: { @@ -164,6 +164,8 @@ const ShippingZoneDetails: React.FC = ({ } } }); + + return result.data.shippingZoneUpdate.errors; }; if (data?.shippingZone === null) { diff --git a/src/siteSettings/components/SiteSettingsPage/SiteSettingsPage.tsx b/src/siteSettings/components/SiteSettingsPage/SiteSettingsPage.tsx index b05db7280..46738b3b2 100644 --- a/src/siteSettings/components/SiteSettingsPage/SiteSettingsPage.tsx +++ b/src/siteSettings/components/SiteSettingsPage/SiteSettingsPage.tsx @@ -54,7 +54,7 @@ export interface SiteSettingsPageProps { onBack: () => void; onKeyAdd: () => void; onKeyRemove: (keyType: AuthorizationKeyType) => void; - onSubmit: (data: SiteSettingsPageFormData) => void; + onSubmit: (data: SiteSettingsPageFormData) => Promise; } export function areAddressInputFieldsModified( @@ -105,7 +105,7 @@ const SiteSettingsPage: React.FC = props => { const { errors: validationErrors, submit: handleSubmitWithAddress - } = useAddressValidation(onSubmit); + } = useAddressValidation(onSubmit); const initialFormAddress: SiteSettingsPageAddressFormData = { city: maybe(() => shop.companyAddress.city, ""), @@ -134,7 +134,7 @@ const SiteSettingsPage: React.FC = props => { const submitFunc = areAddressInputFieldsModified(data) ? handleSubmitWithAddress : onSubmit; - submitFunc(data); + return submitFunc(data); }} confirmLeave > diff --git a/src/siteSettings/views/index.tsx b/src/siteSettings/views/index.tsx index b090eda9d..88e7601ae 100644 --- a/src/siteSettings/views/index.tsx +++ b/src/siteSettings/views/index.tsx @@ -106,7 +106,7 @@ export const SiteSettings: React.FC = ({ params }) => { keyType: data.type } }); - const handleUpdateShopSettings = ( + const handleUpdateShopSettings = async ( data: SiteSettingsPageFormData ) => { const addressInput = areAddressInputFieldsModified(data) @@ -123,7 +123,7 @@ export const SiteSettings: React.FC = ({ params }) => { : { companyName: data.companyName }; - updateShopSettings({ + const result = await updateShopSettings({ variables: { addressInput, shopDomainInput: { @@ -139,6 +139,12 @@ export const SiteSettings: React.FC = ({ params }) => { } } }); + + return [ + result.data.shopAddressUpdate.errors, + result.data.shopDomainUpdate.errors, + result.data.shopSettingsUpdate.errors + ]; }; return ( diff --git a/src/staff/components/StaffDetailsPage/StaffDetailsPage.tsx b/src/staff/components/StaffDetailsPage/StaffDetailsPage.tsx index 11ccc1439..5a3eea8ab 100644 --- a/src/staff/components/StaffDetailsPage/StaffDetailsPage.tsx +++ b/src/staff/components/StaffDetailsPage/StaffDetailsPage.tsx @@ -50,7 +50,7 @@ export interface StaffDetailsPageProps extends SearchPageProps { onChangePassword: () => void; onDelete: () => void; onImageDelete: () => void; - onSubmit: (data: StaffDetailsFormData) => void; + onSubmit: (data: StaffDetailsFormData) => Promise; onImageUpload(file: File); } diff --git a/src/staff/views/StaffDetails.tsx b/src/staff/views/StaffDetails.tsx index 9c571fbe8..589149c2f 100644 --- a/src/staff/views/StaffDetails.tsx +++ b/src/staff/views/StaffDetails.tsx @@ -12,7 +12,9 @@ import usePermissionGroupSearch from "@saleor/searches/usePermissionGroupSearch" import React from "react"; import { FormattedMessage, useIntl } from "react-intl"; -import StaffDetailsPage from "../components/StaffDetailsPage/StaffDetailsPage"; +import StaffDetailsPage, { + StaffDetailsFormData +} from "../components/StaffDetailsPage/StaffDetailsPage"; import StaffPasswordResetDialog from "../components/StaffPasswordResetDialog"; import { TypedStaffAvatarDeleteMutation, @@ -122,168 +124,175 @@ export const StaffDetails: React.FC = ({ id, params }) => { return ( - {(updateStaffMember, updateResult) => ( - - {(deleteStaffMember, deleteResult) => ( - - {updateStaffAvatar => ( - - {(deleteStaffAvatar, deleteAvatarResult) => { - const isUserSameAsViewer = - user.user?.id === data?.user?.id; + {(updateStaffMember, updateResult) => { + const handleSubmit = async (formData: StaffDetailsFormData) => { + const result = await updateStaffMember({ + variables: { + id, + input: { + email: formData.email, + firstName: formData.firstName, + isActive: formData.isActive, + lastName: formData.lastName, + ...groupsDiff(data?.user, formData) + } + } + }); - return ( - <> - - - navigate( - staffMemberDetailsUrl(id, { - action: "change-password" - }) - ) - } - onDelete={() => - navigate( - staffMemberDetailsUrl(id, { - action: "remove" - }) - ) - } - onSubmit={variables => { - updateStaffMember({ - variables: { - id, - input: { - email: variables.email, - firstName: variables.firstName, - isActive: variables.isActive, - lastName: variables.lastName, - ...groupsDiff(data?.user, variables) + return result.data.staffUpdate.errors; + }; + + return ( + + {(deleteStaffMember, deleteResult) => ( + + {updateStaffAvatar => ( + + {(deleteStaffAvatar, deleteAvatarResult) => { + const isUserSameAsViewer = + user.user?.id === data?.user?.id; + + return ( + <> + + + navigate( + staffMemberDetailsUrl(id, { + action: "change-password" + }) + ) + } + onDelete={() => + navigate( + staffMemberDetailsUrl(id, { + action: "remove" + }) + ) + } + onSubmit={handleSubmit} + onImageUpload={file => + updateStaffAvatar({ + variables: { + image: file } - } - }); - }} - onImageUpload={file => - updateStaffAvatar({ - variables: { - image: file - } - }) - } - onImageDelete={() => - navigate( - staffMemberDetailsUrl(id, { - action: "remove-avatar" }) - ) - } - availablePermissionGroups={searchPermissionGroupsOpts.data?.search.edges.map( - edge => edge.node - )} - staffMember={staffMember} - saveButtonBarState={updateResult.status} - fetchMorePermissionGroups={{ - hasMore: - searchPermissionGroupsOpts.data?.search - .pageInfo.hasNextPage, - loading: searchPermissionGroupsOpts.loading, - onFetchMore: loadMorePermissionGroups - }} - onSearchChange={searchPermissionGroups} - /> - - - - - - - - - {getStringOrPlaceholder( - data?.user?.email - )} - - ) - }} - /> - - - - changePassword({ - variables: data - }) - } - /> - - ); - }} - - )} - - )} - - )} + } + onImageDelete={() => + navigate( + staffMemberDetailsUrl(id, { + action: "remove-avatar" + }) + ) + } + availablePermissionGroups={searchPermissionGroupsOpts.data?.search.edges.map( + edge => edge.node + )} + staffMember={staffMember} + saveButtonBarState={updateResult.status} + fetchMorePermissionGroups={{ + hasMore: + searchPermissionGroupsOpts.data?.search + .pageInfo.hasNextPage, + loading: searchPermissionGroupsOpts.loading, + onFetchMore: loadMorePermissionGroups + }} + onSearchChange={searchPermissionGroups} + /> + + + + + + + + + {getStringOrPlaceholder( + data?.user?.email + )} + + ) + }} + /> + + + + changePassword({ + variables: data + }) + } + /> + + ); + }} + + )} + + )} + + ); + }} ); }} diff --git a/src/storybook/stories/discounts/VoucherDetailsPage.tsx b/src/storybook/stories/discounts/VoucherDetailsPage.tsx index e94786671..7263eb720 100644 --- a/src/storybook/stories/discounts/VoucherDetailsPage.tsx +++ b/src/storybook/stories/discounts/VoucherDetailsPage.tsx @@ -3,7 +3,7 @@ import { storiesOf } from "@storybook/react"; import React from "react"; import VoucherDetailsPage, { - FormData, + VoucherDetailsPageFormData, VoucherDetailsPageProps, VoucherDetailsPageTab } from "../../../discounts/components/VoucherDetailsPage"; @@ -59,7 +59,7 @@ storiesOf("Views / Discounts / Voucher details", module) "type", "usageLimit", "discountValue" - ] as Array).map(field => ({ + ] as Array).map(field => ({ __typename: "DiscountError", code: DiscountErrorCode.INVALID, field diff --git a/src/storybook/stories/pages/PageDetailsPage.tsx b/src/storybook/stories/pages/PageDetailsPage.tsx index 67bd9b3f6..51af7b057 100644 --- a/src/storybook/stories/pages/PageDetailsPage.tsx +++ b/src/storybook/stories/pages/PageDetailsPage.tsx @@ -3,7 +3,7 @@ import { storiesOf } from "@storybook/react"; import React from "react"; import PageDetailsPage, { - FormData, + PageDetailsPageFormData, PageDetailsPageProps } from "../../../pages/components/PageDetailsPage"; import { page } from "../../../pages/fixtures"; @@ -36,7 +36,7 @@ storiesOf("Views / Pages / Page details", module) "isPublished", "seoDescription", "seoTitle" - ] as Array).map(field => ({ + ] as Array).map(field => ({ __typename: "PageError", code: PageErrorCode.INVALID, field diff --git a/src/storybook/stories/plugins/PluginDetailsPage.tsx b/src/storybook/stories/plugins/PluginDetailsPage.tsx index 3a79bbc76..0e0c787f3 100644 --- a/src/storybook/stories/plugins/PluginDetailsPage.tsx +++ b/src/storybook/stories/plugins/PluginDetailsPage.tsx @@ -3,7 +3,7 @@ import { storiesOf } from "@storybook/react"; import React from "react"; import PluginsDetailsPage, { - FormData, + PluginDetailsPageFormData, PluginsDetailsPageProps } from "../../../plugins/components/PluginsDetailsPage"; import { plugin } from "../../../plugins/fixtures"; @@ -31,7 +31,7 @@ storiesOf("Views / Plugins / Plugin details", module) {...props} errors={[ ...(["active", "Username or account", "Password or license"] as Array< - keyof FormData + keyof PluginDetailsPageFormData >).map(field => ({ __typename: "PluginError" as "PluginError", code: PluginErrorCode.INVALID, diff --git a/src/warehouses/components/WarehouseDetailsPage/WarehouseDetailsPage.tsx b/src/warehouses/components/WarehouseDetailsPage/WarehouseDetailsPage.tsx index 38aefea3f..44c97b269 100644 --- a/src/warehouses/components/WarehouseDetailsPage/WarehouseDetailsPage.tsx +++ b/src/warehouses/components/WarehouseDetailsPage/WarehouseDetailsPage.tsx @@ -36,7 +36,7 @@ export interface WarehouseDetailsPageProps { onBack: () => void; onDelete: () => void; onShippingZoneClick: (id: string) => void; - onSubmit: (data: WarehouseDetailsPageFormData) => void; + onSubmit: (data: WarehouseDetailsPageFormData) => Promise; } const WarehouseDetailsPage: React.FC = ({ @@ -58,7 +58,7 @@ const WarehouseDetailsPage: React.FC = ({ const { errors: validationErrors, submit: handleSubmit - } = useAddressValidation(onSubmit); + } = useAddressValidation(onSubmit); const initialForm: WarehouseDetailsPageFormData = { city: maybe(() => warehouse.address.city, ""), @@ -76,7 +76,7 @@ const WarehouseDetailsPage: React.FC = ({ return (
- {({ change, data, submit }) => { + {({ change, data, hasChanged, submit }) => { const countryChoices = mapCountriesToChoices(countries); const handleCountryChange = createSingleAutocompleteSelectHandler( change, @@ -121,7 +121,7 @@ const WarehouseDetailsPage: React.FC = ({ = ({ id, params }) => { return navigate(warehouseListUrl())} />; } + const handleSubmit = async (data: WarehouseDetailsPageFormData) => { + const result = await updateWarehouse({ + variables: { + id, + input: { + address: { + city: data.city, + cityArea: data.cityArea, + country: findValueInEnum(data.country, CountryCode), + countryArea: data.countryArea, + phone: data.phone, + postalCode: data.postalCode, + streetAddress1: data.streetAddress1, + streetAddress2: data.streetAddress2 + }, + name: data.name + } + } + }); + + return result.data.updateWarehouse.errors; + }; return ( <> @@ -88,26 +112,7 @@ const WarehouseDetails: React.FC = ({ id, params }) => { onBack={() => navigate(warehouseListUrl())} onDelete={() => openModal("delete")} onShippingZoneClick={id => navigate(shippingZoneUrl(id))} - onSubmit={data => - updateWarehouse({ - variables: { - id, - input: { - address: { - city: data.city, - cityArea: data.cityArea, - country: findValueInEnum(data.country, CountryCode), - countryArea: data.countryArea, - phone: data.phone, - postalCode: data.postalCode, - streetAddress1: data.streetAddress1, - streetAddress2: data.streetAddress2 - }, - name: data.name - } - } - }) - } + onSubmit={handleSubmit} />