Use error codes in account sections

This commit is contained in:
dominik-zeglen 2020-03-11 10:55:14 +01:00
parent 93ba9378ef
commit 96c98077d8
28 changed files with 351 additions and 138 deletions

View file

@ -1,12 +1,15 @@
import { makeStyles } from "@material-ui/core/styles"; import { makeStyles } from "@material-ui/core/styles";
import TextField from "@material-ui/core/TextField"; import TextField from "@material-ui/core/TextField";
import React from "react"; import React from "react";
import { useIntl } from "react-intl"; import { useIntl, IntlShape } from "react-intl";
import { AddressTypeInput } from "@saleor/customers/types"; import { AddressTypeInput } from "@saleor/customers/types";
import { commonMessages } from "@saleor/intl"; import { commonMessages } from "@saleor/intl";
import { UserError } from "@saleor/types"; import { getFormErrors } from "@saleor/utils/errors";
import { getFieldError } 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 FormSpacer from "../FormSpacer";
import SingleAutocompleteSelectField, { import SingleAutocompleteSelectField, {
SingleAutocompleteChoiceType SingleAutocompleteChoiceType
@ -28,11 +31,22 @@ interface AddressEditProps {
countryDisplayValue: string; countryDisplayValue: string;
data: AddressTypeInput; data: AddressTypeInput;
disabled?: boolean; disabled?: boolean;
errors: UserError[]; errors: Array<AccountErrorFragment | OrderErrorFragment>;
onChange(event: React.ChangeEvent<any>); onChange(event: React.ChangeEvent<any>);
onCountryChange(event: React.ChangeEvent<any>); onCountryChange(event: React.ChangeEvent<any>);
} }
function getErrorMessage(
err: AccountErrorFragment | OrderErrorFragment,
intl: IntlShape
): string {
if (err?.__typename === "AccountError") {
return getAccountErrorMessage(err, intl);
}
return getOrderErrorMessage(err, intl);
}
const AddressEdit: React.FC<AddressEditProps> = props => { const AddressEdit: React.FC<AddressEditProps> = props => {
const { const {
countries, countries,
@ -43,18 +57,36 @@ const AddressEdit: React.FC<AddressEditProps> = props => {
onChange, onChange,
onCountryChange onCountryChange
} = props; } = props;
const classes = useStyles(props);
const classes = useStyles(props);
const intl = useIntl(); const intl = useIntl();
const formFields: Array<keyof AddressTypeInput> = [
"city",
"cityArea",
"country",
"countryArea",
"firstName",
"lastName",
"companyName",
"phone",
"postalCode",
"streetAddress1",
"streetAddress2"
];
const formErrors = getFormErrors<
keyof AddressTypeInput,
AccountErrorFragment | OrderErrorFragment
>(formFields, errors);
return ( return (
<> <>
<div className={classes.root}> <div className={classes.root}>
<div> <div>
<TextField <TextField
disabled={disabled} disabled={disabled}
error={!!getFieldError(errors, "firstName")} error={!!formErrors.firstName}
helperText={getFieldError(errors, "firstName")?.message} helperText={getErrorMessage(formErrors.firstName, intl)}
label={intl.formatMessage(commonMessages.firstName)} label={intl.formatMessage(commonMessages.firstName)}
name="firstName" name="firstName"
onChange={onChange} onChange={onChange}
@ -65,8 +97,8 @@ const AddressEdit: React.FC<AddressEditProps> = props => {
<div> <div>
<TextField <TextField
disabled={disabled} disabled={disabled}
error={!!getFieldError(errors, "lastName")} error={!!formErrors.lastName}
helperText={getFieldError(errors, "lastName")?.message} helperText={getErrorMessage(formErrors.lastName, intl)}
label={intl.formatMessage(commonMessages.lastName)} label={intl.formatMessage(commonMessages.lastName)}
name="lastName" name="lastName"
onChange={onChange} onChange={onChange}
@ -80,8 +112,8 @@ const AddressEdit: React.FC<AddressEditProps> = props => {
<div> <div>
<TextField <TextField
disabled={disabled} disabled={disabled}
error={!!getFieldError(errors, "companyName")} error={!!formErrors.companyName}
helperText={getFieldError(errors, "companyName")?.message} helperText={getErrorMessage(formErrors.companyName, intl)}
label={intl.formatMessage({ label={intl.formatMessage({
defaultMessage: "Company" defaultMessage: "Company"
})} })}
@ -94,9 +126,9 @@ const AddressEdit: React.FC<AddressEditProps> = props => {
<div> <div>
<TextField <TextField
disabled={disabled} disabled={disabled}
error={!!getFieldError(errors, "phone")} error={!!formErrors.phone}
fullWidth fullWidth
helperText={getFieldError(errors, "phone")?.message} helperText={getErrorMessage(formErrors.phone, intl)}
label={intl.formatMessage({ label={intl.formatMessage({
defaultMessage: "Phone" defaultMessage: "Phone"
})} })}
@ -109,8 +141,8 @@ const AddressEdit: React.FC<AddressEditProps> = props => {
<FormSpacer /> <FormSpacer />
<TextField <TextField
disabled={disabled} disabled={disabled}
error={!!getFieldError(errors, "streetAddress1")} error={!!formErrors.streetAddress1}
helperText={getFieldError(errors, "streetAddress1")?.message} helperText={getErrorMessage(formErrors.streetAddress1, intl)}
label={intl.formatMessage({ label={intl.formatMessage({
defaultMessage: "Address line 1" defaultMessage: "Address line 1"
})} })}
@ -122,8 +154,8 @@ const AddressEdit: React.FC<AddressEditProps> = props => {
<FormSpacer /> <FormSpacer />
<TextField <TextField
disabled={disabled} disabled={disabled}
error={!!getFieldError(errors, "streetAddress2")} error={!!formErrors.streetAddress2}
helperText={getFieldError(errors, "streetAddress2")?.message} helperText={getErrorMessage(formErrors.streetAddress2, intl)}
label={intl.formatMessage({ label={intl.formatMessage({
defaultMessage: "Address line 2" defaultMessage: "Address line 2"
})} })}
@ -137,8 +169,8 @@ const AddressEdit: React.FC<AddressEditProps> = props => {
<div> <div>
<TextField <TextField
disabled={disabled} disabled={disabled}
error={!!getFieldError(errors, "city")} error={!!formErrors.city}
helperText={getFieldError(errors, "city")?.message} helperText={getErrorMessage(formErrors.city, intl)}
label={intl.formatMessage({ label={intl.formatMessage({
defaultMessage: "City" defaultMessage: "City"
})} })}
@ -151,8 +183,8 @@ const AddressEdit: React.FC<AddressEditProps> = props => {
<div> <div>
<TextField <TextField
disabled={disabled} disabled={disabled}
error={!!getFieldError(errors, "postalCode")} error={!!formErrors.postalCode}
helperText={getFieldError(errors, "postalCode")?.message} helperText={getErrorMessage(formErrors.postalCode, intl)}
label={intl.formatMessage({ label={intl.formatMessage({
defaultMessage: "ZIP / Postal code" defaultMessage: "ZIP / Postal code"
})} })}
@ -170,8 +202,8 @@ const AddressEdit: React.FC<AddressEditProps> = props => {
<SingleAutocompleteSelectField <SingleAutocompleteSelectField
disabled={disabled} disabled={disabled}
displayValue={countryDisplayValue} displayValue={countryDisplayValue}
error={!!getFieldError(errors, "country")} error={!!formErrors.country}
helperText={getFieldError(errors, "country")?.message} helperText={getErrorMessage(formErrors.country, intl)}
label={intl.formatMessage({ label={intl.formatMessage({
defaultMessage: "Country" defaultMessage: "Country"
})} })}
@ -187,8 +219,8 @@ const AddressEdit: React.FC<AddressEditProps> = props => {
<div> <div>
<TextField <TextField
disabled={disabled} disabled={disabled}
error={!!getFieldError(errors, "countryArea")} error={!!formErrors.countryArea}
helperText={getFieldError(errors, "countryArea")?.message} helperText={getErrorMessage(formErrors.countryArea, intl)}
label={intl.formatMessage({ label={intl.formatMessage({
defaultMessage: "Country area" defaultMessage: "Country area"
})} })}

View file

@ -17,9 +17,9 @@ import useModalDialogErrors from "@saleor/hooks/useModalDialogErrors";
import useStateFromProps from "@saleor/hooks/useStateFromProps"; import useStateFromProps from "@saleor/hooks/useStateFromProps";
import { buttonMessages } from "@saleor/intl"; import { buttonMessages } from "@saleor/intl";
import { maybe } from "@saleor/misc"; import { maybe } from "@saleor/misc";
import { UserError } from "@saleor/types";
import { AddressInput } from "@saleor/types/globalTypes"; import { AddressInput } from "@saleor/types/globalTypes";
import createSingleAutocompleteSelectHandler from "@saleor/utils/handlers/singleAutocompleteSelectChangeHandler"; import createSingleAutocompleteSelectHandler from "@saleor/utils/handlers/singleAutocompleteSelectChangeHandler";
import { AccountErrorFragment } from "@saleor/customers/types/AccountErrorFragment";
import { AddressTypeInput } from "../../types"; import { AddressTypeInput } from "../../types";
import { CustomerAddresses_user_addresses } from "../../types/CustomerAddresses"; import { CustomerAddresses_user_addresses } from "../../types/CustomerAddresses";
@ -30,7 +30,7 @@ export interface CustomerAddressDialogProps {
code: string; code: string;
label: string; label: string;
}>; }>;
errors: UserError[]; errors: AccountErrorFragment[];
open: boolean; open: boolean;
variant: "create" | "edit"; variant: "create" | "edit";
onClose: () => void; onClose: () => void;

View file

@ -9,7 +9,7 @@ import AddressEdit from "@saleor/components/AddressEdit";
import CardTitle from "@saleor/components/CardTitle"; import CardTitle from "@saleor/components/CardTitle";
import { FormSpacer } from "@saleor/components/FormSpacer"; import { FormSpacer } from "@saleor/components/FormSpacer";
import { SingleAutocompleteChoiceType } from "@saleor/components/SingleAutocompleteSelectField"; import { SingleAutocompleteChoiceType } from "@saleor/components/SingleAutocompleteSelectField";
import { UserError } from "../../../types"; import { AccountErrorFragment } from "@saleor/customers/types/AccountErrorFragment";
import { AddressTypeInput } from "../../types"; import { AddressTypeInput } from "../../types";
const useStyles = makeStyles( const useStyles = makeStyles(
@ -26,7 +26,7 @@ export interface CustomerCreateAddressProps {
countryDisplayName: string; countryDisplayName: string;
data: AddressTypeInput; data: AddressTypeInput;
disabled: boolean; disabled: boolean;
errors: UserError[]; errors: AccountErrorFragment[];
onChange(event: React.ChangeEvent<any>); onChange(event: React.ChangeEvent<any>);
onCountryChange(event: React.ChangeEvent<any>); onCountryChange(event: React.ChangeEvent<any>);
} }

View file

@ -7,8 +7,9 @@ import { useIntl } from "react-intl";
import CardTitle from "@saleor/components/CardTitle"; import CardTitle from "@saleor/components/CardTitle";
import { commonMessages } from "@saleor/intl"; import { commonMessages } from "@saleor/intl";
import { getFieldError } from "@saleor/utils/errors"; import { getFormErrors } from "@saleor/utils/errors";
import { UserError } from "../../../types"; import { AccountErrorFragment } from "@saleor/customers/types/AccountErrorFragment";
import getAccountErrorMessage from "@saleor/utils/errors/account";
import { CustomerCreatePageFormData } from "../CustomerCreatePage"; import { CustomerCreatePageFormData } from "../CustomerCreatePage";
const useStyles = makeStyles( const useStyles = makeStyles(
@ -26,16 +27,21 @@ const useStyles = makeStyles(
export interface CustomerCreateDetailsProps { export interface CustomerCreateDetailsProps {
data: CustomerCreatePageFormData; data: CustomerCreatePageFormData;
disabled: boolean; disabled: boolean;
errors: UserError[]; errors: AccountErrorFragment[];
onChange: (event: React.ChangeEvent<any>) => void; onChange: (event: React.ChangeEvent<any>) => void;
} }
const CustomerCreateDetails: React.FC<CustomerCreateDetailsProps> = props => { const CustomerCreateDetails: React.FC<CustomerCreateDetailsProps> = props => {
const { data, disabled, errors, onChange } = props; const { data, disabled, errors, onChange } = props;
const classes = useStyles(props);
const classes = useStyles(props);
const intl = useIntl(); const intl = useIntl();
const formErrors = getFormErrors(
["customerFirstName", "customerLastName", "email"],
errors
);
return ( return (
<Card> <Card>
<CardTitle <CardTitle
@ -48,33 +54,39 @@ const CustomerCreateDetails: React.FC<CustomerCreateDetailsProps> = props => {
<div className={classes.root}> <div className={classes.root}>
<TextField <TextField
disabled={disabled} disabled={disabled}
error={!!getFieldError(errors, "customerFirstName")} error={!!formErrors.customerFirstName}
fullWidth fullWidth
name="customerFirstName" name="customerFirstName"
label={intl.formatMessage(commonMessages.firstName)} label={intl.formatMessage(commonMessages.firstName)}
helperText={getFieldError(errors, "customerFirstName")?.message} helperText={getAccountErrorMessage(
formErrors.customerFirstName,
intl
)}
type="text" type="text"
value={data.customerFirstName} value={data.customerFirstName}
onChange={onChange} onChange={onChange}
/> />
<TextField <TextField
disabled={disabled} disabled={disabled}
error={!!getFieldError(errors, "customerLastName")} error={!!formErrors.customerLastName}
fullWidth fullWidth
name="customerLastName" name="customerLastName"
label={intl.formatMessage(commonMessages.lastName)} label={intl.formatMessage(commonMessages.lastName)}
helperText={getFieldError(errors, "customerLastName")?.message} helperText={getAccountErrorMessage(
formErrors.customerLastName,
intl
)}
type="text" type="text"
value={data.customerLastName} value={data.customerLastName}
onChange={onChange} onChange={onChange}
/> />
<TextField <TextField
disabled={disabled} disabled={disabled}
error={!!getFieldError(errors, "email")} error={!!formErrors.email}
fullWidth fullWidth
name="email" name="email"
label={intl.formatMessage(commonMessages.email)} label={intl.formatMessage(commonMessages.email)}
helperText={getFieldError(errors, "email")?.message} helperText={getAccountErrorMessage(formErrors.email, intl)}
type="email" type="email"
value={data.email} value={data.email}
onChange={onChange} onChange={onChange}
@ -84,5 +96,6 @@ const CustomerCreateDetails: React.FC<CustomerCreateDetailsProps> = props => {
</Card> </Card>
); );
}; };
CustomerCreateDetails.displayName = "CustomerCreateDetails"; CustomerCreateDetails.displayName = "CustomerCreateDetails";
export default CustomerCreateDetails; export default CustomerCreateDetails;

View file

@ -7,15 +7,16 @@ import { FormattedMessage, useIntl } from "react-intl";
import CardTitle from "@saleor/components/CardTitle"; import CardTitle from "@saleor/components/CardTitle";
import { FormSpacer } from "@saleor/components/FormSpacer"; import { FormSpacer } from "@saleor/components/FormSpacer";
import { UserError } from "@saleor/types"; import { getFormErrors } from "@saleor/utils/errors";
import { getFieldError } from "@saleor/utils/errors"; import getAccountErrorMessage from "@saleor/utils/errors/account";
import { AccountErrorFragment } from "@saleor/customers/types/AccountErrorFragment";
export interface CustomerCreateNoteProps { export interface CustomerCreateNoteProps {
data: { data: {
note: string; note: string;
}; };
disabled: boolean; disabled: boolean;
errors: UserError[]; errors: AccountErrorFragment[];
onChange: (event: React.ChangeEvent<any>) => void; onChange: (event: React.ChangeEvent<any>) => void;
} }
@ -27,6 +28,8 @@ const CustomerCreateNote: React.FC<CustomerCreateNoteProps> = ({
}) => { }) => {
const intl = useIntl(); const intl = useIntl();
const formErrors = getFormErrors(["note"], errors);
return ( return (
<Card> <Card>
<CardTitle <CardTitle
@ -42,11 +45,11 @@ const CustomerCreateNote: React.FC<CustomerCreateNoteProps> = ({
<FormSpacer /> <FormSpacer />
<TextField <TextField
disabled={disabled} disabled={disabled}
error={!!getFieldError(errors, "note")} error={!!formErrors.note}
fullWidth fullWidth
multiline multiline
name="note" name="note"
helperText={getFieldError(errors, "note")?.message} helperText={getAccountErrorMessage(formErrors.note, intl)}
label={intl.formatMessage({ label={intl.formatMessage({
defaultMessage: "Note", defaultMessage: "Note",
description: "note about customer" description: "note about customer"

View file

@ -13,7 +13,7 @@ import useAddressValidation from "@saleor/hooks/useAddressValidation";
import { sectionNames } from "@saleor/intl"; import { sectionNames } from "@saleor/intl";
import { AddressInput } from "@saleor/types/globalTypes"; import { AddressInput } from "@saleor/types/globalTypes";
import createSingleAutocompleteSelectHandler from "@saleor/utils/handlers/singleAutocompleteSelectChangeHandler"; import createSingleAutocompleteSelectHandler from "@saleor/utils/handlers/singleAutocompleteSelectChangeHandler";
import { UserError } from "../../../types"; import { AccountErrorFragment } from "@saleor/customers/types/AccountErrorFragment";
import { AddressTypeInput } from "../../types"; import { AddressTypeInput } from "../../types";
import { CustomerCreateData_shop_countries } from "../../types/CustomerCreateData"; import { CustomerCreateData_shop_countries } from "../../types/CustomerCreateData";
import CustomerCreateAddress from "../CustomerCreateAddress/CustomerCreateAddress"; import CustomerCreateAddress from "../CustomerCreateAddress/CustomerCreateAddress";
@ -52,7 +52,7 @@ const initialForm: CustomerCreatePageFormData & AddressTypeInput = {
export interface CustomerCreatePageProps { export interface CustomerCreatePageProps {
countries: CustomerCreateData_shop_countries[]; countries: CustomerCreateData_shop_countries[];
disabled: boolean; disabled: boolean;
errors: UserError[]; errors: AccountErrorFragment[];
saveButtonBar: ConfirmButtonTransitionState; saveButtonBar: ConfirmButtonTransitionState;
onBack: () => void; onBack: () => void;
onSubmit: (data: CustomerCreatePageSubmitData) => void; onSubmit: (data: CustomerCreatePageSubmitData) => void;

View file

@ -11,8 +11,9 @@ import CardTitle from "@saleor/components/CardTitle";
import { ControlledCheckbox } from "@saleor/components/ControlledCheckbox"; import { ControlledCheckbox } from "@saleor/components/ControlledCheckbox";
import Skeleton from "@saleor/components/Skeleton"; import Skeleton from "@saleor/components/Skeleton";
import { maybe } from "@saleor/misc"; import { maybe } from "@saleor/misc";
import { UserError } from "@saleor/types"; import { getFormErrors } from "@saleor/utils/errors";
import { getFieldError } from "@saleor/utils/errors"; import getAccountErrorMessage from "@saleor/utils/errors/account";
import { AccountErrorFragment } from "@saleor/customers/types/AccountErrorFragment";
import { CustomerDetails_user } from "../../types/CustomerDetails"; import { CustomerDetails_user } from "../../types/CustomerDetails";
const useStyles = makeStyles( const useStyles = makeStyles(
@ -40,16 +41,18 @@ export interface CustomerDetailsProps {
note: string; note: string;
}; };
disabled: boolean; disabled: boolean;
errors: UserError[]; errors: AccountErrorFragment[];
onChange: (event: React.ChangeEvent<any>) => void; onChange: (event: React.ChangeEvent<any>) => void;
} }
const CustomerDetails: React.FC<CustomerDetailsProps> = props => { const CustomerDetails: React.FC<CustomerDetailsProps> = props => {
const { customer, data, disabled, errors, onChange } = props; const { customer, data, disabled, errors, onChange } = props;
const classes = useStyles(props);
const classes = useStyles(props);
const intl = useIntl(); const intl = useIntl();
const formErrors = getFormErrors(["note"], errors);
return ( return (
<Card> <Card>
<CardTitle <CardTitle
@ -91,10 +94,10 @@ const CustomerDetails: React.FC<CustomerDetailsProps> = props => {
/> />
<TextField <TextField
disabled={disabled} disabled={disabled}
error={!!getFieldError(errors, "note")} error={!!formErrors.note}
fullWidth fullWidth
multiline multiline
helperText={getFieldError(errors, "note")?.message} helperText={getAccountErrorMessage(formErrors.note, intl)}
name="note" name="note"
label={intl.formatMessage({ label={intl.formatMessage({
defaultMessage: "Note", defaultMessage: "Note",

View file

@ -10,8 +10,8 @@ import Grid from "@saleor/components/Grid";
import PageHeader from "@saleor/components/PageHeader"; import PageHeader from "@saleor/components/PageHeader";
import SaveButtonBar from "@saleor/components/SaveButtonBar"; import SaveButtonBar from "@saleor/components/SaveButtonBar";
import { sectionNames } from "@saleor/intl"; import { sectionNames } from "@saleor/intl";
import { AccountErrorFragment } from "@saleor/customers/types/AccountErrorFragment";
import { getUserName, maybe } from "../../../misc"; import { getUserName, maybe } from "../../../misc";
import { UserError } from "../../../types";
import { CustomerDetails_user } from "../../types/CustomerDetails"; import { CustomerDetails_user } from "../../types/CustomerDetails";
import CustomerAddresses from "../CustomerAddresses"; import CustomerAddresses from "../CustomerAddresses";
import CustomerDetails from "../CustomerDetails"; import CustomerDetails from "../CustomerDetails";
@ -30,7 +30,7 @@ export interface CustomerDetailsPageFormData {
export interface CustomerDetailsPageProps { export interface CustomerDetailsPageProps {
customer: CustomerDetails_user; customer: CustomerDetails_user;
disabled: boolean; disabled: boolean;
errors: UserError[]; errors: AccountErrorFragment[];
saveButtonBar: ConfirmButtonTransitionState; saveButtonBar: ConfirmButtonTransitionState;
onBack: () => void; onBack: () => void;
onSubmit: (data: CustomerDetailsPageFormData) => void; onSubmit: (data: CustomerDetailsPageFormData) => void;

View file

@ -10,8 +10,9 @@ import CardTitle from "@saleor/components/CardTitle";
import Grid from "@saleor/components/Grid"; import Grid from "@saleor/components/Grid";
import Hr from "@saleor/components/Hr"; import Hr from "@saleor/components/Hr";
import { commonMessages } from "@saleor/intl"; import { commonMessages } from "@saleor/intl";
import { UserError } from "@saleor/types"; import { AccountErrorFragment } from "@saleor/customers/types/AccountErrorFragment";
import { getFieldError } from "@saleor/utils/errors"; import { getFormErrors } from "@saleor/utils/errors";
import getAccountErrorMessage from "@saleor/utils/errors/account";
const useStyles = makeStyles( const useStyles = makeStyles(
theme => ({ theme => ({
@ -35,16 +36,18 @@ export interface CustomerInfoProps {
email: string; email: string;
}; };
disabled: boolean; disabled: boolean;
errors: UserError[]; errors: AccountErrorFragment[];
onChange: (event: React.ChangeEvent<any>) => void; onChange: (event: React.ChangeEvent<any>) => void;
} }
const CustomerInfo: React.FC<CustomerInfoProps> = props => { const CustomerInfo: React.FC<CustomerInfoProps> = props => {
const { data, disabled, errors, onChange } = props; const { data, disabled, errors, onChange } = props;
const classes = useStyles(props);
const classes = useStyles(props);
const intl = useIntl(); const intl = useIntl();
const formErrors = getFormErrors(["firstName", "lastName", "email"], errors);
return ( return (
<Card> <Card>
<CardTitle <CardTitle
@ -62,9 +65,9 @@ const CustomerInfo: React.FC<CustomerInfoProps> = props => {
<Grid variant="uniform"> <Grid variant="uniform">
<TextField <TextField
disabled={disabled} disabled={disabled}
error={!!getFieldError(errors, "firstName")} error={!!formErrors.firstName}
fullWidth fullWidth
helperText={getFieldError(errors, "firstName")?.message} helperText={getAccountErrorMessage(formErrors.firstName, intl)}
name="firstName" name="firstName"
type="text" type="text"
label={intl.formatMessage(commonMessages.firstName)} label={intl.formatMessage(commonMessages.firstName)}
@ -73,9 +76,9 @@ const CustomerInfo: React.FC<CustomerInfoProps> = props => {
/> />
<TextField <TextField
disabled={disabled} disabled={disabled}
error={!!getFieldError(errors, "lastName")} error={!!formErrors.lastName}
fullWidth fullWidth
helperText={getFieldError(errors, "lastName")?.message} helperText={getAccountErrorMessage(formErrors.lastName, intl)}
name="lastName" name="lastName"
type="text" type="text"
label={intl.formatMessage(commonMessages.lastName)} label={intl.formatMessage(commonMessages.lastName)}
@ -92,9 +95,9 @@ const CustomerInfo: React.FC<CustomerInfoProps> = props => {
</Typography> </Typography>
<TextField <TextField
disabled={disabled} disabled={disabled}
error={!!getFieldError(errors, "email")} error={!!formErrors.email}
fullWidth fullWidth
helperText={getFieldError(errors, "email")?.message} helperText={getAccountErrorMessage(formErrors.email, intl)}
name="email" name="email"
type="email" type="email"
label={intl.formatMessage(commonMessages.email)} label={intl.formatMessage(commonMessages.email)}

View file

@ -41,20 +41,8 @@ export const CustomerCreate: React.FC<{}> = () => {
<CustomerCreatePage <CustomerCreatePage
countries={maybe(() => data.shop.countries, [])} countries={maybe(() => data.shop.countries, [])}
disabled={loading || createCustomerOpts.loading} disabled={loading || createCustomerOpts.loading}
errors={maybe(() => { errors={createCustomerOpts.data?.customerCreate.errors || []}
const errs = createCustomerOpts.data.customerCreate.errors; saveButtonBar={createCustomerOpts.status}
return errs.map(err =>
err.field.split(":").length > 1
? {
...err,
field: err.field.split(":")[1]
}
: err
);
}, [])}
saveButtonBar={
createCustomerOpts.loading ? "loading" : "default"
}
onBack={() => navigate(customerListUrl())} onBack={() => navigate(customerListUrl())}
onSubmit={formData => { onSubmit={formData => {
createCustomer({ createCustomer({

View file

@ -1,27 +1,27 @@
import { useState } from "react"; import { useState } from "react";
import { useIntl } from "react-intl";
import { AddressTypeInput } from "@saleor/customers/types"; import { AddressTypeInput } from "@saleor/customers/types";
import { commonMessages } from "@saleor/intl";
import { transformFormToAddress } from "@saleor/misc"; import { transformFormToAddress } from "@saleor/misc";
import { UserError } from "@saleor/types"; import { AddressInput, AccountErrorCode } from "@saleor/types/globalTypes";
import { AddressInput } from "@saleor/types/globalTypes";
import { add, remove } from "@saleor/utils/lists"; import { add, remove } from "@saleor/utils/lists";
import { AccountErrorFragment } from "@saleor/customers/types/AccountErrorFragment";
interface UseAddressValidation<T> { interface UseAddressValidation<T> {
errors: UserError[]; errors: AccountErrorFragment[];
submit: (data: T & AddressTypeInput) => void; submit: (data: T & AddressTypeInput) => void;
} }
function useAddressValidation<T>( function useAddressValidation<T>(
onSubmit: (address: T & AddressInput) => void onSubmit: (address: T & AddressInput) => void
): UseAddressValidation<T> { ): UseAddressValidation<T> {
const intl = useIntl(); const [validationErrors, setValidationErrors] = useState<
const [validationErrors, setValidationErrors] = useState<UserError[]>([]); AccountErrorFragment[]
>([]);
const countryRequiredError = { const countryRequiredError: AccountErrorFragment = {
field: "country", __typename: "AccountError",
message: intl.formatMessage(commonMessages.requiredField) code: AccountErrorCode.REQUIRED,
field: "country"
}; };
return { return {

View file

@ -18,9 +18,9 @@ import useModalDialogErrors from "@saleor/hooks/useModalDialogErrors";
import useStateFromProps from "@saleor/hooks/useStateFromProps"; import useStateFromProps from "@saleor/hooks/useStateFromProps";
import { buttonMessages } from "@saleor/intl"; import { buttonMessages } from "@saleor/intl";
import { maybe } from "@saleor/misc"; import { maybe } from "@saleor/misc";
import { UserError } from "@saleor/types";
import { AddressInput } from "@saleor/types/globalTypes"; import { AddressInput } from "@saleor/types/globalTypes";
import createSingleAutocompleteSelectHandler from "@saleor/utils/handlers/singleAutocompleteSelectChangeHandler"; import createSingleAutocompleteSelectHandler from "@saleor/utils/handlers/singleAutocompleteSelectChangeHandler";
import { OrderErrorFragment } from "@saleor/orders/types/OrderErrorFragment";
const useStyles = makeStyles( const useStyles = makeStyles(
{ {
@ -35,7 +35,7 @@ interface OrderAddressEditDialogProps {
confirmButtonState: ConfirmButtonTransitionState; confirmButtonState: ConfirmButtonTransitionState;
address: AddressTypeInput; address: AddressTypeInput;
open: boolean; open: boolean;
errors: UserError[]; errors: OrderErrorFragment[];
variant: "billing" | "shipping" | string; variant: "billing" | "shipping" | string;
countries?: Array<{ countries?: Array<{
code: string; code: string;

View file

@ -64,6 +64,13 @@ import {
import { OrderUpdate, OrderUpdateVariables } from "./types/OrderUpdate"; import { OrderUpdate, OrderUpdateVariables } from "./types/OrderUpdate";
import { OrderVoid, OrderVoidVariables } from "./types/OrderVoid"; import { OrderVoid, OrderVoidVariables } from "./types/OrderVoid";
export const orderErrorFragment = gql`
fragment OrderErrorFragment on OrderError {
code
field
}
`;
const orderCancelMutation = gql` const orderCancelMutation = gql`
${fragmentOrderDetails} ${fragmentOrderDetails}
mutation OrderCancel($id: ID!, $restock: Boolean!) { mutation OrderCancel($id: ID!, $restock: Boolean!) {
@ -314,11 +321,11 @@ export const TypedOrderAddNoteMutation = TypedMutation<
const orderUpdateMutation = gql` const orderUpdateMutation = gql`
${fragmentAddress} ${fragmentAddress}
${orderErrorFragment}
mutation OrderUpdate($id: ID!, $input: OrderUpdateInput!) { mutation OrderUpdate($id: ID!, $input: OrderUpdateInput!) {
orderUpdate(id: $id, input: $input) { orderUpdate(id: $id, input: $input) {
errors { errors: orderErrors {
field ...OrderErrorFragment
message
} }
order { order {
id id
@ -342,7 +349,8 @@ const orderDraftUpdateMutation = gql`
${fragmentOrderDetails} ${fragmentOrderDetails}
mutation OrderDraftUpdate($id: ID!, $input: DraftOrderInput!) { mutation OrderDraftUpdate($id: ID!, $input: DraftOrderInput!) {
draftOrderUpdate(id: $id, input: $input) { draftOrderUpdate(id: $id, input: $input) {
errors { errors: orderErrors {
code
field field
message message
} }

View file

@ -2,14 +2,15 @@
/* eslint-disable */ /* eslint-disable */
// This file was automatically generated and should not be edited. // 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 // GraphQL mutation operation: OrderDraftUpdate
// ==================================================== // ====================================================
export interface OrderDraftUpdate_draftOrderUpdate_errors { export interface OrderDraftUpdate_draftOrderUpdate_errors {
__typename: "Error"; __typename: "OrderError";
code: OrderErrorCode;
field: string | null; field: string | null;
message: string | null; message: string | null;
} }

View file

@ -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;
}

View file

@ -2,16 +2,16 @@
/* eslint-disable */ /* eslint-disable */
// This file was automatically generated and should not be edited. // 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 // GraphQL mutation operation: OrderUpdate
// ==================================================== // ====================================================
export interface OrderUpdate_orderUpdate_errors { export interface OrderUpdate_orderUpdate_errors {
__typename: "Error"; __typename: "OrderError";
code: OrderErrorCode;
field: string | null; field: string | null;
message: string | null;
} }
export interface OrderUpdate_orderUpdate_order_billingAddress_country { export interface OrderUpdate_orderUpdate_order_billingAddress_country {

View file

@ -3,7 +3,7 @@ import React from "react";
import { permissions } from "@saleor/fixtures"; import { permissions } from "@saleor/fixtures";
import Decorator from "@saleor/storybook/Decorator"; import Decorator from "@saleor/storybook/Decorator";
import { formError } from "@saleor/storybook/misc"; import { AccountErrorCode } from "@saleor/types/globalTypes";
import ServiceCreatePage, { ServiceCreatePageProps } from "./ServiceCreatePage"; import ServiceCreatePage, { ServiceCreatePageProps } from "./ServiceCreatePage";
const props: ServiceCreatePageProps = { const props: ServiceCreatePageProps = {
@ -21,6 +21,10 @@ storiesOf("Views / Services / Create service", module)
.add("form errors", () => ( .add("form errors", () => (
<ServiceCreatePage <ServiceCreatePage
{...props} {...props}
errors={["name"].map(field => formError(field))} errors={["name"].map(field => ({
__typename: "AccountError",
code: AccountErrorCode.INVALID,
field
}))}
/> />
)); ));

View file

@ -13,8 +13,8 @@ import PageHeader from "@saleor/components/PageHeader";
import SaveButtonBar from "@saleor/components/SaveButtonBar"; import SaveButtonBar from "@saleor/components/SaveButtonBar";
import { ShopInfo_shop_permissions } from "@saleor/components/Shop/types/ShopInfo"; import { ShopInfo_shop_permissions } from "@saleor/components/Shop/types/ShopInfo";
import { sectionNames } from "@saleor/intl"; import { sectionNames } from "@saleor/intl";
import { UserError } from "@saleor/types";
import { PermissionEnum } from "@saleor/types/globalTypes"; import { PermissionEnum } from "@saleor/types/globalTypes";
import { AccountErrorFragment } from "@saleor/customers/types/AccountErrorFragment";
import ServiceInfo from "../ServiceInfo"; import ServiceInfo from "../ServiceInfo";
export interface ServiceCreatePageFormData { export interface ServiceCreatePageFormData {
@ -25,7 +25,7 @@ export interface ServiceCreatePageFormData {
} }
export interface ServiceCreatePageProps { export interface ServiceCreatePageProps {
disabled: boolean; disabled: boolean;
errors: UserError[]; errors: AccountErrorFragment[];
permissions: ShopInfo_shop_permissions[]; permissions: ShopInfo_shop_permissions[];
saveButtonBarState: ConfirmButtonTransitionState; saveButtonBarState: ConfirmButtonTransitionState;
onBack: () => void; onBack: () => void;

View file

@ -3,7 +3,7 @@ import React from "react";
import { permissions } from "@saleor/fixtures"; import { permissions } from "@saleor/fixtures";
import Decorator from "@saleor/storybook/Decorator"; import Decorator from "@saleor/storybook/Decorator";
import { formError } from "@saleor/storybook/misc"; import { AccountErrorCode } from "@saleor/types/globalTypes";
import { service } from "../../fixtures"; import { service } from "../../fixtures";
import ServiceDetailsPage, { import ServiceDetailsPage, {
ServiceDetailsPageProps ServiceDetailsPageProps
@ -34,7 +34,11 @@ storiesOf("Views / Services / Service details", module)
.add("form errors", () => ( .add("form errors", () => (
<ServiceDetailsPage <ServiceDetailsPage
{...props} {...props}
errors={["name"].map(field => formError(field))} errors={["name"].map(field => ({
__typename: "AccountError",
code: AccountErrorCode.INVALID,
field
}))}
/> />
)) ))
.add("default token", () => ( .add("default token", () => (

View file

@ -15,8 +15,8 @@ import { ShopInfo_shop_permissions } from "@saleor/components/Shop/types/ShopInf
import { sectionNames } from "@saleor/intl"; import { sectionNames } from "@saleor/intl";
import { maybe } from "@saleor/misc"; import { maybe } from "@saleor/misc";
import { ServiceDetails_serviceAccount } from "@saleor/services/types/ServiceDetails"; import { ServiceDetails_serviceAccount } from "@saleor/services/types/ServiceDetails";
import { UserError } from "@saleor/types";
import { PermissionEnum } from "@saleor/types/globalTypes"; import { PermissionEnum } from "@saleor/types/globalTypes";
import { AccountErrorFragment } from "@saleor/customers/types/AccountErrorFragment";
import ServiceDefaultToken from "../ServiceDefaultToken"; import ServiceDefaultToken from "../ServiceDefaultToken";
import ServiceInfo from "../ServiceInfo"; import ServiceInfo from "../ServiceInfo";
import ServiceTokens from "../ServiceTokens"; import ServiceTokens from "../ServiceTokens";
@ -30,7 +30,7 @@ export interface ServiceDetailsPageFormData {
export interface ServiceDetailsPageProps { export interface ServiceDetailsPageProps {
apiUri: string; apiUri: string;
disabled: boolean; disabled: boolean;
errors: UserError[]; errors: AccountErrorFragment[];
permissions: ShopInfo_shop_permissions[]; permissions: ShopInfo_shop_permissions[];
saveButtonBarState: ConfirmButtonTransitionState; saveButtonBarState: ConfirmButtonTransitionState;
service: ServiceDetails_serviceAccount; service: ServiceDetails_serviceAccount;
@ -107,7 +107,7 @@ const ServiceDetailsPage: React.FC<ServiceDetailsPageProps> = props => {
/> />
<CardSpacer /> <CardSpacer />
<ServiceTokens <ServiceTokens
tokens={maybe(() => service.tokens)} tokens={service?.tokens}
onCreate={onTokenCreate} onCreate={onTokenCreate}
onDelete={onTokenDelete} onDelete={onTokenDelete}
/> />

View file

@ -6,22 +6,29 @@ import { useIntl } from "react-intl";
import CardTitle from "@saleor/components/CardTitle"; import CardTitle from "@saleor/components/CardTitle";
import { FormChange } from "@saleor/hooks/useForm"; import { FormChange } from "@saleor/hooks/useForm";
import { UserError } from "@saleor/types"; import { AccountErrorFragment } from "@saleor/customers/types/AccountErrorFragment";
import { getFieldError } from "@saleor/utils/errors"; import { getFormErrors } from "@saleor/utils/errors";
import getAccountErrorMessage from "@saleor/utils/errors/account";
export interface ServiceInfoProps { export interface ServiceInfoProps {
data: { data: {
name: string; name: string;
}; };
disabled: boolean; disabled: boolean;
errors: UserError[]; errors: AccountErrorFragment[];
onChange: FormChange; onChange: FormChange;
} }
const ServiceInfo: React.FC<ServiceInfoProps> = props => { const ServiceInfo: React.FC<ServiceInfoProps> = ({
const { data, disabled, errors, onChange } = props; data,
disabled,
errors,
onChange
}) => {
const intl = useIntl(); const intl = useIntl();
const formErrors = getFormErrors(["name"], errors);
return ( return (
<Card> <Card>
<CardTitle <CardTitle
@ -33,12 +40,12 @@ const ServiceInfo: React.FC<ServiceInfoProps> = props => {
<CardContent> <CardContent>
<TextField <TextField
disabled={disabled} disabled={disabled}
error={!!getFieldError(errors, "name")} error={!!formErrors.name}
label={intl.formatMessage({ label={intl.formatMessage({
defaultMessage: "Account Name", defaultMessage: "Account Name",
description: "service account" description: "service account"
})} })}
helperText={getFieldError(errors, "name")?.message} helperText={getAccountErrorMessage(formErrors.name, intl)}
fullWidth fullWidth
name="name" name="name"
value={data.name} value={data.name}

View file

@ -17,8 +17,9 @@ import Form from "@saleor/components/Form";
import FormSpacer from "@saleor/components/FormSpacer"; import FormSpacer from "@saleor/components/FormSpacer";
import { buttonMessages, commonMessages } from "@saleor/intl"; import { buttonMessages, commonMessages } from "@saleor/intl";
import useModalDialogErrors from "@saleor/hooks/useModalDialogErrors"; import useModalDialogErrors from "@saleor/hooks/useModalDialogErrors";
import { getFieldError } from "@saleor/utils/errors"; import { AccountErrorFragment } from "@saleor/customers/types/AccountErrorFragment";
import { UserError } from "../../../types"; import { getFormErrors } from "@saleor/utils/errors";
import getAccountErrorMessage from "@saleor/utils/errors/account";
export interface FormData { export interface FormData {
email: string; email: string;
@ -58,7 +59,7 @@ const useStyles = makeStyles(
interface StaffAddMemberDialogProps { interface StaffAddMemberDialogProps {
confirmButtonState: ConfirmButtonTransitionState; confirmButtonState: ConfirmButtonTransitionState;
errors: UserError[]; errors: AccountErrorFragment[];
open: boolean; open: boolean;
onClose: () => void; onClose: () => void;
onConfirm: (data: FormData) => void; onConfirm: (data: FormData) => void;
@ -66,11 +67,16 @@ interface StaffAddMemberDialogProps {
const StaffAddMemberDialog: React.FC<StaffAddMemberDialogProps> = props => { const StaffAddMemberDialog: React.FC<StaffAddMemberDialogProps> = props => {
const { confirmButtonState, errors, open, onClose, onConfirm } = props; const { confirmButtonState, errors, open, onClose, onConfirm } = props;
const classes = useStyles(props); const classes = useStyles(props);
const dialogErrors = useModalDialogErrors(errors, open); const dialogErrors = useModalDialogErrors(errors, open);
const intl = useIntl(); const intl = useIntl();
const formErrors = getFormErrors(
["firstName", "lastName", "email"],
dialogErrors
);
return ( return (
<Dialog onClose={onClose} open={open}> <Dialog onClose={onClose} open={open}>
<Form initial={initialForm} onSubmit={onConfirm}> <Form initial={initialForm} onSubmit={onConfirm}>
@ -85,8 +91,11 @@ const StaffAddMemberDialog: React.FC<StaffAddMemberDialogProps> = props => {
<DialogContent> <DialogContent>
<div className={classes.textFieldGrid}> <div className={classes.textFieldGrid}>
<TextField <TextField
error={!!getFieldError(dialogErrors, "firstName")} error={!!formErrors.firstName}
helperText={getFieldError(dialogErrors, "firstName")?.message} helperText={getAccountErrorMessage(
formErrors.firstName,
intl
)}
label={intl.formatMessage(commonMessages.firstName)} label={intl.formatMessage(commonMessages.firstName)}
name="firstName" name="firstName"
type="text" type="text"
@ -94,8 +103,8 @@ const StaffAddMemberDialog: React.FC<StaffAddMemberDialogProps> = props => {
onChange={change} onChange={change}
/> />
<TextField <TextField
error={!!getFieldError(dialogErrors, "lastName")} error={!!formErrors.lastName}
helperText={getFieldError(dialogErrors, "lastName")?.message} helperText={getAccountErrorMessage(formErrors.lastName, intl)}
label={intl.formatMessage(commonMessages.lastName)} label={intl.formatMessage(commonMessages.lastName)}
name="lastName" name="lastName"
type="text" type="text"
@ -105,9 +114,9 @@ const StaffAddMemberDialog: React.FC<StaffAddMemberDialogProps> = props => {
</div> </div>
<FormSpacer /> <FormSpacer />
<TextField <TextField
error={!!getFieldError(dialogErrors, "email")} error={!!formErrors.email}
fullWidth fullWidth
helperText={getFieldError(dialogErrors, "email")?.message} helperText={getAccountErrorMessage(formErrors.email, intl)}
label={intl.formatMessage(commonMessages.email)} label={intl.formatMessage(commonMessages.email)}
name="email" name="email"
type="email" type="email"

View file

@ -7,7 +7,7 @@ import TextField from "@material-ui/core/TextField";
import DialogTitle from "@material-ui/core/DialogTitle"; import DialogTitle from "@material-ui/core/DialogTitle";
import { FormattedMessage, useIntl } from "react-intl"; import { FormattedMessage, useIntl } from "react-intl";
import { DialogProps, UserError } from "@saleor/types"; import { DialogProps } from "@saleor/types";
import { buttonMessages } from "@saleor/intl"; import { buttonMessages } from "@saleor/intl";
import Form from "@saleor/components/Form"; import Form from "@saleor/components/Form";
import ConfirmButton, { import ConfirmButton, {
@ -15,7 +15,9 @@ import ConfirmButton, {
} from "@saleor/components/ConfirmButton"; } from "@saleor/components/ConfirmButton";
import FormSpacer from "@saleor/components/FormSpacer"; import FormSpacer from "@saleor/components/FormSpacer";
import useModalDialogErrors from "@saleor/hooks/useModalDialogErrors"; import useModalDialogErrors from "@saleor/hooks/useModalDialogErrors";
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";
interface StaffPasswordResetDialogFormData { interface StaffPasswordResetDialogFormData {
newPassword: string; newPassword: string;
@ -23,7 +25,7 @@ interface StaffPasswordResetDialogFormData {
} }
export interface StaffPasswordResetDialogProps extends DialogProps { export interface StaffPasswordResetDialogProps extends DialogProps {
confirmButtonState: ConfirmButtonTransitionState; confirmButtonState: ConfirmButtonTransitionState;
errors: UserError[]; errors: AccountErrorFragment[];
onSubmit: (data: StaffPasswordResetDialogFormData) => void; onSubmit: (data: StaffPasswordResetDialogFormData) => void;
} }
@ -42,6 +44,11 @@ const StaffPasswordResetDialog: React.FC<StaffPasswordResetDialogProps> = ({
const intl = useIntl(); const intl = useIntl();
const dialogErrors = useModalDialogErrors(errors, open); const dialogErrors = useModalDialogErrors(errors, open);
const formErrors = getFormErrors(
["oldPassword", "newPassword"],
dialogErrors
);
return ( return (
<Dialog onClose={onClose} open={open} fullWidth maxWidth="sm"> <Dialog onClose={onClose} open={open} fullWidth maxWidth="sm">
<DialogTitle> <DialogTitle>
@ -55,9 +62,12 @@ const StaffPasswordResetDialog: React.FC<StaffPasswordResetDialogProps> = ({
<> <>
<DialogContent> <DialogContent>
<TextField <TextField
error={!!getFieldError(dialogErrors, "oldPassword")} error={!!formErrors.oldPassword}
fullWidth fullWidth
helperText={getFieldError(dialogErrors, "oldPassword")?.message} helperText={getAccountErrorMessage(
formErrors.oldPassword,
intl
)}
label={intl.formatMessage({ label={intl.formatMessage({
defaultMessage: "Previous Password", defaultMessage: "Previous Password",
description: "input label" description: "input label"
@ -68,10 +78,10 @@ const StaffPasswordResetDialog: React.FC<StaffPasswordResetDialogProps> = ({
/> />
<FormSpacer /> <FormSpacer />
<TextField <TextField
error={!!getFieldError(dialogErrors, "newPassword")} error={!!formErrors.newPassword}
fullWidth fullWidth
helperText={ helperText={
getFieldError(dialogErrors, "newPassword") || getAccountErrorMessage(formErrors.newPassword, intl) ||
intl.formatMessage({ intl.formatMessage({
defaultMessage: defaultMessage:
"New password must be at least 8 characters long" "New password must be at least 8 characters long"

View file

@ -2,12 +2,12 @@ import { Omit } from "@material-ui/core";
import { storiesOf } from "@storybook/react"; import { storiesOf } from "@storybook/react";
import React from "react"; import React from "react";
import { AccountErrorCode } from "@saleor/types/globalTypes";
import CustomerCreatePage, { import CustomerCreatePage, {
CustomerCreatePageFormData, CustomerCreatePageFormData,
CustomerCreatePageProps CustomerCreatePageProps
} from "../../../customers/components/CustomerCreatePage"; } from "../../../customers/components/CustomerCreatePage";
import Decorator from "../../Decorator"; import Decorator from "../../Decorator";
import { formError } from "../../misc";
const props: Omit<CustomerCreatePageProps, "classes"> = { const props: Omit<CustomerCreatePageProps, "classes"> = {
countries: [ countries: [
@ -42,8 +42,10 @@ storiesOf("Views / Customers / Create customer", module)
"postalCode", "postalCode",
"streetAddress1", "streetAddress1",
"streetAddress2" "streetAddress2"
] as Array<keyof CustomerCreatePageFormData>).map(field => ] as Array<keyof CustomerCreatePageFormData>).map(field => ({
formError(field) __typename: "AccountError",
)} code: AccountErrorCode.INVALID,
field
}))}
/> />
)); ));

View file

@ -2,12 +2,12 @@ import { Omit } from "@material-ui/core";
import { storiesOf } from "@storybook/react"; import { storiesOf } from "@storybook/react";
import React from "react"; import React from "react";
import { AccountErrorCode } from "@saleor/types/globalTypes";
import CustomerDetailsPage, { import CustomerDetailsPage, {
CustomerDetailsPageProps CustomerDetailsPageProps
} from "../../../customers/components/CustomerDetailsPage"; } from "../../../customers/components/CustomerDetailsPage";
import { customer } from "../../../customers/fixtures"; import { customer } from "../../../customers/fixtures";
import Decorator from "../../Decorator"; import Decorator from "../../Decorator";
import { formError } from "../../misc";
const props: Omit<CustomerDetailsPageProps, "classes"> = { const props: Omit<CustomerDetailsPageProps, "classes"> = {
customer, customer,
@ -40,7 +40,11 @@ storiesOf("Views / Customers / Customer details", module)
{...props} {...props}
errors={(["email", "firstName", "lastName"] as Array< errors={(["email", "firstName", "lastName"] as Array<
keyof CustomerDetailsPageErrors keyof CustomerDetailsPageErrors
>).map(field => formError(field))} >).map(field => ({
__typename: "AccountError",
code: AccountErrorCode.INVALID,
field
}))}
/> />
)) ))
.add("different addresses", () => ( .add("different addresses", () => (

View file

@ -425,6 +425,29 @@ export enum OrderDirection {
DESC = "DESC", 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 { export enum OrderEventsEmailsEnum {
DIGITAL_LINKS = "DIGITAL_LINKS", DIGITAL_LINKS = "DIGITAL_LINKS",
FULFILLMENT_CONFIRMATION = "FULFILLMENT_CONFIRMATION", FULFILLMENT_CONFIRMATION = "FULFILLMENT_CONFIRMATION",

View file

@ -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;

28
src/utils/errors/order.ts Normal file
View file

@ -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;