diff --git a/src/components/SeoForm/SeoForm.tsx b/src/components/SeoForm/SeoForm.tsx index 302ef76d4..717afc81c 100644 --- a/src/components/SeoForm/SeoForm.tsx +++ b/src/components/SeoForm/SeoForm.tsx @@ -6,12 +6,11 @@ import TextField from "@material-ui/core/TextField"; import Typography from "@material-ui/core/Typography"; import { PageErrorFragment } from "@saleor/fragments/types/PageErrorFragment"; import { ProductErrorFragment } from "@saleor/fragments/types/ProductErrorFragment"; -import { PageErrorCode, ProductErrorCode } from "@saleor/types/globalTypes"; -import { getProductErrorMessage } from "@saleor/utils/errors"; +import { getFieldError, getProductErrorMessage } from "@saleor/utils/errors"; import getPageErrorMessage from "@saleor/utils/errors/page"; import classNames from "classnames"; import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; +import { defineMessages, FormattedMessage, useIntl } from "react-intl"; import slugify from "slugify"; import CardTitle from "../CardTitle"; @@ -23,16 +22,7 @@ enum SeoField { description = "seoDescription" } -const DEFAULT_INPUT_MESSAGE = - "If empty, the preview shows what will be autogenerated."; - -interface Error { - __typename: "ProductError" | "PageError"; - field: string | null; - code: ProductErrorCode | PageErrorCode; -} - -const SLUG_REGEX = /^[a-z0-9]+(?:[\-a-z0-9]+)*$/; +const SLUG_REGEX = /^[a-zA-Z0-9\-\_]+$/; const useStyles = makeStyles( theme => ({ @@ -88,7 +78,7 @@ interface SeoFormProps { description?: string; descriptionPlaceholder: string; disabled?: boolean; - errors?: ProductErrorFragment[] | PageErrorFragment[]; + errors?: Array; loading?: boolean; helperText?: string; isCreating?: boolean; @@ -105,7 +95,7 @@ const SeoForm: React.FC = props => { description, descriptionPlaceholder, disabled, - errors, + errors = [], helperText, isCreating = false, loading, @@ -125,33 +115,27 @@ const SeoForm: React.FC = props => { const shouldDisplayHelperText = helperText && !expanded; - const getFilteredErrors = () => - (errors as Error[])?.filter(({ field }) => - Object.keys(SeoField).includes(field) - ) || []; + const { seoFieldMessage } = defineMessages({ + seoFieldMessage: { + defaultMessage: "If empty, the preview shows what will be autogenerated." + } + }); - const getError = (fieldName: SeoField) => - getFilteredErrors().find(({ field }) => fieldName === field); - - const isError = (fieldName: SeoField) => !!getError(fieldName); - - const getSlugHelperText = () => { - const error = isError(SeoField.slug); + const getSlugHelperMessage = () => { + const error = !!getError(SeoField.slug); if (isCreating && !error) { - return intl.formatMessage({ - defaultMessage: DEFAULT_INPUT_MESSAGE - }); + return intl.formatMessage(seoFieldMessage); } if (error) { - return getSlugErrorText(); + return getSlugErrorMessage(); } return ""; }; - const getSlugErrorText = () => { + const getSlugErrorMessage = () => { const error = getError(SeoField.slug); const { __typename: type } = error; @@ -163,11 +147,13 @@ const SeoForm: React.FC = props => { const handleSlugChange = event => { const { value } = event.target; - if (value === "" || !!value.match(SLUG_REGEX)) { + if (value === "" || SLUG_REGEX.test(value)) { onChange(event); } }; + const getError = fieldName => getFieldError(errors, fieldName); + return ( = props => { {expanded && (
@@ -215,7 +201,7 @@ const SeoForm: React.FC = props => { )}
} - helperText={getSlugHelperText()} + helperText={getSlugHelperMessage()} value={slug?.slice(0, 69)} disabled={loading || disabled} placeholder={slug || slugify(slugPlaceholder, { lower: true })} @@ -225,7 +211,7 @@ const SeoForm: React.FC = props => {
@@ -245,9 +231,7 @@ const SeoForm: React.FC = props => { )}
} - helperText={intl.formatMessage({ - defaultMessage: DEFAULT_INPUT_MESSAGE - })} + helperText={intl.formatMessage(seoFieldMessage)} value={title?.slice(0, 69)} disabled={loading || disabled} placeholder={titlePlaceholder} @@ -256,7 +240,7 @@ const SeoForm: React.FC = props => { /> @@ -277,9 +261,7 @@ const SeoForm: React.FC = props => { )} } - helperText={intl.formatMessage({ - defaultMessage: DEFAULT_INPUT_MESSAGE - })} + helperText={intl.formatMessage(seoFieldMessage)} value={description?.slice(0, 299)} onChange={onChange} disabled={loading || disabled} diff --git a/src/utils/errors/product.ts b/src/utils/errors/product.ts index 976010a4b..45a1e36dc 100644 --- a/src/utils/errors/product.ts +++ b/src/utils/errors/product.ts @@ -24,6 +24,9 @@ const messages = defineMessages({ duplicatedInputItem: { defaultMessage: "Variant with these attributes already exists" }, + nameAlreadyTaken: { + defaultMessage: "This name is already taken. Please provide another." + }, skuUnique: { defaultMessage: "SKUs must be unique", description: "bulk variant create error" @@ -59,6 +62,8 @@ function getProductErrorMessage( return intl.formatMessage(messages.variantNoDigitalContent); case ProductErrorCode.INVALID: return intl.formatMessage(commonErrorMessages.invalid); + case ProductErrorCode.UNIQUE: + return intl.formatMessage(messages.nameAlreadyTaken); default: return intl.formatMessage(commonErrorMessages.unknownError); }