diff --git a/src/fragments/types/ProductErrorFragment.ts b/src/fragments/types/ProductErrorFragment.ts index 2f4d1fccb..fff392cb5 100644 --- a/src/fragments/types/ProductErrorFragment.ts +++ b/src/fragments/types/ProductErrorFragment.ts @@ -10,6 +10,7 @@ import { ProductErrorCode } from "./../../types/globalTypes"; export interface ProductErrorFragment { __typename: "ProductError"; + attributeId: string | null; code: ProductErrorCode; field: string | null; } diff --git a/src/products/components/ProductAttributes/ProductAttributes.tsx b/src/products/components/ProductAttributes/ProductAttributes.tsx index c6018c2ef..a25df70e2 100644 --- a/src/products/components/ProductAttributes/ProductAttributes.tsx +++ b/src/products/components/ProductAttributes/ProductAttributes.tsx @@ -13,10 +13,12 @@ import MultiAutocompleteSelectField, { import SingleAutocompleteSelectField, { SingleAutocompleteChoiceType } from "@saleor/components/SingleAutocompleteSelectField"; +import { ProductErrorFragment } from "@saleor/fragments/types/ProductErrorFragment"; import { FormsetAtomicData, FormsetChange } from "@saleor/hooks/useFormset"; import { maybe } from "@saleor/misc"; import { ProductDetails_product_attributes_attribute_values } from "@saleor/products/types/ProductDetails"; import { AttributeInputTypeEnum } from "@saleor/types/globalTypes"; +import { getProductErrorMessage } from "@saleor/utils/errors"; import classNames from "classnames"; import React from "react"; import { FormattedMessage, useIntl } from "react-intl"; @@ -33,6 +35,7 @@ export type ProductAttributeInput = FormsetAtomicData< export interface ProductAttributesProps { attributes: ProductAttributeInput[]; disabled: boolean; + errors: ProductErrorFragment[]; onChange: FormsetChange; onMultiChange: FormsetChange; } @@ -125,6 +128,7 @@ function getSingleChoices( const ProductAttributes: React.FC = ({ attributes, disabled, + errors, onChange, onMultiChange }) => { @@ -169,61 +173,71 @@ const ProductAttributes: React.FC = ({ {expanded && attributes.length > 0 && ( <>
- {attributes.map((attribute, attributeIndex) => ( - - {attributeIndex > 0 &&
} - -
- {attribute.label} -
-
- {attribute.data.inputType === - AttributeInputTypeEnum.DROPDOWN ? ( - - attribute.data.values.find( - value => value.slug === attribute.value[0] - ).name, - attribute.value[0] - )} - emptyOption - name={`attribute:${attribute.label}`} - label={intl.formatMessage({ - defaultMessage: "Value", - description: "attribute value" - })} - value={attribute.value[0]} - onChange={event => - onChange(attribute.id, event.target.value) - } - allowCustomValues={!attribute.data.isRequired} - /> - ) : ( - - onMultiChange(attribute.id, event.target.value) - } - allowCustomValues={!attribute.data.isRequired} - /> - )} -
-
-
- ))} + {attributes.map((attribute, attributeIndex) => { + const error = errors.find( + err => err.attributeId === attribute.id + ); + + return ( + + {attributeIndex > 0 &&
} + +
+ {attribute.label} +
+
+ {attribute.data.inputType === + AttributeInputTypeEnum.DROPDOWN ? ( + + attribute.data.values.find( + value => value.slug === attribute.value[0] + ).name, + attribute.value[0] + )} + emptyOption + error={!!error} + helperText={getProductErrorMessage(error, intl)} + name={`attribute:${attribute.label}`} + label={intl.formatMessage({ + defaultMessage: "Value", + description: "attribute value" + })} + value={attribute.value[0]} + onChange={event => + onChange(attribute.id, event.target.value) + } + allowCustomValues={!attribute.data.isRequired} + /> + ) : ( + + onMultiChange(attribute.id, event.target.value) + } + allowCustomValues={!attribute.data.isRequired} + /> + )} +
+
+
+ ); + })} )} diff --git a/src/products/components/ProductUpdatePage/ProductUpdatePage.tsx b/src/products/components/ProductUpdatePage/ProductUpdatePage.tsx index 8160eff20..a4e9fd0d9 100644 --- a/src/products/components/ProductUpdatePage/ProductUpdatePage.tsx +++ b/src/products/components/ProductUpdatePage/ProductUpdatePage.tsx @@ -296,6 +296,7 @@ export const ProductUpdatePage: React.FC = ({ {attributes.length > 0 && ( ).map(field => ({ - __typename: "ProductError", - code: ProductErrorCode.INVALID, - field - }))} + ] as Array).map( + field => ({ + __typename: "ProductError", + attributeId: + field === "attributes" ? product.attributes[0].attribute.id : null, + code: ProductErrorCode.INVALID, + field + }) + )} /> ));