299 lines
9.6 KiB
JavaScript
299 lines
9.6 KiB
JavaScript
import { useCallback, useMemo } from "react";
|
|
import { IoInformationCircleOutline } from "react-icons/io5";
|
|
import {
|
|
Tooltip,
|
|
TooltipContent,
|
|
TooltipProvider,
|
|
TooltipTrigger,
|
|
} from "@/components/ui/tooltip";
|
|
import { useDropzone } from "react-dropzone";
|
|
import { HiOutlineUpload } from "react-icons/hi";
|
|
import { MdClose } from "react-icons/md";
|
|
import { t } from "@/utils";
|
|
import CustomImage from "@/components/Common/CustomImage";
|
|
|
|
const EditComponentThree = ({
|
|
uploadedImages,
|
|
setUploadedImages,
|
|
OtherImages,
|
|
setOtherImages,
|
|
handleImageSubmit,
|
|
handleGoBack,
|
|
setDeleteImagesId,
|
|
}) => {
|
|
|
|
|
|
const onDrop = useCallback((acceptedFiles) => {
|
|
if (acceptedFiles.length == 0) {
|
|
toast.error(t("wrongFile"));
|
|
} else {
|
|
setUploadedImages(acceptedFiles);
|
|
}
|
|
}, []);
|
|
|
|
const { getRootProps, getInputProps, isDragActive } = useDropzone({
|
|
onDrop,
|
|
accept: {
|
|
"image/jpeg": [".jpeg", ".jpg"],
|
|
"image/png": [".png"],
|
|
},
|
|
multiple: false,
|
|
});
|
|
|
|
const files = useMemo(() => {
|
|
if (typeof uploadedImages === "string") {
|
|
return (
|
|
<div className="relative">
|
|
<CustomImage
|
|
width={591}
|
|
height={350}
|
|
className="rounded-2xl object-cover aspect-[591/350]"
|
|
src={uploadedImages}
|
|
alt="Uploaded Image"
|
|
/>
|
|
<div className="absolute top-2 left-2 flex gap-2 items-center">
|
|
<button
|
|
className="bg-white p-1 rounded-full"
|
|
onClick={() => removeImage(0)}
|
|
>
|
|
<MdClose
|
|
size={14}
|
|
color="black"
|
|
className="flex items-center justify-center rounded-full"
|
|
/>
|
|
</button>
|
|
<div className="text-white flex flex-col">
|
|
<span>{t("uploadedImage")}</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
} else {
|
|
return (
|
|
uploadedImages?.map((file, index) => (
|
|
<div key={index} className="relative">
|
|
<CustomImage
|
|
width={591}
|
|
height={350}
|
|
className="rounded-2xl object-cover aspect-[591/350]"
|
|
src={URL.createObjectURL(file)}
|
|
alt={index}
|
|
/>
|
|
<div className="absolute top-2 left-2 flex gap-2 items-center">
|
|
<button
|
|
className="bg-white p-1 rounded-full"
|
|
onClick={() => removeImage(index)}
|
|
>
|
|
<MdClose
|
|
size={14}
|
|
color="black"
|
|
className="flex items-center justify-center rounded-full"
|
|
/>
|
|
</button>
|
|
<div className="text-white text-xs flex flex-col">
|
|
<span>{file.name}</span>
|
|
<span>{Math.round(file.size / 1024)} KB</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)) || []
|
|
);
|
|
}
|
|
}, [uploadedImages]);
|
|
|
|
const removeImage = (index) => {
|
|
if (typeof uploadedImages === "string") {
|
|
setUploadedImages([]);
|
|
} else {
|
|
setUploadedImages((prevImages) =>
|
|
prevImages?.filter((_, i) => i !== index)
|
|
);
|
|
}
|
|
};
|
|
|
|
const onOtherDrop = useCallback(
|
|
(acceptedFiles) => {
|
|
const currentFilesCount = OtherImages.length; // Number of files already uploaded
|
|
const remainingSlots = 5 - currentFilesCount; // How many more files can be uploaded
|
|
|
|
if (remainingSlots === 0) {
|
|
// Show error if the limit has been reached
|
|
toast.error(t("imageLimitExceeded"));
|
|
return;
|
|
}
|
|
|
|
if (acceptedFiles.length > remainingSlots) {
|
|
// Show error if the number of new files exceeds the remaining slots
|
|
toast.error(
|
|
t("youCanUpload") + " " + remainingSlots + " " + t("moreImages")
|
|
);
|
|
return;
|
|
}
|
|
|
|
// Add the new files to the state
|
|
setOtherImages((prevImages) => [...prevImages, ...acceptedFiles]);
|
|
},
|
|
[OtherImages]
|
|
);
|
|
|
|
const {
|
|
getRootProps: getRootOtheProps,
|
|
getInputProps: getInputOtherProps,
|
|
isDragActive: isDragOtherActive,
|
|
} = useDropzone({
|
|
onDrop: onOtherDrop,
|
|
accept: {
|
|
"image/jpeg": [".jpeg", ".jpg"],
|
|
"image/png": [".png"],
|
|
},
|
|
multiple: true,
|
|
});
|
|
|
|
const removeOtherImage = (index, file) => {
|
|
setOtherImages((prevImages) => prevImages.filter((_, i) => i !== index));
|
|
setDeleteImagesId((prevIds) => {
|
|
const newId = file?.id;
|
|
if (prevIds) {
|
|
return `${prevIds},${newId}`;
|
|
} else {
|
|
return `${newId}`;
|
|
}
|
|
});
|
|
};
|
|
|
|
const filesOther = useMemo(
|
|
() =>
|
|
OtherImages &&
|
|
OtherImages?.map((file, index) => (
|
|
<div key={file.id || `${file?.name}-${file?.size}`} className="relative">
|
|
<CustomImage
|
|
width={591}
|
|
height={350}
|
|
className="rounded-2xl object-cover aspect-[591/350]"
|
|
src={file.image ? file.image : URL.createObjectURL(file)}
|
|
alt={index}
|
|
/>
|
|
<div className="absolute top-2 left-2 flex gap-2 items-center">
|
|
<button
|
|
className="bg-white p-1 rounded-full"
|
|
onClick={() => removeOtherImage(index, file)}
|
|
>
|
|
<MdClose
|
|
size={14}
|
|
color="black"
|
|
className="flex items-center justify-center rounded-full"
|
|
/>
|
|
</button>
|
|
{
|
|
(file?.name || file?.size) &&
|
|
<div className="text-white text-xs flex flex-col">
|
|
<span>{file.name}</span>
|
|
<span>{Math.round(file.size / 1024)} KB</span>
|
|
</div>
|
|
}
|
|
</div>
|
|
</div>
|
|
)),
|
|
[OtherImages]
|
|
);
|
|
return (
|
|
<div className="flex flex-col gap-8">
|
|
<div className="grid grid-col-1 md:grid-cols-2 gap-4">
|
|
<div className="flex flex-col gap-2">
|
|
<span className="requiredInputLabel text-sm">{t("mainPicture")}</span>
|
|
<div className="border-2 border-dashed rounded-lg p-2">
|
|
<div
|
|
{...getRootProps()}
|
|
className="flex flex-col min-h-[175px] items-center justify-center cursor-pointer"
|
|
style={{ display: uploadedImages.length > 0 ? "none" : "" }}
|
|
>
|
|
<input {...getInputProps()} />
|
|
{isDragActive ? (
|
|
<span className="text-muted-foreground font-medium">
|
|
{t("dropFiles")}
|
|
</span>
|
|
) : (
|
|
<div className="flex flex-col items-center gap-2 text-center">
|
|
<span className="text-muted-foreground">
|
|
{t("dragFiles")}
|
|
</span>
|
|
<span className="text-muted-foreground">{t("or")}</span>
|
|
<div className="flex items-center gap-2 text-primary">
|
|
<HiOutlineUpload size={24} />
|
|
<span className="font-medium">{t("upload")}</span>
|
|
</div>
|
|
</div>
|
|
)}
|
|
</div>
|
|
<div>{files}</div>
|
|
</div>
|
|
</div>
|
|
<div className="flex flex-col gap-2">
|
|
<span className="flex items-center gap-1 font-semibold text-sm">
|
|
{t("otherPicture")}
|
|
|
|
<TooltipProvider>
|
|
<Tooltip>
|
|
<TooltipTrigger asChild>
|
|
<span className="inline-flex">
|
|
<IoInformationCircleOutline size={22} />
|
|
</span>
|
|
</TooltipTrigger>
|
|
<TooltipContent
|
|
side="top"
|
|
align="center"
|
|
className="font-normal"
|
|
>
|
|
<p>{t("maxOtherImages")}</p>
|
|
</TooltipContent>
|
|
</Tooltip>
|
|
</TooltipProvider>
|
|
</span>
|
|
<div className="border-2 border-dashed rounded-lg p-2">
|
|
<div
|
|
{...getRootOtheProps()}
|
|
className="flex flex-col items-center justify-center min-h-[175px] cursor-pointer"
|
|
style={{ display: OtherImages.length >= 5 ? "none" : "" }}
|
|
>
|
|
<input {...getInputOtherProps()} />
|
|
{isDragOtherActive ? (
|
|
<span className="text-primary font-medium">
|
|
{t("dropFiles")}
|
|
</span>
|
|
) : (
|
|
<div className="flex flex-col gap-2 items-center text-center">
|
|
<span className="text-muted-foreground">
|
|
{t("dragFiles")}
|
|
</span>
|
|
<span className="text-muted-foreground">{t("or")}</span>
|
|
<div className="flex items-center gap-2 text-primary">
|
|
<HiOutlineUpload size={24} />
|
|
<span className="font-medium">{t("upload")}</span>
|
|
</div>
|
|
</div>
|
|
)}
|
|
</div>
|
|
<div className="flex flex-col gap-3">{filesOther}</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div className="flex justify-end gap-3">
|
|
<button
|
|
className="bg-black text-white px-4 py-2 rounded-md text-xl font-light"
|
|
onClick={handleGoBack}
|
|
>
|
|
{t("back")}
|
|
</button>
|
|
<button
|
|
className="bg-primary text-white px-4 py-2 rounded-md text-xl font-light"
|
|
onClick={handleImageSubmit}
|
|
>
|
|
{t("next")}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default EditComponentThree;
|