diff --git a/CHANGELOG.md b/CHANGELOG.md index a3ef7a604..bff7e51f0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ All notable, unreleased changes to this project will be documented in this file. ## [Unreleased] -.. +- Fix minor bugs - #244 by @dominik-zeglen ## 2.0.0 diff --git a/src/customers/components/CustomerAddressDialog/CustomerAddressDialog.tsx b/src/customers/components/CustomerAddressDialog/CustomerAddressDialog.tsx index b77002e71..3b7a77679 100644 --- a/src/customers/components/CustomerAddressDialog/CustomerAddressDialog.tsx +++ b/src/customers/components/CustomerAddressDialog/CustomerAddressDialog.tsx @@ -4,7 +4,6 @@ import DialogActions from "@material-ui/core/DialogActions"; import DialogContent from "@material-ui/core/DialogContent"; import DialogTitle from "@material-ui/core/DialogTitle"; import { createStyles, withStyles, WithStyles } from "@material-ui/core/styles"; - import React from "react"; import { FormattedMessage } from "react-intl"; @@ -13,10 +12,13 @@ import ConfirmButton, { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; import Form from "@saleor/components/Form"; +import useAddressValidation from "@saleor/hooks/useAddressValidation"; +import useModalDialogErrors from "@saleor/hooks/useModalDialogErrors"; import useStateFromProps from "@saleor/hooks/useStateFromProps"; import { buttonMessages } from "@saleor/intl"; import { maybe } from "@saleor/misc"; import { UserError } from "@saleor/types"; +import { AddressInput } from "@saleor/types/globalTypes"; import createSingleAutocompleteSelectHandler from "@saleor/utils/handlers/singleAutocompleteSelectChangeHandler"; import { AddressTypeInput } from "../../types"; import { CustomerAddresses_user_addresses } from "../../types/CustomerAddresses"; @@ -32,7 +34,7 @@ export interface CustomerAddressDialogProps { open: boolean; variant: "create" | "edit"; onClose: () => void; - onConfirm: (data: AddressTypeInput) => void; + onConfirm: (data: AddressInput) => void; } const styles = createStyles({ @@ -56,6 +58,15 @@ const CustomerAddressDialog = withStyles(styles, {})( const [countryDisplayName, setCountryDisplayName] = useStateFromProps( maybe(() => address.country.country, "") ); + const { + errors: validationErrors, + submit: handleSubmit + } = useAddressValidation(onConfirm); + const dialogErrors = useModalDialogErrors( + [...errors, ...validationErrors], + open + ); + const initialForm: AddressTypeInput = { city: maybe(() => address.city, ""), cityArea: maybe(() => address.cityArea, ""), @@ -87,8 +98,12 @@ const CustomerAddressDialog = withStyles(styles, {})( fullWidth maxWidth="sm" > -
- {({ change, data, errors }) => { + + {({ change, data, errors: formErrors }) => { const handleCountrySelect = createSingleAutocompleteSelectHandler( change, setCountryDisplayName, @@ -115,7 +130,7 @@ const CustomerAddressDialog = withStyles(styles, {})( countries={countryChoices} data={data} countryDisplayValue={countryDisplayName} - errors={errors} + errors={formErrors} onChange={change} onCountryChange={handleCountrySelect} /> diff --git a/src/customers/views/CustomerAddresses.tsx b/src/customers/views/CustomerAddresses.tsx index d8b483c92..da7c30019 100644 --- a/src/customers/views/CustomerAddresses.tsx +++ b/src/customers/views/CustomerAddresses.tsx @@ -8,7 +8,7 @@ import useNavigator from "@saleor/hooks/useNavigator"; import useNotifier from "@saleor/hooks/useNotifier"; import useShop from "@saleor/hooks/useShop"; import { commonMessages } from "@saleor/intl"; -import { getMutationState, maybe, transformFormToAddress } from "../../misc"; +import { getMutationState, maybe } from "../../misc"; import CustomerAddressDialog from "../components/CustomerAddressDialog"; import CustomerAddressListPage from "../components/CustomerAddressListPage"; import { @@ -176,7 +176,7 @@ const CustomerAddresses: React.FC = ({ createCustomerAddress({ variables: { id, - input: transformFormToAddress(input) + input } }) } @@ -202,7 +202,7 @@ const CustomerAddresses: React.FC = ({ updateCustomerAddress({ variables: { id: params.id, - input: transformFormToAddress(input) + input } }) } diff --git a/src/customers/views/CustomerCreate.tsx b/src/customers/views/CustomerCreate.tsx index 9aaf7f538..60d729211 100644 --- a/src/customers/views/CustomerCreate.tsx +++ b/src/customers/views/CustomerCreate.tsx @@ -8,6 +8,7 @@ import { maybe, transformFormToAddress } from "../../misc"; import CustomerCreatePage from "../components/CustomerCreatePage"; import { TypedCreateCustomerMutation } from "../mutations"; import { TypedCustomerCreateDataQuery } from "../queries"; +import { AddressTypeInput } from "../types"; import { CreateCustomer } from "../types/CreateCustomer"; import { customerListUrl, customerUrl } from "../urls"; @@ -57,6 +58,21 @@ export const CustomerCreate: React.FC<{}> = () => { } onBack={() => navigate(customerListUrl())} onSubmit={formData => { + const areAddressInputFieldsModified = ([ + "city", + "companyName", + "country", + "countryArea", + "firstName", + "lastName", + "phone", + "postalCode", + "streetAddress1", + "streetAddress2" + ] as Array) + .map(key => formData[key]) + .some(field => field !== ""); + const address = { city: formData.city, cityArea: formData.cityArea, @@ -73,8 +89,12 @@ export const CustomerCreate: React.FC<{}> = () => { createCustomer({ variables: { input: { - defaultBillingAddress: transformFormToAddress(address), - defaultShippingAddress: transformFormToAddress(address), + defaultBillingAddress: areAddressInputFieldsModified + ? transformFormToAddress(address) + : null, + defaultShippingAddress: areAddressInputFieldsModified + ? transformFormToAddress(address) + : null, email: formData.email, firstName: formData.customerFirstName, lastName: formData.customerLastName, diff --git a/src/hooks/useAddressValidation.ts b/src/hooks/useAddressValidation.ts new file mode 100644 index 000000000..9bd1e401d --- /dev/null +++ b/src/hooks/useAddressValidation.ts @@ -0,0 +1,46 @@ +import { useState } from "react"; +import { useIntl } from "react-intl"; + +import { AddressTypeInput } from "@saleor/customers/types"; +import { commonMessages } from "@saleor/intl"; +import { transformFormToAddress } from "@saleor/misc"; +import { UserError } from "@saleor/types"; +import { AddressInput } from "@saleor/types/globalTypes"; +import { add, remove } from "@saleor/utils/lists"; + +interface UseAddressValidation { + errors: UserError[]; + submit: (data: AddressTypeInput) => void; +} + +function useAddressValidation( + onSubmit: (address: AddressInput) => void +): UseAddressValidation { + const intl = useIntl(); + const [validationErrors, setValidationErrors] = useState([]); + + const countryRequiredError = { + field: "country", + message: intl.formatMessage(commonMessages.requiredField) + }; + + return { + errors: validationErrors, + submit: (data: AddressTypeInput) => { + try { + setValidationErrors( + remove( + countryRequiredError, + validationErrors, + (a, b) => a.field === b.field + ) + ); + onSubmit(transformFormToAddress(data)); + } catch { + setValidationErrors(add(countryRequiredError, validationErrors)); + } + } + }; +} + +export default useAddressValidation; diff --git a/src/orders/components/OrderAddressEditDialog/OrderAddressEditDialog.tsx b/src/orders/components/OrderAddressEditDialog/OrderAddressEditDialog.tsx index ba084169f..56b031f97 100644 --- a/src/orders/components/OrderAddressEditDialog/OrderAddressEditDialog.tsx +++ b/src/orders/components/OrderAddressEditDialog/OrderAddressEditDialog.tsx @@ -12,12 +12,15 @@ import ConfirmButton, { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; import Form from "@saleor/components/Form"; +import { AddressTypeInput } from "@saleor/customers/types"; +import useAddressValidation from "@saleor/hooks/useAddressValidation"; +import useModalDialogErrors from "@saleor/hooks/useModalDialogErrors"; import useStateFromProps from "@saleor/hooks/useStateFromProps"; import { buttonMessages } from "@saleor/intl"; import { maybe } from "@saleor/misc"; +import { UserError } from "@saleor/types"; +import { AddressInput } from "@saleor/types/globalTypes"; import createSingleAutocompleteSelectHandler from "@saleor/utils/handlers/singleAutocompleteSelectChangeHandler"; -import { AddressTypeInput } from "../../../customers/types"; -import { UserError } from "../../../types"; const styles = createStyles({ overflow: { @@ -36,7 +39,7 @@ interface OrderAddressEditDialogProps extends WithStyles { label: string; }>; onClose(); - onConfirm(data: AddressTypeInput); + onConfirm(data: AddressInput); } const OrderAddressEditDialog = withStyles(styles, { @@ -59,6 +62,15 @@ const OrderAddressEditDialog = withStyles(styles, { () => countries.find(country => address.country === country.code).label ) ); + const { + errors: validationErrors, + submit: handleSubmit + } = useAddressValidation(onConfirm); + const dialogErrors = useModalDialogErrors( + [...errors, ...validationErrors], + open + ); + const countryChoices = countries.map(country => ({ label: country.label, value: country.code @@ -70,7 +82,7 @@ const OrderAddressEditDialog = withStyles(styles, { open={open} classes={{ paper: classes.overflow }} > - + {({ change, data, errors, submit }) => { const handleCountrySelect = createSingleAutocompleteSelectHandler( change, diff --git a/src/orders/components/OrderDraftCancelDialog/OrderDraftCancelDialog.tsx b/src/orders/components/OrderDraftCancelDialog/OrderDraftCancelDialog.tsx index 3d501de55..c1ab59405 100644 --- a/src/orders/components/OrderDraftCancelDialog/OrderDraftCancelDialog.tsx +++ b/src/orders/components/OrderDraftCancelDialog/OrderDraftCancelDialog.tsx @@ -36,9 +36,9 @@ const OrderDraftCancelDialog: React.FC = ({ > {orderNumber} }} /> diff --git a/src/orders/views/OrderDetails/index.tsx b/src/orders/views/OrderDetails/index.tsx index 1c7b765bd..6d48bebe7 100644 --- a/src/orders/views/OrderDetails/index.tsx +++ b/src/orders/views/OrderDetails/index.tsx @@ -6,12 +6,7 @@ import useUser from "@saleor/hooks/useUser"; import { DEFAULT_INITIAL_SEARCH_DATA } from "../../../config"; import SearchCustomers from "../../../containers/SearchCustomers"; import { customerUrl } from "../../../customers/urls"; -import { - getMutationState, - maybe, - transformAddressToForm, - transformFormToAddress -} from "../../../misc"; +import { getMutationState, maybe, transformAddressToForm } from "../../../misc"; import { productUrl } from "../../../products/urls"; import { OrderStatus } from "../../../types/globalTypes"; import OrderAddressEditDialog from "../../components/OrderAddressEditDialog"; @@ -604,9 +599,7 @@ export const OrderDetails: React.FC = ({ id, params }) => { orderUpdate.mutate({ id, input: { - shippingAddress: transformFormToAddress( - shippingAddress - ) + shippingAddress } }) } @@ -639,9 +632,7 @@ export const OrderDetails: React.FC = ({ id, params }) => { orderUpdate.mutate({ id, input: { - billingAddress: transformFormToAddress( - billingAddress - ) + billingAddress } }) } diff --git a/src/translations/components/TranslationsCategoriesPage/TranslationsCategoriesPage.tsx b/src/translations/components/TranslationsCategoriesPage/TranslationsCategoriesPage.tsx index af012fea9..85995b1df 100644 --- a/src/translations/components/TranslationsCategoriesPage/TranslationsCategoriesPage.tsx +++ b/src/translations/components/TranslationsCategoriesPage/TranslationsCategoriesPage.tsx @@ -49,7 +49,7 @@ const TranslationsCategoriesPage: React.FC = ({ title={intl.formatMessage( { defaultMessage: - 'Translation Category "{categoryNane}" - {languageCode}' + 'Translation Category "{categoryName}" - {languageCode}' }, { categoryName: maybe(() => category.name, "..."),