diff --git a/src/components/AddressEdit/AddressEdit.tsx b/src/components/AddressEdit/AddressEdit.tsx index 96ce090c1..041bbd99d 100644 --- a/src/components/AddressEdit/AddressEdit.tsx +++ b/src/components/AddressEdit/AddressEdit.tsx @@ -1,12 +1,15 @@ import { makeStyles } from "@material-ui/core/styles"; import TextField from "@material-ui/core/TextField"; import React from "react"; -import { useIntl } from "react-intl"; +import { useIntl, IntlShape } from "react-intl"; import { AddressTypeInput } from "@saleor/customers/types"; import { commonMessages } from "@saleor/intl"; -import { UserError } from "@saleor/types"; -import { getFieldError } from "@saleor/utils/errors"; +import { getFormErrors } from "@saleor/utils/errors"; +import { AccountErrorFragment } from "@saleor/customers/types/AccountErrorFragment"; +import getAccountErrorMessage from "@saleor/utils/errors/account"; +import { OrderErrorFragment } from "@saleor/orders/types/OrderErrorFragment"; +import getOrderErrorMessage from "@saleor/utils/errors/order"; import FormSpacer from "../FormSpacer"; import SingleAutocompleteSelectField, { SingleAutocompleteChoiceType @@ -28,11 +31,22 @@ interface AddressEditProps { countryDisplayValue: string; data: AddressTypeInput; disabled?: boolean; - errors: UserError[]; + errors: Array; onChange(event: React.ChangeEvent); onCountryChange(event: React.ChangeEvent); } +function getErrorMessage( + err: AccountErrorFragment | OrderErrorFragment, + intl: IntlShape +): string { + if (err?.__typename === "AccountError") { + return getAccountErrorMessage(err, intl); + } + + return getOrderErrorMessage(err, intl); +} + const AddressEdit: React.FC = props => { const { countries, @@ -43,18 +57,36 @@ const AddressEdit: React.FC = props => { onChange, onCountryChange } = props; - const classes = useStyles(props); + const classes = useStyles(props); const intl = useIntl(); + const formFields: Array = [ + "city", + "cityArea", + "country", + "countryArea", + "firstName", + "lastName", + "companyName", + "phone", + "postalCode", + "streetAddress1", + "streetAddress2" + ]; + const formErrors = getFormErrors< + keyof AddressTypeInput, + AccountErrorFragment | OrderErrorFragment + >(formFields, errors); + return ( <>
= props => {
= props => {
= props => {
= props => { = props => { = props => {
= props => {
= props => { = props => {
; - errors: UserError[]; + errors: AccountErrorFragment[]; open: boolean; variant: "create" | "edit"; onClose: () => void; diff --git a/src/customers/components/CustomerCreateAddress/CustomerCreateAddress.tsx b/src/customers/components/CustomerCreateAddress/CustomerCreateAddress.tsx index 2f98fbe18..5ef7e309b 100644 --- a/src/customers/components/CustomerCreateAddress/CustomerCreateAddress.tsx +++ b/src/customers/components/CustomerCreateAddress/CustomerCreateAddress.tsx @@ -9,7 +9,7 @@ import AddressEdit from "@saleor/components/AddressEdit"; import CardTitle from "@saleor/components/CardTitle"; import { FormSpacer } from "@saleor/components/FormSpacer"; import { SingleAutocompleteChoiceType } from "@saleor/components/SingleAutocompleteSelectField"; -import { UserError } from "../../../types"; +import { AccountErrorFragment } from "@saleor/customers/types/AccountErrorFragment"; import { AddressTypeInput } from "../../types"; const useStyles = makeStyles( @@ -26,7 +26,7 @@ export interface CustomerCreateAddressProps { countryDisplayName: string; data: AddressTypeInput; disabled: boolean; - errors: UserError[]; + errors: AccountErrorFragment[]; onChange(event: React.ChangeEvent); onCountryChange(event: React.ChangeEvent); } diff --git a/src/customers/components/CustomerCreateDetails/CustomerCreateDetails.tsx b/src/customers/components/CustomerCreateDetails/CustomerCreateDetails.tsx index f4d8f44ac..785f5ccef 100644 --- a/src/customers/components/CustomerCreateDetails/CustomerCreateDetails.tsx +++ b/src/customers/components/CustomerCreateDetails/CustomerCreateDetails.tsx @@ -7,8 +7,9 @@ import { useIntl } from "react-intl"; import CardTitle from "@saleor/components/CardTitle"; import { commonMessages } from "@saleor/intl"; -import { getFieldError } from "@saleor/utils/errors"; -import { UserError } from "../../../types"; +import { getFormErrors } from "@saleor/utils/errors"; +import { AccountErrorFragment } from "@saleor/customers/types/AccountErrorFragment"; +import getAccountErrorMessage from "@saleor/utils/errors/account"; import { CustomerCreatePageFormData } from "../CustomerCreatePage"; const useStyles = makeStyles( @@ -26,16 +27,21 @@ const useStyles = makeStyles( export interface CustomerCreateDetailsProps { data: CustomerCreatePageFormData; disabled: boolean; - errors: UserError[]; + errors: AccountErrorFragment[]; onChange: (event: React.ChangeEvent) => void; } const CustomerCreateDetails: React.FC = props => { const { data, disabled, errors, onChange } = props; - const classes = useStyles(props); + const classes = useStyles(props); const intl = useIntl(); + const formErrors = getFormErrors( + ["customerFirstName", "customerLastName", "email"], + errors + ); + return ( = props => {
= props => { ); }; + CustomerCreateDetails.displayName = "CustomerCreateDetails"; export default CustomerCreateDetails; diff --git a/src/customers/components/CustomerCreateNote/CustomerCreateNote.tsx b/src/customers/components/CustomerCreateNote/CustomerCreateNote.tsx index 35b00baef..6765547d9 100644 --- a/src/customers/components/CustomerCreateNote/CustomerCreateNote.tsx +++ b/src/customers/components/CustomerCreateNote/CustomerCreateNote.tsx @@ -7,15 +7,16 @@ import { FormattedMessage, useIntl } from "react-intl"; import CardTitle from "@saleor/components/CardTitle"; import { FormSpacer } from "@saleor/components/FormSpacer"; -import { UserError } from "@saleor/types"; -import { getFieldError } from "@saleor/utils/errors"; +import { getFormErrors } from "@saleor/utils/errors"; +import getAccountErrorMessage from "@saleor/utils/errors/account"; +import { AccountErrorFragment } from "@saleor/customers/types/AccountErrorFragment"; export interface CustomerCreateNoteProps { data: { note: string; }; disabled: boolean; - errors: UserError[]; + errors: AccountErrorFragment[]; onChange: (event: React.ChangeEvent) => void; } @@ -27,6 +28,8 @@ const CustomerCreateNote: React.FC = ({ }) => { const intl = useIntl(); + const formErrors = getFormErrors(["note"], errors); + return ( = ({ void; onSubmit: (data: CustomerCreatePageSubmitData) => void; diff --git a/src/customers/components/CustomerDetails/CustomerDetails.tsx b/src/customers/components/CustomerDetails/CustomerDetails.tsx index d9b180398..6007dfe3f 100644 --- a/src/customers/components/CustomerDetails/CustomerDetails.tsx +++ b/src/customers/components/CustomerDetails/CustomerDetails.tsx @@ -11,8 +11,9 @@ import CardTitle from "@saleor/components/CardTitle"; import { ControlledCheckbox } from "@saleor/components/ControlledCheckbox"; import Skeleton from "@saleor/components/Skeleton"; import { maybe } from "@saleor/misc"; -import { UserError } from "@saleor/types"; -import { getFieldError } from "@saleor/utils/errors"; +import { getFormErrors } from "@saleor/utils/errors"; +import getAccountErrorMessage from "@saleor/utils/errors/account"; +import { AccountErrorFragment } from "@saleor/customers/types/AccountErrorFragment"; import { CustomerDetails_user } from "../../types/CustomerDetails"; const useStyles = makeStyles( @@ -40,16 +41,18 @@ export interface CustomerDetailsProps { note: string; }; disabled: boolean; - errors: UserError[]; + errors: AccountErrorFragment[]; onChange: (event: React.ChangeEvent) => void; } const CustomerDetails: React.FC = props => { const { customer, data, disabled, errors, onChange } = props; - const classes = useStyles(props); + const classes = useStyles(props); const intl = useIntl(); + const formErrors = getFormErrors(["note"], errors); + return ( = props => { /> void; onSubmit: (data: CustomerDetailsPageFormData) => void; diff --git a/src/customers/components/CustomerInfo/CustomerInfo.tsx b/src/customers/components/CustomerInfo/CustomerInfo.tsx index 9f8cdb596..f0b985921 100644 --- a/src/customers/components/CustomerInfo/CustomerInfo.tsx +++ b/src/customers/components/CustomerInfo/CustomerInfo.tsx @@ -10,8 +10,9 @@ import CardTitle from "@saleor/components/CardTitle"; import Grid from "@saleor/components/Grid"; import Hr from "@saleor/components/Hr"; import { commonMessages } from "@saleor/intl"; -import { UserError } from "@saleor/types"; -import { getFieldError } from "@saleor/utils/errors"; +import { AccountErrorFragment } from "@saleor/customers/types/AccountErrorFragment"; +import { getFormErrors } from "@saleor/utils/errors"; +import getAccountErrorMessage from "@saleor/utils/errors/account"; const useStyles = makeStyles( theme => ({ @@ -35,16 +36,18 @@ export interface CustomerInfoProps { email: string; }; disabled: boolean; - errors: UserError[]; + errors: AccountErrorFragment[]; onChange: (event: React.ChangeEvent) => void; } const CustomerInfo: React.FC = props => { const { data, disabled, errors, onChange } = props; - const classes = useStyles(props); + const classes = useStyles(props); const intl = useIntl(); + const formErrors = getFormErrors(["firstName", "lastName", "email"], errors); + return ( = props => { = props => { /> = props => { = () => { data.shop.countries, [])} disabled={loading || createCustomerOpts.loading} - errors={maybe(() => { - const errs = createCustomerOpts.data.customerCreate.errors; - return errs.map(err => - err.field.split(":").length > 1 - ? { - ...err, - field: err.field.split(":")[1] - } - : err - ); - }, [])} - saveButtonBar={ - createCustomerOpts.loading ? "loading" : "default" - } + errors={createCustomerOpts.data?.customerCreate.errors || []} + saveButtonBar={createCustomerOpts.status} onBack={() => navigate(customerListUrl())} onSubmit={formData => { createCustomer({ diff --git a/src/hooks/useAddressValidation.ts b/src/hooks/useAddressValidation.ts index ef7ad365a..8db050f74 100644 --- a/src/hooks/useAddressValidation.ts +++ b/src/hooks/useAddressValidation.ts @@ -1,27 +1,27 @@ 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 { AddressInput, AccountErrorCode } from "@saleor/types/globalTypes"; import { add, remove } from "@saleor/utils/lists"; +import { AccountErrorFragment } from "@saleor/customers/types/AccountErrorFragment"; interface UseAddressValidation { - errors: UserError[]; + errors: AccountErrorFragment[]; submit: (data: T & AddressTypeInput) => void; } function useAddressValidation( onSubmit: (address: T & AddressInput) => void ): UseAddressValidation { - const intl = useIntl(); - const [validationErrors, setValidationErrors] = useState([]); + const [validationErrors, setValidationErrors] = useState< + AccountErrorFragment[] + >([]); - const countryRequiredError = { - field: "country", - message: intl.formatMessage(commonMessages.requiredField) + const countryRequiredError: AccountErrorFragment = { + __typename: "AccountError", + code: AccountErrorCode.REQUIRED, + field: "country" }; return { diff --git a/src/orders/components/OrderAddressEditDialog/OrderAddressEditDialog.tsx b/src/orders/components/OrderAddressEditDialog/OrderAddressEditDialog.tsx index 5e995e757..22d7e4279 100644 --- a/src/orders/components/OrderAddressEditDialog/OrderAddressEditDialog.tsx +++ b/src/orders/components/OrderAddressEditDialog/OrderAddressEditDialog.tsx @@ -18,9 +18,9 @@ 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 { OrderErrorFragment } from "@saleor/orders/types/OrderErrorFragment"; const useStyles = makeStyles( { @@ -35,7 +35,7 @@ interface OrderAddressEditDialogProps { confirmButtonState: ConfirmButtonTransitionState; address: AddressTypeInput; open: boolean; - errors: UserError[]; + errors: OrderErrorFragment[]; variant: "billing" | "shipping" | string; countries?: Array<{ code: string; diff --git a/src/orders/mutations.ts b/src/orders/mutations.ts index 4a68ab6ba..16b360e79 100644 --- a/src/orders/mutations.ts +++ b/src/orders/mutations.ts @@ -64,6 +64,13 @@ import { import { OrderUpdate, OrderUpdateVariables } from "./types/OrderUpdate"; import { OrderVoid, OrderVoidVariables } from "./types/OrderVoid"; +export const orderErrorFragment = gql` + fragment OrderErrorFragment on OrderError { + code + field + } +`; + const orderCancelMutation = gql` ${fragmentOrderDetails} mutation OrderCancel($id: ID!, $restock: Boolean!) { @@ -314,11 +321,11 @@ export const TypedOrderAddNoteMutation = TypedMutation< const orderUpdateMutation = gql` ${fragmentAddress} + ${orderErrorFragment} mutation OrderUpdate($id: ID!, $input: OrderUpdateInput!) { orderUpdate(id: $id, input: $input) { - errors { - field - message + errors: orderErrors { + ...OrderErrorFragment } order { id @@ -342,7 +349,8 @@ const orderDraftUpdateMutation = gql` ${fragmentOrderDetails} mutation OrderDraftUpdate($id: ID!, $input: DraftOrderInput!) { draftOrderUpdate(id: $id, input: $input) { - errors { + errors: orderErrors { + code field message } diff --git a/src/orders/types/OrderDraftUpdate.ts b/src/orders/types/OrderDraftUpdate.ts index 97353b776..a613167e2 100644 --- a/src/orders/types/OrderDraftUpdate.ts +++ b/src/orders/types/OrderDraftUpdate.ts @@ -2,14 +2,15 @@ /* eslint-disable */ // This file was automatically generated and should not be edited. -import { DraftOrderInput, OrderEventsEmailsEnum, OrderEventsEnum, FulfillmentStatus, PaymentChargeStatusEnum, OrderStatus, OrderAction } from "./../../types/globalTypes"; +import { DraftOrderInput, OrderErrorCode, OrderEventsEmailsEnum, OrderEventsEnum, FulfillmentStatus, PaymentChargeStatusEnum, OrderStatus, OrderAction } from "./../../types/globalTypes"; // ==================================================== // GraphQL mutation operation: OrderDraftUpdate // ==================================================== export interface OrderDraftUpdate_draftOrderUpdate_errors { - __typename: "Error"; + __typename: "OrderError"; + code: OrderErrorCode; field: string | null; message: string | null; } diff --git a/src/orders/types/OrderErrorFragment.ts b/src/orders/types/OrderErrorFragment.ts new file mode 100644 index 000000000..481de0908 --- /dev/null +++ b/src/orders/types/OrderErrorFragment.ts @@ -0,0 +1,15 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { OrderErrorCode } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL fragment: OrderErrorFragment +// ==================================================== + +export interface OrderErrorFragment { + __typename: "OrderError"; + code: OrderErrorCode; + field: string | null; +} diff --git a/src/orders/types/OrderUpdate.ts b/src/orders/types/OrderUpdate.ts index 19cdcb37f..b199f05e6 100644 --- a/src/orders/types/OrderUpdate.ts +++ b/src/orders/types/OrderUpdate.ts @@ -2,16 +2,16 @@ /* eslint-disable */ // This file was automatically generated and should not be edited. -import { OrderUpdateInput } from "./../../types/globalTypes"; +import { OrderUpdateInput, OrderErrorCode } from "./../../types/globalTypes"; // ==================================================== // GraphQL mutation operation: OrderUpdate // ==================================================== export interface OrderUpdate_orderUpdate_errors { - __typename: "Error"; + __typename: "OrderError"; + code: OrderErrorCode; field: string | null; - message: string | null; } export interface OrderUpdate_orderUpdate_order_billingAddress_country { diff --git a/src/services/components/ServiceCreatePage/ServiceCreatePage.stories.tsx b/src/services/components/ServiceCreatePage/ServiceCreatePage.stories.tsx index b4e1884ec..3f0dce218 100644 --- a/src/services/components/ServiceCreatePage/ServiceCreatePage.stories.tsx +++ b/src/services/components/ServiceCreatePage/ServiceCreatePage.stories.tsx @@ -3,7 +3,7 @@ import React from "react"; import { permissions } from "@saleor/fixtures"; import Decorator from "@saleor/storybook/Decorator"; -import { formError } from "@saleor/storybook/misc"; +import { AccountErrorCode } from "@saleor/types/globalTypes"; import ServiceCreatePage, { ServiceCreatePageProps } from "./ServiceCreatePage"; const props: ServiceCreatePageProps = { @@ -21,6 +21,10 @@ storiesOf("Views / Services / Create service", module) .add("form errors", () => ( formError(field))} + errors={["name"].map(field => ({ + __typename: "AccountError", + code: AccountErrorCode.INVALID, + field + }))} /> )); diff --git a/src/services/components/ServiceCreatePage/ServiceCreatePage.tsx b/src/services/components/ServiceCreatePage/ServiceCreatePage.tsx index 6a5a0bb8a..d9eaa4e5c 100644 --- a/src/services/components/ServiceCreatePage/ServiceCreatePage.tsx +++ b/src/services/components/ServiceCreatePage/ServiceCreatePage.tsx @@ -13,8 +13,8 @@ import PageHeader from "@saleor/components/PageHeader"; import SaveButtonBar from "@saleor/components/SaveButtonBar"; import { ShopInfo_shop_permissions } from "@saleor/components/Shop/types/ShopInfo"; import { sectionNames } from "@saleor/intl"; -import { UserError } from "@saleor/types"; import { PermissionEnum } from "@saleor/types/globalTypes"; +import { AccountErrorFragment } from "@saleor/customers/types/AccountErrorFragment"; import ServiceInfo from "../ServiceInfo"; export interface ServiceCreatePageFormData { @@ -25,7 +25,7 @@ export interface ServiceCreatePageFormData { } export interface ServiceCreatePageProps { disabled: boolean; - errors: UserError[]; + errors: AccountErrorFragment[]; permissions: ShopInfo_shop_permissions[]; saveButtonBarState: ConfirmButtonTransitionState; onBack: () => void; diff --git a/src/services/components/ServiceDetailsPage/ServiceDetailsPage.stories.tsx b/src/services/components/ServiceDetailsPage/ServiceDetailsPage.stories.tsx index dad65167a..f3f705011 100644 --- a/src/services/components/ServiceDetailsPage/ServiceDetailsPage.stories.tsx +++ b/src/services/components/ServiceDetailsPage/ServiceDetailsPage.stories.tsx @@ -3,7 +3,7 @@ import React from "react"; import { permissions } from "@saleor/fixtures"; import Decorator from "@saleor/storybook/Decorator"; -import { formError } from "@saleor/storybook/misc"; +import { AccountErrorCode } from "@saleor/types/globalTypes"; import { service } from "../../fixtures"; import ServiceDetailsPage, { ServiceDetailsPageProps @@ -34,7 +34,11 @@ storiesOf("Views / Services / Service details", module) .add("form errors", () => ( formError(field))} + errors={["name"].map(field => ({ + __typename: "AccountError", + code: AccountErrorCode.INVALID, + field + }))} /> )) .add("default token", () => ( diff --git a/src/services/components/ServiceDetailsPage/ServiceDetailsPage.tsx b/src/services/components/ServiceDetailsPage/ServiceDetailsPage.tsx index f2f658356..9e7c96630 100644 --- a/src/services/components/ServiceDetailsPage/ServiceDetailsPage.tsx +++ b/src/services/components/ServiceDetailsPage/ServiceDetailsPage.tsx @@ -15,8 +15,8 @@ import { ShopInfo_shop_permissions } from "@saleor/components/Shop/types/ShopInf import { sectionNames } from "@saleor/intl"; import { maybe } from "@saleor/misc"; import { ServiceDetails_serviceAccount } from "@saleor/services/types/ServiceDetails"; -import { UserError } from "@saleor/types"; import { PermissionEnum } from "@saleor/types/globalTypes"; +import { AccountErrorFragment } from "@saleor/customers/types/AccountErrorFragment"; import ServiceDefaultToken from "../ServiceDefaultToken"; import ServiceInfo from "../ServiceInfo"; import ServiceTokens from "../ServiceTokens"; @@ -30,7 +30,7 @@ export interface ServiceDetailsPageFormData { export interface ServiceDetailsPageProps { apiUri: string; disabled: boolean; - errors: UserError[]; + errors: AccountErrorFragment[]; permissions: ShopInfo_shop_permissions[]; saveButtonBarState: ConfirmButtonTransitionState; service: ServiceDetails_serviceAccount; @@ -107,7 +107,7 @@ const ServiceDetailsPage: React.FC = props => { /> service.tokens)} + tokens={service?.tokens} onCreate={onTokenCreate} onDelete={onTokenDelete} /> diff --git a/src/services/components/ServiceInfo/ServiceInfo.tsx b/src/services/components/ServiceInfo/ServiceInfo.tsx index 2b43c5600..1dbdba2c3 100644 --- a/src/services/components/ServiceInfo/ServiceInfo.tsx +++ b/src/services/components/ServiceInfo/ServiceInfo.tsx @@ -6,22 +6,29 @@ import { useIntl } from "react-intl"; import CardTitle from "@saleor/components/CardTitle"; import { FormChange } from "@saleor/hooks/useForm"; -import { UserError } from "@saleor/types"; -import { getFieldError } from "@saleor/utils/errors"; +import { AccountErrorFragment } from "@saleor/customers/types/AccountErrorFragment"; +import { getFormErrors } from "@saleor/utils/errors"; +import getAccountErrorMessage from "@saleor/utils/errors/account"; export interface ServiceInfoProps { data: { name: string; }; disabled: boolean; - errors: UserError[]; + errors: AccountErrorFragment[]; onChange: FormChange; } -const ServiceInfo: React.FC = props => { - const { data, disabled, errors, onChange } = props; +const ServiceInfo: React.FC = ({ + data, + disabled, + errors, + onChange +}) => { const intl = useIntl(); + const formErrors = getFormErrors(["name"], errors); + return ( = props => { void; onConfirm: (data: FormData) => void; @@ -66,11 +67,16 @@ interface StaffAddMemberDialogProps { const StaffAddMemberDialog: React.FC = props => { const { confirmButtonState, errors, open, onClose, onConfirm } = props; + const classes = useStyles(props); const dialogErrors = useModalDialogErrors(errors, open); - const intl = useIntl(); + const formErrors = getFormErrors( + ["firstName", "lastName", "email"], + dialogErrors + ); + return (
@@ -85,8 +91,11 @@ const StaffAddMemberDialog: React.FC = props => {
= props => { onChange={change} /> = props => {
void; } @@ -42,6 +44,11 @@ const StaffPasswordResetDialog: React.FC = ({ const intl = useIntl(); const dialogErrors = useModalDialogErrors(errors, open); + const formErrors = getFormErrors( + ["oldPassword", "newPassword"], + dialogErrors + ); + return ( @@ -55,9 +62,12 @@ const StaffPasswordResetDialog: React.FC = ({ <> = ({ /> = { countries: [ @@ -42,8 +42,10 @@ storiesOf("Views / Customers / Create customer", module) "postalCode", "streetAddress1", "streetAddress2" - ] as Array).map(field => - formError(field) - )} + ] as Array).map(field => ({ + __typename: "AccountError", + code: AccountErrorCode.INVALID, + field + }))} /> )); diff --git a/src/storybook/stories/customers/CustomerDetailsPage.tsx b/src/storybook/stories/customers/CustomerDetailsPage.tsx index e5086b83a..85c1eedcf 100644 --- a/src/storybook/stories/customers/CustomerDetailsPage.tsx +++ b/src/storybook/stories/customers/CustomerDetailsPage.tsx @@ -2,12 +2,12 @@ import { Omit } from "@material-ui/core"; import { storiesOf } from "@storybook/react"; import React from "react"; +import { AccountErrorCode } from "@saleor/types/globalTypes"; import CustomerDetailsPage, { CustomerDetailsPageProps } from "../../../customers/components/CustomerDetailsPage"; import { customer } from "../../../customers/fixtures"; import Decorator from "../../Decorator"; -import { formError } from "../../misc"; const props: Omit = { customer, @@ -40,7 +40,11 @@ storiesOf("Views / Customers / Customer details", module) {...props} errors={(["email", "firstName", "lastName"] as Array< keyof CustomerDetailsPageErrors - >).map(field => formError(field))} + >).map(field => ({ + __typename: "AccountError", + code: AccountErrorCode.INVALID, + field + }))} /> )) .add("different addresses", () => ( diff --git a/src/types/globalTypes.ts b/src/types/globalTypes.ts index ec11c64f4..66b279ffd 100644 --- a/src/types/globalTypes.ts +++ b/src/types/globalTypes.ts @@ -425,6 +425,29 @@ export enum OrderDirection { DESC = "DESC", } +export enum OrderErrorCode { + BILLING_ADDRESS_NOT_SET = "BILLING_ADDRESS_NOT_SET", + CANNOT_CANCEL_FULFILLMENT = "CANNOT_CANCEL_FULFILLMENT", + CANNOT_CANCEL_ORDER = "CANNOT_CANCEL_ORDER", + CANNOT_DELETE = "CANNOT_DELETE", + CANNOT_REFUND = "CANNOT_REFUND", + CAPTURE_INACTIVE_PAYMENT = "CAPTURE_INACTIVE_PAYMENT", + FULFILL_ORDER_LINE = "FULFILL_ORDER_LINE", + GRAPHQL_ERROR = "GRAPHQL_ERROR", + INVALID = "INVALID", + NOT_EDITABLE = "NOT_EDITABLE", + NOT_FOUND = "NOT_FOUND", + ORDER_NO_SHIPPING_ADDRESS = "ORDER_NO_SHIPPING_ADDRESS", + PAYMENT_ERROR = "PAYMENT_ERROR", + PAYMENT_MISSING = "PAYMENT_MISSING", + REQUIRED = "REQUIRED", + SHIPPING_METHOD_NOT_APPLICABLE = "SHIPPING_METHOD_NOT_APPLICABLE", + SHIPPING_METHOD_REQUIRED = "SHIPPING_METHOD_REQUIRED", + UNIQUE = "UNIQUE", + VOID_INACTIVE_PAYMENT = "VOID_INACTIVE_PAYMENT", + ZERO_QUANTITY = "ZERO_QUANTITY", +} + export enum OrderEventsEmailsEnum { DIGITAL_LINKS = "DIGITAL_LINKS", FULFILLMENT_CONFIRMATION = "FULFILLMENT_CONFIRMATION", diff --git a/src/utils/errors/account.ts b/src/utils/errors/account.ts new file mode 100644 index 000000000..bc7846667 --- /dev/null +++ b/src/utils/errors/account.ts @@ -0,0 +1,56 @@ +import { IntlShape, defineMessages } from "react-intl"; + +import { AccountErrorCode } from "@saleor/types/globalTypes"; +import { commonMessages } from "@saleor/intl"; +import { AccountErrorFragment } from "@saleor/customers/types/AccountErrorFragment"; +import commonErrorMessages from "./common"; + +const messages = defineMessages({ + invalidPassword: { + defaultMessage: "Invalid password" + }, + passwordNumeric: { + defaultMessage: "Password cannot be entirely numeric" + }, + tooCommon: { + defaultMessage: "This password is too commonly used" + }, + tooShort: { + defaultMessage: "This password is too short" + }, + tooSimilar: { + defaultMessage: "These passwords are too similar" + } +}); + +function getAccountErrorMessage( + err: AccountErrorFragment, + intl: IntlShape +): string { + if (err) { + switch (err.code) { + case AccountErrorCode.GRAPHQL_ERROR: + return intl.formatMessage(commonErrorMessages.graphqlError); + case AccountErrorCode.INVALID: + return intl.formatMessage(commonErrorMessages.invalid); + case AccountErrorCode.INVALID_PASSWORD: + return intl.formatMessage(messages.invalidPassword); + case AccountErrorCode.PASSWORD_ENTIRELY_NUMERIC: + return intl.formatMessage(messages.passwordNumeric); + case AccountErrorCode.PASSWORD_TOO_COMMON: + return intl.formatMessage(messages.tooCommon); + case AccountErrorCode.PASSWORD_TOO_SHORT: + return intl.formatMessage(messages.tooShort); + case AccountErrorCode.PASSWORD_TOO_SIMILAR: + return intl.formatMessage(messages.tooSimilar); + case AccountErrorCode.REQUIRED: + return intl.formatMessage(commonMessages.requiredField); + default: + return intl.formatMessage(commonErrorMessages.unknownError); + } + } + + return undefined; +} + +export default getAccountErrorMessage; diff --git a/src/utils/errors/order.ts b/src/utils/errors/order.ts new file mode 100644 index 000000000..525420dbb --- /dev/null +++ b/src/utils/errors/order.ts @@ -0,0 +1,28 @@ +import { IntlShape } from "react-intl"; + +import { OrderErrorCode } from "@saleor/types/globalTypes"; +import { commonMessages } from "@saleor/intl"; +import { OrderErrorFragment } from "@saleor/orders/types/OrderErrorFragment"; +import commonErrorMessages from "./common"; + +function getOrderErrorMessage( + err: OrderErrorFragment, + intl: IntlShape +): string { + if (err) { + switch (err.code) { + case OrderErrorCode.GRAPHQL_ERROR: + return intl.formatMessage(commonErrorMessages.graphqlError); + case OrderErrorCode.INVALID: + return intl.formatMessage(commonErrorMessages.invalid); + case OrderErrorCode.REQUIRED: + return intl.formatMessage(commonMessages.requiredField); + default: + return intl.formatMessage(commonErrorMessages.unknownError); + } + } + + return undefined; +} + +export default getOrderErrorMessage;