Add custom form component to product create

This commit is contained in:
dominik-zeglen 2020-10-16 15:42:57 +02:00
parent f128253c06
commit d192bcac34
6 changed files with 427 additions and 330 deletions

View file

@ -51,7 +51,7 @@ function handleRefresh<T extends FormData>(
function useForm<T extends FormData>(
initial: T,
onSubmit: (data: T) => void
onSubmit?: (data: T) => void
): UseFormResult<T> {
const [hasChanged, setChanged] = useState(false);
const [data, setData] = useStateFromProps(initial, {
@ -107,7 +107,9 @@ function useForm<T extends FormData>(
}
function submit() {
return onSubmit(data);
if (typeof onSubmit === "function") {
onSubmit(data);
}
}
function triggerChange() {

View file

@ -3,9 +3,8 @@ import AvailabilityCard from "@saleor/components/AvailabilityCard";
import CardSpacer from "@saleor/components/CardSpacer";
import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton";
import Container from "@saleor/components/Container";
import Form from "@saleor/components/Form";
import Grid from "@saleor/components/Grid";
import Metadata, { MetadataFormData } from "@saleor/components/Metadata";
import Metadata from "@saleor/components/Metadata";
import { MultiAutocompleteChoiceType } from "@saleor/components/MultiAutocompleteSelectField";
import PageHeader from "@saleor/components/PageHeader";
import SaveButtonBar from "@saleor/components/SaveButtonBar";
@ -13,70 +12,29 @@ import SeoForm from "@saleor/components/SeoForm";
import { ProductErrorWithAttributesFragment } from "@saleor/fragments/types/ProductErrorWithAttributesFragment";
import { TaxTypeFragment } from "@saleor/fragments/types/TaxTypeFragment";
import useDateLocalize from "@saleor/hooks/useDateLocalize";
import useFormset from "@saleor/hooks/useFormset";
import useStateFromProps from "@saleor/hooks/useStateFromProps";
import { sectionNames } from "@saleor/intl";
import {
getAttributeInputFromProductType,
getChoices,
ProductType
} from "@saleor/products/utils/data";
import { getChoices } from "@saleor/products/utils/data";
import { SearchCategories_search_edges_node } from "@saleor/searches/types/SearchCategories";
import { SearchCollections_search_edges_node } from "@saleor/searches/types/SearchCollections";
import { SearchProductTypes_search_edges_node_productAttributes } from "@saleor/searches/types/SearchProductTypes";
import { SearchProductTypes_search_edges_node } from "@saleor/searches/types/SearchProductTypes";
import { SearchWarehouses_search_edges_node } from "@saleor/searches/types/SearchWarehouses";
import createMultiAutocompleteSelectHandler from "@saleor/utils/handlers/multiAutocompleteSelectChangeHandler";
import createSingleAutocompleteSelectHandler from "@saleor/utils/handlers/singleAutocompleteSelectChangeHandler";
import useMetadataChangeTrigger from "@saleor/utils/metadata/useMetadataChangeTrigger";
import { ContentState, convertToRaw, RawDraftContentState } from "draft-js";
import { ContentState, convertToRaw } from "draft-js";
import React from "react";
import { useIntl } from "react-intl";
import { FetchMoreProps } from "../../../types";
import {
createAttributeChangeHandler,
createAttributeMultiChangeHandler,
createProductTypeSelectHandler
} from "../../utils/handlers";
import ProductAttributes, {
ProductAttributeInput,
ProductAttributeInputData
} from "../ProductAttributes";
import ProductAttributes from "../ProductAttributes";
import ProductDetailsForm from "../ProductDetailsForm";
import ProductOrganization from "../ProductOrganization";
import ProductPricing from "../ProductPricing";
import ProductShipping from "../ProductShipping/ProductShipping";
import ProductStocks, { ProductStockInput } from "../ProductStocks";
import ProductStocks from "../ProductStocks";
import ProductTaxes from "../ProductTaxes";
interface FormData extends MetadataFormData {
availableForPurchase: string;
basePrice: number;
category: string;
changeTaxCode: boolean;
chargeTaxes: boolean;
collections: string[];
description: RawDraftContentState;
isAvailable: boolean;
isAvailableForPurchase: boolean;
isPublished: boolean;
name: string;
slug: string;
productType: string;
publicationDate: string;
seoDescription: string;
seoTitle: string;
sku: string;
stockQuantity: number;
taxCode: string;
trackInventory: boolean;
visibleInListings: boolean;
weight: string;
}
export interface ProductCreatePageSubmitData extends FormData {
attributes: ProductAttributeInput[];
stocks: ProductStockInput[];
}
import ProductCreateForm, {
ProductCreateData,
ProductCreateFormData
} from "./form";
interface ProductCreatePageProps {
errors: ProductErrorWithAttributesFragment[];
@ -87,13 +45,8 @@ interface ProductCreatePageProps {
fetchMoreCategories: FetchMoreProps;
fetchMoreCollections: FetchMoreProps;
fetchMoreProductTypes: FetchMoreProps;
initial?: Partial<FormData>;
productTypes?: Array<{
id: string;
name: string;
hasVariants: boolean;
productAttributes: SearchProductTypes_search_edges_node_productAttributes[];
}>;
initial?: Partial<ProductCreateFormData>;
productTypes?: SearchProductTypes_search_edges_node[];
header: string;
saveButtonBarState: ConfirmButtonTransitionState;
weightUnit: string;
@ -104,7 +57,7 @@ interface ProductCreatePageProps {
fetchProductTypes: (data: string) => void;
onWarehouseConfigure: () => void;
onBack?();
onSubmit?(data: ProductCreatePageSubmitData);
onSubmit?(data: ProductCreateData);
}
export const ProductCreatePage: React.FC<ProductCreatePageProps> = ({
@ -133,65 +86,12 @@ export const ProductCreatePage: React.FC<ProductCreatePageProps> = ({
const intl = useIntl();
const localizeDate = useDateLocalize();
const initialProductType = productTypeChoiceList?.find(
productType => initial?.productType === productType.id
);
// Form values
const {
change: changeAttributeData,
data: attributes,
set: setAttributeData
} = useFormset<ProductAttributeInputData>(
initial?.productType
? getAttributeInputFromProductType(initialProductType)
: []
);
const {
add: addStock,
change: changeStockData,
data: stocks,
remove: removeStock
} = useFormset<null, string>([]);
// Ensures that it will not change after component rerenders, because it
// generates different block keys and it causes editor to lose its content.
const initialDescription = React.useRef(
convertToRaw(ContentState.createFromText(""))
);
const {
makeChangeHandler: makeMetadataChangeHandler
} = useMetadataChangeTrigger();
const initialData: FormData = {
...(initial || {}),
availableForPurchase: "",
basePrice: 0,
category: "",
changeTaxCode: false,
chargeTaxes: false,
collections: [],
description: {} as any,
isAvailable: false,
isAvailableForPurchase: false,
isPublished: false,
metadata: [],
name: "",
privateMetadata: [],
productType: "",
publicationDate: "",
seoDescription: "",
seoTitle: "",
sku: null,
slug: "",
stockQuantity: null,
taxCode: null,
trackInventory: false,
visibleInListings: false,
weight: ""
};
// Display values
const [selectedCategory, setSelectedCategory] = useStateFromProps(
initial?.category || ""
@ -201,9 +101,6 @@ export const ProductCreatePage: React.FC<ProductCreatePageProps> = ({
MultiAutocompleteChoiceType[]
>([]);
const [productType, setProductType] = useStateFromProps<ProductType>(
initialProductType || null
);
const [selectedTaxType, setSelectedTaxType] = useStateFromProps(
initial?.taxCode || null
);
@ -217,214 +114,166 @@ export const ProductCreatePage: React.FC<ProductCreatePageProps> = ({
value: taxType.taxCode
})) || [];
const handleSubmit = (data: FormData) =>
onSubmit({
...data,
attributes,
stocks
});
return (
<Form onSubmit={handleSubmit} initial={initialData} confirmLeave>
{({ change, data, hasChanged, submit, triggerChange, toggleValue }) => {
const handleCollectionSelect = createMultiAutocompleteSelectHandler(
toggleValue,
setSelectedCollections,
selectedCollections,
collections
);
const handleCategorySelect = createSingleAutocompleteSelectHandler(
change,
setSelectedCategory,
categories
);
const handleAttributeChange = createAttributeChangeHandler(
changeAttributeData,
triggerChange
);
const handleAttributeMultiChange = createAttributeMultiChangeHandler(
changeAttributeData,
attributes,
triggerChange
);
const handleProductTypeSelect = createProductTypeSelectHandler(
change,
setAttributeData,
setProductType,
productTypeChoiceList
);
const handleTaxTypeSelect = createSingleAutocompleteSelectHandler(
change,
setSelectedTaxType,
taxTypeChoices
);
const changeMetadata = makeMetadataChangeHandler(change);
return (
<Container>
<AppHeader onBack={onBack}>
{intl.formatMessage(sectionNames.products)}
</AppHeader>
<PageHeader title={header} />
<Grid>
<div>
<ProductDetailsForm
data={data}
<ProductCreateForm
onSubmit={onSubmit}
initial={initial}
categories={categories}
collections={collections}
productTypes={productTypeChoiceList}
selectedCollections={selectedCollections}
setSelectedCategory={setSelectedCategory}
setSelectedCollections={setSelectedCollections}
setSelectedTaxType={setSelectedTaxType}
taxTypes={taxTypeChoices}
warehouses={warehouses}
>
{({ change, data, handlers, hasChanged, submit }) => (
<Container>
<AppHeader onBack={onBack}>
{intl.formatMessage(sectionNames.products)}
</AppHeader>
<PageHeader title={header} />
<Grid>
<div>
<ProductDetailsForm
data={data}
disabled={disabled}
errors={errors}
initialDescription={initialDescription.current}
onChange={change}
/>
<CardSpacer />
{data.attributes.length > 0 && (
<ProductAttributes
attributes={data.attributes}
disabled={disabled}
errors={errors}
initialDescription={initialDescription.current}
onChange={change}
onChange={handlers.selectAttribute}
onMultiChange={handlers.selectAttributeMultiple}
/>
<CardSpacer />
{attributes.length > 0 && (
<ProductAttributes
attributes={attributes}
)}
<CardSpacer />
{!data.productType?.hasVariants && (
<>
<ProductShipping
data={data}
disabled={disabled}
errors={errors}
onChange={handleAttributeChange}
onMultiChange={handleAttributeMultiChange}
weightUnit={weightUnit}
onChange={change}
/>
)}
<CardSpacer />
{!!productType && !productType.hasVariants && (
<>
<ProductShipping
data={data}
disabled={disabled}
errors={errors}
weightUnit={weightUnit}
onChange={change}
/>
<ProductPricing
currency={currency}
data={data}
disabled={disabled}
errors={errors}
onChange={change}
/>
<CardSpacer />
<ProductStocks
data={data}
disabled={disabled}
hasVariants={false}
onFormDataChange={change}
errors={errors}
stocks={stocks}
warehouses={warehouses}
onChange={(id, value) => {
triggerChange();
changeStockData(id, value);
}}
onWarehouseStockAdd={id => {
triggerChange();
addStock({
data: null,
id,
label: warehouses.find(
warehouse => warehouse.id === id
).name,
value: "0"
});
}}
onWarehouseStockDelete={id => {
triggerChange();
removeStock(id);
}}
onWarehouseConfigure={onWarehouseConfigure}
/>
<CardSpacer />
</>
)}
<SeoForm
allowEmptySlug={true}
helperText={intl.formatMessage({
defaultMessage:
"Add search engine title and description to make this product easier to find"
})}
title={data.seoTitle}
slug={data.slug}
slugPlaceholder={data.name}
titlePlaceholder={data.name}
description={data.seoDescription}
descriptionPlaceholder={data.seoTitle}
loading={disabled}
onChange={change}
/>
<CardSpacer />
<Metadata data={data} onChange={changeMetadata} />
</div>
<div>
<ProductOrganization
canChangeType={true}
categories={categories}
categoryInputDisplayValue={selectedCategory}
collections={collections}
data={data}
disabled={disabled}
errors={errors}
fetchCategories={fetchCategories}
fetchCollections={fetchCollections}
fetchMoreCategories={fetchMoreCategories}
fetchMoreCollections={fetchMoreCollections}
fetchMoreProductTypes={fetchMoreProductTypes}
fetchProductTypes={fetchProductTypes}
productType={productType}
productTypeInputDisplayValue={productType?.name || ""}
productTypes={productTypes}
onCategoryChange={handleCategorySelect}
onCollectionChange={handleCollectionSelect}
onProductTypeChange={handleProductTypeSelect}
collectionsInputDisplayValue={selectedCollections}
/>
<CardSpacer />
<AvailabilityCard
data={data}
errors={errors}
disabled={disabled}
messages={{
hiddenLabel: intl.formatMessage({
defaultMessage: "Not published",
description: "product label"
}),
hiddenSecondLabel: intl.formatMessage(
{
defaultMessage: "will become published on {date}",
description: "product publication date label"
},
{
date: localizeDate(data.publicationDate, "L")
}
),
visibleLabel: intl.formatMessage({
defaultMessage: "Published",
description: "product label"
})
}}
onChange={change}
/>
<CardSpacer />
<ProductTaxes
data={data}
disabled={disabled}
onChange={change}
onTaxTypeChange={handleTaxTypeSelect}
selectedTaxTypeDisplayName={selectedTaxType}
taxTypes={taxTypes}
/>
</div>
</Grid>
<SaveButtonBar
onCancel={onBack}
onSave={submit}
state={saveButtonBarState}
disabled={disabled || !onSubmit || !hasChanged}
/>
</Container>
);
}}
</Form>
<ProductPricing
currency={currency}
data={data}
disabled={disabled}
errors={errors}
onChange={change}
/>
<CardSpacer />
<ProductStocks
data={data}
disabled={disabled}
hasVariants={false}
onFormDataChange={change}
errors={errors}
stocks={data.stocks}
warehouses={warehouses}
onChange={handlers.changeStock}
onWarehouseStockAdd={handlers.addStock}
onWarehouseStockDelete={handlers.deleteStock}
onWarehouseConfigure={onWarehouseConfigure}
/>
<CardSpacer />
</>
)}
<SeoForm
allowEmptySlug={true}
helperText={intl.formatMessage({
defaultMessage:
"Add search engine title and description to make this product easier to find"
})}
title={data.seoTitle}
slug={data.slug}
slugPlaceholder={data.name}
titlePlaceholder={data.name}
description={data.seoDescription}
descriptionPlaceholder={data.seoTitle}
loading={disabled}
onChange={change}
/>
<CardSpacer />
<Metadata data={data} onChange={handlers.changeMetadata} />
</div>
<div>
<ProductOrganization
canChangeType={true}
categories={categories}
categoryInputDisplayValue={selectedCategory}
collections={collections}
data={data}
disabled={disabled}
errors={errors}
fetchCategories={fetchCategories}
fetchCollections={fetchCollections}
fetchMoreCategories={fetchMoreCategories}
fetchMoreCollections={fetchMoreCollections}
fetchMoreProductTypes={fetchMoreProductTypes}
fetchProductTypes={fetchProductTypes}
productType={data.productType}
productTypeInputDisplayValue={data.productType?.name || ""}
productTypes={productTypes}
onCategoryChange={handlers.selectCategory}
onCollectionChange={handlers.selectCollection}
onProductTypeChange={handlers.selectProductType}
collectionsInputDisplayValue={selectedCollections}
/>
<CardSpacer />
<AvailabilityCard
data={data}
errors={errors}
disabled={disabled}
messages={{
hiddenLabel: intl.formatMessage({
defaultMessage: "Not published",
description: "product label"
}),
hiddenSecondLabel: intl.formatMessage(
{
defaultMessage: "will become published on {date}",
description: "product publication date label"
},
{
date: localizeDate(data.publicationDate, "L")
}
),
visibleLabel: intl.formatMessage({
defaultMessage: "Published",
description: "product label"
})
}}
onChange={change}
/>
<CardSpacer />
<ProductTaxes
data={data}
disabled={disabled}
onChange={change}
onTaxTypeChange={handlers.selectTaxRate}
selectedTaxTypeDisplayName={selectedTaxType}
taxTypes={taxTypes}
/>
</div>
</Grid>
<SaveButtonBar
onCancel={onBack}
onSave={submit}
state={saveButtonBarState}
disabled={disabled || !onSubmit || !hasChanged}
/>
</Container>
)}
</ProductCreateForm>
);
};
ProductCreatePage.displayName = "ProductCreatePage";

View file

@ -0,0 +1,248 @@
import { MetadataFormData } from "@saleor/components/Metadata";
import { MultiAutocompleteChoiceType } from "@saleor/components/MultiAutocompleteSelectField";
import { SingleAutocompleteChoiceType } from "@saleor/components/SingleAutocompleteSelectField";
import useForm, { FormChange } from "@saleor/hooks/useForm";
import useFormset, { FormsetChange } from "@saleor/hooks/useFormset";
import useStateFromProps from "@saleor/hooks/useStateFromProps";
import {
getAttributeInputFromProductType,
ProductType
} from "@saleor/products/utils/data";
import {
createAttributeChangeHandler,
createAttributeMultiChangeHandler,
createProductTypeSelectHandler
} from "@saleor/products/utils/handlers";
import { SearchWarehouses_search_edges_node } from "@saleor/searches/types/SearchWarehouses";
import createMultiAutocompleteSelectHandler from "@saleor/utils/handlers/multiAutocompleteSelectChangeHandler";
import createSingleAutocompleteSelectHandler from "@saleor/utils/handlers/singleAutocompleteSelectChangeHandler";
import useMetadataChangeTrigger from "@saleor/utils/metadata/useMetadataChangeTrigger";
import { RawDraftContentState } from "draft-js";
import React from "react";
import { SearchProductTypes_search_edges_node } from "../../../searches/types/SearchProductTypes";
import {
ProductAttributeInput,
ProductAttributeInputData
} from "../ProductAttributes";
import { ProductStockInput } from "../ProductStocks";
export interface ProductCreateFormData extends MetadataFormData {
availableForPurchase: string;
basePrice: number;
category: string;
changeTaxCode: boolean;
chargeTaxes: boolean;
collections: string[];
description: RawDraftContentState;
isAvailable: boolean;
isAvailableForPurchase: boolean;
isPublished: boolean;
name: string;
productType: ProductType;
publicationDate: string;
seoDescription: string;
seoTitle: string;
sku: string;
slug: string;
stockQuantity: number;
taxCode: string;
trackInventory: boolean;
visibleInListings: boolean;
weight: string;
}
export interface ProductCreateData extends ProductCreateFormData {
attributes: ProductAttributeInput[];
stocks: ProductStockInput[];
}
export interface UseProductCreateFormResult {
change: FormChange;
data: ProductCreateData;
handlers: Record<
| "changeMetadata"
| "selectCategory"
| "selectCollection"
| "selectProductType"
| "selectTaxRate",
FormChange
> &
Record<
"changeStock" | "selectAttribute" | "selectAttributeMultiple",
FormsetChange
> &
Record<"addStock" | "deleteStock", (id: string) => void>;
hasChanged: boolean;
submit: () => Promise<boolean>;
}
export interface UseProductCreateFormOpts
extends Record<
"categories" | "collections" | "taxTypes",
SingleAutocompleteChoiceType[]
> {
setSelectedCategory: React.Dispatch<React.SetStateAction<string>>;
setSelectedCollections: React.Dispatch<
React.SetStateAction<MultiAutocompleteChoiceType[]>
>;
setSelectedTaxType: React.Dispatch<React.SetStateAction<string>>;
selectedCollections: MultiAutocompleteChoiceType[];
productTypes: SearchProductTypes_search_edges_node[];
warehouses: SearchWarehouses_search_edges_node[];
}
export interface ProductCreateFormProps extends UseProductCreateFormOpts {
children: (props: UseProductCreateFormResult) => React.ReactNode;
initial?: Partial<ProductCreateFormData>;
onSubmit: (data: ProductCreateData) => Promise<boolean>;
}
const defaultInitialFormData: ProductCreateFormData &
Record<"productType", string> = {
availableForPurchase: "",
basePrice: 0,
category: "",
changeTaxCode: false,
chargeTaxes: false,
collections: [],
description: {} as any,
isAvailable: false,
isAvailableForPurchase: false,
isPublished: false,
metadata: [],
name: "",
privateMetadata: [],
productType: null,
publicationDate: "",
seoDescription: "",
seoTitle: "",
sku: null,
slug: "",
stockQuantity: null,
taxCode: null,
trackInventory: false,
visibleInListings: false,
weight: ""
};
function useProductCreateForm(
initial: Partial<ProductCreateFormData>,
onSubmit: (data: ProductCreateData) => Promise<boolean>,
opts: UseProductCreateFormOpts
): UseProductCreateFormResult {
const initialProductType =
opts.productTypes?.find(
productType => initial?.productType?.id === productType.id
) || null;
const [changed, setChanged] = React.useState(false);
const triggerChange = () => setChanged(true);
const form = useForm({
...initial,
...defaultInitialFormData
});
const attributes = useFormset<ProductAttributeInputData>(
initial?.productType
? getAttributeInputFromProductType(initialProductType)
: []
);
const stocks = useFormset<null, string>([]);
const [productType, setProductType] = useStateFromProps<ProductType>(
initialProductType || null
);
const {
makeChangeHandler: makeMetadataChangeHandler
} = useMetadataChangeTrigger();
const handleCollectionSelect = createMultiAutocompleteSelectHandler(
form.toggleValue,
opts.setSelectedCollections,
opts.selectedCollections,
opts.collections
);
const handleCategorySelect = createSingleAutocompleteSelectHandler(
form.change,
opts.setSelectedCategory,
opts.categories
);
const handleAttributeChange = createAttributeChangeHandler(
attributes.change,
triggerChange
);
const handleAttributeMultiChange = createAttributeMultiChangeHandler(
attributes.change,
attributes.data,
triggerChange
);
const handleProductTypeSelect = createProductTypeSelectHandler(
attributes.set,
setProductType,
opts.productTypes,
triggerChange
);
const handleStockChange: FormsetChange = (id, value) => {
triggerChange();
stocks.change(id, value);
};
const handleStockAdd = (id: string) => {
triggerChange();
stocks.add({
data: null,
id,
label: opts.warehouses.find(warehouse => warehouse.id === id).name,
value: "0"
});
};
const handleStockDelete = (id: string) => {
triggerChange();
stocks.remove(id);
};
const handleTaxTypeSelect = createSingleAutocompleteSelectHandler(
form.change,
opts.setSelectedTaxType,
opts.taxTypes
);
const changeMetadata = makeMetadataChangeHandler(form.change);
const data: ProductCreateData = {
...form.data,
attributes: attributes.data,
productType,
stocks: stocks.data
};
const submit = () => onSubmit(data);
return {
change: form.change,
data,
handlers: {
addStock: handleStockAdd,
changeMetadata,
changeStock: handleStockChange,
deleteStock: handleStockDelete,
selectAttribute: handleAttributeChange,
selectAttributeMultiple: handleAttributeMultiChange,
selectCategory: handleCategorySelect,
selectCollection: handleCollectionSelect,
selectProductType: handleProductTypeSelect,
selectTaxRate: handleTaxTypeSelect
},
hasChanged: changed,
submit
};
}
const ProductCreateForm: React.FC<ProductCreateFormProps> = ({
children,
initial,
onSubmit,
...rest
}) => {
const props = useProductCreateForm(initial || {}, onSubmit, rest);
return <form onSubmit={props.submit}>{children(props)}</form>;
};
ProductCreateForm.displayName = "ProductCreateForm";
export default ProductCreateForm;

View file

@ -51,7 +51,7 @@ interface ProductOrganizationProps {
data: {
category: string;
collections: string[];
productType?: string;
productType?: ProductType;
};
disabled: boolean;
errors: ProductErrorFragment[];
@ -121,7 +121,7 @@ const ProductOrganization: React.FC<ProductOrganizationProps> = props => {
defaultMessage: "Product Type"
})}
choices={productTypes}
value={data.productType}
value={data.productType?.id}
onChange={onProductTypeChange}
fetchChoices={fetchProductTypes}
data-test="product-type"

View file

@ -37,19 +37,18 @@ export function createAttributeMultiChangeHandler(
}
export function createProductTypeSelectHandler(
change: FormChange,
setAttributes: (data: FormsetData<ProductAttributeInputData>) => void,
setProductType: (productType: ProductType) => void,
productTypeChoiceList: ProductType[]
productTypeChoiceList: ProductType[],
triggerChange: () => void
): FormChange {
return (event: React.ChangeEvent<any>) => {
const id = event.target.value;
const selectedProductType = productTypeChoiceList.find(
productType => productType.id === id
);
triggerChange();
setProductType(selectedProductType);
change(event);
setAttributes(getAttributeInputFromProductType(selectedProductType));
};
}

View file

@ -19,9 +19,8 @@ import React from "react";
import { useIntl } from "react-intl";
import { decimal, weight } from "../../misc";
import ProductCreatePage, {
ProductCreatePageSubmitData
} from "../components/ProductCreatePage";
import ProductCreatePage from "../components/ProductCreatePage";
import { ProductCreateData } from "../components/ProductCreatePage/form";
import {
useProductCreateMutation,
useProductSetAvailabilityForPurchase
@ -91,7 +90,7 @@ export const ProductCreateView: React.FC = () => {
}
});
const handleCreate = async (formData: ProductCreatePageSubmitData) => {
const handleCreate = async (formData: ProductCreateData) => {
const result = await productCreate({
variables: {
input: {
@ -106,7 +105,7 @@ export const ProductCreateView: React.FC = () => {
descriptionJson: JSON.stringify(formData.description),
isPublished: formData.isPublished,
name: formData.name,
productType: formData.productType,
productType: formData.productType?.id,
publicationDate:
formData.publicationDate !== "" ? formData.publicationDate : null,
seo: {