Handle attribute errors in product views
This commit is contained in:
parent
369fd09853
commit
ee1ecff1f8
6 changed files with 51 additions and 26 deletions
|
@ -8,10 +8,10 @@ import SingleAutocompleteSelectField, {
|
||||||
SingleAutocompleteChoiceType
|
SingleAutocompleteChoiceType
|
||||||
} from "@saleor/components/SingleAutocompleteSelectField";
|
} from "@saleor/components/SingleAutocompleteSelectField";
|
||||||
import Skeleton from "@saleor/components/Skeleton";
|
import Skeleton from "@saleor/components/Skeleton";
|
||||||
|
import { ProductErrorFragment } from "@saleor/fragments/types/ProductErrorFragment";
|
||||||
import { ProductVariant_attributes_attribute_values } from "@saleor/fragments/types/ProductVariant";
|
import { ProductVariant_attributes_attribute_values } from "@saleor/fragments/types/ProductVariant";
|
||||||
import { FormsetAtomicData, FormsetChange } from "@saleor/hooks/useFormset";
|
import { FormsetAtomicData, FormsetChange } from "@saleor/hooks/useFormset";
|
||||||
import { commonMessages } from "@saleor/intl";
|
import { commonMessages } from "@saleor/intl";
|
||||||
import { VariantCreate_productVariantCreate_errors } from "@saleor/products/types/VariantCreate";
|
|
||||||
import { getProductVariantAttributeErrorMessage } from "@saleor/utils/errors/product";
|
import { getProductVariantAttributeErrorMessage } from "@saleor/utils/errors/product";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { useIntl } from "react-intl";
|
import { useIntl } from "react-intl";
|
||||||
|
@ -27,7 +27,7 @@ export type VariantAttributeInput = FormsetAtomicData<
|
||||||
interface ProductVariantAttributesProps {
|
interface ProductVariantAttributesProps {
|
||||||
attributes: VariantAttributeInput[];
|
attributes: VariantAttributeInput[];
|
||||||
disabled: boolean;
|
disabled: boolean;
|
||||||
errors: VariantCreate_productVariantCreate_errors[];
|
errors: ProductErrorFragment[];
|
||||||
onChange: FormsetChange<VariantAttributeInputData>;
|
onChange: FormsetChange<VariantAttributeInputData>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,7 +84,12 @@ const ProductVariantAttributes: React.FC<ProductVariantAttributesProps> = ({
|
||||||
{attributes === undefined ? (
|
{attributes === undefined ? (
|
||||||
<Skeleton />
|
<Skeleton />
|
||||||
) : (
|
) : (
|
||||||
attributes.map(attribute => (
|
attributes.map(attribute => {
|
||||||
|
const error = errors.find(
|
||||||
|
err => err.attributeId === attribute.id
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
<SingleAutocompleteSelectField
|
<SingleAutocompleteSelectField
|
||||||
key={attribute.id}
|
key={attribute.id}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
|
@ -93,6 +98,12 @@ const ProductVariantAttributes: React.FC<ProductVariantAttributesProps> = ({
|
||||||
attribute.value,
|
attribute.value,
|
||||||
attributes
|
attributes
|
||||||
)}
|
)}
|
||||||
|
emptyOption
|
||||||
|
error={!!error}
|
||||||
|
helperText={getProductVariantAttributeErrorMessage(
|
||||||
|
error,
|
||||||
|
intl
|
||||||
|
)}
|
||||||
label={attribute.label}
|
label={attribute.label}
|
||||||
name={`attribute:${attribute.id}`}
|
name={`attribute:${attribute.id}`}
|
||||||
onChange={event => onChange(attribute.id, event.target.value)}
|
onChange={event => onChange(attribute.id, event.target.value)}
|
||||||
|
@ -101,14 +112,18 @@ const ProductVariantAttributes: React.FC<ProductVariantAttributesProps> = ({
|
||||||
allowCustomValues
|
allowCustomValues
|
||||||
data-test="variant-attribute-input"
|
data-test="variant-attribute-input"
|
||||||
/>
|
/>
|
||||||
))
|
);
|
||||||
|
})
|
||||||
)}
|
)}
|
||||||
</Grid>
|
</Grid>
|
||||||
{errors.length > 0 && (
|
{errors.length > 0 && (
|
||||||
<>
|
<>
|
||||||
<FormSpacer />
|
<FormSpacer />
|
||||||
{errors
|
{errors
|
||||||
.filter(error => error.field === "attributes")
|
.filter(
|
||||||
|
error =>
|
||||||
|
error.field === "attributes" && error.attributeId === null
|
||||||
|
)
|
||||||
.map(error => (
|
.map(error => (
|
||||||
<Typography color="error" key={error.code}>
|
<Typography color="error" key={error.code}>
|
||||||
{getProductVariantAttributeErrorMessage(error, intl)}
|
{getProductVariantAttributeErrorMessage(error, intl)}
|
||||||
|
|
|
@ -28,6 +28,9 @@ const useStyles = makeStyles(
|
||||||
colName: {
|
colName: {
|
||||||
paddingLeft: 0
|
paddingLeft: 0
|
||||||
},
|
},
|
||||||
|
firstVariant: {
|
||||||
|
width: 88
|
||||||
|
},
|
||||||
link: {
|
link: {
|
||||||
cursor: "pointer"
|
cursor: "pointer"
|
||||||
},
|
},
|
||||||
|
@ -126,7 +129,10 @@ const ProductVariantNavigation: React.FC<ProductVariantNavigationProps> = props
|
||||||
className={classNames(
|
className={classNames(
|
||||||
classes.colAvatar,
|
classes.colAvatar,
|
||||||
classes.tabActive,
|
classes.tabActive,
|
||||||
classes.noHandle
|
classes.noHandle,
|
||||||
|
{
|
||||||
|
[classes.firstVariant]: variants.length === 0
|
||||||
|
}
|
||||||
)}
|
)}
|
||||||
thumbnail={null}
|
thumbnail={null}
|
||||||
colSpan={2}
|
colSpan={2}
|
||||||
|
|
|
@ -8,13 +8,13 @@ import { MetadataFormData } from "@saleor/components/Metadata";
|
||||||
import Metadata from "@saleor/components/Metadata/Metadata";
|
import Metadata from "@saleor/components/Metadata/Metadata";
|
||||||
import PageHeader from "@saleor/components/PageHeader";
|
import PageHeader from "@saleor/components/PageHeader";
|
||||||
import SaveButtonBar from "@saleor/components/SaveButtonBar";
|
import SaveButtonBar from "@saleor/components/SaveButtonBar";
|
||||||
|
import { ProductErrorFragment } from "@saleor/fragments/types/ProductErrorFragment";
|
||||||
import { ProductVariant } from "@saleor/fragments/types/ProductVariant";
|
import { ProductVariant } from "@saleor/fragments/types/ProductVariant";
|
||||||
import { WarehouseFragment } from "@saleor/fragments/types/WarehouseFragment";
|
import { WarehouseFragment } from "@saleor/fragments/types/WarehouseFragment";
|
||||||
import useFormset, {
|
import useFormset, {
|
||||||
FormsetChange,
|
FormsetChange,
|
||||||
FormsetData
|
FormsetData
|
||||||
} from "@saleor/hooks/useFormset";
|
} from "@saleor/hooks/useFormset";
|
||||||
import { VariantUpdate_productVariantUpdate_errors } from "@saleor/products/types/VariantUpdate";
|
|
||||||
import {
|
import {
|
||||||
getAttributeInputFromVariant,
|
getAttributeInputFromVariant,
|
||||||
getStockInputFromVariant
|
getStockInputFromVariant
|
||||||
|
@ -56,7 +56,7 @@ export interface ProductVariantPageSubmitData
|
||||||
interface ProductVariantPageProps {
|
interface ProductVariantPageProps {
|
||||||
defaultWeightUnit: string;
|
defaultWeightUnit: string;
|
||||||
variant?: ProductVariant;
|
variant?: ProductVariant;
|
||||||
errors: VariantUpdate_productVariantUpdate_errors[];
|
errors: ProductErrorFragment[];
|
||||||
saveButtonBarState: ConfirmButtonTransitionState;
|
saveButtonBarState: ConfirmButtonTransitionState;
|
||||||
loading?: boolean;
|
loading?: boolean;
|
||||||
placeholderImage?: string;
|
placeholderImage?: string;
|
||||||
|
|
|
@ -36,14 +36,17 @@ storiesOf("Views / Products / Create product variant", module)
|
||||||
disabled={false}
|
disabled={false}
|
||||||
errors={[
|
errors={[
|
||||||
{
|
{
|
||||||
|
attributeId: product.productType.variantAttributes[0].id,
|
||||||
code: ProductErrorCode.REQUIRED,
|
code: ProductErrorCode.REQUIRED,
|
||||||
field: "attributes"
|
field: "attributes"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
attributeId: null,
|
||||||
code: ProductErrorCode.UNIQUE,
|
code: ProductErrorCode.UNIQUE,
|
||||||
field: "attributes"
|
field: "attributes"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
attributeId: null,
|
||||||
code: ProductErrorCode.ALREADY_EXISTS,
|
code: ProductErrorCode.ALREADY_EXISTS,
|
||||||
field: "sku"
|
field: "sku"
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,14 +86,17 @@ storiesOf("Views / Products / Product variant details", module)
|
||||||
saveButtonBarState="default"
|
saveButtonBarState="default"
|
||||||
errors={[
|
errors={[
|
||||||
{
|
{
|
||||||
|
attributeId: variant.attributes[0].attribute.id,
|
||||||
code: ProductErrorCode.REQUIRED,
|
code: ProductErrorCode.REQUIRED,
|
||||||
field: "attributes"
|
field: "attributes"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
attributeId: null,
|
||||||
code: ProductErrorCode.UNIQUE,
|
code: ProductErrorCode.UNIQUE,
|
||||||
field: "attributes"
|
field: "attributes"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
attributeId: null,
|
||||||
code: ProductErrorCode.ALREADY_EXISTS,
|
code: ProductErrorCode.ALREADY_EXISTS,
|
||||||
field: "sku"
|
field: "sku"
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,8 +83,6 @@ export function getProductVariantAttributeErrorMessage(
|
||||||
): string {
|
): string {
|
||||||
if (err) {
|
if (err) {
|
||||||
switch (err.code) {
|
switch (err.code) {
|
||||||
case ProductErrorCode.REQUIRED:
|
|
||||||
return intl.formatMessage(messages.attributeRequired);
|
|
||||||
case ProductErrorCode.UNIQUE:
|
case ProductErrorCode.UNIQUE:
|
||||||
return intl.formatMessage(messages.variantUnique);
|
return intl.formatMessage(messages.variantUnique);
|
||||||
default:
|
default:
|
||||||
|
|
Loading…
Reference in a new issue