diff --git a/src/app/dashboard/product/attribut/[id]/termeImage/[imageId]/edit/page.tsx b/src/app/dashboard/product/attribut/[id]/termeImage/[imageId]/edit/page.tsx new file mode 100644 index 0000000000000000000000000000000000000000..09768de0e7dda952027c177013fbbab97573e8c7 --- /dev/null +++ b/src/app/dashboard/product/attribut/[id]/termeImage/[imageId]/edit/page.tsx @@ -0,0 +1,22 @@ +import ColorEditView from "@/shared/sections/product/add-edit-ConfigurationIColorTerme/termeColor-edit-view"; +import ImageEditView from "@/shared/sections/product/add-edit-ConfigurationImageTerme/edit-termImage-view"; + + +// ---------------------------------------------------------------------- + +export const metadata = { + title: "Dashboard: modification d'un terme image ", +}; + +type Props = { + params: { + id: string; + imageId : string + }; + }; + + +export default function ColorEditPage({ params }: Props) { + const { id, imageId } = params; + return < ImageEditView id={id} imageId={imageId} />; +} diff --git a/src/app/dashboard/product/attribut/[id]/termeImage/page.tsx b/src/app/dashboard/product/attribut/[id]/termeImage/page.tsx new file mode 100644 index 0000000000000000000000000000000000000000..4d5d8e1d96d345323119fff6c43c2943fce96aa7 --- /dev/null +++ b/src/app/dashboard/product/attribut/[id]/termeImage/page.tsx @@ -0,0 +1,18 @@ +import TermeImage from "@/shared/sections/product/add-edit-ConfigurationImageTerme/create-termeImage"; + +// ---------------------------------------------------------------------- + +type Props = { + params: { + id: string; + }; +}; + +export const metadata = { + title: "Dashboard: terme Image", +}; + +export default function TermImageListPage({ params }: Props) { + const {id} = params; + return <TermeImage attributid = {id}/>; +} diff --git a/src/app/dashboard/product/attribut/termeImage/page.tsx b/src/app/dashboard/product/attribut/termeImage/page.tsx deleted file mode 100644 index e168b7493ae39e313c4b504604563bfc22017987..0000000000000000000000000000000000000000 --- a/src/app/dashboard/product/attribut/termeImage/page.tsx +++ /dev/null @@ -1,11 +0,0 @@ -import TermeImage from "@/shared/sections/product/add-edit-ConfigurationImageTerme/create-termeImage"; - -// ---------------------------------------------------------------------- - -export const metadata = { - title: "Dashboard: Configuration Attribut", -}; - -export default function ProductListPage() { - return <TermeImage />; -} diff --git a/src/routes/paths.ts b/src/routes/paths.ts index 208e5b7b55532242ce56c1ff32e3a1edfb8d3a61..7dd747b8fb1db4dbb16d44d1e9484f8839a52e3d 100644 --- a/src/routes/paths.ts +++ b/src/routes/paths.ts @@ -36,7 +36,12 @@ export const paths = { `${ROOTS.DASHBOARD}/product/attribut/${attributId}/termeChoix/${choiceId}/edit`, }, - termeImage: `${ROOTS.DASHBOARD}/product/attribut/termeImage`, + termeImage: { + root: (id: string) => + `${ROOTS.DASHBOARD}/product/attribut/${id}/termeImage`, + editImage : (attributId: string, imageId: string )=> + `${ROOTS.DASHBOARD}/product/attribut/${attributId}/termeImage/${imageId}/edit`, + }, termeLabel: `${ROOTS.DASHBOARD}/product/attribut/termeLabel`, termeColor: { root: (attributId: string) => diff --git a/src/shared/sections/product/add-edit-ConfigurationImageTerme/create-termeImage.tsx b/src/shared/sections/product/add-edit-ConfigurationImageTerme/create-termeImage.tsx index 11528ea2791a25e392e1cc1198fc505a1cb9ac7f..a4d2f35c606ccdefa49b9ce7eab4b1c355d3bc68 100644 --- a/src/shared/sections/product/add-edit-ConfigurationImageTerme/create-termeImage.tsx +++ b/src/shared/sections/product/add-edit-ConfigurationImageTerme/create-termeImage.tsx @@ -13,6 +13,7 @@ import { useBoolean } from "@/hooks/use-boolean"; import ConfirmDialog from "@/shared/components/confirm-dialog"; import AddTermeImage from "./form-termeImage"; import { useRouter } from "@/hooks"; +import {useDeleteImage, useDeleteImages, useGetImageByAttribut} from "@/shared/api/terms" import { DataGrid, @@ -24,24 +25,83 @@ import { GridRowSelectionModel, GridToolbarFilterButton, } from "@mui/x-data-grid"; -import { _categories } from "@/shared/_mock/_categories"; -import { Avatar } from "@mui/material"; + +import { Alert, Avatar, CircularProgress, Typography } from "@mui/material"; +import { Description } from "@mui/icons-material"; //---------------------------------------------------------------------------------------- -export default function TermeImage() { +export default function TermeImage({ attributid }: { attributid: string }) { const [selectedRowIds, setSelectedRowIds] = useState<GridRowSelectionModel>( [] ); + const [errorMessage, setErrorMessage] = useState<string | null>(null); + const [successMessage, setSuccessMessage] = useState<string | null>(null); + + const {ImagesData, ImagesLoading, ImagesError, ImagesMutate} = useGetImageByAttribut(attributid) const router = useRouter(); const handleEditRow = useCallback( (id: string) => { - router.push(paths.dashboard.admin.product.editCategory(id)); + router.push(paths.dashboard.admin.product.termeImage.editImage(attributid, id)); }, [router] ); const confirmRows = useBoolean(); + const handleRetry = async () => { + try { + await ImagesMutate(); + } catch (err) { + setErrorMessage("Erreur lors du rechargement des termes Images."); + setTimeout(() => { + setErrorMessage(null); + }, 5000); + } + }; - const handleDeleteRows = () => {}; + const handleDeleteRow = async (id: number) => { + try { + const response = await useDeleteImage(id.toString()); + ImagesMutate(); + + if (response.status === 200) { + setSelectedRowIds([]); + setSuccessMessage("Image supprimée avec succès."); + + } + } catch (error) { + setErrorMessage("Erreur lors de la suppression de l'image."); + } finally { + const timeoutId = setTimeout(() => { + setSuccessMessage(null); + setErrorMessage(null); + clearTimeout(timeoutId) + }, 5000); + } + }; + const handleDeleteRows = async () => { + try { + if (selectedRowIds.length > 0) { + const idsToDelete = selectedRowIds.map((id) => id.toString()); + const response = await useDeleteImages(idsToDelete); + setSelectedRowIds([]); + ImagesMutate(); + + if (response.status === 200) { + + setSuccessMessage("Images(s) supprimée(s) avec succès."); + + } + } + } catch (error) { + + setErrorMessage("Erreur lors de la suppression des images."); + } finally { + const timeoutId = setTimeout(() => { + setSuccessMessage(null); + setErrorMessage(null); + clearTimeout(timeoutId) + }, 5000); + } + }; const columns: GridColDef[] = [ { @@ -103,7 +163,7 @@ export default function TermeImage() { icon={<Iconify icon="solar:trash-bin-trash-bold" />} label="Supprimer" onClick={() => { - //handleDeleteRow(params.row.id); + handleDeleteRow(params.row.id); }} sx={{ color: "error.main" }} />, @@ -111,13 +171,14 @@ export default function TermeImage() { }, ]; - const rows = _categories.map((category) => ({ - id: category.id, - Preview: category.image, - name: category.name, - slug: category.slug, - - total: category.total, + const rows = ImagesData.map((image) => ( + { + id: image.id, + Preview: image.image, + name: image.nom, + slug: image.slug, + description : image.description, + total: image.total, })); return ( @@ -137,7 +198,12 @@ export default function TermeImage() { name: "Product", href: paths.dashboard.admin.product.root, }, - { name: "Attribut", href: paths.dashboard.admin.product.attribut }, + { name: "Attribut", + href: paths.dashboard.admin.product.attribut }, + { + name : "Images", + href : paths.dashboard.admin.product.termeImage.root(attributid) + } ]} sx={{ mb: { @@ -149,10 +215,33 @@ export default function TermeImage() { <Grid container spacing={3}> <Grid item xs={4}> - <AddTermeImage /> + <AddTermeImage attributid={attributid} /> </Grid> <Grid item xs={8}> + {ImagesLoading ? ( + <Stack + direction="row" + spacing={2} + justifyContent="center" + alignItems="center" + sx={{ height: '100%', width: '100%' }} + > + <CircularProgress /> + <Typography>Chargement des termes Images...</Typography> + </Stack> + ): ImagesError? ( + <Container> + <Alert severity="error" sx={{ mb: 2 }}> + Impossible de charger la liste des termes images + </Alert> + <Button variant="contained" color="primary" onClick={handleRetry}> + Réessayer + </Button> + </Container> + ) : ( + + <Card variant="outlined"> <DataGrid checkboxSelection @@ -208,7 +297,18 @@ export default function TermeImage() { }, }} /> + {errorMessage && ( + <Alert severity="error" onClose={() => setErrorMessage(null)}> + {errorMessage} + </Alert> + )} + {successMessage && ( + <Alert severity="success" onClose={() => setSuccessMessage(null)}> + {successMessage} + </Alert> + )} </Card> + )} <ConfirmDialog open={confirmRows.value} onClose={confirmRows.onFalse} diff --git a/src/shared/sections/product/add-edit-ConfigurationImageTerme/edit-termImage-view.tsx b/src/shared/sections/product/add-edit-ConfigurationImageTerme/edit-termImage-view.tsx new file mode 100644 index 0000000000000000000000000000000000000000..ba257c599d8ac1377c58e3c9784524708611a344 --- /dev/null +++ b/src/shared/sections/product/add-edit-ConfigurationImageTerme/edit-termImage-view.tsx @@ -0,0 +1,52 @@ +"use client"; + +import Container from "@mui/material/Container"; + +import { paths } from "@/routes/paths"; + +import { useSettingsContext } from "@/shared/components/settings"; + +import CustomBreadcrumbs from "@/shared/components/custom-breadcrumbs"; +import EditTermeImageForm from "./form-edit-termImage"; +// import EditTermLabForm from "./termeLabel-edit-form"; + + +// ---------------------------------------------------------------------- + +type Props = { + id: string; + imageId : string; +}; + +export default function ImageEditView({ id , imageId}: Props) { + const settings = useSettingsContext(); + + return ( + <Container maxWidth={settings.themeStretch ? false : "lg"}> + <CustomBreadcrumbs + heading="Modifier" + links={[ + { name: "Dashboard", href: paths.dashboard.root }, + { + name: "Product", + href: paths.dashboard.admin.product.root, + }, + { name: "Attribut", + href: paths.dashboard.admin.product.attribut }, + { + name : "Image", + href : paths.dashboard.admin.product.termeImage.root(id) + }, + { + name: "Modifier le terme image" + } + ]} + sx={{ + mb: { xs: 3, md: 5 }, + }} + /> + + <EditTermeImageForm attributid={id} imageId= {imageId}/> + </Container> + ); +} diff --git a/src/shared/sections/product/add-edit-ConfigurationImageTerme/form-edit-termImage.tsx b/src/shared/sections/product/add-edit-ConfigurationImageTerme/form-edit-termImage.tsx new file mode 100644 index 0000000000000000000000000000000000000000..80425c166d0705487414b03c3187d468b435303e --- /dev/null +++ b/src/shared/sections/product/add-edit-ConfigurationImageTerme/form-edit-termImage.tsx @@ -0,0 +1,265 @@ +"use client"; +import { useEffect, useState } from "react"; +import TextField from "@mui/material/TextField"; +import Button from "@mui/material/Button"; +import DeleteIcon from "@mui/icons-material/Delete"; +import Stack from "@mui/material/Stack"; +import Typography from "@mui/material/Typography"; +import Avatar from "@mui/material/Avatar"; +import Card from "@mui/material/Card"; +import { AccessLevel, FileType, IMedia, Visibility } from "@/shared/types/media"; +import AddMediaButton from "../../media/view/Add-media-button"; +import { Alert, Grid, IconButton, Snackbar } from "@mui/material"; +import { + useGetImageByAttribut, + useUpdateImage, + useGetImage, +} from "@/shared/api/terms"; +import { IImage } from "@/shared/types/term"; +import CloseIcon from "@mui/icons-material/Close"; + +function extractUrl(str: string | null){ + if (!str) { + return null; + } + const match = str.match(/\[(.*?)\]/); + return match ? match[1] : str; // Returns full string if no brackets found +} + +export default function EditTermeImageForm({ + attributid, + imageId, +}: { + attributid: string; + imageId: string; +}) { + + const { ImagesMutate } = useGetImageByAttribut(attributid); + const { ImageData, ImageMutate } = useGetImage(imageId); + const [returnedMultiMedia, setReturnedMultiMedia] = useState<IMedia[]>([]); + + const [nom, setNom] = useState<string>(""); + const [slug, setSlug] = useState<string>(""); + const [description, setDescription] = useState<string>(""); + const [initialImageLoaded, setInitialImageLoaded] = useState<boolean>(false); + const [isEditing, setIsEditing] = useState<boolean>(false); + + + const formSetter = () => { + setNom(ImageData.nom); + setSlug(ImageData.slug); + setDescription(ImageData.description); + if (ImageData.image && !initialImageLoaded) { + setReturnedMultiMedia([{ + id: "", + title: "", + description: "", + name: "", + createdAt: "", + modifiedAt: "", + size: 0, + userId: "", + fileType: FileType.IMAGE, + visibility: Visibility.PUBLIC, + permissions: AccessLevel.READ, + path: "", + uniqueId: "", + url: ImageData.image, + }]); + setInitialImageLoaded(true); + } + }; + + useEffect(() => { + + if (ImageData) { + formSetter(); + } + }, [ImageData]); + + const [openSnackbar, setOpenSnackbar] = useState<boolean>(false); + const [snackbarMessage, setSnackbarMessage] = useState<string>(""); + const [showSuccessMessage, setShowSuccessMessage] = useState(false); + + const handleCloseSnackbar = () => { + setOpenSnackbar(false); + }; + + const regex = /^[a-zA-Z0-9]+(?:[- ][a-zA-Z0-9]+)*$/; // Regex pour accepter lettres, chiffres et tirets + const slugRegex = /^[a-zA-Z0-9]+(?:[a-zA-Z0-9- ]*[a-zA-Z0-9]+)*$/; + + const validateForm = (): boolean => { + if (!nom || !description) { + setSnackbarMessage("Tous les champs requis doivent être remplis."); + setOpenSnackbar(true); + return false; + } + + if (!regex.test(nom)) { + setSnackbarMessage( + "Nom ne doit contenir que des lettres, des chiffres et des tirets." + ); + setOpenSnackbar(true); + return false; + } + + if (!slugRegex.test(slug) && slug !== "") { + setSnackbarMessage( + "Le slug doit commencer par une lettre ou un chiffre, peut contenir des tirets, et ne doit pas contenir uniquement des caractères spéciaux." + ); + setOpenSnackbar(true); + return false; + } + + if (!returnedMultiMedia) { + setSnackbarMessage("Veuillez sélectionner une image."); + setOpenSnackbar(true); + return false; + } + + return true; + }; + + const handleOnSubmit = async (event: React.FormEvent<HTMLFormElement>) => { + event.preventDefault(); + if (!validateForm()) { + return; + } + const imageURL = returnedMultiMedia.length > 0 ? returnedMultiMedia[0].url : null; + + const imageRequest: IImage = { + nom, + slug, + description, + image: extractUrl(imageURL), + attributeId: attributid, + }; + + try { + await useUpdateImage(imageRequest, imageId); + ImagesMutate(); + ImageMutate() + setShowSuccessMessage(true); + const timeoutId = setTimeout(() => { + setShowSuccessMessage(false); + clearTimeout(timeoutId); + }, 5000); + } catch (error) { + let errorMessage; + if ( + typeof error === "string" && + error.includes("An Image with this name already exists") + ) { + errorMessage = "Le slug doit également être unique."; + } else if ( + error instanceof Error && + error.message.includes("An Image with this name already exists") + ) { + errorMessage = "Le slug doit également être unique."; + } + setSnackbarMessage(errorMessage ?? "L'image n'a pas pu être modifiée."); + setOpenSnackbar(true); + } + }; + + const handleDeleteSingleImage = () => { + setReturnedMultiMedia([]); + }; + + return ( + <Card variant="outlined"> + <form onSubmit={handleOnSubmit}> + <Stack spacing={1.5} sx={{ p: 3 }}> + <Typography variant="subtitle2">Modifier le Terme</Typography> + + <TextField + name="nom" + label="Nom *" + InputLabelProps={{ shrink: true }} + value={nom} + onChange={(e) => setNom(e.target.value)} + /> + + <TextField + label="Slug" + name="slug" + InputLabelProps={{ shrink: true }} + value={slug} + onChange={(e) => setSlug(e.target.value)} + /> + + <TextField + name="description" + label="Description *" + multiline + rows={4} + InputLabelProps={{ shrink: true }} + value={description} + onChange={(e) => setDescription(e.target.value)} + /> + +<Stack spacing={1.5}> + <Grid container spacing={1} mt={1}> + <AddMediaButton + variant="outlined" + color="success" + size="medium" + sx={{ mt: 1 }} + nameBtn="Modifier l'image" + returnedMultiMedia={returnedMultiMedia} + setReturnedSingleMedia={(media) => { + setReturnedMultiMedia(media); + setIsEditing(true); // Activer le mode édition lorsque l'utilisateur clique + }} + /> + </Grid> + {returnedMultiMedia.length > 0 && !isEditing && ( + <Grid md={12} xs={12} style={{ display: 'flex', flexWrap: 'wrap' }}> + <Typography + component="span" + style={{ + fontSize: '15px', + color: 'text.secondary', + marginTop: 4, + width: '100%' + }} + > + {returnedMultiMedia.length} Média sélectionné + </Typography> + {returnedMultiMedia.map((media) => ( + <Grid key={media.id} style={{ margin: '10px', position: 'relative' }}> + <img src={extractUrl(media.url) ?? undefined} alt="image" style={{ width: '100px', height: '100px', objectFit: 'contain' }} /> + <IconButton onClick={() => setReturnedMultiMedia([])} style={{ position: 'absolute', top: 0, right: 0 }}> + <CloseIcon /> + </IconButton> + </Grid> + ))} + </Grid> + )} +</Stack> + + <Button type="submit" variant="contained" color="primary"> + Modifier + </Button> + </Stack> + <Snackbar + open={openSnackbar} + autoHideDuration={6000} + onClose={handleCloseSnackbar} + > + <Alert onClose={handleCloseSnackbar} severity="error"> + {snackbarMessage} + </Alert> + </Snackbar> + {showSuccessMessage && ( + <Alert + severity="success" + onClose={() => setShowSuccessMessage(false)} + > + L'image a été modifiée avec succès + </Alert> + )} + </form> + </Card> + ); +} diff --git a/src/shared/sections/product/add-edit-ConfigurationImageTerme/form-termeImage.tsx b/src/shared/sections/product/add-edit-ConfigurationImageTerme/form-termeImage.tsx index f7bd88a92a8c5cdb9b0e86bbc9f8e0d2f7c12699..2454cbfc7afb8b16628d34a958b21692b85a0d46 100644 --- a/src/shared/sections/product/add-edit-ConfigurationImageTerme/form-termeImage.tsx +++ b/src/shared/sections/product/add-edit-ConfigurationImageTerme/form-termeImage.tsx @@ -1,5 +1,5 @@ "use client"; -import { useState } from "react"; +import { useEffect, useState } from "react"; import TextField from "@mui/material/TextField"; import Button from "@mui/material/Button"; import DeleteIcon from "@mui/icons-material/Delete"; @@ -7,83 +7,185 @@ import Stack from "@mui/material/Stack"; import Typography from "@mui/material/Typography"; import Avatar from "@mui/material/Avatar"; import Card from "@mui/material/Card"; +import { IMedia } from "@/shared/types/media"; +import AddMediaButton from "../../media/view/Add-media-button"; +import { Alert, Grid, Snackbar } from "@mui/material"; +import { useAddImage, useGetImageByAttribut } from "@/shared/api/terms"; +import { IImage } from "@/shared/types/term"; +function extractUrl(str: string | null) { + if (!str) { + return null; + } + const match = str.match(/\[(.*?)\]/); + return match ? match[1] : null; +} //------------------------------------------------------ -export default function AddTermeImage() { +export default function AddTermeImage({ attributid }: { attributid: string }) { const [categoryImage, setCategoryImage] = useState<string | null>(null); - const handleImageChange = (event: React.ChangeEvent<HTMLInputElement>) => { - const file = event.target.files?.[0]; - if (file) { - if (file.size > 1048576) { - alert("La taille de l'image ne doit pas dépasser 1MB"); - return; + const [returnedMultiMedia, setReturnedMultiMedia] = useState< + IMedia[] | undefined + >(); + const { ImagesMutate } = useGetImageByAttribut(attributid); + + const [nom, setNom] = useState<string>(""); + const [slug, setSlug] = useState<string>(""); + const [description, setDescription] = useState<string>(""); + + // States for Snackbar + const [openSnackbar, setOpenSnackbar] = useState<boolean>(false); + const [snackbarMessage, setSnackbarMessage] = useState<string>(""); + const [showSuccessMessage, setShowSuccessMessage] = useState(false); + + const handleCloseSnackbar = () => { + setOpenSnackbar(false); + }; + + const regex = /^[a-zA-Z0-9]+(?:[- ][a-zA-Z0-9]+)*$/; // Regex pour accepter lettres, chiffres et tirets + const slugRegex = /^[a-zA-Z0-9]+(?:[a-zA-Z0-9- ]*[a-zA-Z0-9]+)*$/; + + const validateForm = (): boolean => { + if (!nom || !description) { + setSnackbarMessage("Tous les champs requis doivent être remplis."); + setOpenSnackbar(true); + return false; + } + + if (!regex.test(nom)) { + setSnackbarMessage( + "Nom ne doit contenir que des lettres, des chiffres et des tirets." + ); + setOpenSnackbar(true); + return false; + } + + if (!slugRegex.test(slug) && slug !== "") { + setSnackbarMessage( + "Le slug doit commencer par une lettre ou un chiffre, peut contenir des tirets, et ne doit pas contenir uniquement des caractères spéciaux." + ); + setOpenSnackbar(true); + return false; + } + + if (!returnedMultiMedia) { + setSnackbarMessage("Veuillez sélectionner une image."); + setOpenSnackbar(true); + return false; + } + + return true; + }; + + const handleOnSubmit = async (event: React.FormEvent<HTMLFormElement>) => { + event.preventDefault(); + if (!validateForm()) { + return; + } + let imageURL = null; + if (returnedMultiMedia !== undefined) { + imageURL = returnedMultiMedia[0].url; + } + + const imageRequest: IImage = { + nom, + slug, + description, + image: extractUrl(imageURL), + attributeId: attributid, + }; + + try { + await useAddImage(imageRequest); + ImagesMutate(); + setShowSuccessMessage(true); + const timeoutId = setTimeout(() => { + setShowSuccessMessage(false); + clearTimeout(timeoutId); + }, 5000); + } catch (error) { + let errorMessage; + if ( + typeof error === "string" && + error.includes("An Image with this name already exists") + ) { + errorMessage = "Le slug doit également être unique."; + } else if ( + error instanceof Error && + error.message.includes("An Image with this name already exists") + ) { + errorMessage = "Le slug doit également être unique."; } - const reader = new FileReader(); - reader.onloadend = () => { - setCategoryImage(reader.result as string); - }; - reader.readAsDataURL(file); + setSnackbarMessage(errorMessage ?? "L'image n'a pas pu être créée."); + setOpenSnackbar(true); } }; return ( <Card variant="outlined"> - <Stack spacing={1.5} sx={{ p: 3 }}> - <Typography variant="subtitle2">Ajouter le Terme</Typography> - - <TextField name="nom" label="Nom" InputLabelProps={{ shrink: true }} /> - - <TextField - label="Slug" - name="slug" - InputLabelProps={{ shrink: true }} - /> - - <TextField - name="Description" - label="Description " - multiline - rows={4} - InputLabelProps={{ shrink: true }} - /> - - <Stack spacing={1.5}> - <Typography variant="subtitle2">Images</Typography> - <input - accept="image/*" - style={{ display: "none" }} - id="category-image-input" - type="file" - onChange={handleImageChange} + <form onSubmit={handleOnSubmit}> + <Stack spacing={1.5} sx={{ p: 3 }}> + <Typography variant="subtitle2">Ajouter le Terme</Typography> + + <TextField + name="nom" + label="Nom *" + InputLabelProps={{ shrink: true }} + value={nom} + onChange={(e) => setNom(e.target.value)} + /> + + <TextField + label="Slug" + name="slug" + InputLabelProps={{ shrink: true }} + value={slug} + onChange={(e) => setSlug(e.target.value)} /> - <label htmlFor="category-image-input"> - <Button variant="outlined" component="span"> - Choisir une image - </Button> - </label> - {categoryImage && ( - <Stack direction="row" alignItems="center" spacing={1}> - <Avatar - alt="Catégorie Image" - src={categoryImage} - sx={{ width: 56, height: 56 }} - /> - <Button + <TextField + name="Description" + label="Description *" + multiline + rows={4} + InputLabelProps={{ shrink: true }} + value={description} + onChange={(e) => setDescription(e.target.value)} + /> + + <Stack spacing={1.5}> + <Grid container spacing={1} mt={1}> + <AddMediaButton variant="outlined" - size="small" - startIcon={<DeleteIcon />} - onClick={() => setCategoryImage(null)} - > - Supprimer l'image - </Button> - </Stack> - )} + color="success" + size="medium" + sx={{ mt: 1 }} + returnedMultiMedia={returnedMultiMedia} + setReturnedSingleMedia={setReturnedMultiMedia} + /> + </Grid> + </Stack> + <Button type="submit" variant="contained" color="primary"> + Ajouter + </Button> </Stack> - <Button type="submit" variant="contained" color="primary"> - Ajouter - </Button> - </Stack> + <Snackbar + open={openSnackbar} + autoHideDuration={6000} + onClose={handleCloseSnackbar} + > + <Alert onClose={handleCloseSnackbar} severity="error"> + {snackbarMessage} + </Alert> + </Snackbar> + {showSuccessMessage && ( + <Alert + severity="success" + onClose={() => setShowSuccessMessage(false)} + > + l'image a été ajouté avec succès + </Alert> + )} + </form> </Card> ); } diff --git a/src/shared/sections/product/add-edit-list-attribut/product-create-attrribut.tsx b/src/shared/sections/product/add-edit-list-attribut/product-create-attrribut.tsx index f85b61de5b9b17fc5cd60f0ab4ceac14ad2d97ac..897c0542bd70ae2e9a82e1982c2b4964d376b508 100644 --- a/src/shared/sections/product/add-edit-list-attribut/product-create-attrribut.tsx +++ b/src/shared/sections/product/add-edit-list-attribut/product-create-attrribut.tsx @@ -85,7 +85,7 @@ export default function ProductAttribut() { router.push(paths.dashboard.admin.product.termeChoix.root(id)); break; case "IMAGE": - router.push(paths.dashboard.admin.product.termeImage); + router.push(paths.dashboard.admin.product.termeImage.root(id)); break; case "COLOR": router.push(paths.dashboard.admin.product.termeColor.root(id));