Merge pull request #410 from mirumee/ref/do-not-format-errors-in-forms
Do not store errors in form component
This commit is contained in:
commit
16291446a0
85 changed files with 2242 additions and 778 deletions
|
@ -35,6 +35,7 @@ All notable, unreleased changes to this project will be documented in this file.
|
|||
- Use structurized JSON files instead of PO - #403 by @dominik-zeglen
|
||||
- Remove PO files from repo and update translations #409 by @dominik-zeglen
|
||||
- Add optional chaining and explicitely return "Not found" page - #408 by @dominik-zeglen
|
||||
- Do not store errors in form component - #410 by @dominik-zeglen
|
||||
|
||||
## 2.0.0
|
||||
|
||||
|
|
|
@ -10,15 +10,16 @@ import ControlledCheckbox from "@saleor/components/ControlledCheckbox";
|
|||
import FormSpacer from "@saleor/components/FormSpacer";
|
||||
import SingleSelectField from "@saleor/components/SingleSelectField";
|
||||
import { commonMessages } from "@saleor/intl";
|
||||
import { FormErrors } from "@saleor/types";
|
||||
import { UserError } from "@saleor/types";
|
||||
import { AttributeInputTypeEnum } from "@saleor/types/globalTypes";
|
||||
import { getFieldError } from "@saleor/utils/errors";
|
||||
import { AttributePageFormData } from "../AttributePage";
|
||||
|
||||
export interface AttributeDetailsProps {
|
||||
canChangeType: boolean;
|
||||
data: AttributePageFormData;
|
||||
disabled: boolean;
|
||||
errors: FormErrors<"name" | "slug" | "inputType">;
|
||||
errors: UserError[];
|
||||
onChange: (event: React.ChangeEvent<any>) => void;
|
||||
}
|
||||
|
||||
|
@ -55,21 +56,21 @@ const AttributeDetails: React.FC<AttributeDetailsProps> = ({
|
|||
<CardContent>
|
||||
<TextField
|
||||
disabled={disabled}
|
||||
error={!!errors.name}
|
||||
error={!!getFieldError(errors, "name")}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Default Label",
|
||||
description: "attribute's label"
|
||||
})}
|
||||
name={"name" as keyof AttributePageFormData}
|
||||
fullWidth
|
||||
helperText={errors.name}
|
||||
helperText={getFieldError(errors, "name")?.message}
|
||||
value={data.name}
|
||||
onChange={onChange}
|
||||
/>
|
||||
<FormSpacer />
|
||||
<TextField
|
||||
disabled={disabled}
|
||||
error={!!errors.slug}
|
||||
error={!!getFieldError(errors, "slug")}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Attribute Code",
|
||||
description: "attribute's slug short code label"
|
||||
|
@ -78,7 +79,7 @@ const AttributeDetails: React.FC<AttributeDetailsProps> = ({
|
|||
placeholder={slugify(data.name).toLowerCase()}
|
||||
fullWidth
|
||||
helperText={
|
||||
errors.slug ||
|
||||
getFieldError(errors, "slug")?.message ||
|
||||
intl.formatMessage({
|
||||
defaultMessage:
|
||||
"This is used internally. Make sure you don’t use spaces",
|
||||
|
@ -92,8 +93,8 @@ const AttributeDetails: React.FC<AttributeDetailsProps> = ({
|
|||
<SingleSelectField
|
||||
choices={inputTypeChoices}
|
||||
disabled={disabled || !canChangeType}
|
||||
error={!!errors.inputType}
|
||||
hint={errors.inputType}
|
||||
error={!!getFieldError(errors, "inputType")}
|
||||
hint={getFieldError(errors, "inputType")?.message}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Catalog Input type for Store Owner",
|
||||
description: "attribute's editor component"
|
||||
|
|
|
@ -108,8 +108,8 @@ const AttributePage: React.FC<AttributePageProps> = ({
|
|||
});
|
||||
|
||||
return (
|
||||
<Form errors={errors} initial={initialForm} onSubmit={handleSubmit}>
|
||||
{({ change, errors: formErrors, data, submit }) => (
|
||||
<Form initial={initialForm} onSubmit={handleSubmit}>
|
||||
{({ change, data, submit }) => (
|
||||
<Container>
|
||||
<AppHeader onBack={onBack}>
|
||||
{intl.formatMessage(sectionNames.attributes)}
|
||||
|
@ -130,7 +130,7 @@ const AttributePage: React.FC<AttributePageProps> = ({
|
|||
canChangeType={attribute === null}
|
||||
data={data}
|
||||
disabled={disabled}
|
||||
errors={formErrors}
|
||||
errors={errors}
|
||||
onChange={change}
|
||||
/>
|
||||
<CardSpacer />
|
||||
|
@ -146,7 +146,7 @@ const AttributePage: React.FC<AttributePageProps> = ({
|
|||
<div>
|
||||
<AttributeProperties
|
||||
data={data}
|
||||
errors={formErrors}
|
||||
errors={errors}
|
||||
disabled={disabled}
|
||||
onChange={change}
|
||||
/>
|
||||
|
|
|
@ -11,13 +11,14 @@ import ControlledCheckbox from "@saleor/components/ControlledCheckbox";
|
|||
import FormSpacer from "@saleor/components/FormSpacer";
|
||||
import Hr from "@saleor/components/Hr";
|
||||
import { commonMessages } from "@saleor/intl";
|
||||
import { FormErrors } from "@saleor/types";
|
||||
import { UserError } from "@saleor/types";
|
||||
import { getFieldError } from "@saleor/utils/errors";
|
||||
import { AttributePageFormData } from "../AttributePage";
|
||||
|
||||
export interface AttributePropertiesProps {
|
||||
data: AttributePageFormData;
|
||||
disabled: boolean;
|
||||
errors: FormErrors<"storefrontSearchPosition">;
|
||||
errors: UserError[];
|
||||
onChange: (event: React.ChangeEvent<any>) => void;
|
||||
}
|
||||
|
||||
|
@ -85,9 +86,11 @@ const AttributeProperties: React.FC<AttributePropertiesProps> = ({
|
|||
{data.filterableInStorefront && (
|
||||
<TextField
|
||||
disabled={disabled}
|
||||
error={!!errors.storefrontSearchPosition}
|
||||
error={!!getFieldError(errors, "storefrontSearchPosition")}
|
||||
fullWidth
|
||||
helperText={errors.storefrontSearchPosition}
|
||||
helperText={
|
||||
getFieldError(errors, "storefrontSearchPosition")?.message
|
||||
}
|
||||
name={"storefrontSearchPosition" as keyof AttributePageFormData}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Position in faceted navigation",
|
||||
|
|
|
@ -15,6 +15,7 @@ import useModalDialogErrors from "@saleor/hooks/useModalDialogErrors";
|
|||
import { buttonMessages } from "@saleor/intl";
|
||||
import { maybe } from "@saleor/misc";
|
||||
import { UserError } from "@saleor/types";
|
||||
import { getFieldError } from "@saleor/utils/errors";
|
||||
import { AttributeDetails_attribute_values } from "../../types/AttributeDetails";
|
||||
|
||||
export interface AttributeValueEditDialogFormData {
|
||||
|
@ -60,16 +61,16 @@ const AttributeValueEditDialog: React.FC<AttributeValueEditDialogProps> = ({
|
|||
/>
|
||||
)}
|
||||
</DialogTitle>
|
||||
<Form errors={errors} initial={initialForm} onSubmit={onSubmit}>
|
||||
{({ change, data, errors: formErrors, submit }) => (
|
||||
<Form initial={initialForm} onSubmit={onSubmit}>
|
||||
{({ change, data, submit }) => (
|
||||
<>
|
||||
<DialogContent>
|
||||
<TextField
|
||||
autoFocus
|
||||
disabled={disabled}
|
||||
error={!!formErrors.name}
|
||||
error={!!getFieldError(errors, "name")}
|
||||
fullWidth
|
||||
helperText={formErrors.name}
|
||||
helperText={getFieldError(errors, "name")?.message}
|
||||
name={"name" as keyof AttributeValueEditDialogFormData}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Name",
|
||||
|
|
|
@ -40,18 +40,13 @@ export const CategoryCreatePage: React.FC<CategoryCreatePageProps> = ({
|
|||
disabled,
|
||||
onSubmit,
|
||||
onBack,
|
||||
errors: userErrors,
|
||||
errors,
|
||||
saveButtonBarState
|
||||
}) => {
|
||||
const intl = useIntl();
|
||||
return (
|
||||
<Form
|
||||
onSubmit={onSubmit}
|
||||
initial={initialData}
|
||||
errors={userErrors}
|
||||
confirmLeave
|
||||
>
|
||||
{({ data, change, errors, submit, hasChanged }) => (
|
||||
<Form onSubmit={onSubmit} initial={initialData} confirmLeave>
|
||||
{({ data, change, submit, hasChanged }) => (
|
||||
<Container>
|
||||
<AppHeader onBack={onBack}>
|
||||
{intl.formatMessage(sectionNames.categories)}
|
||||
|
|
|
@ -9,6 +9,8 @@ import CardTitle from "@saleor/components/CardTitle";
|
|||
import FormSpacer from "@saleor/components/FormSpacer";
|
||||
import RichTextEditor from "@saleor/components/RichTextEditor";
|
||||
import { commonMessages } from "@saleor/intl";
|
||||
import { UserError } from "@saleor/types";
|
||||
import { getFieldError } from "@saleor/utils/errors";
|
||||
import { maybe } from "../../../misc";
|
||||
import { CategoryDetails_category } from "../../types/CategoryDetails";
|
||||
|
||||
|
@ -19,7 +21,7 @@ interface CategoryDetailsFormProps {
|
|||
description: RawDraftContentState;
|
||||
};
|
||||
disabled: boolean;
|
||||
errors: { [key: string]: string };
|
||||
errors: UserError[];
|
||||
onChange: (event: React.ChangeEvent<any>) => void;
|
||||
}
|
||||
|
||||
|
@ -47,16 +49,16 @@ export const CategoryDetailsForm: React.FC<CategoryDetailsFormProps> = ({
|
|||
disabled={disabled}
|
||||
value={data && data.name}
|
||||
onChange={onChange}
|
||||
error={!!errors.name}
|
||||
helperText={errors.name}
|
||||
error={!!getFieldError(errors, "name")}
|
||||
helperText={getFieldError(errors, "name")?.message}
|
||||
fullWidth
|
||||
/>
|
||||
</div>
|
||||
<FormSpacer />
|
||||
<RichTextEditor
|
||||
disabled={disabled}
|
||||
error={!!errors.descriptionJson}
|
||||
helperText={errors.descriptionJson}
|
||||
error={!!getFieldError(errors, "descriptionJson")}
|
||||
helperText={getFieldError(errors, "descriptionJson")?.message}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Category Description"
|
||||
})}
|
||||
|
|
|
@ -75,7 +75,7 @@ export const CategoryUpdatePage: React.FC<CategoryUpdatePageProps> = ({
|
|||
currentTab,
|
||||
category,
|
||||
disabled,
|
||||
errors: userErrors,
|
||||
errors,
|
||||
pageInfo,
|
||||
products,
|
||||
saveButtonBarState,
|
||||
|
@ -115,13 +115,8 @@ export const CategoryUpdatePage: React.FC<CategoryUpdatePageProps> = ({
|
|||
seoTitle: ""
|
||||
};
|
||||
return (
|
||||
<Form
|
||||
onSubmit={onSubmit}
|
||||
initial={initialData}
|
||||
errors={userErrors}
|
||||
confirmLeave
|
||||
>
|
||||
{({ data, change, errors, submit, hasChanged }) => (
|
||||
<Form onSubmit={onSubmit} initial={initialData} confirmLeave>
|
||||
{({ data, change, submit, hasChanged }) => (
|
||||
<Container>
|
||||
<AppHeader onBack={onBack}>
|
||||
{intl.formatMessage(sectionNames.categories)}
|
||||
|
|
|
@ -68,8 +68,8 @@ const CollectionCreatePage: React.FC<CollectionCreatePageProps> = ({
|
|||
const localizeDate = useDateLocalize();
|
||||
|
||||
return (
|
||||
<Form errors={errors} initial={initialForm} onSubmit={onSubmit}>
|
||||
{({ change, data, errors: formErrors, hasChanged, submit }) => (
|
||||
<Form initial={initialForm} onSubmit={onSubmit}>
|
||||
{({ change, data, hasChanged, submit }) => (
|
||||
<Container>
|
||||
<AppHeader onBack={onBack}>
|
||||
{intl.formatMessage(sectionNames.collections)}
|
||||
|
@ -85,7 +85,7 @@ const CollectionCreatePage: React.FC<CollectionCreatePageProps> = ({
|
|||
<CollectionDetails
|
||||
data={data}
|
||||
disabled={disabled}
|
||||
errors={formErrors}
|
||||
errors={errors}
|
||||
onChange={change}
|
||||
/>
|
||||
<CardSpacer />
|
||||
|
@ -147,7 +147,7 @@ const CollectionCreatePage: React.FC<CollectionCreatePageProps> = ({
|
|||
<CardContent>
|
||||
<VisibilityCard
|
||||
data={data}
|
||||
errors={formErrors}
|
||||
errors={errors}
|
||||
disabled={disabled}
|
||||
hiddenMessage={intl.formatMessage(
|
||||
{
|
||||
|
|
|
@ -10,7 +10,8 @@ import FormSpacer from "@saleor/components/FormSpacer";
|
|||
import RichTextEditor from "@saleor/components/RichTextEditor";
|
||||
import { commonMessages } from "@saleor/intl";
|
||||
import { maybe } from "@saleor/misc";
|
||||
import { FormErrors } from "@saleor/types";
|
||||
import { UserError } from "@saleor/types";
|
||||
import { getFieldError } from "@saleor/utils/errors";
|
||||
import { CollectionDetails_collection } from "../../types/CollectionDetails";
|
||||
|
||||
export interface CollectionDetailsProps {
|
||||
|
@ -20,7 +21,7 @@ export interface CollectionDetailsProps {
|
|||
name: string;
|
||||
};
|
||||
disabled: boolean;
|
||||
errors: FormErrors<"descriptionJson" | "name">;
|
||||
errors: UserError[];
|
||||
onChange: (event: React.ChangeEvent<any>) => void;
|
||||
}
|
||||
|
||||
|
@ -48,14 +49,14 @@ const CollectionDetails: React.FC<CollectionDetailsProps> = ({
|
|||
disabled={disabled}
|
||||
value={data.name}
|
||||
onChange={onChange}
|
||||
error={!!errors.name}
|
||||
helperText={errors.name}
|
||||
error={!!getFieldError(errors, "name")}
|
||||
helperText={getFieldError(errors, "name")?.message}
|
||||
fullWidth
|
||||
/>
|
||||
<FormSpacer />
|
||||
<RichTextEditor
|
||||
error={!!errors.descriptionJson}
|
||||
helperText={errors.descriptionJson}
|
||||
error={!!getFieldError(errors, "descriptionJson")}
|
||||
helperText={getFieldError(errors, "descriptionJson")?.message}
|
||||
initial={maybe(() => JSON.parse(collection.descriptionJson))}
|
||||
label={intl.formatMessage(commonMessages.description)}
|
||||
name="description"
|
||||
|
|
|
@ -18,7 +18,7 @@ import VisibilityCard from "@saleor/components/VisibilityCard";
|
|||
import useDateLocalize from "@saleor/hooks/useDateLocalize";
|
||||
import { sectionNames } from "@saleor/intl";
|
||||
import { maybe } from "../../../misc";
|
||||
import { ListActions, PageListProps } from "../../../types";
|
||||
import { ListActions, PageListProps, UserError } from "../../../types";
|
||||
import { CollectionDetails_collection } from "../../types/CollectionDetails";
|
||||
import CollectionDetails from "../CollectionDetails/CollectionDetails";
|
||||
import { CollectionImage } from "../CollectionImage/CollectionImage";
|
||||
|
@ -37,6 +37,7 @@ export interface CollectionDetailsPageFormData {
|
|||
|
||||
export interface CollectionDetailsPageProps extends PageListProps, ListActions {
|
||||
collection: CollectionDetails_collection;
|
||||
errors: UserError[];
|
||||
isFeatured: boolean;
|
||||
saveButtonBarState: ConfirmButtonTransitionState;
|
||||
onBack: () => void;
|
||||
|
@ -50,6 +51,7 @@ export interface CollectionDetailsPageProps extends PageListProps, ListActions {
|
|||
const CollectionDetailsPage: React.FC<CollectionDetailsPageProps> = ({
|
||||
collection,
|
||||
disabled,
|
||||
errors,
|
||||
isFeatured,
|
||||
saveButtonBarState,
|
||||
onBack,
|
||||
|
@ -77,7 +79,7 @@ const CollectionDetailsPage: React.FC<CollectionDetailsPageProps> = ({
|
|||
onSubmit={onSubmit}
|
||||
confirmLeave
|
||||
>
|
||||
{({ change, data, errors: formErrors, hasChanged, submit }) => (
|
||||
{({ change, data, hasChanged, submit }) => (
|
||||
<Container>
|
||||
<AppHeader onBack={onBack}>
|
||||
{intl.formatMessage(sectionNames.collections)}
|
||||
|
@ -89,7 +91,7 @@ const CollectionDetailsPage: React.FC<CollectionDetailsPageProps> = ({
|
|||
collection={collection}
|
||||
data={data}
|
||||
disabled={disabled}
|
||||
errors={formErrors}
|
||||
errors={errors}
|
||||
onChange={change}
|
||||
/>
|
||||
<CardSpacer />
|
||||
|
@ -124,7 +126,7 @@ const CollectionDetailsPage: React.FC<CollectionDetailsPageProps> = ({
|
|||
<div>
|
||||
<VisibilityCard
|
||||
data={data}
|
||||
errors={formErrors}
|
||||
errors={errors}
|
||||
disabled={disabled}
|
||||
hiddenMessage={intl.formatMessage(
|
||||
{
|
||||
|
|
|
@ -205,6 +205,9 @@ export const CollectionDetails: React.FC<CollectionDetailsProps> = ({
|
|||
onBack={handleBack}
|
||||
disabled={loading}
|
||||
collection={maybe(() => data.collection)}
|
||||
errors={
|
||||
updateCollection.opts?.data?.collectionUpdate.errors || []
|
||||
}
|
||||
isFeatured={maybe(
|
||||
() =>
|
||||
data.shop.homepageCollection.id === data.collection.id,
|
||||
|
|
|
@ -5,7 +5,8 @@ import { useIntl } from "react-intl";
|
|||
|
||||
import { AddressTypeInput } from "@saleor/customers/types";
|
||||
import { commonMessages } from "@saleor/intl";
|
||||
import { FormErrors } from "@saleor/types";
|
||||
import { UserError } from "@saleor/types";
|
||||
import { getFieldError } from "@saleor/utils/errors";
|
||||
import FormSpacer from "../FormSpacer";
|
||||
import SingleAutocompleteSelectField, {
|
||||
SingleAutocompleteChoiceType
|
||||
|
@ -27,7 +28,7 @@ interface AddressEditProps {
|
|||
countryDisplayValue: string;
|
||||
data: AddressTypeInput;
|
||||
disabled?: boolean;
|
||||
errors: FormErrors<keyof AddressTypeInput>;
|
||||
errors: UserError[];
|
||||
onChange(event: React.ChangeEvent<any>);
|
||||
onCountryChange(event: React.ChangeEvent<any>);
|
||||
}
|
||||
|
@ -52,8 +53,8 @@ const AddressEdit: React.FC<AddressEditProps> = props => {
|
|||
<div>
|
||||
<TextField
|
||||
disabled={disabled}
|
||||
error={!!errors.firstName}
|
||||
helperText={errors.firstName}
|
||||
error={!!getFieldError(errors, "firstName")}
|
||||
helperText={getFieldError(errors, "firstName")?.message}
|
||||
label={intl.formatMessage(commonMessages.firstName)}
|
||||
name="firstName"
|
||||
onChange={onChange}
|
||||
|
@ -64,8 +65,8 @@ const AddressEdit: React.FC<AddressEditProps> = props => {
|
|||
<div>
|
||||
<TextField
|
||||
disabled={disabled}
|
||||
error={!!errors.lastName}
|
||||
helperText={errors.lastName}
|
||||
error={!!getFieldError(errors, "lastName")}
|
||||
helperText={getFieldError(errors, "lastName")?.message}
|
||||
label={intl.formatMessage(commonMessages.lastName)}
|
||||
name="lastName"
|
||||
onChange={onChange}
|
||||
|
@ -79,8 +80,8 @@ const AddressEdit: React.FC<AddressEditProps> = props => {
|
|||
<div>
|
||||
<TextField
|
||||
disabled={disabled}
|
||||
error={!!errors.companyName}
|
||||
helperText={errors.companyName}
|
||||
error={!!getFieldError(errors, "companyName")}
|
||||
helperText={getFieldError(errors, "companyName")?.message}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Company"
|
||||
})}
|
||||
|
@ -93,9 +94,9 @@ const AddressEdit: React.FC<AddressEditProps> = props => {
|
|||
<div>
|
||||
<TextField
|
||||
disabled={disabled}
|
||||
error={!!errors.phone}
|
||||
error={!!getFieldError(errors, "phone")}
|
||||
fullWidth
|
||||
helperText={errors.phone}
|
||||
helperText={getFieldError(errors, "phone")?.message}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Phone"
|
||||
})}
|
||||
|
@ -108,8 +109,8 @@ const AddressEdit: React.FC<AddressEditProps> = props => {
|
|||
<FormSpacer />
|
||||
<TextField
|
||||
disabled={disabled}
|
||||
error={!!errors.streetAddress1}
|
||||
helperText={errors.streetAddress1}
|
||||
error={!!getFieldError(errors, "streetAddress1")}
|
||||
helperText={getFieldError(errors, "streetAddress1")?.message}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Address line 1"
|
||||
})}
|
||||
|
@ -121,8 +122,8 @@ const AddressEdit: React.FC<AddressEditProps> = props => {
|
|||
<FormSpacer />
|
||||
<TextField
|
||||
disabled={disabled}
|
||||
error={!!errors.streetAddress2}
|
||||
helperText={errors.streetAddress2}
|
||||
error={!!getFieldError(errors, "streetAddress2")}
|
||||
helperText={getFieldError(errors, "streetAddress2")?.message}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Address line 2"
|
||||
})}
|
||||
|
@ -136,8 +137,8 @@ const AddressEdit: React.FC<AddressEditProps> = props => {
|
|||
<div>
|
||||
<TextField
|
||||
disabled={disabled}
|
||||
error={!!errors.city}
|
||||
helperText={errors.city}
|
||||
error={!!getFieldError(errors, "city")}
|
||||
helperText={getFieldError(errors, "city")?.message}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "City"
|
||||
})}
|
||||
|
@ -150,8 +151,8 @@ const AddressEdit: React.FC<AddressEditProps> = props => {
|
|||
<div>
|
||||
<TextField
|
||||
disabled={disabled}
|
||||
error={!!errors.postalCode}
|
||||
helperText={errors.postalCode}
|
||||
error={!!getFieldError(errors, "postalCode")}
|
||||
helperText={getFieldError(errors, "postalCode")?.message}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "ZIP / Postal code"
|
||||
})}
|
||||
|
@ -169,8 +170,8 @@ const AddressEdit: React.FC<AddressEditProps> = props => {
|
|||
<SingleAutocompleteSelectField
|
||||
disabled={disabled}
|
||||
displayValue={countryDisplayValue}
|
||||
error={!!errors.country}
|
||||
helperText={errors.country}
|
||||
error={!!getFieldError(errors, "country")}
|
||||
helperText={getFieldError(errors, "country")?.message}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Country"
|
||||
})}
|
||||
|
@ -186,8 +187,8 @@ const AddressEdit: React.FC<AddressEditProps> = props => {
|
|||
<div>
|
||||
<TextField
|
||||
disabled={disabled}
|
||||
error={!!errors.countryArea}
|
||||
helperText={errors.countryArea}
|
||||
error={!!getFieldError(errors, "countryArea")}
|
||||
helperText={getFieldError(errors, "countryArea")?.message}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Country area"
|
||||
})}
|
||||
|
|
|
@ -68,7 +68,7 @@ export const EditableTableCell: React.FC<EditableTableCellProps> = props => {
|
|||
};
|
||||
|
||||
const [opened, setOpenStatus] = React.useState(focused);
|
||||
const { change, data } = useForm({ value }, [], handleConfirm);
|
||||
const { change, data } = useForm({ value }, handleConfirm);
|
||||
const enable = () => setOpenStatus(true);
|
||||
const disable = () => setOpenStatus(false);
|
||||
|
||||
|
|
|
@ -1,20 +1,18 @@
|
|||
import React from "react";
|
||||
|
||||
import useForm, { UseFormResult } from "@saleor/hooks/useForm";
|
||||
import { UserError } from "@saleor/types";
|
||||
|
||||
export interface FormProps<T> {
|
||||
children: (props: UseFormResult<T>) => React.ReactNode;
|
||||
confirmLeave?: boolean;
|
||||
errors?: UserError[];
|
||||
initial?: T;
|
||||
resetOnSubmit?: boolean;
|
||||
onSubmit?: (data: T) => void;
|
||||
}
|
||||
|
||||
function Form<T>(props: FormProps<T>) {
|
||||
const { children, errors, initial, resetOnSubmit, onSubmit } = props;
|
||||
const renderProps = useForm(initial, errors, onSubmit);
|
||||
const { children, initial, resetOnSubmit, onSubmit } = props;
|
||||
const renderProps = useForm(initial, onSubmit);
|
||||
|
||||
function handleSubmit(event?: React.FormEvent<any>, cb?: () => void) {
|
||||
const { reset, submit } = renderProps;
|
||||
|
|
|
@ -8,7 +8,8 @@ import { useIntl } from "react-intl";
|
|||
|
||||
import CardTitle from "@saleor/components/CardTitle";
|
||||
import RadioSwitchField from "@saleor/components/RadioSwitchField";
|
||||
import { FormErrors } from "@saleor/types";
|
||||
import { UserError } from "@saleor/types";
|
||||
import { getFieldError } from "@saleor/utils/errors";
|
||||
import { DateContext } from "../Date/DateContext";
|
||||
import FormSpacer from "../FormSpacer";
|
||||
|
||||
|
@ -52,7 +53,7 @@ interface VisibilityCardProps {
|
|||
isPublished: boolean;
|
||||
publicationDate: string;
|
||||
};
|
||||
errors: FormErrors<"isPublished" | "publicationDate">;
|
||||
errors: UserError[];
|
||||
disabled?: boolean;
|
||||
hiddenMessage: string;
|
||||
onChange: (event: React.ChangeEvent<any>) => void;
|
||||
|
@ -62,7 +63,6 @@ interface VisibilityCardProps {
|
|||
export const VisibilityCard: React.FC<VisibilityCardProps> = props => {
|
||||
const {
|
||||
children,
|
||||
|
||||
data: { isPublished, publicationDate },
|
||||
errors,
|
||||
disabled,
|
||||
|
@ -101,7 +101,7 @@ export const VisibilityCard: React.FC<VisibilityCardProps> = props => {
|
|||
<CardContent>
|
||||
<RadioSwitchField
|
||||
disabled={disabled}
|
||||
error={!!errors.isPublished}
|
||||
error={!!getFieldError(errors, "isPublished")}
|
||||
firstOptionLabel={
|
||||
<>
|
||||
<p className={classes.label}>
|
||||
|
@ -140,7 +140,7 @@ export const VisibilityCard: React.FC<VisibilityCardProps> = props => {
|
|||
)}
|
||||
{isPublicationDate && (
|
||||
<TextField
|
||||
error={!!errors.publicationDate}
|
||||
error={!!getFieldError(errors, "publicationDate")}
|
||||
disabled={disabled}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Publish on",
|
||||
|
@ -149,7 +149,7 @@ export const VisibilityCard: React.FC<VisibilityCardProps> = props => {
|
|||
name="publicationDate"
|
||||
type="date"
|
||||
fullWidth={true}
|
||||
helperText={errors.publicationDate}
|
||||
helperText={getFieldError(errors, "publicationDate")?.message}
|
||||
value={publicationDate ? publicationDate : ""}
|
||||
onChange={onChange}
|
||||
className={classes.date}
|
||||
|
@ -160,10 +160,12 @@ export const VisibilityCard: React.FC<VisibilityCardProps> = props => {
|
|||
)}
|
||||
</>
|
||||
)}
|
||||
{errors.isPublished && (
|
||||
{getFieldError(errors, "isPublished") && (
|
||||
<>
|
||||
<FormSpacer />
|
||||
<Typography color="error">{errors.isPublished}</Typography>
|
||||
<Typography color="error">
|
||||
{getFieldError(errors, "isPublished")?.message}
|
||||
</Typography>
|
||||
</>
|
||||
)}
|
||||
<div className={classes.children}>{children}</div>
|
||||
|
|
|
@ -43,7 +43,10 @@ const styles = createStyles({
|
|||
}
|
||||
});
|
||||
|
||||
const CustomerAddressDialog = withStyles(styles, {})(
|
||||
const CustomerAddressDialog = withStyles(
|
||||
styles,
|
||||
{}
|
||||
)(
|
||||
({
|
||||
address,
|
||||
classes,
|
||||
|
@ -98,12 +101,8 @@ const CustomerAddressDialog = withStyles(styles, {})(
|
|||
fullWidth
|
||||
maxWidth="sm"
|
||||
>
|
||||
<Form
|
||||
initial={initialForm}
|
||||
errors={dialogErrors}
|
||||
onSubmit={handleSubmit}
|
||||
>
|
||||
{({ change, data, errors: formErrors }) => {
|
||||
<Form initial={initialForm} onSubmit={handleSubmit}>
|
||||
{({ change, data }) => {
|
||||
const handleCountrySelect = createSingleAutocompleteSelectHandler(
|
||||
change,
|
||||
setCountryDisplayName,
|
||||
|
@ -130,7 +129,7 @@ const CustomerAddressDialog = withStyles(styles, {})(
|
|||
countries={countryChoices}
|
||||
data={data}
|
||||
countryDisplayValue={countryDisplayName}
|
||||
errors={formErrors}
|
||||
errors={dialogErrors}
|
||||
onChange={change}
|
||||
onCountryChange={handleCountrySelect}
|
||||
/>
|
||||
|
|
|
@ -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 { FormErrors } from "../../../types";
|
||||
import { UserError } from "../../../types";
|
||||
import { AddressTypeInput } from "../../types";
|
||||
|
||||
const useStyles = makeStyles(
|
||||
|
@ -26,7 +26,7 @@ export interface CustomerCreateAddressProps {
|
|||
countryDisplayName: string;
|
||||
data: AddressTypeInput;
|
||||
disabled: boolean;
|
||||
errors: FormErrors<keyof AddressTypeInput>;
|
||||
errors: UserError[];
|
||||
onChange(event: React.ChangeEvent<any>);
|
||||
onCountryChange(event: React.ChangeEvent<any>);
|
||||
}
|
||||
|
|
|
@ -7,7 +7,8 @@ import { useIntl } from "react-intl";
|
|||
|
||||
import CardTitle from "@saleor/components/CardTitle";
|
||||
import { commonMessages } from "@saleor/intl";
|
||||
import { FormErrors } from "../../../types";
|
||||
import { getFieldError } from "@saleor/utils/errors";
|
||||
import { UserError } from "../../../types";
|
||||
import { CustomerCreatePageFormData } from "../CustomerCreatePage";
|
||||
|
||||
const useStyles = makeStyles(
|
||||
|
@ -25,7 +26,7 @@ const useStyles = makeStyles(
|
|||
export interface CustomerCreateDetailsProps {
|
||||
data: CustomerCreatePageFormData;
|
||||
disabled: boolean;
|
||||
errors: FormErrors<"customerFirstName" | "customerLastName" | "email">;
|
||||
errors: UserError[];
|
||||
onChange: (event: React.ChangeEvent<any>) => void;
|
||||
}
|
||||
|
||||
|
@ -47,33 +48,33 @@ const CustomerCreateDetails: React.FC<CustomerCreateDetailsProps> = props => {
|
|||
<div className={classes.root}>
|
||||
<TextField
|
||||
disabled={disabled}
|
||||
error={!!errors.customerFirstName}
|
||||
error={!!getFieldError(errors, "customerFirstName")}
|
||||
fullWidth
|
||||
name="customerFirstName"
|
||||
label={intl.formatMessage(commonMessages.firstName)}
|
||||
helperText={errors.customerFirstName}
|
||||
helperText={getFieldError(errors, "customerFirstName")?.message}
|
||||
type="text"
|
||||
value={data.customerFirstName}
|
||||
onChange={onChange}
|
||||
/>
|
||||
<TextField
|
||||
disabled={disabled}
|
||||
error={!!errors.customerLastName}
|
||||
error={!!getFieldError(errors, "customerLastName")}
|
||||
fullWidth
|
||||
name="customerLastName"
|
||||
label={intl.formatMessage(commonMessages.lastName)}
|
||||
helperText={errors.customerLastName}
|
||||
helperText={getFieldError(errors, "customerLastName")?.message}
|
||||
type="text"
|
||||
value={data.customerLastName}
|
||||
onChange={onChange}
|
||||
/>
|
||||
<TextField
|
||||
disabled={disabled}
|
||||
error={!!errors.email}
|
||||
error={!!getFieldError(errors, "email")}
|
||||
fullWidth
|
||||
name="email"
|
||||
label={intl.formatMessage(commonMessages.email)}
|
||||
helperText={errors.email}
|
||||
helperText={getFieldError(errors, "email")?.message}
|
||||
type="email"
|
||||
value={data.email}
|
||||
onChange={onChange}
|
||||
|
|
|
@ -7,15 +7,15 @@ 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";
|
||||
|
||||
export interface CustomerCreateNoteProps {
|
||||
data: {
|
||||
note: string;
|
||||
};
|
||||
disabled: boolean;
|
||||
errors: Partial<{
|
||||
note: string;
|
||||
}>;
|
||||
errors: UserError[];
|
||||
onChange: (event: React.ChangeEvent<any>) => void;
|
||||
}
|
||||
|
||||
|
@ -42,11 +42,11 @@ const CustomerCreateNote: React.FC<CustomerCreateNoteProps> = ({
|
|||
<FormSpacer />
|
||||
<TextField
|
||||
disabled={disabled}
|
||||
error={!!errors.note}
|
||||
error={!!getFieldError(errors, "note")}
|
||||
fullWidth
|
||||
multiline
|
||||
name="note"
|
||||
helperText={errors.note}
|
||||
helperText={getFieldError(errors, "note")?.message}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Note",
|
||||
description: "note about customer"
|
||||
|
|
|
@ -61,7 +61,7 @@ export interface CustomerCreatePageProps {
|
|||
const CustomerCreatePage: React.FC<CustomerCreatePageProps> = ({
|
||||
countries,
|
||||
disabled,
|
||||
errors,
|
||||
errors: apiErrors,
|
||||
saveButtonBar,
|
||||
onBack,
|
||||
onSubmit
|
||||
|
@ -98,6 +98,8 @@ const CustomerCreatePage: React.FC<CustomerCreatePageProps> = ({
|
|||
})
|
||||
);
|
||||
|
||||
const errors = [...apiErrors, ...validationErrors];
|
||||
|
||||
const handleSubmit = (
|
||||
formData: CustomerCreatePageFormData & AddressTypeInput
|
||||
) => {
|
||||
|
@ -130,13 +132,8 @@ const CustomerCreatePage: React.FC<CustomerCreatePageProps> = ({
|
|||
};
|
||||
|
||||
return (
|
||||
<Form
|
||||
initial={initialForm}
|
||||
onSubmit={handleSubmit}
|
||||
errors={[...errors, ...validationErrors]}
|
||||
confirmLeave
|
||||
>
|
||||
{({ change, data, errors: formErrors, hasChanged, submit }) => {
|
||||
<Form initial={initialForm} onSubmit={handleSubmit} confirmLeave>
|
||||
{({ change, data, hasChanged, submit }) => {
|
||||
const handleCountrySelect = createSingleAutocompleteSelectHandler(
|
||||
change,
|
||||
setCountryDisplayName,
|
||||
|
@ -159,7 +156,7 @@ const CustomerCreatePage: React.FC<CustomerCreatePageProps> = ({
|
|||
<CustomerCreateDetails
|
||||
data={data}
|
||||
disabled={disabled}
|
||||
errors={formErrors}
|
||||
errors={errors}
|
||||
onChange={change}
|
||||
/>
|
||||
<CardSpacer />
|
||||
|
@ -168,7 +165,7 @@ const CustomerCreatePage: React.FC<CustomerCreatePageProps> = ({
|
|||
countryDisplayName={countryDisplayName}
|
||||
data={data}
|
||||
disabled={disabled}
|
||||
errors={formErrors}
|
||||
errors={errors}
|
||||
onChange={change}
|
||||
onCountryChange={handleCountrySelect}
|
||||
/>
|
||||
|
@ -176,7 +173,7 @@ const CustomerCreatePage: React.FC<CustomerCreatePageProps> = ({
|
|||
<CustomerCreateNote
|
||||
data={data}
|
||||
disabled={disabled}
|
||||
errors={formErrors}
|
||||
errors={errors}
|
||||
onChange={change}
|
||||
/>
|
||||
</div>
|
||||
|
|
|
@ -11,7 +11,8 @@ import CardTitle from "@saleor/components/CardTitle";
|
|||
import { ControlledCheckbox } from "@saleor/components/ControlledCheckbox";
|
||||
import Skeleton from "@saleor/components/Skeleton";
|
||||
import { maybe } from "@saleor/misc";
|
||||
import { FormErrors } from "@saleor/types";
|
||||
import { UserError } from "@saleor/types";
|
||||
import { getFieldError } from "@saleor/utils/errors";
|
||||
import { CustomerDetails_user } from "../../types/CustomerDetails";
|
||||
|
||||
const useStyles = makeStyles(
|
||||
|
@ -39,7 +40,7 @@ export interface CustomerDetailsProps {
|
|||
note: string;
|
||||
};
|
||||
disabled: boolean;
|
||||
errors: FormErrors<"isActive" | "note">;
|
||||
errors: UserError[];
|
||||
onChange: (event: React.ChangeEvent<any>) => void;
|
||||
}
|
||||
|
||||
|
@ -90,10 +91,10 @@ const CustomerDetails: React.FC<CustomerDetailsProps> = props => {
|
|||
/>
|
||||
<TextField
|
||||
disabled={disabled}
|
||||
error={!!errors.note}
|
||||
error={!!getFieldError(errors, "note")}
|
||||
fullWidth
|
||||
multiline
|
||||
helperText={errors.note}
|
||||
helperText={getFieldError(errors, "note")?.message}
|
||||
name="note"
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Note",
|
||||
|
|
|
@ -56,7 +56,6 @@ const CustomerDetailsPage: React.FC<CustomerDetailsPageProps> = ({
|
|||
|
||||
return (
|
||||
<Form
|
||||
errors={errors}
|
||||
initial={{
|
||||
email: maybe(() => customer.email, ""),
|
||||
firstName: maybe(() => customer.firstName, ""),
|
||||
|
@ -67,7 +66,7 @@ const CustomerDetailsPage: React.FC<CustomerDetailsPageProps> = ({
|
|||
onSubmit={onSubmit}
|
||||
confirmLeave
|
||||
>
|
||||
{({ change, data, errors: formErrors, hasChanged, submit }) => (
|
||||
{({ change, data, hasChanged, submit }) => (
|
||||
<Container>
|
||||
<AppHeader onBack={onBack}>
|
||||
{intl.formatMessage(sectionNames.customers)}
|
||||
|
@ -79,14 +78,14 @@ const CustomerDetailsPage: React.FC<CustomerDetailsPageProps> = ({
|
|||
customer={customer}
|
||||
data={data}
|
||||
disabled={disabled}
|
||||
errors={formErrors}
|
||||
errors={errors}
|
||||
onChange={change}
|
||||
/>
|
||||
<CardSpacer />
|
||||
<CustomerInfo
|
||||
data={data}
|
||||
disabled={disabled}
|
||||
errors={formErrors}
|
||||
errors={errors}
|
||||
onChange={change}
|
||||
/>
|
||||
<CardSpacer />
|
||||
|
|
|
@ -10,6 +10,8 @@ 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";
|
||||
|
||||
const useStyles = makeStyles(
|
||||
theme => ({
|
||||
|
@ -33,11 +35,7 @@ export interface CustomerInfoProps {
|
|||
email: string;
|
||||
};
|
||||
disabled: boolean;
|
||||
errors: {
|
||||
firstName?: string;
|
||||
lastName?: string;
|
||||
email?: string;
|
||||
};
|
||||
errors: UserError[];
|
||||
onChange: (event: React.ChangeEvent<any>) => void;
|
||||
}
|
||||
|
||||
|
@ -64,9 +62,9 @@ const CustomerInfo: React.FC<CustomerInfoProps> = props => {
|
|||
<Grid variant="uniform">
|
||||
<TextField
|
||||
disabled={disabled}
|
||||
error={!!errors.firstName}
|
||||
error={!!getFieldError(errors, "firstName")}
|
||||
fullWidth
|
||||
helperText={errors.firstName}
|
||||
helperText={getFieldError(errors, "firstName")?.message}
|
||||
name="firstName"
|
||||
type="text"
|
||||
label={intl.formatMessage(commonMessages.firstName)}
|
||||
|
@ -75,9 +73,9 @@ const CustomerInfo: React.FC<CustomerInfoProps> = props => {
|
|||
/>
|
||||
<TextField
|
||||
disabled={disabled}
|
||||
error={!!errors.lastName}
|
||||
error={!!getFieldError(errors, "lastName")}
|
||||
fullWidth
|
||||
helperText={errors.lastName}
|
||||
helperText={getFieldError(errors, "lastName")?.message}
|
||||
name="lastName"
|
||||
type="text"
|
||||
label={intl.formatMessage(commonMessages.lastName)}
|
||||
|
@ -94,9 +92,9 @@ const CustomerInfo: React.FC<CustomerInfoProps> = props => {
|
|||
</Typography>
|
||||
<TextField
|
||||
disabled={disabled}
|
||||
error={!!errors.email}
|
||||
error={!!getFieldError(errors, "email")}
|
||||
fullWidth
|
||||
helperText={errors.email}
|
||||
helperText={getFieldError(errors, "email")?.message}
|
||||
name="email"
|
||||
type="email"
|
||||
label={intl.formatMessage(commonMessages.email)}
|
||||
|
|
|
@ -8,7 +8,8 @@ import CardTitle from "@saleor/components/CardTitle";
|
|||
import { ControlledCheckbox } from "@saleor/components/ControlledCheckbox";
|
||||
import Grid from "@saleor/components/Grid";
|
||||
import { commonMessages } from "@saleor/intl";
|
||||
import { FormErrors } from "../../../types";
|
||||
import { getFieldError } from "@saleor/utils/errors";
|
||||
import { UserError } from "../../../types";
|
||||
|
||||
interface DiscountDatesProps {
|
||||
data: {
|
||||
|
@ -20,7 +21,7 @@ interface DiscountDatesProps {
|
|||
};
|
||||
defaultCurrency: string;
|
||||
disabled: boolean;
|
||||
errors: FormErrors<"endDate" | "startDate">;
|
||||
errors: UserError[];
|
||||
onChange: (event: React.ChangeEvent<any>) => void;
|
||||
}
|
||||
|
||||
|
@ -44,8 +45,8 @@ const DiscountDates = ({
|
|||
<Grid variant="uniform">
|
||||
<TextField
|
||||
disabled={disabled}
|
||||
error={!!errors.startDate}
|
||||
helperText={errors.startDate}
|
||||
error={!!getFieldError(errors, "startDate")}
|
||||
helperText={getFieldError(errors, "startDate")?.message}
|
||||
name={"startDate" as keyof FormData}
|
||||
onChange={onChange}
|
||||
label={intl.formatMessage(commonMessages.startDate)}
|
||||
|
@ -58,8 +59,8 @@ const DiscountDates = ({
|
|||
/>
|
||||
<TextField
|
||||
disabled={disabled}
|
||||
error={!!errors.startDate}
|
||||
helperText={errors.startDate}
|
||||
error={!!getFieldError(errors, "startDate")}
|
||||
helperText={getFieldError(errors, "startDate")?.message}
|
||||
name={"startTime" as keyof FormData}
|
||||
onChange={onChange}
|
||||
label={intl.formatMessage(commonMessages.startHour)}
|
||||
|
@ -84,8 +85,8 @@ const DiscountDates = ({
|
|||
<Grid variant="uniform">
|
||||
<TextField
|
||||
disabled={disabled}
|
||||
error={!!errors.endDate}
|
||||
helperText={errors.endDate}
|
||||
error={!!getFieldError(errors, "endDate")}
|
||||
helperText={getFieldError(errors, "endDate")?.message}
|
||||
name={"endDate" as keyof FormData}
|
||||
onChange={onChange}
|
||||
label={intl.formatMessage(commonMessages.endDate)}
|
||||
|
@ -98,8 +99,8 @@ const DiscountDates = ({
|
|||
/>
|
||||
<TextField
|
||||
disabled={disabled}
|
||||
error={!!errors.endDate}
|
||||
helperText={errors.endDate}
|
||||
error={!!getFieldError(errors, "endDate")}
|
||||
helperText={getFieldError(errors, "endDate")?.message}
|
||||
name={"endTime" as keyof FormData}
|
||||
onChange={onChange}
|
||||
label={intl.formatMessage(commonMessages.endHour)}
|
||||
|
|
|
@ -57,8 +57,8 @@ const SaleCreatePage: React.FC<SaleCreatePageProps> = ({
|
|||
value: ""
|
||||
};
|
||||
return (
|
||||
<Form errors={errors} initial={initialForm} onSubmit={onSubmit}>
|
||||
{({ change, data, errors: formErrors, hasChanged, submit }) => (
|
||||
<Form initial={initialForm} onSubmit={onSubmit}>
|
||||
{({ change, data, hasChanged, submit }) => (
|
||||
<Container>
|
||||
<AppHeader onBack={onBack}>
|
||||
{intl.formatMessage(sectionNames.sales)}
|
||||
|
@ -74,7 +74,7 @@ const SaleCreatePage: React.FC<SaleCreatePageProps> = ({
|
|||
<SaleInfo
|
||||
data={data}
|
||||
disabled={disabled}
|
||||
errors={formErrors}
|
||||
errors={errors}
|
||||
onChange={change}
|
||||
/>
|
||||
<CardSpacer />
|
||||
|
@ -84,7 +84,7 @@ const SaleCreatePage: React.FC<SaleCreatePageProps> = ({
|
|||
data={data}
|
||||
disabled={disabled}
|
||||
defaultCurrency={defaultCurrency}
|
||||
errors={formErrors}
|
||||
errors={errors}
|
||||
onChange={change}
|
||||
/>
|
||||
</div>
|
||||
|
|
|
@ -121,8 +121,8 @@ const SaleDetailsPage: React.FC<SaleDetailsPageProps> = ({
|
|||
value: maybe(() => sale.value.toString(), "")
|
||||
};
|
||||
return (
|
||||
<Form errors={errors} initial={initialForm} onSubmit={onSubmit}>
|
||||
{({ change, data, errors: formErrors, hasChanged, submit }) => (
|
||||
<Form initial={initialForm} onSubmit={onSubmit}>
|
||||
{({ change, data, hasChanged, submit }) => (
|
||||
<Container>
|
||||
<AppHeader onBack={onBack}>
|
||||
{intl.formatMessage(sectionNames.sales)}
|
||||
|
@ -133,7 +133,7 @@ const SaleDetailsPage: React.FC<SaleDetailsPageProps> = ({
|
|||
<SaleInfo
|
||||
data={data}
|
||||
disabled={disabled}
|
||||
errors={formErrors}
|
||||
errors={errors}
|
||||
onChange={change}
|
||||
/>
|
||||
<CardSpacer />
|
||||
|
@ -143,7 +143,7 @@ const SaleDetailsPage: React.FC<SaleDetailsPageProps> = ({
|
|||
currencySymbol={defaultCurrency}
|
||||
data={data}
|
||||
disabled={disabled}
|
||||
errors={formErrors}
|
||||
errors={errors}
|
||||
onChange={change}
|
||||
/>
|
||||
<CardSpacer />
|
||||
|
@ -258,7 +258,7 @@ const SaleDetailsPage: React.FC<SaleDetailsPageProps> = ({
|
|||
data={data}
|
||||
disabled={disabled}
|
||||
defaultCurrency={defaultCurrency}
|
||||
errors={formErrors}
|
||||
errors={errors}
|
||||
onChange={change}
|
||||
/>
|
||||
</div>
|
||||
|
|
|
@ -6,14 +6,14 @@ import { useIntl } from "react-intl";
|
|||
|
||||
import CardTitle from "@saleor/components/CardTitle";
|
||||
import { commonMessages } from "@saleor/intl";
|
||||
import { UserError } from "@saleor/types";
|
||||
import { getFieldError } from "@saleor/utils/errors";
|
||||
import { FormData } from "../SaleDetailsPage";
|
||||
|
||||
export interface SaleInfoProps {
|
||||
data: FormData;
|
||||
disabled: boolean;
|
||||
errors: {
|
||||
name?: string;
|
||||
};
|
||||
errors: UserError[];
|
||||
onChange: (event: React.ChangeEvent<any>) => void;
|
||||
}
|
||||
|
||||
|
@ -33,8 +33,8 @@ const SaleInfo: React.FC<SaleInfoProps> = ({
|
|||
<CardContent>
|
||||
<TextField
|
||||
disabled={disabled}
|
||||
error={!!errors.name}
|
||||
helperText={errors.name}
|
||||
error={!!getFieldError(errors, "name")}
|
||||
helperText={getFieldError(errors, "name")?.message}
|
||||
name={"name" as keyof FormData}
|
||||
onChange={onChange}
|
||||
label={intl.formatMessage({
|
||||
|
|
|
@ -6,15 +6,16 @@ import { useIntl } from "react-intl";
|
|||
|
||||
import CardTitle from "@saleor/components/CardTitle";
|
||||
import { FormChange } from "@saleor/hooks/useForm";
|
||||
import { FormErrors } from "@saleor/types";
|
||||
import { UserError } from "@saleor/types";
|
||||
import { SaleType } from "@saleor/types/globalTypes";
|
||||
import { getFieldError } from "@saleor/utils/errors";
|
||||
import { FormData } from "../SaleDetailsPage";
|
||||
|
||||
export interface SaleValueProps {
|
||||
currencySymbol: string;
|
||||
data: FormData;
|
||||
disabled: boolean;
|
||||
errors: FormErrors<"value">;
|
||||
errors: UserError[];
|
||||
onChange: FormChange;
|
||||
}
|
||||
|
||||
|
@ -43,12 +44,12 @@ const SaleValue: React.FC<SaleValueProps> = ({
|
|||
defaultMessage: "Discount Value",
|
||||
description: "sale discount"
|
||||
})}
|
||||
error={!!errors.value}
|
||||
error={!!getFieldError(errors, "value")}
|
||||
name="value"
|
||||
InputProps={{
|
||||
endAdornment: data.type === SaleType.FIXED ? currencySymbol : "%"
|
||||
}}
|
||||
helperText={errors.value}
|
||||
helperText={getFieldError(errors, "value")?.message}
|
||||
value={data.value}
|
||||
onChange={onChange}
|
||||
/>
|
||||
|
|
|
@ -81,8 +81,8 @@ const VoucherCreatePage: React.FC<VoucherCreatePageProps> = ({
|
|||
};
|
||||
|
||||
return (
|
||||
<Form errors={errors} initial={initialForm} onSubmit={onSubmit}>
|
||||
{({ change, data, errors: formErrors, hasChanged, submit }) => (
|
||||
<Form initial={initialForm} onSubmit={onSubmit}>
|
||||
{({ change, data, hasChanged, submit }) => (
|
||||
<Container>
|
||||
<AppHeader onBack={onBack}>
|
||||
{intl.formatMessage(sectionNames.vouchers)}
|
||||
|
@ -97,7 +97,7 @@ const VoucherCreatePage: React.FC<VoucherCreatePageProps> = ({
|
|||
<div>
|
||||
<VoucherInfo
|
||||
data={data}
|
||||
errors={formErrors}
|
||||
errors={errors}
|
||||
disabled={disabled}
|
||||
onChange={change}
|
||||
variant="create"
|
||||
|
@ -106,7 +106,7 @@ const VoucherCreatePage: React.FC<VoucherCreatePageProps> = ({
|
|||
<VoucherTypes
|
||||
data={data}
|
||||
disabled={disabled}
|
||||
errors={formErrors}
|
||||
errors={errors}
|
||||
onChange={change}
|
||||
/>
|
||||
{data.discountType.toString() !== "SHIPPING" ? (
|
||||
|
@ -114,7 +114,7 @@ const VoucherCreatePage: React.FC<VoucherCreatePageProps> = ({
|
|||
data={data}
|
||||
disabled={disabled}
|
||||
defaultCurrency={defaultCurrency}
|
||||
errors={formErrors}
|
||||
errors={errors}
|
||||
onChange={change}
|
||||
variant="create"
|
||||
/>
|
||||
|
@ -124,7 +124,7 @@ const VoucherCreatePage: React.FC<VoucherCreatePageProps> = ({
|
|||
data={data}
|
||||
disabled={disabled}
|
||||
defaultCurrency={defaultCurrency}
|
||||
errors={formErrors}
|
||||
errors={errors}
|
||||
onChange={change}
|
||||
/>
|
||||
<CardSpacer />
|
||||
|
@ -132,7 +132,7 @@ const VoucherCreatePage: React.FC<VoucherCreatePageProps> = ({
|
|||
data={data}
|
||||
disabled={disabled}
|
||||
defaultCurrency={defaultCurrency}
|
||||
errors={formErrors}
|
||||
errors={errors}
|
||||
onChange={change}
|
||||
/>
|
||||
<CardSpacer />
|
||||
|
@ -140,7 +140,7 @@ const VoucherCreatePage: React.FC<VoucherCreatePageProps> = ({
|
|||
data={data}
|
||||
disabled={disabled}
|
||||
defaultCurrency={defaultCurrency}
|
||||
errors={formErrors}
|
||||
errors={errors}
|
||||
onChange={change}
|
||||
/>
|
||||
</div>
|
||||
|
|
|
@ -8,14 +8,15 @@ import CardTitle from "@saleor/components/CardTitle";
|
|||
import { ControlledCheckbox } from "@saleor/components/ControlledCheckbox";
|
||||
import Grid from "@saleor/components/Grid";
|
||||
import { commonMessages } from "@saleor/intl";
|
||||
import { FormErrors } from "../../../types";
|
||||
import { getFieldError } from "@saleor/utils/errors";
|
||||
import { UserError } from "../../../types";
|
||||
import { FormData } from "../VoucherDetailsPage";
|
||||
|
||||
interface VoucherDatesProps {
|
||||
data: FormData;
|
||||
defaultCurrency: string;
|
||||
disabled: boolean;
|
||||
errors: FormErrors<"endDate" | "startDate">;
|
||||
errors: UserError[];
|
||||
onChange: (event: React.ChangeEvent<any>) => void;
|
||||
}
|
||||
|
||||
|
@ -39,8 +40,8 @@ const VoucherDates = ({
|
|||
<Grid variant="uniform">
|
||||
<TextField
|
||||
disabled={disabled}
|
||||
error={!!errors.startDate}
|
||||
helperText={errors.startDate}
|
||||
error={!!getFieldError(errors, "startDate")}
|
||||
helperText={getFieldError(errors, "startDate")?.message}
|
||||
name={"startDate" as keyof FormData}
|
||||
onChange={onChange}
|
||||
label={intl.formatMessage(commonMessages.startDate)}
|
||||
|
@ -53,8 +54,8 @@ const VoucherDates = ({
|
|||
/>
|
||||
<TextField
|
||||
disabled={disabled}
|
||||
error={!!errors.startDate}
|
||||
helperText={errors.startDate}
|
||||
error={!!getFieldError(errors, "startDate")}
|
||||
helperText={getFieldError(errors, "startDate")?.message}
|
||||
name={"startTime" as keyof FormData}
|
||||
onChange={onChange}
|
||||
label={intl.formatMessage(commonMessages.startHour)}
|
||||
|
@ -79,8 +80,8 @@ const VoucherDates = ({
|
|||
<Grid variant="uniform">
|
||||
<TextField
|
||||
disabled={disabled}
|
||||
error={!!errors.endDate}
|
||||
helperText={errors.endDate}
|
||||
error={!!getFieldError(errors, "endDate")}
|
||||
helperText={getFieldError(errors, "endDate")?.message}
|
||||
name={"endDate" as keyof FormData}
|
||||
onChange={onChange}
|
||||
label={intl.formatMessage(commonMessages.endDate)}
|
||||
|
@ -93,8 +94,8 @@ const VoucherDates = ({
|
|||
/>
|
||||
<TextField
|
||||
disabled={disabled}
|
||||
error={!!errors.endDate}
|
||||
helperText={errors.endDate}
|
||||
error={!!getFieldError(errors, "endDate")}
|
||||
helperText={getFieldError(errors, "endDate")?.message}
|
||||
name={"endTime" as keyof FormData}
|
||||
onChange={onChange}
|
||||
label={intl.formatMessage(commonMessages.endHour)}
|
||||
|
|
|
@ -166,8 +166,8 @@ const VoucherDetailsPage: React.FC<VoucherDetailsPageProps> = ({
|
|||
};
|
||||
|
||||
return (
|
||||
<Form errors={errors} initial={initialForm} onSubmit={onSubmit}>
|
||||
{({ change, data, errors: formErrors, hasChanged, submit }) => (
|
||||
<Form initial={initialForm} onSubmit={onSubmit}>
|
||||
{({ change, data, hasChanged, submit }) => (
|
||||
<Container>
|
||||
<AppHeader onBack={onBack}>
|
||||
{intl.formatMessage(sectionNames.vouchers)}
|
||||
|
@ -178,7 +178,7 @@ const VoucherDetailsPage: React.FC<VoucherDetailsPageProps> = ({
|
|||
<VoucherInfo
|
||||
data={data}
|
||||
disabled={disabled}
|
||||
errors={formErrors}
|
||||
errors={errors}
|
||||
onChange={change}
|
||||
variant="update"
|
||||
/>
|
||||
|
@ -186,7 +186,7 @@ const VoucherDetailsPage: React.FC<VoucherDetailsPageProps> = ({
|
|||
<VoucherTypes
|
||||
data={data}
|
||||
disabled={disabled}
|
||||
errors={formErrors}
|
||||
errors={errors}
|
||||
onChange={change}
|
||||
/>
|
||||
<CardSpacer />
|
||||
|
@ -195,7 +195,7 @@ const VoucherDetailsPage: React.FC<VoucherDetailsPageProps> = ({
|
|||
data={data}
|
||||
disabled={disabled}
|
||||
defaultCurrency={defaultCurrency}
|
||||
errors={formErrors}
|
||||
errors={errors}
|
||||
onChange={change}
|
||||
variant="update"
|
||||
/>
|
||||
|
@ -337,7 +337,7 @@ const VoucherDetailsPage: React.FC<VoucherDetailsPageProps> = ({
|
|||
data={data}
|
||||
disabled={disabled}
|
||||
defaultCurrency={defaultCurrency}
|
||||
errors={formErrors}
|
||||
errors={errors}
|
||||
onChange={change}
|
||||
/>
|
||||
<CardSpacer />
|
||||
|
@ -345,7 +345,7 @@ const VoucherDetailsPage: React.FC<VoucherDetailsPageProps> = ({
|
|||
data={data}
|
||||
disabled={disabled}
|
||||
defaultCurrency={defaultCurrency}
|
||||
errors={formErrors}
|
||||
errors={errors}
|
||||
onChange={change}
|
||||
/>
|
||||
<CardSpacer />
|
||||
|
@ -353,7 +353,7 @@ const VoucherDetailsPage: React.FC<VoucherDetailsPageProps> = ({
|
|||
data={data}
|
||||
disabled={disabled}
|
||||
defaultCurrency={defaultCurrency}
|
||||
errors={formErrors}
|
||||
errors={errors}
|
||||
onChange={change}
|
||||
/>
|
||||
</div>
|
||||
|
|
|
@ -7,13 +7,14 @@ import { FormattedMessage, useIntl } from "react-intl";
|
|||
import Button from "@material-ui/core/Button";
|
||||
import CardTitle from "@saleor/components/CardTitle";
|
||||
import { commonMessages } from "@saleor/intl";
|
||||
import { getFieldError } from "@saleor/utils/errors";
|
||||
import { generateCode } from "../../../misc";
|
||||
import { FormErrors } from "../../../types";
|
||||
import { UserError } from "../../../types";
|
||||
import { FormData } from "../VoucherDetailsPage";
|
||||
|
||||
interface VoucherInfoProps {
|
||||
data: FormData;
|
||||
errors: FormErrors<"code">;
|
||||
errors: UserError[];
|
||||
disabled: boolean;
|
||||
variant: "create" | "update";
|
||||
onChange: (event: any) => void;
|
||||
|
@ -54,9 +55,9 @@ const VoucherInfo = ({
|
|||
<CardContent>
|
||||
<TextField
|
||||
disabled={variant === "update" || disabled}
|
||||
error={!!errors.code}
|
||||
error={!!getFieldError(errors, "code")}
|
||||
fullWidth
|
||||
helperText={errors.code}
|
||||
helperText={getFieldError(errors, "code")?.message}
|
||||
name={"code" as keyof FormData}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Discount Code"
|
||||
|
|
|
@ -6,14 +6,15 @@ import { useIntl } from "react-intl";
|
|||
|
||||
import CardTitle from "@saleor/components/CardTitle";
|
||||
import { ControlledCheckbox } from "@saleor/components/ControlledCheckbox";
|
||||
import { FormErrors } from "../../../types";
|
||||
import { getFieldError } from "@saleor/utils/errors";
|
||||
import { UserError } from "../../../types";
|
||||
import { FormData } from "../VoucherDetailsPage";
|
||||
|
||||
interface VoucherLimitsProps {
|
||||
data: FormData;
|
||||
defaultCurrency: string;
|
||||
disabled: boolean;
|
||||
errors: FormErrors<"usageLimit">;
|
||||
errors: UserError[];
|
||||
onChange: (event: React.ChangeEvent<any>) => void;
|
||||
}
|
||||
|
||||
|
@ -46,8 +47,8 @@ const VoucherLimits = ({
|
|||
{data.hasUsageLimit && (
|
||||
<TextField
|
||||
disabled={disabled}
|
||||
error={!!errors.usageLimit}
|
||||
helperText={errors.usageLimit}
|
||||
error={!!getFieldError(errors, "usageLimit")}
|
||||
helperText={getFieldError(errors, "usageLimit")?.message}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Limit of Uses",
|
||||
description: "voucher"
|
||||
|
|
|
@ -8,14 +8,15 @@ import CardTitle from "@saleor/components/CardTitle";
|
|||
import { FormSpacer } from "@saleor/components/FormSpacer";
|
||||
import RadioGroupField from "@saleor/components/RadioGroupField";
|
||||
import { RequirementsPicker } from "@saleor/discounts/types";
|
||||
import { FormErrors } from "@saleor/types";
|
||||
import { UserError } from "@saleor/types";
|
||||
import { getFieldError } from "@saleor/utils/errors";
|
||||
import { FormData } from "../VoucherDetailsPage";
|
||||
|
||||
interface VoucherRequirementsProps {
|
||||
data: FormData;
|
||||
defaultCurrency: string;
|
||||
disabled: boolean;
|
||||
errors: FormErrors<"minSpent" | "minCheckoutItemsQuantity">;
|
||||
errors: UserError[];
|
||||
onChange: (event: React.ChangeEvent<any>) => void;
|
||||
}
|
||||
|
||||
|
@ -76,8 +77,8 @@ const VoucherRequirements = ({
|
|||
{data.requirementsPicker === RequirementsPicker.ORDER ? (
|
||||
<TextField
|
||||
disabled={disabled}
|
||||
error={!!errors.minSpent}
|
||||
helperText={errors.minSpent}
|
||||
error={!!getFieldError(errors, "minSpent")}
|
||||
helperText={getFieldError(errors, "minSpent")?.message}
|
||||
label={minimalOrderValueText}
|
||||
name={"minSpent" as keyof FormData}
|
||||
value={data.minSpent}
|
||||
|
@ -87,8 +88,10 @@ const VoucherRequirements = ({
|
|||
) : data.requirementsPicker === RequirementsPicker.ITEM ? (
|
||||
<TextField
|
||||
disabled={disabled}
|
||||
error={!!errors.minCheckoutItemsQuantity}
|
||||
helperText={errors.minCheckoutItemsQuantity}
|
||||
error={!!getFieldError(errors, "minCheckoutItemsQuantity")}
|
||||
helperText={
|
||||
getFieldError(errors, "minCheckoutItemsQuantity")?.message
|
||||
}
|
||||
label={minimalQuantityText}
|
||||
name={"minCheckoutItemsQuantity" as keyof FormData}
|
||||
value={data.minCheckoutItemsQuantity}
|
||||
|
|
|
@ -6,13 +6,14 @@ import { useIntl } from "react-intl";
|
|||
import CardTitle from "@saleor/components/CardTitle";
|
||||
import Grid from "@saleor/components/Grid";
|
||||
import RadioGroupField from "@saleor/components/RadioGroupField";
|
||||
import { FormErrors } from "../../../types";
|
||||
import { getFieldError } from "@saleor/utils/errors";
|
||||
import { UserError } from "../../../types";
|
||||
import { DiscountValueTypeEnum } from "../../../types/globalTypes";
|
||||
import { FormData } from "../VoucherDetailsPage";
|
||||
|
||||
interface VoucherTypesProps {
|
||||
data: FormData;
|
||||
errors: FormErrors<"discountType">;
|
||||
errors: UserError[];
|
||||
disabled: boolean;
|
||||
onChange: (event: React.ChangeEvent<any>) => void;
|
||||
}
|
||||
|
@ -62,8 +63,8 @@ const VoucherTypes = ({
|
|||
<RadioGroupField
|
||||
choices={voucherTypeChoices}
|
||||
disabled={disabled}
|
||||
error={!!errors.discountType}
|
||||
hint={errors.discountType}
|
||||
error={!!getFieldError(errors, "discountType")}
|
||||
hint={getFieldError(errors, "discountType")?.message}
|
||||
name={"discountType" as keyof FormData}
|
||||
value={data.discountType}
|
||||
onChange={onChange}
|
||||
|
|
|
@ -11,7 +11,8 @@ import { FormSpacer } from "@saleor/components/FormSpacer";
|
|||
import Hr from "@saleor/components/Hr";
|
||||
import RadioGroupField from "@saleor/components/RadioGroupField";
|
||||
import TextFieldWithChoice from "@saleor/components/TextFieldWithChoice";
|
||||
import { FormErrors } from "../../../types";
|
||||
import { getFieldError } from "@saleor/utils/errors";
|
||||
import { UserError } from "../../../types";
|
||||
import { DiscountValueTypeEnum } from "../../../types/globalTypes";
|
||||
import { translateVoucherTypes } from "../../translations";
|
||||
import { FormData } from "../VoucherDetailsPage";
|
||||
|
@ -19,7 +20,7 @@ import { FormData } from "../VoucherDetailsPage";
|
|||
interface VoucherValueProps {
|
||||
data: FormData;
|
||||
defaultCurrency: string;
|
||||
errors: FormErrors<"discountValue" | "type">;
|
||||
errors: UserError[];
|
||||
disabled: boolean;
|
||||
variant: string;
|
||||
onChange: (event: React.ChangeEvent<any>) => void;
|
||||
|
@ -64,7 +65,7 @@ const VoucherValue: React.FC<VoucherValueProps> = props => {
|
|||
<CardContent>
|
||||
<TextFieldWithChoice
|
||||
disabled={disabled}
|
||||
error={!!errors.discountValue}
|
||||
error={!!getFieldError(errors, "discountValue")}
|
||||
ChoiceProps={{
|
||||
label:
|
||||
data.discountType === DiscountValueTypeEnum.FIXED
|
||||
|
@ -73,7 +74,7 @@ const VoucherValue: React.FC<VoucherValueProps> = props => {
|
|||
name: "discountType" as keyof FormData,
|
||||
values: null
|
||||
}}
|
||||
helperText={errors.discountValue}
|
||||
helperText={getFieldError(errors, "discountValue")?.message}
|
||||
name={"value" as keyof FormData}
|
||||
onChange={onChange}
|
||||
label={intl.formatMessage({
|
||||
|
@ -93,8 +94,8 @@ const VoucherValue: React.FC<VoucherValueProps> = props => {
|
|||
<RadioGroupField
|
||||
choices={voucherTypeChoices}
|
||||
disabled={disabled}
|
||||
error={!!errors.type}
|
||||
hint={errors.type}
|
||||
error={!!getFieldError(errors, "type")}
|
||||
hint={getFieldError(errors, "type")?.message}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Voucher Specific Information"
|
||||
})}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import isEqual from "lodash-es/isEqual";
|
||||
import { useState } from "react";
|
||||
|
||||
import { UserError } from "@saleor/types";
|
||||
import { toggle } from "@saleor/utils/lists";
|
||||
import useStateFromProps from "./useStateFromProps";
|
||||
|
||||
|
@ -17,7 +16,6 @@ export type FormChange = (event: ChangeEvent, cb?: () => void) => void;
|
|||
export interface UseFormResult<T> {
|
||||
change: FormChange;
|
||||
data: T;
|
||||
errors: Record<string, string>;
|
||||
hasChanged: boolean;
|
||||
reset: () => void;
|
||||
set: (data: T) => void;
|
||||
|
@ -26,21 +24,6 @@ export interface UseFormResult<T> {
|
|||
toggleValue: FormChange;
|
||||
}
|
||||
|
||||
function parseErrors(errors: UserError[]): Record<string, string> {
|
||||
return errors
|
||||
? errors.reduce(
|
||||
(acc, curr) =>
|
||||
curr.field
|
||||
? {
|
||||
...acc,
|
||||
[curr.field.split(":")[0]]: curr.message
|
||||
}
|
||||
: acc,
|
||||
{}
|
||||
)
|
||||
: {};
|
||||
}
|
||||
|
||||
type FormData = Record<string, any | any[]>;
|
||||
|
||||
function merge<T extends FormData>(prevData: T, prevState: T, data: T): T {
|
||||
|
@ -68,7 +51,6 @@ function handleRefresh<T extends FormData>(
|
|||
|
||||
function useForm<T extends FormData>(
|
||||
initial: T,
|
||||
errors: UserError[],
|
||||
onSubmit: (data: T) => void
|
||||
): UseFormResult<T> {
|
||||
const [hasChanged, setChanged] = useState(false);
|
||||
|
@ -135,7 +117,6 @@ function useForm<T extends FormData>(
|
|||
return {
|
||||
change,
|
||||
data,
|
||||
errors: parseErrors(errors),
|
||||
hasChanged,
|
||||
reset,
|
||||
set,
|
||||
|
|
|
@ -12,6 +12,8 @@ import ConfirmButton, {
|
|||
} from "@saleor/components/ConfirmButton";
|
||||
import Form from "@saleor/components/Form";
|
||||
import { buttonMessages } from "@saleor/intl";
|
||||
import { getFieldError } from "@saleor/utils/errors";
|
||||
import { UserError } from "@saleor/types";
|
||||
|
||||
export interface MenuCreateDialogFormData {
|
||||
name: string;
|
||||
|
@ -20,6 +22,7 @@ export interface MenuCreateDialogFormData {
|
|||
export interface MenuCreateDialogProps {
|
||||
confirmButtonState: ConfirmButtonTransitionState;
|
||||
disabled: boolean;
|
||||
errors: UserError[];
|
||||
open: boolean;
|
||||
onClose: () => void;
|
||||
onConfirm: (data: MenuCreateDialogFormData) => void;
|
||||
|
@ -32,6 +35,7 @@ const initialForm: MenuCreateDialogFormData = {
|
|||
const MenuCreateDialog: React.FC<MenuCreateDialogProps> = ({
|
||||
confirmButtonState,
|
||||
disabled,
|
||||
errors,
|
||||
onClose,
|
||||
onConfirm,
|
||||
open
|
||||
|
@ -48,14 +52,14 @@ const MenuCreateDialog: React.FC<MenuCreateDialogProps> = ({
|
|||
/>
|
||||
</DialogTitle>
|
||||
<Form initial={initialForm} onSubmit={onConfirm}>
|
||||
{({ change, data, errors: formErrors, submit }) => (
|
||||
{({ change, data, submit }) => (
|
||||
<>
|
||||
<DialogContent>
|
||||
<TextField
|
||||
disabled={disabled}
|
||||
error={!!formErrors.name}
|
||||
error={!!getFieldError(errors, "name")}
|
||||
fullWidth
|
||||
helperText={formErrors.name}
|
||||
helperText={getFieldError(errors, "name")?.message}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Menu Title",
|
||||
id: "menuCreateDialogMenuTitleLabel"
|
||||
|
|
|
@ -253,7 +253,7 @@ const MenuItemDialog: React.FC<MenuItemDialogProps> = ({
|
|||
}
|
||||
name="name"
|
||||
error={!!getFieldError(errors, "name")}
|
||||
helperText={getFieldError(errors, "name")}
|
||||
helperText={getFieldError(errors, "name")?.message}
|
||||
/>
|
||||
<FormSpacer />
|
||||
<AutocompleteSelectMenu
|
||||
|
@ -269,7 +269,7 @@ const MenuItemDialog: React.FC<MenuItemDialogProps> = ({
|
|||
loading={loading}
|
||||
options={options}
|
||||
error={!!idError}
|
||||
helperText={idError}
|
||||
helperText={idError?.message}
|
||||
placeholder={intl.formatMessage({
|
||||
defaultMessage: "Start typing to begin search...",
|
||||
id: "menuItemDialogLinkPlaceholder"
|
||||
|
|
|
@ -174,6 +174,7 @@ const MenuList: React.FC<MenuListProps> = ({ params }) => {
|
|||
open={params.action === "add"}
|
||||
confirmButtonState={menuCreateOpts.status}
|
||||
disabled={menuCreateOpts.loading}
|
||||
errors={menuCreateOpts?.data?.menuCreate.errors || []}
|
||||
onClose={closeModal}
|
||||
onConfirm={formData =>
|
||||
menuCreate({
|
||||
|
|
|
@ -80,8 +80,8 @@ const OrderAddressEditDialog: React.FC<OrderAddressEditDialogProps> = props => {
|
|||
|
||||
return (
|
||||
<Dialog onClose={onClose} open={open} classes={{ paper: classes.overflow }}>
|
||||
<Form initial={address} errors={dialogErrors} onSubmit={handleSubmit}>
|
||||
{({ change, data, errors, submit }) => {
|
||||
<Form initial={address} onSubmit={handleSubmit}>
|
||||
{({ change, data, submit }) => {
|
||||
const handleCountrySelect = createSingleAutocompleteSelectHandler(
|
||||
change,
|
||||
setCountryDisplayName,
|
||||
|
@ -106,7 +106,7 @@ const OrderAddressEditDialog: React.FC<OrderAddressEditDialogProps> = props => {
|
|||
countries={countryChoices}
|
||||
countryDisplayValue={countryDisplayName}
|
||||
data={data}
|
||||
errors={errors}
|
||||
errors={dialogErrors}
|
||||
onChange={change}
|
||||
onCountryChange={handleCountrySelect}
|
||||
/>
|
||||
|
|
|
@ -70,8 +70,8 @@ const PageDetailsPage: React.FC<PageDetailsPageProps> = ({
|
|||
title: maybe(() => page.title, "")
|
||||
};
|
||||
return (
|
||||
<Form errors={errors} initial={initialForm} onSubmit={onSubmit}>
|
||||
{({ change, data, errors: formErrors, hasChanged, submit }) => (
|
||||
<Form initial={initialForm} onSubmit={onSubmit}>
|
||||
{({ change, data, hasChanged, submit }) => (
|
||||
<Container>
|
||||
<AppHeader onBack={onBack}>
|
||||
{intl.formatMessage(sectionNames.pages)}
|
||||
|
@ -91,7 +91,7 @@ const PageDetailsPage: React.FC<PageDetailsPageProps> = ({
|
|||
<PageInfo
|
||||
data={data}
|
||||
disabled={disabled}
|
||||
errors={formErrors}
|
||||
errors={errors}
|
||||
page={page}
|
||||
onChange={change}
|
||||
/>
|
||||
|
@ -119,13 +119,13 @@ const PageDetailsPage: React.FC<PageDetailsPageProps> = ({
|
|||
<PageSlug
|
||||
data={data}
|
||||
disabled={disabled}
|
||||
errors={formErrors}
|
||||
errors={errors}
|
||||
onChange={change}
|
||||
/>
|
||||
<CardSpacer />
|
||||
<VisibilityCard
|
||||
data={data}
|
||||
errors={formErrors}
|
||||
errors={errors}
|
||||
disabled={disabled}
|
||||
hiddenMessage={intl.formatMessage(
|
||||
{
|
||||
|
|
|
@ -9,15 +9,16 @@ import CardTitle from "@saleor/components/CardTitle";
|
|||
import FormSpacer from "@saleor/components/FormSpacer";
|
||||
import RichTextEditor from "@saleor/components/RichTextEditor";
|
||||
import { commonMessages } from "@saleor/intl";
|
||||
import { getFieldError } from "@saleor/utils/errors";
|
||||
import { maybe } from "../../../misc";
|
||||
import { FormErrors } from "../../../types";
|
||||
import { UserError } from "../../../types";
|
||||
import { PageDetails_page } from "../../types/PageDetails";
|
||||
import { FormData } from "../PageDetailsPage";
|
||||
|
||||
export interface PageInfoProps {
|
||||
data: FormData;
|
||||
disabled: boolean;
|
||||
errors: FormErrors<"contentJson" | "title">;
|
||||
errors: UserError[];
|
||||
page: PageDetails_page;
|
||||
onChange: (event: React.ChangeEvent<any>) => void;
|
||||
}
|
||||
|
@ -45,9 +46,9 @@ const PageInfo: React.FC<PageInfoProps> = props => {
|
|||
<CardContent>
|
||||
<TextField
|
||||
disabled={disabled}
|
||||
error={!!errors.title}
|
||||
error={!!getFieldError(errors, "title")}
|
||||
fullWidth
|
||||
helperText={errors.title}
|
||||
helperText={getFieldError(errors, "title")?.message}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Title",
|
||||
description: "page title"
|
||||
|
@ -59,8 +60,8 @@ const PageInfo: React.FC<PageInfoProps> = props => {
|
|||
<FormSpacer />
|
||||
<RichTextEditor
|
||||
disabled={disabled}
|
||||
error={!!errors.contentJson}
|
||||
helperText={errors.contentJson}
|
||||
error={!!getFieldError(errors, "contentJson")}
|
||||
helperText={getFieldError(errors, "contentJson")?.message}
|
||||
initial={maybe(() => JSON.parse(page.contentJson))}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Content",
|
||||
|
|
|
@ -6,12 +6,14 @@ import { useIntl } from "react-intl";
|
|||
import slugify from "slugify";
|
||||
|
||||
import CardTitle from "@saleor/components/CardTitle";
|
||||
import { UserError } from "@saleor/types";
|
||||
import { getFieldError } from "@saleor/utils/errors";
|
||||
import { FormData } from "../PageDetailsPage";
|
||||
|
||||
export interface PageSlugProps {
|
||||
data: FormData;
|
||||
disabled: boolean;
|
||||
errors: Partial<Record<"slug", string>>;
|
||||
errors: UserError[];
|
||||
onChange: (event: React.ChangeEvent<any>) => void;
|
||||
}
|
||||
|
||||
|
@ -34,13 +36,13 @@ const PageSlug: React.FC<PageSlugProps> = ({
|
|||
<TextField
|
||||
name={"slug" as keyof FormData}
|
||||
disabled={disabled}
|
||||
error={!!errors.slug}
|
||||
error={!!getFieldError(errors, "slug")}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Slug",
|
||||
description: "page internal name"
|
||||
})}
|
||||
helperText={
|
||||
errors.slug ||
|
||||
getFieldError(errors, "slug")?.message ||
|
||||
intl.formatMessage({
|
||||
defaultMessage:
|
||||
"If empty, URL will be autogenerated from Page Name"
|
||||
|
|
|
@ -4,17 +4,18 @@ import makeStyles from "@material-ui/core/styles/makeStyles";
|
|||
import TextField from "@material-ui/core/TextField";
|
||||
import CardTitle from "@saleor/components/CardTitle";
|
||||
import ControlledCheckbox from "@saleor/components/ControlledCheckbox";
|
||||
import { FormErrors } from "@saleor/types";
|
||||
import { UserError } from "@saleor/types";
|
||||
import { ConfigurationTypeFieldEnum } from "@saleor/types/globalTypes";
|
||||
import React from "react";
|
||||
import { useIntl } from "react-intl";
|
||||
|
||||
import { Plugin_plugin_configuration } from "@saleor/plugins/types/Plugin";
|
||||
import { getFieldError } from "@saleor/utils/errors";
|
||||
import { FormData } from "../PluginsDetailsPage";
|
||||
|
||||
interface PluginSettingsProps {
|
||||
data: FormData;
|
||||
errors: FormErrors<"name" | "configuration">;
|
||||
errors: UserError[];
|
||||
disabled: boolean;
|
||||
onChange: (event: React.ChangeEvent<any>) => void;
|
||||
fields: Plugin_plugin_configuration[];
|
||||
|
@ -84,7 +85,7 @@ const PluginSettings: React.FC<PluginSettingsProps> = ({
|
|||
) : (
|
||||
<TextField
|
||||
disabled={disabled}
|
||||
error={!!errors.name}
|
||||
error={!!getFieldError(errors, "name")}
|
||||
helperText={fieldData.helpText}
|
||||
label={fieldData.label}
|
||||
name={field.name}
|
||||
|
|
|
@ -77,8 +77,8 @@ const PluginsDetailsPage: React.FC<PluginsDetailsPageProps> = props => {
|
|||
};
|
||||
|
||||
return (
|
||||
<Form errors={errors} initial={initialForm} onSubmit={onSubmit}>
|
||||
{({ data, errors, hasChanged, submit, set, triggerChange }) => {
|
||||
<Form initial={initialForm} onSubmit={onSubmit}>
|
||||
{({ data, hasChanged, submit, set, triggerChange }) => {
|
||||
const onChange = (event: ChangeEvent) => {
|
||||
const { name, value } = event.target;
|
||||
const newData = {
|
||||
|
|
|
@ -11,6 +11,8 @@ import Form from "@saleor/components/Form";
|
|||
import { FormSpacer } from "@saleor/components/FormSpacer";
|
||||
import ListField from "@saleor/components/ListField";
|
||||
import { buttonMessages } from "@saleor/intl";
|
||||
import { UserError } from "@saleor/types";
|
||||
import { getFieldError } from "@saleor/utils/errors";
|
||||
|
||||
export interface FormData {
|
||||
name: string;
|
||||
|
@ -22,10 +24,7 @@ export interface FormData {
|
|||
|
||||
export interface ProductTypeAttributeEditDialogProps {
|
||||
disabled: boolean;
|
||||
errors: Array<{
|
||||
field: string;
|
||||
message: string;
|
||||
}>;
|
||||
errors: UserError[];
|
||||
name: string;
|
||||
opened: boolean;
|
||||
title: string;
|
||||
|
@ -37,9 +36,16 @@ export interface ProductTypeAttributeEditDialogProps {
|
|||
onConfirm: (data: FormData) => void;
|
||||
}
|
||||
|
||||
const ProductTypeAttributeEditDialog: React.FC<
|
||||
ProductTypeAttributeEditDialogProps
|
||||
> = ({ disabled, errors, name, opened, title, values, onClose, onConfirm }) => {
|
||||
const ProductTypeAttributeEditDialog: React.FC<ProductTypeAttributeEditDialogProps> = ({
|
||||
disabled,
|
||||
errors,
|
||||
name,
|
||||
opened,
|
||||
title,
|
||||
values,
|
||||
onClose,
|
||||
onConfirm
|
||||
}) => {
|
||||
const intl = useIntl();
|
||||
|
||||
const initialForm: FormData = {
|
||||
|
@ -48,19 +54,19 @@ const ProductTypeAttributeEditDialog: React.FC<
|
|||
};
|
||||
return (
|
||||
<Dialog onClose={onClose} open={opened}>
|
||||
<Form errors={errors} initial={initialForm} onSubmit={onConfirm}>
|
||||
{({ change, data, errors: formErrors }) => (
|
||||
<Form initial={initialForm} onSubmit={onConfirm}>
|
||||
{({ change, data }) => (
|
||||
<>
|
||||
<DialogTitle>{title}</DialogTitle>
|
||||
<DialogContent>
|
||||
<TextField
|
||||
disabled={disabled}
|
||||
error={!!formErrors.name}
|
||||
error={!!getFieldError(errors, "name")}
|
||||
fullWidth
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Attribute name"
|
||||
})}
|
||||
helperText={formErrors.name}
|
||||
helperText={getFieldError(errors, "name")?.message}
|
||||
name="name"
|
||||
value={data.name}
|
||||
onChange={change}
|
||||
|
@ -70,9 +76,9 @@ const ProductTypeAttributeEditDialog: React.FC<
|
|||
autoComplete="off"
|
||||
disabled={disabled}
|
||||
error={
|
||||
!!formErrors.values ||
|
||||
!!formErrors.addValues ||
|
||||
!!formErrors.removeValues
|
||||
!!getFieldError(errors, "values") ||
|
||||
!!getFieldError(errors, "addValues") ||
|
||||
!!getFieldError(errors, "removeValues")
|
||||
}
|
||||
fullWidth
|
||||
name="values"
|
||||
|
@ -80,9 +86,9 @@ const ProductTypeAttributeEditDialog: React.FC<
|
|||
defaultMessage: "Attribute values"
|
||||
})}
|
||||
helperText={
|
||||
formErrors.values ||
|
||||
formErrors.addValues ||
|
||||
formErrors.removeValues
|
||||
getFieldError(errors, "values") ||
|
||||
getFieldError(errors, "addValues") ||
|
||||
getFieldError(errors, "removeValues")
|
||||
}
|
||||
values={data.values}
|
||||
onChange={change}
|
||||
|
|
|
@ -70,13 +70,8 @@ const ProductTypeCreatePage: React.FC<ProductTypeCreatePageProps> = ({
|
|||
const [taxTypeDisplayName, setTaxTypeDisplayName] = useStateFromProps("");
|
||||
|
||||
return (
|
||||
<Form
|
||||
errors={errors}
|
||||
initial={formInitialData}
|
||||
onSubmit={onSubmit}
|
||||
confirmLeave
|
||||
>
|
||||
{({ change, data, errors: formErrors, hasChanged, submit }) => (
|
||||
<Form initial={formInitialData} onSubmit={onSubmit} confirmLeave>
|
||||
{({ change, data, hasChanged, submit }) => (
|
||||
<Container>
|
||||
<AppHeader onBack={onBack}>
|
||||
{intl.formatMessage(sectionNames.productTypes)}
|
||||
|
@ -87,7 +82,7 @@ const ProductTypeCreatePage: React.FC<ProductTypeCreatePageProps> = ({
|
|||
<ProductTypeDetails
|
||||
data={data}
|
||||
disabled={disabled}
|
||||
errors={formErrors}
|
||||
errors={errors}
|
||||
onChange={change}
|
||||
/>
|
||||
<CardSpacer />
|
||||
|
|
|
@ -7,7 +7,8 @@ import { useIntl } from "react-intl";
|
|||
|
||||
import CardTitle from "@saleor/components/CardTitle";
|
||||
import { commonMessages } from "@saleor/intl";
|
||||
import { FormErrors } from "@saleor/types";
|
||||
import { UserError } from "@saleor/types";
|
||||
import { getFieldError } from "@saleor/utils/errors";
|
||||
|
||||
const useStyles = makeStyles(
|
||||
{
|
||||
|
@ -23,7 +24,7 @@ interface ProductTypeDetailsProps {
|
|||
name: string;
|
||||
};
|
||||
disabled: boolean;
|
||||
errors: FormErrors<"name">;
|
||||
errors: UserError[];
|
||||
onChange: (event: React.ChangeEvent<any>) => void;
|
||||
}
|
||||
|
||||
|
@ -41,9 +42,9 @@ const ProductTypeDetails: React.FC<ProductTypeDetailsProps> = props => {
|
|||
<CardContent>
|
||||
<TextField
|
||||
disabled={disabled}
|
||||
error={!!errors.name}
|
||||
error={!!getFieldError(errors, "name")}
|
||||
fullWidth
|
||||
helperText={errors.name}
|
||||
helperText={getFieldError(errors, "name")?.message}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Product Type Name"
|
||||
})}
|
||||
|
|
|
@ -123,13 +123,8 @@ const ProductTypeDetailsPage: React.FC<ProductTypeDetailsPageProps> = ({
|
|||
weight: maybe(() => productType.weight.value)
|
||||
};
|
||||
return (
|
||||
<Form
|
||||
errors={errors}
|
||||
initial={formInitialData}
|
||||
onSubmit={onSubmit}
|
||||
confirmLeave
|
||||
>
|
||||
{({ change, data, errors: formErrors, hasChanged, submit }) => (
|
||||
<Form initial={formInitialData} onSubmit={onSubmit} confirmLeave>
|
||||
{({ change, data, hasChanged, submit }) => (
|
||||
<Container>
|
||||
<AppHeader onBack={onBack}>
|
||||
{intl.formatMessage(sectionNames.productTypes)}
|
||||
|
@ -140,7 +135,7 @@ const ProductTypeDetailsPage: React.FC<ProductTypeDetailsPageProps> = ({
|
|||
<ProductTypeDetails
|
||||
data={data}
|
||||
disabled={disabled}
|
||||
errors={formErrors}
|
||||
errors={errors}
|
||||
onChange={change}
|
||||
/>
|
||||
<CardSpacer />
|
||||
|
|
|
@ -90,7 +90,7 @@ export const ProductCreatePage: React.FC<ProductCreatePageProps> = ({
|
|||
disabled,
|
||||
categories: categoryChoiceList,
|
||||
collections: collectionChoiceList,
|
||||
errors: userErrors,
|
||||
errors,
|
||||
fetchCategories,
|
||||
fetchCollections,
|
||||
fetchMoreCategories,
|
||||
|
@ -162,21 +162,8 @@ export const ProductCreatePage: React.FC<ProductCreatePageProps> = ({
|
|||
});
|
||||
|
||||
return (
|
||||
<Form
|
||||
onSubmit={handleSubmit}
|
||||
errors={userErrors}
|
||||
initial={initialData}
|
||||
confirmLeave
|
||||
>
|
||||
{({
|
||||
change,
|
||||
data,
|
||||
errors,
|
||||
hasChanged,
|
||||
submit,
|
||||
triggerChange,
|
||||
toggleValue
|
||||
}) => {
|
||||
<Form onSubmit={handleSubmit} initial={initialData} confirmLeave>
|
||||
{({ change, data, hasChanged, submit, triggerChange, toggleValue }) => {
|
||||
const handleCollectionSelect = createMultiAutocompleteSelectHandler(
|
||||
toggleValue,
|
||||
setSelectedCollections,
|
||||
|
|
|
@ -9,6 +9,8 @@ import CardTitle from "@saleor/components/CardTitle";
|
|||
import FormSpacer from "@saleor/components/FormSpacer";
|
||||
import RichTextEditor from "@saleor/components/RichTextEditor";
|
||||
import { commonMessages } from "@saleor/intl";
|
||||
import { UserError } from "@saleor/types";
|
||||
import { getFieldError } from "@saleor/utils/errors";
|
||||
|
||||
interface ProductDetailsFormProps {
|
||||
data: {
|
||||
|
@ -16,7 +18,7 @@ interface ProductDetailsFormProps {
|
|||
name: string;
|
||||
};
|
||||
disabled?: boolean;
|
||||
errors: { [key: string]: string };
|
||||
errors: UserError[];
|
||||
// Draftail isn't controlled - it needs only initial input
|
||||
// because it's autosaving on its own.
|
||||
// Ref https://github.com/mirumee/saleor/issues/4470
|
||||
|
@ -40,8 +42,8 @@ export const ProductDetailsForm: React.FC<ProductDetailsFormProps> = ({
|
|||
/>
|
||||
<CardContent>
|
||||
<TextField
|
||||
error={!!errors.name}
|
||||
helperText={errors.name}
|
||||
error={!!getFieldError(errors, "name")}
|
||||
helperText={getFieldError(errors, "name")?.message}
|
||||
disabled={disabled}
|
||||
fullWidth
|
||||
label={intl.formatMessage({
|
||||
|
@ -55,8 +57,8 @@ export const ProductDetailsForm: React.FC<ProductDetailsFormProps> = ({
|
|||
<FormSpacer />
|
||||
<RichTextEditor
|
||||
disabled={disabled}
|
||||
error={!!errors.descriptionJson}
|
||||
helperText={errors.descriptionJson}
|
||||
error={!!getFieldError(errors, "descriptionJson")}
|
||||
helperText={getFieldError(errors, "descriptionJson")?.message}
|
||||
initial={initialDescription}
|
||||
label={intl.formatMessage(commonMessages.description)}
|
||||
name="description"
|
||||
|
|
|
@ -17,7 +17,8 @@ import SingleAutocompleteSelectField, {
|
|||
} from "@saleor/components/SingleAutocompleteSelectField";
|
||||
import { ChangeEvent } from "@saleor/hooks/useForm";
|
||||
import { maybe } from "@saleor/misc";
|
||||
import { FetchMoreProps, FormErrors } from "@saleor/types";
|
||||
import { FetchMoreProps, UserError } from "@saleor/types";
|
||||
import { getFieldError } from "@saleor/utils/errors";
|
||||
|
||||
interface ProductType {
|
||||
hasVariants: boolean;
|
||||
|
@ -53,7 +54,7 @@ interface ProductOrganizationProps {
|
|||
productType?: string;
|
||||
};
|
||||
disabled: boolean;
|
||||
errors: FormErrors<"productType" | "category">;
|
||||
errors: UserError[];
|
||||
productType?: ProductType;
|
||||
productTypeInputDisplayValue?: string;
|
||||
productTypes?: SingleAutocompleteChoiceType[];
|
||||
|
@ -73,7 +74,6 @@ const ProductOrganization: React.FC<ProductOrganizationProps> = props => {
|
|||
canChangeType,
|
||||
categories,
|
||||
categoryInputDisplayValue,
|
||||
|
||||
collections,
|
||||
collectionsInputDisplayValue,
|
||||
data,
|
||||
|
@ -108,8 +108,8 @@ const ProductOrganization: React.FC<ProductOrganizationProps> = props => {
|
|||
{canChangeType ? (
|
||||
<SingleAutocompleteSelectField
|
||||
displayValue={productTypeInputDisplayValue}
|
||||
error={!!errors.productType}
|
||||
helperText={errors.productType}
|
||||
error={!!getFieldError(errors, "productType")}
|
||||
helperText={getFieldError(errors, "productType")?.message}
|
||||
name="productType"
|
||||
disabled={disabled}
|
||||
label={intl.formatMessage({
|
||||
|
@ -154,8 +154,8 @@ const ProductOrganization: React.FC<ProductOrganizationProps> = props => {
|
|||
<FormSpacer />
|
||||
<SingleAutocompleteSelectField
|
||||
displayValue={categoryInputDisplayValue}
|
||||
error={!!errors.category}
|
||||
helperText={errors.category}
|
||||
error={!!getFieldError(errors, "category")}
|
||||
helperText={getFieldError(errors, "category")?.message}
|
||||
disabled={disabled}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Category"
|
||||
|
|
|
@ -6,6 +6,8 @@ import React from "react";
|
|||
import { useIntl } from "react-intl";
|
||||
|
||||
import CardTitle from "@saleor/components/CardTitle";
|
||||
import { UserError } from "@saleor/types";
|
||||
import { getFieldError } from "@saleor/utils/errors";
|
||||
import { maybe } from "../../../misc";
|
||||
import { ProductDetails_product } from "../../types/ProductDetails";
|
||||
|
||||
|
@ -26,7 +28,7 @@ interface ProductStockProps {
|
|||
stockQuantity: number;
|
||||
};
|
||||
disabled: boolean;
|
||||
errors: { [key: string]: string };
|
||||
errors: UserError[];
|
||||
product: ProductDetails_product;
|
||||
onChange: (event: React.ChangeEvent<any>) => void;
|
||||
}
|
||||
|
@ -56,8 +58,8 @@ const ProductStock: React.FC<ProductStockProps> = props => {
|
|||
})}
|
||||
value={data.sku}
|
||||
onChange={onChange}
|
||||
error={!!errors.sku}
|
||||
helperText={errors.sku}
|
||||
error={!!getFieldError(errors, "sku")}
|
||||
helperText={getFieldError(errors, "sku")?.message}
|
||||
/>
|
||||
<TextField
|
||||
disabled={disabled}
|
||||
|
|
|
@ -85,7 +85,7 @@ export const ProductUpdatePage: React.FC<ProductUpdatePageProps> = ({
|
|||
disabled,
|
||||
categories: categoryChoiceList,
|
||||
collections: collectionChoiceList,
|
||||
errors: userErrors,
|
||||
errors,
|
||||
fetchCategories,
|
||||
fetchCollections,
|
||||
fetchMoreCategories,
|
||||
|
@ -152,21 +152,8 @@ export const ProductUpdatePage: React.FC<ProductUpdatePageProps> = ({
|
|||
});
|
||||
|
||||
return (
|
||||
<Form
|
||||
onSubmit={handleSubmit}
|
||||
errors={userErrors}
|
||||
initial={initialData}
|
||||
confirmLeave
|
||||
>
|
||||
{({
|
||||
change,
|
||||
data,
|
||||
errors,
|
||||
hasChanged,
|
||||
submit,
|
||||
triggerChange,
|
||||
toggleValue
|
||||
}) => {
|
||||
<Form onSubmit={handleSubmit} initial={initialData} confirmLeave>
|
||||
{({ change, data, hasChanged, submit, triggerChange, toggleValue }) => {
|
||||
const handleCollectionSelect = createMultiAutocompleteSelectHandler(
|
||||
toggleValue,
|
||||
setSelectedCollections,
|
||||
|
|
|
@ -51,7 +51,7 @@ interface ProductVariantCreatePageProps {
|
|||
|
||||
const ProductVariantCreatePage: React.FC<ProductVariantCreatePageProps> = ({
|
||||
currencySymbol,
|
||||
errors: apiErrors,
|
||||
errors,
|
||||
loading,
|
||||
header,
|
||||
product,
|
||||
|
@ -93,8 +93,8 @@ const ProductVariantCreatePage: React.FC<ProductVariantCreatePageProps> = ({
|
|||
});
|
||||
|
||||
return (
|
||||
<Form initial={initialForm} errors={apiErrors} onSubmit={handleSubmit}>
|
||||
{({ change, data, errors, hasChanged, submit, triggerChange }) => {
|
||||
<Form initial={initialForm} onSubmit={handleSubmit}>
|
||||
{({ change, data, hasChanged, submit, triggerChange }) => {
|
||||
const handleAttributeChange: FormsetChange = (id, value) => {
|
||||
changeAttributeData(id, value);
|
||||
triggerChange();
|
||||
|
@ -120,7 +120,7 @@ const ProductVariantCreatePage: React.FC<ProductVariantCreatePageProps> = ({
|
|||
<ProductVariantAttributes
|
||||
attributes={attributes}
|
||||
disabled={loading}
|
||||
errors={apiErrors}
|
||||
errors={errors}
|
||||
onChange={handleAttributeChange}
|
||||
/>
|
||||
<CardSpacer />
|
||||
|
|
|
@ -53,7 +53,7 @@ interface ProductVariantPageProps {
|
|||
}
|
||||
|
||||
const ProductVariantPage: React.FC<ProductVariantPageProps> = ({
|
||||
errors: apiErrors,
|
||||
errors,
|
||||
loading,
|
||||
header,
|
||||
placeholderImage,
|
||||
|
@ -109,13 +109,8 @@ const ProductVariantPage: React.FC<ProductVariantPageProps> = ({
|
|||
{maybe(() => variant.product.name)}
|
||||
</AppHeader>
|
||||
<PageHeader title={header} />
|
||||
<Form
|
||||
initial={initialForm}
|
||||
errors={apiErrors}
|
||||
onSubmit={handleSubmit}
|
||||
confirmLeave
|
||||
>
|
||||
{({ change, data, errors, hasChanged, submit, triggerChange }) => {
|
||||
<Form initial={initialForm} onSubmit={handleSubmit} confirmLeave>
|
||||
{({ change, data, hasChanged, submit, triggerChange }) => {
|
||||
const handleAttributeChange: FormsetChange = (id, value) => {
|
||||
changeAttributeData(id, value);
|
||||
triggerChange();
|
||||
|
@ -143,7 +138,7 @@ const ProductVariantPage: React.FC<ProductVariantPageProps> = ({
|
|||
<ProductVariantAttributes
|
||||
attributes={attributes}
|
||||
disabled={loading}
|
||||
errors={apiErrors}
|
||||
errors={errors}
|
||||
onChange={handleAttributeChange}
|
||||
/>
|
||||
<CardSpacer />
|
||||
|
|
|
@ -6,6 +6,8 @@ import { useIntl } from "react-intl";
|
|||
|
||||
import CardTitle from "@saleor/components/CardTitle";
|
||||
import PriceField from "@saleor/components/PriceField";
|
||||
import { UserError } from "@saleor/types";
|
||||
import { getFieldError } from "@saleor/utils/errors";
|
||||
|
||||
const useStyles = makeStyles(
|
||||
theme => ({
|
||||
|
@ -22,7 +24,7 @@ interface ProductVariantPriceProps {
|
|||
currencySymbol?: string;
|
||||
priceOverride?: string;
|
||||
costPrice?: string;
|
||||
errors: { [key: string]: string };
|
||||
errors: UserError[];
|
||||
loading?: boolean;
|
||||
onChange(event: any);
|
||||
}
|
||||
|
@ -52,15 +54,14 @@ const ProductVariantPrice: React.FC<ProductVariantPriceProps> = props => {
|
|||
<div className={classes.grid}>
|
||||
<div>
|
||||
<PriceField
|
||||
error={!!errors.price_override}
|
||||
error={!!getFieldError(errors, "price_override")}
|
||||
name="priceOverride"
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Selling price override"
|
||||
})}
|
||||
hint={
|
||||
errors.price_override
|
||||
? errors.price_override
|
||||
: intl.formatMessage({
|
||||
getFieldError(errors, "price_override")?.message ||
|
||||
intl.formatMessage({
|
||||
defaultMessage: "Optional",
|
||||
description: "optional field",
|
||||
id: "productVariantPriceOptionalPriceOverrideField"
|
||||
|
@ -74,15 +75,14 @@ const ProductVariantPrice: React.FC<ProductVariantPriceProps> = props => {
|
|||
</div>
|
||||
<div>
|
||||
<PriceField
|
||||
error={!!errors.cost_price}
|
||||
error={!!getFieldError(errors, "cost_price")}
|
||||
name="costPrice"
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Cost price override"
|
||||
})}
|
||||
hint={
|
||||
errors.cost_price
|
||||
? errors.cost_price
|
||||
: intl.formatMessage({
|
||||
getFieldError(errors, "cost_price")?.message ||
|
||||
intl.formatMessage({
|
||||
defaultMessage: "Optional",
|
||||
description: "optional field",
|
||||
id: "productVariantPriceOptionalCostPriceField"
|
||||
|
|
|
@ -6,6 +6,8 @@ import React from "react";
|
|||
import { useIntl } from "react-intl";
|
||||
|
||||
import CardTitle from "@saleor/components/CardTitle";
|
||||
import { UserError } from "@saleor/types";
|
||||
import { getFieldError } from "@saleor/utils/errors";
|
||||
|
||||
const useStyles = makeStyles(
|
||||
theme => ({
|
||||
|
@ -19,10 +21,7 @@ const useStyles = makeStyles(
|
|||
);
|
||||
|
||||
interface ProductVariantStockProps {
|
||||
errors: {
|
||||
quantity?: string;
|
||||
sku?: string;
|
||||
};
|
||||
errors: UserError[];
|
||||
sku: string;
|
||||
quantity: string;
|
||||
stockAllocated?: number;
|
||||
|
@ -48,7 +47,7 @@ const ProductVariantStock: React.FC<ProductVariantStockProps> = props => {
|
|||
<div className={classes.grid}>
|
||||
<div>
|
||||
<TextField
|
||||
error={!!errors.quantity}
|
||||
error={!!getFieldError(errors, "quantity")}
|
||||
name="quantity"
|
||||
value={quantity}
|
||||
label={intl.formatMessage({
|
||||
|
@ -56,8 +55,8 @@ const ProductVariantStock: React.FC<ProductVariantStockProps> = props => {
|
|||
description: "product variant stock"
|
||||
})}
|
||||
helperText={
|
||||
errors.quantity
|
||||
? errors.quantity
|
||||
getFieldError(errors, "quantity")
|
||||
? getFieldError(errors, "quantity")
|
||||
: !!stockAllocated
|
||||
? intl.formatMessage(
|
||||
{
|
||||
|
@ -77,8 +76,8 @@ const ProductVariantStock: React.FC<ProductVariantStockProps> = props => {
|
|||
</div>
|
||||
<div>
|
||||
<TextField
|
||||
error={!!errors.sku}
|
||||
helperText={errors.sku}
|
||||
error={!!getFieldError(errors, "sku")}
|
||||
helperText={getFieldError(errors, "sku")?.message}
|
||||
name="sku"
|
||||
value={sku}
|
||||
label={intl.formatMessage({
|
||||
|
|
|
@ -35,7 +35,7 @@ export interface ServiceCreatePageProps {
|
|||
const ServiceCreatePage: React.FC<ServiceCreatePageProps> = props => {
|
||||
const {
|
||||
disabled,
|
||||
errors: formErrors,
|
||||
errors,
|
||||
permissions,
|
||||
saveButtonBarState,
|
||||
onBack,
|
||||
|
@ -50,13 +50,8 @@ const ServiceCreatePage: React.FC<ServiceCreatePageProps> = props => {
|
|||
permissions: []
|
||||
};
|
||||
return (
|
||||
<Form
|
||||
errors={formErrors}
|
||||
initial={initialForm}
|
||||
onSubmit={onSubmit}
|
||||
confirmLeave
|
||||
>
|
||||
{({ data, change, errors, hasChanged, submit }) => (
|
||||
<Form initial={initialForm} onSubmit={onSubmit} confirmLeave>
|
||||
{({ data, change, hasChanged, submit }) => (
|
||||
<Container>
|
||||
<AppHeader onBack={onBack}>
|
||||
{intl.formatMessage(sectionNames.serviceAccounts)}
|
||||
|
|
|
@ -48,7 +48,7 @@ const ServiceDetailsPage: React.FC<ServiceDetailsPageProps> = props => {
|
|||
const {
|
||||
apiUri,
|
||||
disabled,
|
||||
errors: formErrors,
|
||||
errors,
|
||||
permissions,
|
||||
saveButtonBarState,
|
||||
service,
|
||||
|
@ -79,13 +79,8 @@ const ServiceDetailsPage: React.FC<ServiceDetailsPageProps> = props => {
|
|||
permissions: maybe(() => service.permissions, []).map(perm => perm.code)
|
||||
};
|
||||
return (
|
||||
<Form
|
||||
errors={formErrors}
|
||||
initial={initialForm}
|
||||
onSubmit={onSubmit}
|
||||
confirmLeave
|
||||
>
|
||||
{({ data, change, errors, hasChanged, submit }) => (
|
||||
<Form initial={initialForm} onSubmit={onSubmit} confirmLeave>
|
||||
{({ data, change, hasChanged, submit }) => (
|
||||
<Container>
|
||||
<AppHeader onBack={onBack}>
|
||||
{intl.formatMessage(sectionNames.serviceAccounts)}
|
||||
|
|
|
@ -6,14 +6,15 @@ import { useIntl } from "react-intl";
|
|||
|
||||
import CardTitle from "@saleor/components/CardTitle";
|
||||
import { FormChange } from "@saleor/hooks/useForm";
|
||||
import { FormErrors } from "@saleor/types";
|
||||
import { UserError } from "@saleor/types";
|
||||
import { getFieldError } from "@saleor/utils/errors";
|
||||
|
||||
export interface ServiceInfoProps {
|
||||
data: {
|
||||
name: string;
|
||||
};
|
||||
disabled: boolean;
|
||||
errors: FormErrors<"name">;
|
||||
errors: UserError[];
|
||||
onChange: FormChange;
|
||||
}
|
||||
|
||||
|
@ -32,12 +33,12 @@ const ServiceInfo: React.FC<ServiceInfoProps> = props => {
|
|||
<CardContent>
|
||||
<TextField
|
||||
disabled={disabled}
|
||||
error={!!errors.name}
|
||||
error={!!getFieldError(errors, "name")}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Account Name",
|
||||
description: "service account"
|
||||
})}
|
||||
helperText={errors.name}
|
||||
helperText={getFieldError(errors, "name")?.message}
|
||||
fullWidth
|
||||
name="name"
|
||||
value={data.name}
|
||||
|
|
|
@ -50,8 +50,8 @@ const ShippingZoneCreatePage: React.FC<ShippingZoneCreatePageProps> = ({
|
|||
};
|
||||
|
||||
return (
|
||||
<Form errors={errors} initial={initialForm} onSubmit={onSubmit}>
|
||||
{({ change, data, errors: formErrors, hasChanged, submit }) => (
|
||||
<Form initial={initialForm} onSubmit={onSubmit}>
|
||||
{({ change, data, hasChanged, submit }) => (
|
||||
<>
|
||||
<Container>
|
||||
<AppHeader onBack={onBack}>
|
||||
|
@ -67,7 +67,7 @@ const ShippingZoneCreatePage: React.FC<ShippingZoneCreatePageProps> = ({
|
|||
<div>
|
||||
<ShippingZoneInfo
|
||||
data={data}
|
||||
errors={formErrors}
|
||||
errors={errors}
|
||||
onChange={change}
|
||||
/>
|
||||
<CardSpacer />
|
||||
|
|
|
@ -57,11 +57,11 @@ const ShippingZoneDetailsPage: React.FC<ShippingZoneDetailsPageProps> = ({
|
|||
const intl = useIntl();
|
||||
|
||||
const initialForm: FormData = {
|
||||
name: maybe(() => shippingZone.name, "")
|
||||
name: shippingZone?.name || ""
|
||||
};
|
||||
return (
|
||||
<Form errors={errors} initial={initialForm} onSubmit={onSubmit}>
|
||||
{({ change, data, errors: formErrors, hasChanged, submit }) => (
|
||||
<Form initial={initialForm} onSubmit={onSubmit}>
|
||||
{({ change, data, hasChanged, submit }) => (
|
||||
<Container>
|
||||
<AppHeader onBack={onBack}>
|
||||
<FormattedMessage defaultMessage="Shipping" />
|
||||
|
@ -69,11 +69,7 @@ const ShippingZoneDetailsPage: React.FC<ShippingZoneDetailsPageProps> = ({
|
|||
<PageHeader title={maybe(() => shippingZone.name)} />
|
||||
<Grid>
|
||||
<div>
|
||||
<ShippingZoneInfo
|
||||
data={data}
|
||||
errors={formErrors}
|
||||
onChange={change}
|
||||
/>
|
||||
<ShippingZoneInfo data={data} errors={errors} onChange={change} />
|
||||
<CardSpacer />
|
||||
<CountryList
|
||||
countries={maybe(() => shippingZone.countries)}
|
||||
|
|
|
@ -6,12 +6,13 @@ import { useIntl } from "react-intl";
|
|||
|
||||
import CardTitle from "@saleor/components/CardTitle";
|
||||
import { commonMessages } from "@saleor/intl";
|
||||
import { FormErrors } from "../../../types";
|
||||
import { getFieldError } from "@saleor/utils/errors";
|
||||
import { UserError } from "../../../types";
|
||||
import { FormData } from "../ShippingZoneDetailsPage";
|
||||
|
||||
export interface ShippingZoneInfoProps {
|
||||
data: FormData;
|
||||
errors: FormErrors<"name">;
|
||||
errors: UserError[];
|
||||
onChange: (event: React.ChangeEvent<any>) => void;
|
||||
}
|
||||
|
||||
|
@ -29,9 +30,9 @@ const ShippingZoneInfo: React.FC<ShippingZoneInfoProps> = ({
|
|||
/>
|
||||
<CardContent>
|
||||
<TextField
|
||||
error={!!errors.name}
|
||||
error={!!getFieldError(errors, "name")}
|
||||
fullWidth
|
||||
helperText={errors.name}
|
||||
helperText={getFieldError(errors, "name")?.message}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Shipping Zone Name"
|
||||
})}
|
||||
|
|
|
@ -18,8 +18,9 @@ import FormSpacer from "@saleor/components/FormSpacer";
|
|||
import Hr from "@saleor/components/Hr";
|
||||
import Skeleton from "@saleor/components/Skeleton";
|
||||
import { buttonMessages } from "@saleor/intl";
|
||||
import { getFieldError } from "@saleor/utils/errors";
|
||||
import { maybe } from "../../../misc";
|
||||
import { FormErrors, UserError } from "../../../types";
|
||||
import { UserError } from "../../../types";
|
||||
import { ShippingMethodTypeEnum } from "../../../types/globalTypes";
|
||||
import { ShippingZoneDetailsFragment_shippingMethods } from "../../types/ShippingZoneDetailsFragment";
|
||||
|
||||
|
@ -109,17 +110,8 @@ const ShippingZoneRateDialog: React.FC<ShippingZoneRateDialogProps> = props => {
|
|||
|
||||
return (
|
||||
<Dialog onClose={onClose} open={open} fullWidth maxWidth="sm">
|
||||
<Form errors={errors} initial={initialForm} onSubmit={onSubmit}>
|
||||
{({ change, data, errors: formErrors, hasChanged }) => {
|
||||
const typedFormErrors: FormErrors<
|
||||
| "minimumOrderPrice"
|
||||
| "minimumOrderWeight"
|
||||
| "maximumOrderPrice"
|
||||
| "maximumOrderWeight"
|
||||
| "price"
|
||||
| "name"
|
||||
> = formErrors;
|
||||
return (
|
||||
<Form initial={initialForm} onSubmit={onSubmit}>
|
||||
{({ change, data, hasChanged }) => (
|
||||
<>
|
||||
<DialogTitle>
|
||||
{variant === ShippingMethodTypeEnum.PRICE
|
||||
|
@ -147,10 +139,10 @@ const ShippingZoneRateDialog: React.FC<ShippingZoneRateDialogProps> = props => {
|
|||
<DialogContent>
|
||||
<TextField
|
||||
disabled={disabled}
|
||||
error={!!typedFormErrors.name}
|
||||
error={!!getFieldError(errors, "name")}
|
||||
fullWidth
|
||||
helperText={
|
||||
typedFormErrors.name ||
|
||||
getFieldError(errors, "name") ||
|
||||
intl.formatMessage({
|
||||
defaultMessage:
|
||||
"This will be shown to customers at checkout"
|
||||
|
@ -216,22 +208,22 @@ const ShippingZoneRateDialog: React.FC<ShippingZoneRateDialogProps> = props => {
|
|||
disabled={disabled}
|
||||
error={
|
||||
variant === ShippingMethodTypeEnum.PRICE
|
||||
? !!typedFormErrors.minimumOrderPrice
|
||||
: !!typedFormErrors.minimumOrderWeight
|
||||
? !!getFieldError(errors, "minimumOrderPrice")
|
||||
: !!getFieldError(errors, "minimumOrderWeight")
|
||||
}
|
||||
fullWidth
|
||||
helperText={
|
||||
variant === ShippingMethodTypeEnum.PRICE
|
||||
? typedFormErrors.minimumOrderPrice
|
||||
: typedFormErrors.minimumOrderWeight
|
||||
? getFieldError(errors, "minimumOrderPrice")
|
||||
: getFieldError(errors, "minimumOrderWeight")
|
||||
}
|
||||
label={
|
||||
variant === ShippingMethodTypeEnum.PRICE
|
||||
? typedFormErrors.minimumOrderPrice ||
|
||||
? getFieldError(errors, "minimumOrderPrice") ||
|
||||
intl.formatMessage({
|
||||
defaultMessage: "Minimal Order Value"
|
||||
})
|
||||
: typedFormErrors.minimumOrderWeight ||
|
||||
: getFieldError(errors, "minimumOrderWeight") ||
|
||||
intl.formatMessage({
|
||||
defaultMessage: "Minimal Order Weight"
|
||||
})
|
||||
|
@ -245,22 +237,22 @@ const ShippingZoneRateDialog: React.FC<ShippingZoneRateDialogProps> = props => {
|
|||
disabled={disabled}
|
||||
error={
|
||||
variant === ShippingMethodTypeEnum.PRICE
|
||||
? !!typedFormErrors.maximumOrderPrice
|
||||
: !!typedFormErrors.maximumOrderWeight
|
||||
? !!getFieldError(errors, "maximumOrderPrice")
|
||||
: !!getFieldError(errors, "maximumOrderWeight")
|
||||
}
|
||||
fullWidth
|
||||
helperText={
|
||||
variant === ShippingMethodTypeEnum.PRICE
|
||||
? typedFormErrors.maximumOrderPrice
|
||||
: typedFormErrors.maximumOrderWeight
|
||||
? getFieldError(errors, "maximumOrderPrice")
|
||||
: getFieldError(errors, "maximumOrderWeight")
|
||||
}
|
||||
label={
|
||||
variant === ShippingMethodTypeEnum.PRICE
|
||||
? typedFormErrors.maximumOrderPrice ||
|
||||
? getFieldError(errors, "maximumOrderPrice") ||
|
||||
intl.formatMessage({
|
||||
defaultMessage: "Maximal Order Value"
|
||||
})
|
||||
: typedFormErrors.maximumOrderWeight ||
|
||||
: getFieldError(errors, "maximumOrderWeight") ||
|
||||
intl.formatMessage({
|
||||
defaultMessage: "Maximal Order Weight"
|
||||
})
|
||||
|
@ -302,9 +294,9 @@ const ShippingZoneRateDialog: React.FC<ShippingZoneRateDialogProps> = props => {
|
|||
<div className={classes.grid}>
|
||||
<TextField
|
||||
disabled={disabled}
|
||||
error={!!typedFormErrors.price}
|
||||
error={!!getFieldError(errors, "price")}
|
||||
fullWidth
|
||||
helperText={typedFormErrors.price}
|
||||
helperText={getFieldError(errors, "price")?.message}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Rate Price",
|
||||
description: "shipping method price"
|
||||
|
@ -344,8 +336,7 @@ const ShippingZoneRateDialog: React.FC<ShippingZoneRateDialogProps> = props => {
|
|||
</ConfirmButton>
|
||||
</DialogActions>
|
||||
</>
|
||||
);
|
||||
}}
|
||||
)}
|
||||
</Form>
|
||||
</Dialog>
|
||||
);
|
||||
|
|
|
@ -11,16 +11,16 @@ import Grid from "@saleor/components/Grid";
|
|||
import SingleAutocompleteSelectField, {
|
||||
SingleAutocompleteChoiceType
|
||||
} from "@saleor/components/SingleAutocompleteSelectField";
|
||||
import { AddressTypeInput } from "@saleor/customers/types";
|
||||
import { ChangeEvent } from "@saleor/hooks/useForm";
|
||||
import { FormErrors } from "@saleor/types";
|
||||
import { UserError } from "@saleor/types";
|
||||
import { getFieldError } from "@saleor/utils/errors";
|
||||
import { SiteSettingsPageFormData } from "../SiteSettingsPage";
|
||||
|
||||
interface SiteSettingsAddressProps {
|
||||
countries: SingleAutocompleteChoiceType[];
|
||||
data: SiteSettingsPageFormData;
|
||||
displayCountry: string;
|
||||
errors: FormErrors<keyof AddressTypeInput>;
|
||||
errors: UserError[];
|
||||
disabled: boolean;
|
||||
onChange: (event: ChangeEvent) => void;
|
||||
onCountryChange: (event: ChangeEvent) => void;
|
||||
|
@ -60,8 +60,8 @@ const SiteSettingsAddress: React.FC<SiteSettingsAddressProps> = props => {
|
|||
<CardContent>
|
||||
<TextField
|
||||
disabled={disabled}
|
||||
error={!!errors.companyName}
|
||||
helperText={errors.companyName}
|
||||
error={!!getFieldError(errors, "companyName")}
|
||||
helperText={getFieldError(errors, "companyName")?.message}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Company"
|
||||
})}
|
||||
|
@ -73,8 +73,8 @@ const SiteSettingsAddress: React.FC<SiteSettingsAddressProps> = props => {
|
|||
<FormSpacer />
|
||||
<TextField
|
||||
disabled={disabled}
|
||||
error={!!errors.streetAddress1}
|
||||
helperText={errors.streetAddress1}
|
||||
error={!!getFieldError(errors, "streetAddress1")}
|
||||
helperText={getFieldError(errors, "streetAddress1")?.message}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Address line 1"
|
||||
})}
|
||||
|
@ -86,8 +86,8 @@ const SiteSettingsAddress: React.FC<SiteSettingsAddressProps> = props => {
|
|||
<FormSpacer />
|
||||
<TextField
|
||||
disabled={disabled}
|
||||
error={!!errors.streetAddress2}
|
||||
helperText={errors.streetAddress2}
|
||||
error={!!getFieldError(errors, "streetAddress2")}
|
||||
helperText={getFieldError(errors, "streetAddress2")?.message}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Address line 2"
|
||||
})}
|
||||
|
@ -100,8 +100,8 @@ const SiteSettingsAddress: React.FC<SiteSettingsAddressProps> = props => {
|
|||
<Grid>
|
||||
<TextField
|
||||
disabled={disabled}
|
||||
error={!!errors.city}
|
||||
helperText={errors.city}
|
||||
error={!!getFieldError(errors, "city")}
|
||||
helperText={getFieldError(errors, "city")?.message}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "City"
|
||||
})}
|
||||
|
@ -112,8 +112,8 @@ const SiteSettingsAddress: React.FC<SiteSettingsAddressProps> = props => {
|
|||
/>
|
||||
<TextField
|
||||
disabled={disabled}
|
||||
error={!!errors.postalCode}
|
||||
helperText={errors.postalCode}
|
||||
error={!!getFieldError(errors, "postalCode")}
|
||||
helperText={getFieldError(errors, "postalCode")?.message}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "ZIP / Postal code"
|
||||
})}
|
||||
|
@ -128,8 +128,8 @@ const SiteSettingsAddress: React.FC<SiteSettingsAddressProps> = props => {
|
|||
<SingleAutocompleteSelectField
|
||||
disabled={disabled}
|
||||
displayValue={displayCountry}
|
||||
error={!!errors.country}
|
||||
helperText={errors.country}
|
||||
error={!!getFieldError(errors, "country")}
|
||||
helperText={getFieldError(errors, "country")?.message}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Country"
|
||||
})}
|
||||
|
@ -143,8 +143,8 @@ const SiteSettingsAddress: React.FC<SiteSettingsAddressProps> = props => {
|
|||
/>
|
||||
<TextField
|
||||
disabled={disabled}
|
||||
error={!!errors.countryArea}
|
||||
helperText={errors.countryArea}
|
||||
error={!!getFieldError(errors, "companyArea")}
|
||||
helperText={getFieldError(errors, "companyArea")?.message}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Country area"
|
||||
})}
|
||||
|
@ -157,9 +157,9 @@ const SiteSettingsAddress: React.FC<SiteSettingsAddressProps> = props => {
|
|||
<FormSpacer />
|
||||
<TextField
|
||||
disabled={disabled}
|
||||
error={!!errors.phone}
|
||||
error={!!getFieldError(errors, "phone")}
|
||||
fullWidth
|
||||
helperText={errors.phone}
|
||||
helperText={getFieldError(errors, "phone")?.message}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Phone"
|
||||
})}
|
||||
|
|
|
@ -7,15 +7,13 @@ import { useIntl } from "react-intl";
|
|||
import CardTitle from "@saleor/components/CardTitle";
|
||||
import FormSpacer from "@saleor/components/FormSpacer";
|
||||
import { commonMessages } from "@saleor/intl";
|
||||
import { UserError } from "@saleor/types";
|
||||
import { getFieldError } from "@saleor/utils/errors";
|
||||
import { SiteSettingsPageFormData } from "../SiteSettingsPage";
|
||||
|
||||
interface SiteSettingsDetailsProps {
|
||||
data: SiteSettingsPageFormData;
|
||||
errors: Partial<{
|
||||
description: string;
|
||||
domain: string;
|
||||
name: string;
|
||||
}>;
|
||||
errors: UserError[];
|
||||
disabled: boolean;
|
||||
onChange: (event: React.ChangeEvent<any>) => void;
|
||||
}
|
||||
|
@ -36,14 +34,14 @@ const SiteSettingsDetails: React.FC<SiteSettingsDetailsProps> = ({
|
|||
<CardContent>
|
||||
<TextField
|
||||
disabled={disabled}
|
||||
error={!!errors.name}
|
||||
error={!!getFieldError(errors, "name")}
|
||||
fullWidth
|
||||
name="name"
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Name of your store"
|
||||
})}
|
||||
helperText={
|
||||
errors.name ||
|
||||
getFieldError(errors, "name")?.message ||
|
||||
intl.formatMessage({
|
||||
defaultMessage:
|
||||
"Name of your store is shown on tab in web browser"
|
||||
|
@ -55,27 +53,27 @@ const SiteSettingsDetails: React.FC<SiteSettingsDetailsProps> = ({
|
|||
<FormSpacer />
|
||||
<TextField
|
||||
disabled={disabled}
|
||||
error={!!errors.domain}
|
||||
error={!!getFieldError(errors, "domain")}
|
||||
fullWidth
|
||||
name="domain"
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "URL of your online store"
|
||||
})}
|
||||
helperText={errors.domain}
|
||||
helperText={getFieldError(errors, "domain")?.message}
|
||||
value={data.domain}
|
||||
onChange={onChange}
|
||||
/>
|
||||
<FormSpacer />
|
||||
<TextField
|
||||
disabled={disabled}
|
||||
error={!!errors.domain}
|
||||
error={!!getFieldError(errors, "description")}
|
||||
fullWidth
|
||||
name="description"
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Store Description"
|
||||
})}
|
||||
helperText={
|
||||
errors.description ||
|
||||
getFieldError(errors, "description")?.message ||
|
||||
intl.formatMessage({
|
||||
defaultMessage:
|
||||
"Store description is shown on taskbar after your store name"
|
||||
|
|
|
@ -7,10 +7,12 @@ import TextField from "@material-ui/core/TextField";
|
|||
import React from "react";
|
||||
import { FormattedMessage, useIntl } from "react-intl";
|
||||
|
||||
import Form, { FormProps } from "@saleor/components/Form";
|
||||
import Form from "@saleor/components/Form";
|
||||
import { FormSpacer } from "@saleor/components/FormSpacer";
|
||||
import SingleSelectField from "@saleor/components/SingleSelectField";
|
||||
import { buttonMessages } from "@saleor/intl";
|
||||
import { UserError, DialogProps } from "@saleor/types";
|
||||
import { getFieldError } from "@saleor/utils/errors";
|
||||
import { authorizationKeyTypes } from "../../../misc";
|
||||
import { AuthorizationKeyType } from "../../../types/globalTypes";
|
||||
|
||||
|
@ -20,13 +22,10 @@ export interface SiteSettingsKeyDialogForm {
|
|||
type: AuthorizationKeyType;
|
||||
}
|
||||
|
||||
export interface SiteSettingsKeyDialogProps
|
||||
extends Pick<
|
||||
FormProps<SiteSettingsKeyDialogForm>,
|
||||
Exclude<keyof FormProps<SiteSettingsKeyDialogForm>, "children">
|
||||
> {
|
||||
open: boolean;
|
||||
onClose: () => void;
|
||||
export interface SiteSettingsKeyDialogProps extends DialogProps {
|
||||
errors: UserError[];
|
||||
initial: SiteSettingsKeyDialogForm;
|
||||
onSubmit: (data: SiteSettingsKeyDialogForm) => void;
|
||||
}
|
||||
|
||||
const SiteSettingsKeyDialog: React.FC<SiteSettingsKeyDialogProps> = ({
|
||||
|
@ -40,8 +39,8 @@ const SiteSettingsKeyDialog: React.FC<SiteSettingsKeyDialogProps> = ({
|
|||
|
||||
return (
|
||||
<Dialog onClose={onClose} maxWidth="xs" open={open}>
|
||||
<Form initial={initial} onSubmit={onSubmit} errors={errors}>
|
||||
{({ change, data, errors }) => (
|
||||
<Form initial={initial} onSubmit={onSubmit}>
|
||||
{({ change, data }) => (
|
||||
<>
|
||||
<DialogTitle>
|
||||
<FormattedMessage
|
||||
|
@ -55,37 +54,37 @@ const SiteSettingsKeyDialog: React.FC<SiteSettingsKeyDialogProps> = ({
|
|||
label: authorizationKeyTypes[key],
|
||||
value: key
|
||||
}))}
|
||||
error={!!errors.keyType}
|
||||
error={!!getFieldError(errors, "keyType")}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Authentication type",
|
||||
description: "authentication provider name"
|
||||
})}
|
||||
hint={errors.keyType}
|
||||
hint={getFieldError(errors, "keyType")?.message}
|
||||
name="type"
|
||||
onChange={change}
|
||||
value={data.type}
|
||||
/>
|
||||
<FormSpacer />
|
||||
<TextField
|
||||
error={!!errors.key}
|
||||
error={!!getFieldError(errors, "key")}
|
||||
fullWidth
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Key",
|
||||
description: "authentication provider API key"
|
||||
})}
|
||||
helperText={errors.key}
|
||||
helperText={getFieldError(errors, "key")?.message}
|
||||
name="key"
|
||||
onChange={change}
|
||||
value={data.key}
|
||||
/>
|
||||
<FormSpacer />
|
||||
<TextField
|
||||
error={!!errors.password}
|
||||
error={!!getFieldError(errors, "password")}
|
||||
fullWidth
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Password"
|
||||
})}
|
||||
helperText={errors.password}
|
||||
helperText={getFieldError(errors, "password")?.message}
|
||||
name="password"
|
||||
onChange={change}
|
||||
value={data.password}
|
||||
|
|
|
@ -9,7 +9,8 @@ import { FormattedMessage, useIntl } from "react-intl";
|
|||
import CardTitle from "@saleor/components/CardTitle";
|
||||
import FormSpacer from "@saleor/components/FormSpacer";
|
||||
import Hr from "@saleor/components/Hr";
|
||||
import { FormErrors } from "@saleor/types";
|
||||
import { UserError } from "@saleor/types";
|
||||
import { getFieldError } from "@saleor/utils/errors";
|
||||
|
||||
export interface SiteSettingsMailingFormData {
|
||||
defaultMailSenderName: string;
|
||||
|
@ -18,11 +19,7 @@ export interface SiteSettingsMailingFormData {
|
|||
}
|
||||
interface SiteSettingsMailingProps {
|
||||
data: SiteSettingsMailingFormData;
|
||||
errors: FormErrors<
|
||||
| "defaultMailSenderAddress"
|
||||
| "defaultMailSenderName"
|
||||
| "customerSetPasswordUrl"
|
||||
>;
|
||||
errors: UserError[];
|
||||
disabled: boolean;
|
||||
onChange: (event: React.ChangeEvent<any>) => void;
|
||||
}
|
||||
|
@ -68,27 +65,29 @@ const SiteSettingsMailing: React.FC<SiteSettingsMailingProps> = props => {
|
|||
</Typography>
|
||||
<TextField
|
||||
disabled={disabled}
|
||||
error={!!errors.defaultMailSenderAddress}
|
||||
error={!!getFieldError(errors, "defaultMailSenderAddress")}
|
||||
fullWidth
|
||||
name="defaultMailSenderAddress"
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Mailing email address"
|
||||
})}
|
||||
helperText={errors.defaultMailSenderAddress}
|
||||
helperText={
|
||||
getFieldError(errors, "defaultMailSenderAddress")?.message
|
||||
}
|
||||
value={data.defaultMailSenderAddress}
|
||||
onChange={onChange}
|
||||
/>
|
||||
<FormSpacer />
|
||||
<TextField
|
||||
disabled={disabled}
|
||||
error={!!errors.defaultMailSenderName}
|
||||
error={!!getFieldError(errors, "defaultMailSenderName")}
|
||||
fullWidth
|
||||
name="defaultMailSenderName"
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Mailing email sender"
|
||||
})}
|
||||
helperText={
|
||||
errors.defaultMailSenderName ||
|
||||
getFieldError(errors, "defaultMailSenderName")?.message ||
|
||||
intl.formatMessage({
|
||||
defaultMessage: 'This will be visible as "from" name',
|
||||
description: "email sender"
|
||||
|
@ -102,7 +101,7 @@ const SiteSettingsMailing: React.FC<SiteSettingsMailingProps> = props => {
|
|||
<FormSpacer />
|
||||
<TextField
|
||||
disabled={disabled}
|
||||
error={!!errors.customerSetPasswordUrl}
|
||||
error={!!getFieldError(errors, "customerSetPasswordUrl")}
|
||||
fullWidth
|
||||
name="customerSetPasswordUrl"
|
||||
label={intl.formatMessage({
|
||||
|
@ -112,7 +111,7 @@ const SiteSettingsMailing: React.FC<SiteSettingsMailingProps> = props => {
|
|||
defaultMessage: "URL address"
|
||||
})}
|
||||
helperText={
|
||||
errors.customerSetPasswordUrl ||
|
||||
getFieldError(errors, "customerSetPasswordUrl")?.message ||
|
||||
intl.formatMessage({
|
||||
defaultMessage:
|
||||
"This URL will be used as a main URL for password resets. It will be sent via email."
|
||||
|
|
|
@ -127,9 +127,10 @@ const SiteSettingsPage: React.FC<SiteSettingsPageProps> = props => {
|
|||
name: maybe(() => shop.name, "")
|
||||
};
|
||||
|
||||
const formErrors = [...errors, ...validationErrors];
|
||||
|
||||
return (
|
||||
<Form
|
||||
errors={[...errors, ...validationErrors]}
|
||||
initial={initialForm}
|
||||
onSubmit={data => {
|
||||
const submitFunc = areAddressInputFieldsModified(data)
|
||||
|
@ -139,8 +140,7 @@ const SiteSettingsPage: React.FC<SiteSettingsPageProps> = props => {
|
|||
}}
|
||||
confirmLeave
|
||||
>
|
||||
{({ change, data, errors: formErrors, hasChanged, submit }) => {
|
||||
const siteFormErrors = { ...formErrors };
|
||||
{({ change, data, hasChanged, submit }) => {
|
||||
const countryChoices = mapCountriesToChoices(
|
||||
maybe(() => shop.countries, [])
|
||||
);
|
||||
|
@ -169,7 +169,7 @@ const SiteSettingsPage: React.FC<SiteSettingsPageProps> = props => {
|
|||
</div>
|
||||
<SiteSettingsDetails
|
||||
data={data}
|
||||
errors={siteFormErrors}
|
||||
errors={formErrors}
|
||||
disabled={disabled}
|
||||
onChange={change}
|
||||
/>
|
||||
|
@ -187,7 +187,7 @@ const SiteSettingsPage: React.FC<SiteSettingsPageProps> = props => {
|
|||
</div>
|
||||
<SiteSettingsMailing
|
||||
data={data}
|
||||
errors={siteFormErrors}
|
||||
errors={formErrors}
|
||||
disabled={disabled}
|
||||
onChange={change}
|
||||
/>
|
||||
|
@ -208,7 +208,7 @@ const SiteSettingsPage: React.FC<SiteSettingsPageProps> = props => {
|
|||
data={data}
|
||||
displayCountry={displayCountry}
|
||||
countries={countryChoices}
|
||||
errors={siteFormErrors}
|
||||
errors={formErrors}
|
||||
disabled={disabled}
|
||||
onChange={change}
|
||||
onCountryChange={handleCountryChange}
|
||||
|
|
|
@ -16,6 +16,8 @@ import { ControlledCheckbox } from "@saleor/components/ControlledCheckbox";
|
|||
import Form from "@saleor/components/Form";
|
||||
import FormSpacer from "@saleor/components/FormSpacer";
|
||||
import { buttonMessages, commonMessages } from "@saleor/intl";
|
||||
import useModalDialogErrors from "@saleor/hooks/useModalDialogErrors";
|
||||
import { getFieldError } from "@saleor/utils/errors";
|
||||
import { UserError } from "../../../types";
|
||||
|
||||
export interface FormData {
|
||||
|
@ -65,13 +67,14 @@ interface StaffAddMemberDialogProps {
|
|||
const StaffAddMemberDialog: React.FC<StaffAddMemberDialogProps> = props => {
|
||||
const { confirmButtonState, errors, open, onClose, onConfirm } = props;
|
||||
const classes = useStyles(props);
|
||||
const dialogErrors = useModalDialogErrors(errors, open);
|
||||
|
||||
const intl = useIntl();
|
||||
|
||||
return (
|
||||
<Dialog onClose={onClose} open={open}>
|
||||
<Form errors={errors} initial={initialForm} onSubmit={onConfirm}>
|
||||
{({ change, data, errors: formErrors, hasChanged }) => (
|
||||
<Form initial={initialForm} onSubmit={onConfirm}>
|
||||
{({ change, data, hasChanged }) => (
|
||||
<>
|
||||
<DialogTitle>
|
||||
<FormattedMessage
|
||||
|
@ -82,8 +85,8 @@ const StaffAddMemberDialog: React.FC<StaffAddMemberDialogProps> = props => {
|
|||
<DialogContent>
|
||||
<div className={classes.textFieldGrid}>
|
||||
<TextField
|
||||
error={!!formErrors.firstName}
|
||||
helperText={formErrors.firstName}
|
||||
error={!!getFieldError(dialogErrors, "firstName")}
|
||||
helperText={getFieldError(dialogErrors, "firstName")?.message}
|
||||
label={intl.formatMessage(commonMessages.firstName)}
|
||||
name="firstName"
|
||||
type="text"
|
||||
|
@ -91,8 +94,8 @@ const StaffAddMemberDialog: React.FC<StaffAddMemberDialogProps> = props => {
|
|||
onChange={change}
|
||||
/>
|
||||
<TextField
|
||||
error={!!formErrors.lastName}
|
||||
helperText={formErrors.lastName}
|
||||
error={!!getFieldError(dialogErrors, "lastName")}
|
||||
helperText={getFieldError(dialogErrors, "lastName")?.message}
|
||||
label={intl.formatMessage(commonMessages.lastName)}
|
||||
name="lastName"
|
||||
type="text"
|
||||
|
@ -102,9 +105,9 @@ const StaffAddMemberDialog: React.FC<StaffAddMemberDialogProps> = props => {
|
|||
</div>
|
||||
<FormSpacer />
|
||||
<TextField
|
||||
error={!!formErrors.email}
|
||||
error={!!getFieldError(dialogErrors, "email")}
|
||||
fullWidth
|
||||
helperText={formErrors.email}
|
||||
helperText={getFieldError(dialogErrors, "email")?.message}
|
||||
label={intl.formatMessage(commonMessages.email)}
|
||||
name="email"
|
||||
type="email"
|
||||
|
|
|
@ -15,6 +15,7 @@ import ConfirmButton, {
|
|||
} from "@saleor/components/ConfirmButton";
|
||||
import FormSpacer from "@saleor/components/FormSpacer";
|
||||
import useModalDialogErrors from "@saleor/hooks/useModalDialogErrors";
|
||||
import { getFieldError } from "@saleor/utils/errors";
|
||||
|
||||
interface StaffPasswordResetDialogFormData {
|
||||
newPassword: string;
|
||||
|
@ -33,13 +34,13 @@ const initialForm: StaffPasswordResetDialogFormData = {
|
|||
|
||||
const StaffPasswordResetDialog: React.FC<StaffPasswordResetDialogProps> = ({
|
||||
confirmButtonState,
|
||||
errors: apiErrors,
|
||||
errors,
|
||||
open,
|
||||
onClose,
|
||||
onSubmit
|
||||
}) => {
|
||||
const intl = useIntl();
|
||||
const dialogErrors = useModalDialogErrors(apiErrors, open);
|
||||
const dialogErrors = useModalDialogErrors(errors, open);
|
||||
|
||||
return (
|
||||
<Dialog onClose={onClose} open={open} fullWidth maxWidth="sm">
|
||||
|
@ -49,14 +50,14 @@ const StaffPasswordResetDialog: React.FC<StaffPasswordResetDialogProps> = ({
|
|||
description="dialog header"
|
||||
/>
|
||||
</DialogTitle>
|
||||
<Form errors={dialogErrors} initial={initialForm} onSubmit={onSubmit}>
|
||||
{({ change, data, errors, submit }) => (
|
||||
<Form initial={initialForm} onSubmit={onSubmit}>
|
||||
{({ change, data, submit }) => (
|
||||
<>
|
||||
<DialogContent>
|
||||
<TextField
|
||||
error={!!errors.oldPassword}
|
||||
error={!!getFieldError(dialogErrors, "oldPassword")}
|
||||
fullWidth
|
||||
helperText={errors.oldPassword}
|
||||
helperText={getFieldError(dialogErrors, "oldPassword")?.message}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Previous Password",
|
||||
description: "input label"
|
||||
|
@ -67,10 +68,10 @@ const StaffPasswordResetDialog: React.FC<StaffPasswordResetDialogProps> = ({
|
|||
/>
|
||||
<FormSpacer />
|
||||
<TextField
|
||||
error={!!errors.newPassword}
|
||||
error={!!getFieldError(dialogErrors, "newPassword")}
|
||||
fullWidth
|
||||
helperText={
|
||||
errors.newPassword ||
|
||||
getFieldError(dialogErrors, "newPassword") ||
|
||||
intl.formatMessage({
|
||||
defaultMessage:
|
||||
"New password must be at least 8 characters long"
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -4,6 +4,7 @@ import React from "react";
|
|||
|
||||
import placeholderCollectionImage from "@assets/images/block1.jpg";
|
||||
import placeholderProductImage from "@assets/images/placeholder60x60.png";
|
||||
import { formError } from "@saleor/storybook/misc";
|
||||
import CollectionDetailsPage, {
|
||||
CollectionDetailsPageProps
|
||||
} from "../../../collections/components/CollectionDetailsPage";
|
||||
|
@ -21,6 +22,7 @@ const props: Omit<CollectionDetailsPageProps, "classes"> = {
|
|||
...pageListProps.default,
|
||||
collection,
|
||||
disabled: false,
|
||||
errors: [],
|
||||
isFeatured: true,
|
||||
onBack: () => undefined,
|
||||
onCollectionRemove: () => undefined,
|
||||
|
@ -37,6 +39,14 @@ storiesOf("Views / Collections / Collection details", module)
|
|||
.add("loading", () => (
|
||||
<CollectionDetailsPage {...props} collection={undefined} disabled={true} />
|
||||
))
|
||||
.add("form errors", () => (
|
||||
<CollectionDetailsPage
|
||||
{...props}
|
||||
errors={["name", "descriptionJson", "publicationDate", "isPublished"].map(
|
||||
formError
|
||||
)}
|
||||
/>
|
||||
))
|
||||
.add("no products", () => (
|
||||
<CollectionDetailsPage
|
||||
{...props}
|
||||
|
|
|
@ -20,7 +20,7 @@ storiesOf("Generics / AddressEdit", module)
|
|||
>
|
||||
<CardContent>
|
||||
<AddressEdit
|
||||
errors={{}}
|
||||
errors={[]}
|
||||
data={transformAddressToForm(customer.defaultBillingAddress)}
|
||||
countries={countries.map(c => ({
|
||||
label: c.label,
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { storiesOf } from "@storybook/react";
|
||||
import React from "react";
|
||||
|
||||
import { formError } from "@saleor/storybook/misc";
|
||||
import MenuCreateDialog, {
|
||||
MenuCreateDialogProps
|
||||
} from "../../../navigation/components/MenuCreateDialog";
|
||||
|
@ -9,6 +10,7 @@ import Decorator from "../../Decorator";
|
|||
const props: MenuCreateDialogProps = {
|
||||
confirmButtonState: "default",
|
||||
disabled: false,
|
||||
errors: [],
|
||||
onClose: () => undefined,
|
||||
onConfirm: () => undefined,
|
||||
open: true
|
||||
|
@ -19,4 +21,7 @@ storiesOf("Navigation / Menu create", module)
|
|||
.add("default", () => <MenuCreateDialog {...props} />)
|
||||
.add("loading", () => (
|
||||
<MenuCreateDialog {...props} disabled={true} confirmButtonState="loading" />
|
||||
))
|
||||
.add("form errors", () => (
|
||||
<MenuCreateDialog {...props} errors={["name"].map(formError)} />
|
||||
));
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { storiesOf } from "@storybook/react";
|
||||
import React from "react";
|
||||
|
||||
import { formError } from "@saleor/storybook/misc";
|
||||
import ProductTypeAttributeEditDialog, {
|
||||
ProductTypeAttributeEditDialogProps
|
||||
} from "../../../productTypes/components/ProductTypeAttributeEditDialog";
|
||||
|
@ -32,10 +33,6 @@ storiesOf("Product types / Edit attribute", module)
|
|||
.add("form errors", () => (
|
||||
<ProductTypeAttributeEditDialog
|
||||
{...props}
|
||||
// errors={["name", "values"].map(field => formError(field))}
|
||||
errors={["name", "values"].map(field => ({
|
||||
field,
|
||||
message: "Generic error"
|
||||
}))}
|
||||
errors={["name", "values"].map(field => formError(field))}
|
||||
/>
|
||||
));
|
||||
|
|
|
@ -16,6 +16,7 @@ const props: SiteSettingsKeyDialogProps = {
|
|||
type: AuthorizationKeyType.FACEBOOK
|
||||
},
|
||||
onClose: () => undefined,
|
||||
onSubmit: () => undefined,
|
||||
open: true
|
||||
};
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ import { IFilter } from "./components/Filter";
|
|||
import { MultiAutocompleteChoiceType } from "./components/MultiAutocompleteSelectField";
|
||||
|
||||
export interface UserError {
|
||||
field: string;
|
||||
field: string | null;
|
||||
message: string;
|
||||
}
|
||||
|
||||
|
@ -116,8 +116,6 @@ export interface Node {
|
|||
id: string;
|
||||
}
|
||||
|
||||
export type FormErrors<TKeys extends string> = Partial<Record<TKeys, string>>;
|
||||
|
||||
export type Pagination = Partial<{
|
||||
after: string;
|
||||
before: string;
|
||||
|
|
|
@ -1,10 +1,7 @@
|
|||
import { maybe } from "@saleor/misc";
|
||||
import { UserError } from "@saleor/types";
|
||||
|
||||
export function getFieldError(errors: UserError[], field: string): string {
|
||||
const err = errors.find(err => err.field === field);
|
||||
|
||||
return maybe(() => err.message);
|
||||
export function getFieldError(errors: UserError[], field: string): UserError {
|
||||
return errors.find(err => err.field === field);
|
||||
}
|
||||
|
||||
export function getErrors(errors: UserError[]): string[] {
|
||||
|
|
|
@ -40,7 +40,7 @@ export interface WebhookCreatePageProps {
|
|||
|
||||
const WebhookCreatePage: React.FC<WebhookCreatePageProps> = ({
|
||||
disabled,
|
||||
errors: apiErrors,
|
||||
errors,
|
||||
saveButtonBarState,
|
||||
services,
|
||||
fetchServiceAccounts,
|
||||
|
@ -70,8 +70,8 @@ const WebhookCreatePage: React.FC<WebhookCreatePageProps> = ({
|
|||
);
|
||||
|
||||
return (
|
||||
<Form errors={apiErrors} initial={initialForm} onSubmit={onSubmit}>
|
||||
{({ data, errors, hasChanged, submit, change }) => {
|
||||
<Form initial={initialForm} onSubmit={onSubmit}>
|
||||
{({ data, hasChanged, submit, change }) => {
|
||||
const handleServiceSelect = createSingleAutocompleteSelectHandler(
|
||||
change,
|
||||
setSelectedServiceAcccount,
|
||||
|
@ -93,11 +93,10 @@ const WebhookCreatePage: React.FC<WebhookCreatePageProps> = ({
|
|||
<WebhookInfo
|
||||
data={data}
|
||||
disabled={disabled}
|
||||
errors={errors}
|
||||
fetchServiceAccounts={fetchServiceAccounts}
|
||||
serviceDisplayValue={selectedServiceAcccount}
|
||||
services={servicesChoiceList}
|
||||
fetchServiceAccounts={fetchServiceAccounts}
|
||||
apiErrors={apiErrors}
|
||||
errors={errors}
|
||||
serviceOnChange={handleServiceSelect}
|
||||
onChange={change}
|
||||
/>
|
||||
|
|
|
@ -14,17 +14,16 @@ import SingleAutocompleteSelectField, {
|
|||
} from "@saleor/components/SingleAutocompleteSelectField";
|
||||
import { ChangeEvent } from "@saleor/hooks/useForm";
|
||||
import { commonMessages } from "@saleor/intl";
|
||||
import { FormErrors } from "@saleor/types";
|
||||
import { WebhookCreate_webhookCreate_webhookErrors } from "@saleor/webhooks/types/WebhookCreate";
|
||||
import { getFieldError } from "@saleor/utils/errors";
|
||||
import { FormData } from "../WebhooksDetailsPage";
|
||||
|
||||
interface WebhookInfoProps {
|
||||
apiErrors: WebhookCreate_webhookCreate_webhookErrors[];
|
||||
data: FormData;
|
||||
disabled: boolean;
|
||||
errors: WebhookCreate_webhookCreate_webhookErrors[];
|
||||
serviceDisplayValue: string;
|
||||
services: SingleAutocompleteChoiceType[];
|
||||
errors: FormErrors<"name" | "targetUrl" | "secretKey">;
|
||||
onChange: (event: React.ChangeEvent<any>) => void;
|
||||
serviceOnChange: (event: ChangeEvent) => void;
|
||||
fetchServiceAccounts: (data: string) => void;
|
||||
|
@ -45,7 +44,6 @@ const useStyles = makeStyles(
|
|||
);
|
||||
|
||||
const WebhookInfo: React.FC<WebhookInfoProps> = ({
|
||||
apiErrors,
|
||||
data,
|
||||
disabled,
|
||||
services,
|
||||
|
@ -58,7 +56,7 @@ const WebhookInfo: React.FC<WebhookInfoProps> = ({
|
|||
const classes = useStyles({});
|
||||
const intl = useIntl();
|
||||
const serviceAccountsError =
|
||||
apiErrors.filter(error => error.field === null).length > 0;
|
||||
errors.filter(error => error.field === null).length > 0;
|
||||
|
||||
return (
|
||||
<Card>
|
||||
|
@ -74,8 +72,8 @@ const WebhookInfo: React.FC<WebhookInfoProps> = ({
|
|||
</Typography>
|
||||
<TextField
|
||||
disabled={disabled}
|
||||
error={!!errors.name}
|
||||
helperText={errors.name}
|
||||
error={!!getFieldError(errors, "name")}
|
||||
helperText={getFieldError(errors, "name")?.message}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Webhook Name",
|
||||
description: "webhook"
|
||||
|
@ -117,11 +115,14 @@ const WebhookInfo: React.FC<WebhookInfoProps> = ({
|
|||
<FormSpacer />
|
||||
<TextField
|
||||
disabled={disabled}
|
||||
error={!!errors.targetUrl}
|
||||
helperText={intl.formatMessage({
|
||||
error={!!getFieldError(errors, "targetUrl")}
|
||||
helperText={
|
||||
getFieldError(errors, "targetUrl")?.message ||
|
||||
intl.formatMessage({
|
||||
defaultMessage: "This URL will receive webhook POST requests",
|
||||
description: "webhook target url help text"
|
||||
})}
|
||||
})
|
||||
}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Target URL",
|
||||
description: "webhook"
|
||||
|
@ -134,12 +135,15 @@ const WebhookInfo: React.FC<WebhookInfoProps> = ({
|
|||
<FormSpacer />
|
||||
<TextField
|
||||
disabled={disabled}
|
||||
error={!!errors.secretKey}
|
||||
helperText={intl.formatMessage({
|
||||
error={!!getFieldError(errors, "secretKey")}
|
||||
helperText={
|
||||
getFieldError(errors, "secretKey")?.message ||
|
||||
intl.formatMessage({
|
||||
defaultMessage:
|
||||
"secret key is used to create a hash signature with each payload. *optional field",
|
||||
description: "webhook secret key help text"
|
||||
})}
|
||||
})
|
||||
}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Secrect Key",
|
||||
description: "webhook"
|
||||
|
|
|
@ -45,7 +45,7 @@ export interface WebhooksDetailsPageProps {
|
|||
|
||||
const WebhooksDetailsPage: React.FC<WebhooksDetailsPageProps> = ({
|
||||
disabled,
|
||||
errors: apiErrors,
|
||||
errors,
|
||||
webhook,
|
||||
saveButtonBarState,
|
||||
services,
|
||||
|
@ -81,8 +81,8 @@ const WebhooksDetailsPage: React.FC<WebhooksDetailsPageProps> = ({
|
|||
[]
|
||||
);
|
||||
return (
|
||||
<Form errors={apiErrors} initial={initialForm} onSubmit={onSubmit}>
|
||||
{({ data, errors, hasChanged, submit, change }) => {
|
||||
<Form initial={initialForm} onSubmit={onSubmit}>
|
||||
{({ data, hasChanged, submit, change }) => {
|
||||
const handleServiceSelect = createSingleAutocompleteSelectHandler(
|
||||
change,
|
||||
setSelectedServiceAcccounts,
|
||||
|
@ -107,7 +107,6 @@ const WebhooksDetailsPage: React.FC<WebhooksDetailsPageProps> = ({
|
|||
<Grid>
|
||||
<div>
|
||||
<WebhookInfo
|
||||
apiErrors={apiErrors}
|
||||
data={data}
|
||||
disabled={disabled}
|
||||
serviceDisplayValue={selectedServiceAcccounts}
|
||||
|
|
Loading…
Reference in a new issue