import React, { useCallback, useMemo, useState } from "react"; import { useParams } from "react-router-dom"; import CancelIcon from "@mui/icons-material/Cancel"; import CheckCircleIcon from "@mui/icons-material/CheckCircle"; import Card from "../../../components/Card"; import CardActions from "../../../components/Card/CardActions"; import CardCancelButton from "../../../components/Card/CardCancelButton"; import CardContent from "../../../components/Card/CardContent"; import CardFieldCheckbox from "../../../components/Card/CardFieldCheckbox"; import CardFieldSelect from "../../../components/Card/CardFieldSelect"; import CardFieldText from "../../../components/Card/CardFieldText"; import CardHeader from "../../../components/Card/CardHeader"; import CardRow from "../../../components/Card/CardRow"; import CardSaveButton from "../../../components/Card/CardSaveButton"; import { useApi } from "../../../contexts/ApiContext"; import { useI18n } from "../../../contexts/I18nContext"; import { useUser } from "../../../contexts/UserContext"; import { hasPermission } from "../../../util/has_permission"; import { ProductCreated, ProductDetail, ProductItemTypeOption } from "../types/product"; import { ProductPropertyField } from "./ProductPropertyField"; export type ProductCardProps = | { create: true; product?: ProductDetail; onCreated: (product: ProductCreated) => void; onUpdated?: never; itemTypes: ProductItemTypeOption[]; } | { create?: false; product: ProductDetail; onCreated?: never; onUpdated: (product: ProductDetail) => void; itemTypes: ProductItemTypeOption[]; }; export interface ProductCardFormValues { number: string; item_type: string; is_active: string; name: string; description: string; } export const ProductCard: React.FC = ({ product, create, onCreated, onUpdated, itemTypes, }) => { const params = useParams(); const api = useApi(); const { t } = useI18n(); const { user } = useUser(); const canCreate = useMemo(() => hasPermission(user, "pim.add_product"), [user]); const canChange = useMemo(() => hasPermission(user, "pim.change_product"), [user]); product ??= { id: 0, name: "", description: "", item_type: "", number: "", is_active: true, } as ProductDetail; const [productItemType, setProductItemType] = useState( undefined, ); const productPropertiesList = productItemType ? productItemType.product_properties : []; const productPropertiesRows = productPropertiesList.reduce<(typeof productPropertiesList)[]>( (rows, prop, index) => { if (index % 2 === 0) rows.push([prop]); else rows[rows.length - 1].push(prop); return rows; }, [], ); const handleSave = useCallback( async ({ is_active, ...values }: ProductCardFormValues) => { if (create != null) { const action = api.operations["pim.product:create"]; if (!action) { throw new Error('Invalid action "pim.product:create".'); } const productData: Record = {}; const productProperties: Record = {}; for (const [key, value] of Object.entries(values)) { if (key.startsWith("properties.")) { const propertyName = key.replace("properties.", ""); productProperties[propertyName] = value; } else { productData[key] = value; } } const response = await action.call({ params, body: { is_active: is_active == "on", ...productData, properties: productProperties, }, }); if (response.ok) { const createdProduct = await response.json(); onCreated?.(createdProduct); return t("Product created successfully."); } else { console.error("[PRODUCT_CARD]", response); throw new Error("creating product."); } } else { const action = api.operations["pim.product:update"]; if (!action) { throw new Error('Invalid action "pim.product:update".'); } const response = await action.call({ params, body: { is_active: is_active == "on", ...values, }, }); if (response.ok) { const updatedProduct = await response.json(); onUpdated?.(updatedProduct); return t("Product updated successfully."); } else { console.error("[PRODUCT_CARD]", response); throw new Error("updating product fields."); } } }, [api, params, create, onCreated, onUpdated, t], ); return ( ({ id: itemType.name, label: itemType.name }))} required={true} size={1} value={ product.item_type ? { id: product.item_type, label: product.item_type } : undefined } onUpdated={(value) => { const selectedItemType = itemTypes.find((itemType) => itemType.name == value); setProductItemType(selectedItemType); }} /> } size={1} value={product.is_active} yesValue={} /> {create && productPropertiesRows.length > 0 && ( <> {productPropertiesRows.map((row, index) => ( {row.map((prop) => ( ))} ))} )} {(canChange || canCreate) && ( {!create && } )} ); };