diff --git a/src/shared/sections/product/add-edit-list-attribut/add-list-edit-termeLabel/termeLabel-edit-form.tsx b/src/shared/sections/product/add-edit-list-attribut/add-list-edit-termeLabel/termeLabel-edit-form.tsx index ea1dd51a69979967a764344cf7a05e2e820fb20d..2d7ccd8935f354bcb9512bc4af4f78db91aa02b9 100644 --- a/src/shared/sections/product/add-edit-list-attribut/add-list-edit-termeLabel/termeLabel-edit-form.tsx +++ b/src/shared/sections/product/add-edit-list-attribut/add-list-edit-termeLabel/termeLabel-edit-form.tsx @@ -57,7 +57,7 @@ export default function EditTermLabForm({ attributid, labelId }: { attributid: s } return true; }), - description: yup.string().required("La description est requise."), + description: yup.string().optional(), }); const validateForm = async (): Promise<boolean> => { diff --git a/src/shared/sections/product/add-list-ConfigurationChoixTerme/termeChoix-edit-form.tsx b/src/shared/sections/product/add-list-ConfigurationChoixTerme/termeChoix-edit-form.tsx index 28cdd98b875fd9e470d9a36cb6feac24d28dabcf..2e46bf69399c5730136639255eb1865d3ce02404 100644 --- a/src/shared/sections/product/add-list-ConfigurationChoixTerme/termeChoix-edit-form.tsx +++ b/src/shared/sections/product/add-list-ConfigurationChoixTerme/termeChoix-edit-form.tsx @@ -63,7 +63,7 @@ export default function TermChoixEditForm({ } return true; // Si le slug n'a pas été modifié, on ne vérifie pas l'unicité }), - description: yup.string().required("La description est requise."), + description: yup.string().optional(), }); const validateForm = async (): Promise<boolean> => { @@ -169,7 +169,7 @@ export default function TermChoixEditForm({ Le choix a été modifié avec succès </Alert> ) : ( - <p>Default message : modifier</p> + <p></p> )} </form> </Card> diff --git a/src/shared/sections/product/add-product/MainForm.tsx b/src/shared/sections/product/add-product/MainForm.tsx index 527946f652fcd39159442a82a5357490885da63f..0c92396a548f3d837adc57e4f276036fe0324a96 100644 --- a/src/shared/sections/product/add-product/MainForm.tsx +++ b/src/shared/sections/product/add-product/MainForm.tsx @@ -54,13 +54,13 @@ export default function ProductNewEditForm({ const { productMutate } = useUpdateProduct(currentProduct?.id!); const [alert, setAlert] = useState<{ message: string; type: 'success' | 'error' } | null>(null); - + useEffect(() => { if (alert) { const timer = setTimeout(() => { setAlert(null); - }, 1000); - return () => clearTimeout(timer); + }, 1000); + return () => clearTimeout(timer); } }, [alert]); const [isCheckingUgs, setIsCheckingUgs] = useState(false); @@ -95,7 +95,33 @@ export default function ProductNewEditForm({ feedStockFromWebStock: Yup.boolean().optional(), authorizeUpdateQuantity: Yup.boolean().optional(), }), - + + stockWebConfig: Yup.object().shape({ + quantity: Yup.number() + .nullable() + .transform((value, originalValue) => (originalValue === "" ? null : value)) + .typeError("La quantité Web doit être un nombre") + .min(0, "La quantité Web ne peut pas être négative"), + thresholdValue: Yup.number() + .nullable() + .transform((value, originalValue) => (originalValue === "" ? null : value)) + .typeError("Le seuil de précommande Web doit être un nombre") + .min(0, "Le seuil de précommande Web ne peut pas être négatif"), + }), + + stockLiveConfig: Yup.object().shape({ + quantity: Yup.number() + .nullable() + .transform((value, originalValue) => (originalValue === "" ? null : value)) + .typeError("La quantité Live doit être un nombre") + .min(0, "La quantité Live ne peut pas être négative"), + thresholdValue: Yup.number() + .nullable() + .transform((value, originalValue) => (originalValue === "" ? null : value)) + .typeError("Le seuil de précommande Web doit être un nombre") + .min(0, "Le seuil de précommande Web ne peut pas être négatif"), + }), + stockAlert: Yup.number() .nullable() .typeError("Le seuil de stock doit être un nombre") @@ -122,8 +148,36 @@ export default function ProductNewEditForm({ .required("Le tarif régulier est requis") .typeError("Le tarif régulier doit être un nombre") .moreThan(0, "Le prix doit être strictement positif"), + + stockWebConfig: Yup.object().shape({ + quantity: Yup.number() + .nullable() + .transform((value, originalValue) => (originalValue === "" ? null : value)) + .typeError("La quantité Web doit être un nombre") + .min(0, "La quantité Web ne peut pas être négative"), + thresholdValue: Yup.number() + .nullable() + .transform((value, originalValue) => (originalValue === "" ? null : value)) + .typeError("Le seuil de précommande Web doit être un nombre") + .min(0, "Le seuil de précommande Web ne peut pas être négatif"), + }), + + stockLiveConfig: Yup.object().shape({ + quantity: Yup.number() + .nullable() + .transform((value, originalValue) => (originalValue === "" ? null : value)) + .typeError("La quantité Live doit être un nombre") + .min(0, "La quantité Live ne peut pas être négative"), + thresholdValue: Yup.number() + .nullable() + .transform((value, originalValue) => (originalValue === "" ? null : value)) + .typeError("Le seuil de précommande Web doit être un nombre") + .min(0, "Le seuil de précommande Web ne peut pas être négatif"), + }), }) + ), + }); const defaultValues = useMemo( @@ -173,8 +227,8 @@ export default function ProductNewEditForm({ }, purchasePrice: currentProduct?.purchasePrice, secondPurchasePrice: currentProduct?.secondPurchasePrice, - supplierNameSecond : currentProduct?.supplierNameSecond, - supplierRefSecond : currentProduct?.supplierRefSecond, + supplierNameSecond: currentProduct?.supplierNameSecond, + supplierRefSecond: currentProduct?.supplierRefSecond, }), [currentProduct, defaultSupplierName] ); @@ -185,7 +239,7 @@ export default function ProductNewEditForm({ any >, defaultValues, - context: { currentProduct }, + context: { currentProduct }, mode: "onChange", }); @@ -247,7 +301,7 @@ export default function ProductNewEditForm({ clearErrors("ugs"); } } - }, 300); + }, 300); return () => { clearTimeout(handler); @@ -266,7 +320,7 @@ export default function ProductNewEditForm({ ...rest, publishWeb, publishLive, - ...( !isNew && { id } ), + ...(!isNew && { id }), }; }); const formData = { @@ -290,7 +344,7 @@ export default function ProductNewEditForm({ formData ); productMutate(); - revalidate(); + revalidate(); } else { if (formData.productType === ProductType.SIMPLE) { response = await useAddSimpleProduct(formData); @@ -337,7 +391,7 @@ export default function ProductNewEditForm({ (v: any) => ({ id: v.id, name: v.name, - productPrice:v.purchasePrice, + productPrice: v.purchasePrice, mainImagePath: v.mainImagePath || response.mainImagePath, quantity: (v.stockWebConfig?.quantity || 0) + (v.stockLiveConfig?.quantity || 0) @@ -412,7 +466,7 @@ export default function ProductNewEditForm({ ugs: 'UGS produit', name: 'Nom du produit', regularPrice: 'Tarif régulier', - + }; return fieldLabels[fieldKey] || fieldKey; }; @@ -424,7 +478,7 @@ export default function ProductNewEditForm({ message={alert.message} type={alert.type} onClose={() => setAlert(null)} - style={{ top: '20px', right: '20px', zIndex: 3000 }} + style={{ top: '20px', right: '20px', zIndex: 3000 }} /> )} <FormProvider methods={methods} onSubmit={handleSubmit(onSubmit, onError)}> @@ -436,7 +490,7 @@ export default function ProductNewEditForm({ setPathList={setPathList} isEditing={isEditing} currentProduct={currentProduct} - defaultSupplierName={defaultSupplierName} + defaultSupplierName={defaultSupplierName} /> <Grid container spacing={3} justifyContent="flex-start"> diff --git a/src/shared/sections/product/add-product/ProductProperties.tsx b/src/shared/sections/product/add-product/ProductProperties.tsx index 0072aed8665eea1ca4913b1189fd5a8fffab0194..d7201136ae8c99e84f652c02ddafc3aec57954c1 100644 --- a/src/shared/sections/product/add-product/ProductProperties.tsx +++ b/src/shared/sections/product/add-product/ProductProperties.tsx @@ -1,4 +1,4 @@ -import React, { Dispatch, SetStateAction, useEffect, useState } from "react"; +import React, { Dispatch, SetStateAction, useEffect, useState, useRef } from "react"; import { Stack, Card, @@ -128,6 +128,8 @@ export default function ProductProperties({ const [showShippingInfo, setShowShippingInfo] = useState(false); + const listboxRef = useRef<HTMLUListElement | null>(null); + const handleSelectAllAttributeValues = (index: number) => { const attr = attributes[index]; const allValues = @@ -540,7 +542,7 @@ export default function ProductProperties({ {...field} label="Tarif régulier" placeholder="0.00" - type="number" + InputLabelProps={{ shrink: true }} onChange={(e) => { const newValue = parseFloat(e.target.value); @@ -561,7 +563,7 @@ export default function ProductProperties({ {...field} label="Tarif promo" placeholder="0.00" - type="number" + InputLabelProps={{ shrink: true }} /> )} @@ -575,7 +577,7 @@ export default function ProductProperties({ <RHFTextField {...field} label="Seuil de stock faible" - type="number" + InputLabelProps={{ shrink: true }} placeholder="0" /> @@ -611,7 +613,7 @@ export default function ProductProperties({ <RHFTextField {...field} label="Quantité Web" - type="number" + InputLabelProps={{ shrink: true }} placeholder="0" /> @@ -673,7 +675,7 @@ export default function ProductProperties({ <RHFTextField {...field} label="Seuil de précommande en Web" - type="number" + InputLabelProps={{ shrink: true }} placeholder="0" /> @@ -716,7 +718,7 @@ export default function ProductProperties({ <RHFTextField {...field} label="Quantité Live" - type="number" + InputLabelProps={{ shrink: true }} placeholder="0" /> @@ -778,7 +780,7 @@ export default function ProductProperties({ <RHFTextField {...field} label="Seuil de précommande Live" - type="number" + InputLabelProps={{ shrink: true }} placeholder="0" /> @@ -877,7 +879,6 @@ export default function ProductProperties({ handleAttributeChange(index, newValue); }} filterOptions={(options, { inputValue }) => { - // Prioritize terms starting with the current input const lowerInput = inputValue.toLowerCase(); const startsWith: string[] = []; const others: string[] = []; @@ -924,7 +925,6 @@ export default function ProductProperties({ : []) } filterOptions={(options, { inputValue }) => { - // Prioritize terms starting with the current input const lowerInput = inputValue.toLowerCase(); const startsWith: string[] = []; const others: string[] = []; @@ -954,6 +954,17 @@ export default function ProductProperties({ fullWidth /> )} + autoHighlight + ListboxProps={{ + ref: (node) => { + listboxRef.current = node as HTMLUListElement; + }, + onScroll: () => { + if (listboxRef.current) { + listboxRef.current.scrollTop = 0; + } + }, + }} sx={{ mt: 2, flexGrow: 1 }} /> <Tooltip title="Tous sélectionner"> diff --git a/src/shared/sections/product/add-product/ProductVariations.tsx b/src/shared/sections/product/add-product/ProductVariations.tsx index 9d5eaa7185553d5ef01e4e90a17f7fa8d6dc71fe..031c3a68f6cc3208caa1a77458f9395fd134bfa4 100644 --- a/src/shared/sections/product/add-product/ProductVariations.tsx +++ b/src/shared/sections/product/add-product/ProductVariations.tsx @@ -315,10 +315,24 @@ const Variations: React.FC<VariationsProps> = ({ const handlePublishWebChange = (checked: boolean) => { setShowWebFields(checked); + // Update variations to reflect the change + const newVariations = localVariations.map(variation => ({ + ...variation, + publishWeb: checked + })); + setLocalVariations(newVariations); + setVariations(newVariations); }; const handlePublishLiveChange = (checked: boolean) => { setShowLiveFields(checked); + // Update variations to reflect the change + const newVariations = localVariations.map(variation => ({ + ...variation, + publishLive: checked + })); + setLocalVariations(newVariations); + setVariations(newVariations); }; const ALLOW_BACKORDER_OPTIONS = [ @@ -690,7 +704,7 @@ const Variations: React.FC<VariationsProps> = ({ render={({ field }) => ( <RHFSelect {...field} - label="Classe d’expédition" + label="Classe d'expédition" variant="outlined" onChange={(e) => { const newValue = e.target.value as unknown as number; @@ -730,10 +744,6 @@ const Variations: React.FC<VariationsProps> = ({ const newValue = e.target.checked; field.onChange(newValue); handlePublishWebChange(newValue); - const newVariations = [...localVariations]; - newVariations[index].publishWeb = newValue; - setLocalVariations(newVariations); - setVariations(newVariations); }} /> } @@ -742,7 +752,7 @@ const Variations: React.FC<VariationsProps> = ({ )} /> - {showWebFields && ( + {variation.publishWeb && ( <> <Controller name={`variations[${index}].stockWebConfig.quantity`} @@ -752,13 +762,11 @@ const Variations: React.FC<VariationsProps> = ({ <RHFTextField {...field} label="Quantité Web" - type="number" InputLabelProps={{ shrink: true }} placeholder="0" onChange={(e) => { const newValue = parseInt(e.target.value, 10); field.onChange(newValue); - const newVariations = [...localVariations]; newVariations[index].stockWebConfig = { ...newVariations[index].stockWebConfig, @@ -816,7 +824,7 @@ const Variations: React.FC<VariationsProps> = ({ } onChange={(e) => { field.onChange(e.target.checked); - setAllowPreorderLive(e.target.checked); + setAllowPreorderWeb(e.target.checked); // Update variations const newVariations = [ ...localVariations, @@ -846,7 +854,6 @@ const Variations: React.FC<VariationsProps> = ({ <RHFTextField {...field} label="Seuil de précommande en Web" - type="number" InputLabelProps={{ shrink: true }} placeholder="0" onChange={(e) => { @@ -889,11 +896,6 @@ const Variations: React.FC<VariationsProps> = ({ const newValue = e.target.checked; field.onChange(newValue); handlePublishLiveChange(newValue); - // Update variations - const newVariations = [...localVariations]; - newVariations[index].publishLive = newValue; - setLocalVariations(newVariations); - setVariations(newVariations); }} /> } @@ -901,7 +903,7 @@ const Variations: React.FC<VariationsProps> = ({ /> )} /> - {showLiveFields && ( + {variation.publishLive && ( <> <Controller name={`variations[${index}].stockLiveConfig.quantity`} @@ -911,7 +913,6 @@ const Variations: React.FC<VariationsProps> = ({ <RHFTextField {...field} label="Quantité Live" - type="number" InputLabelProps={{ shrink: true }} placeholder="0" onChange={(e) => { @@ -1014,7 +1015,7 @@ const Variations: React.FC<VariationsProps> = ({ variation.stockLiveConfig.thresholdValue } label="Seuil de précommande Live" - type="number" + InputLabelProps={{ shrink: true }} placeholder="0" onChange={(e) => { @@ -1054,7 +1055,7 @@ const Variations: React.FC<VariationsProps> = ({ onChange={(e) => { const newValue = e.target.checked; field.onChange(newValue); - // Update variations + const newVariations = [...localVariations]; newVariations[index].liveProductConfigs = { ...newVariations[index].liveProductConfigs,