2025-02-12 13:25:22 +05:30
|
|
|
import {
|
|
|
|
|
DialogBody,
|
|
|
|
|
DialogCloseTrigger,
|
|
|
|
|
DialogContent,
|
|
|
|
|
DialogFooter,
|
|
|
|
|
DialogHeader,
|
|
|
|
|
DialogRoot,
|
|
|
|
|
DialogTitle,
|
|
|
|
|
} from "../../../components/ui/dialog";
|
|
|
|
|
import {
|
|
|
|
|
Box,
|
|
|
|
|
Field,
|
|
|
|
|
Input,
|
|
|
|
|
Stack,
|
|
|
|
|
} from "@chakra-ui/react";
|
|
|
|
|
import { Button } from "../../../components/ui/button";
|
2025-02-07 16:38:38 +05:30
|
|
|
import { FiUpload } from "react-icons/fi";
|
|
|
|
|
import { useState } from "react";
|
2025-03-06 13:50:35 +05:30
|
|
|
// import { FaRegEdit } from "react-icons/fa";
|
2025-02-12 13:25:22 +05:30
|
|
|
import Edit from "../../../components/ActionIcons/Edit";
|
2025-03-06 13:50:35 +05:30
|
|
|
import { Toaster, toaster } from "../../../components/ui/toaster";
|
|
|
|
|
import { Template, useUpdateTemplateMasterMutation } from "../../../Redux/Service/template.master.service";
|
2025-02-07 16:38:38 +05:30
|
|
|
|
2025-03-06 13:50:35 +05:30
|
|
|
const APIURL = import.meta.env.VITE_IMG_TEMPLATES
|
2025-02-12 13:25:22 +05:30
|
|
|
|
2025-03-06 13:50:35 +05:30
|
|
|
function EditTemplateModel({ id, localData }: { id: any, localData: any }) {
|
|
|
|
|
const [title, setTitle] = useState("");
|
|
|
|
|
const [subTitle, setSubTitle] = useState("");
|
|
|
|
|
const [userType, setUserType] = useState<number | "">("");
|
|
|
|
|
const [images, setImages] = useState<(File | string)[]>([]);
|
|
|
|
|
const [updateTemplateMaster] = useUpdateTemplateMasterMutation()
|
|
|
|
|
const [isOpen, setIsOpen] = useState(false);
|
|
|
|
|
const [selectedTemplate, setSelectedTemplate] = useState<Template | null>(null);
|
2025-02-12 13:25:22 +05:30
|
|
|
|
2025-03-06 13:50:35 +05:30
|
|
|
console.log(selectedTemplate);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// const handleImageChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
|
|
|
|
// if (event.target.files) {
|
|
|
|
|
// const selectedFiles = Array.from(event.target.files);
|
|
|
|
|
|
|
|
|
|
// const newImages = selectedFiles.map((file) => {
|
|
|
|
|
// return URL.createObjectURL(file); // Convert to preview URL
|
|
|
|
|
// });
|
|
|
|
|
|
|
|
|
|
// setImages((prevImages) => [...prevImages, ...newImages]); // Append new images
|
|
|
|
|
// }
|
|
|
|
|
// };
|
|
|
|
|
|
|
|
|
|
const handleOpenModal = () => {
|
|
|
|
|
const template = localData?.find((item: any) => item.id === id);
|
|
|
|
|
if (template) {
|
|
|
|
|
setSelectedTemplate(template);
|
|
|
|
|
setTitle(template.post_template_translate.length > 0 ? template.post_template_translate[0].title : "");
|
|
|
|
|
setSubTitle(template.post_template_translate.length > 0 ? template.post_template_translate[0].sub_title : "");
|
|
|
|
|
setUserType(template.principle_type_xid?.toString() || "");
|
|
|
|
|
|
|
|
|
|
// Convert image URLs to File objects if needed
|
|
|
|
|
const templateImages = template.post_template_image.map((img: any) => `${APIURL}${img.image_name}`);
|
|
|
|
|
setImages(templateImages);
|
|
|
|
|
|
|
|
|
|
setIsOpen(true);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const convertFileToBase64 = (file: File): Promise<string> => {
|
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
|
const reader = new FileReader();
|
|
|
|
|
reader.readAsDataURL(file);
|
|
|
|
|
reader.onload = () => resolve(reader.result as string);
|
|
|
|
|
reader.onerror = (error) => reject(error);
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const handleImageChange = async (e: React.ChangeEvent<HTMLInputElement>) => {
|
|
|
|
|
const files = e.target.files;
|
|
|
|
|
if (!files) return;
|
|
|
|
|
|
|
|
|
|
const newImages = await Promise.all(Array.from(files).map(convertFileToBase64));
|
|
|
|
|
|
|
|
|
|
setImages((prevImages) => [...prevImages.filter((img) => typeof img === "string" && !newImages.includes(img)), ...newImages]);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const handleSubmit = async () => {
|
|
|
|
|
if (!title.trim() || !subTitle.trim()) {
|
|
|
|
|
toaster.create({
|
|
|
|
|
title: "Error",
|
|
|
|
|
description: "Title and Subtitle cannot be empty.",
|
|
|
|
|
type: "error",
|
|
|
|
|
});
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (userType === "" || isNaN(Number(userType))) {
|
|
|
|
|
toaster.create({
|
|
|
|
|
title: "Error",
|
|
|
|
|
description: "Please select a valid user type.",
|
|
|
|
|
type: "error",
|
|
|
|
|
});
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (images.length === 0) {
|
|
|
|
|
toaster.create({
|
|
|
|
|
title: "Error",
|
|
|
|
|
description: "Please upload at least one image.",
|
|
|
|
|
type: "error",
|
2025-02-12 13:25:22 +05:30
|
|
|
});
|
2025-03-06 13:50:35 +05:30
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const existingImageUrls = images.filter((img) => typeof img === "string") as string[];
|
|
|
|
|
const newBase64Images = images.filter((img) => typeof img === "string" && img.startsWith("data:image")) as string[];
|
2025-02-12 13:25:22 +05:30
|
|
|
|
2025-03-06 13:50:35 +05:30
|
|
|
const payload = {
|
|
|
|
|
id: id,
|
|
|
|
|
principle_type_xid: userType,
|
|
|
|
|
title,
|
|
|
|
|
sub_title: subTitle,
|
|
|
|
|
image_name: [...existingImageUrls, ...newBase64Images], // Send only Base64 strings
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
await updateTemplateMaster(payload)
|
|
|
|
|
setIsOpen(false)
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error("Error creating template:", error);
|
|
|
|
|
alert("Failed to create template");
|
2025-02-12 13:25:22 +05:30
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return (
|
2025-03-06 13:50:35 +05:30
|
|
|
<DialogRoot placement="center" open={isOpen} onOpenChange={({ open }) => setIsOpen(open)}>
|
|
|
|
|
{/* <Button bg={"transparent"} size="sm">
|
|
|
|
|
<MdOutlineRemoveRedEye style={{ cursor: "pointer", fontSize: "16px" }} />
|
|
|
|
|
</Button> */}
|
|
|
|
|
<Box bg={"transparent"} onClick={handleOpenModal}>
|
|
|
|
|
<Edit />
|
|
|
|
|
</Box>
|
|
|
|
|
|
2025-02-12 13:25:22 +05:30
|
|
|
|
|
|
|
|
<DialogContent
|
|
|
|
|
bg={"#fff"}
|
|
|
|
|
// w={{ lg: "60%", md: "230px" }}
|
2025-03-06 13:50:35 +05:30
|
|
|
w={{ base: '90%', md: '400px' }}
|
|
|
|
|
height={'auto'}
|
|
|
|
|
|
2025-02-12 13:25:22 +05:30
|
|
|
overflowX="hidden"
|
|
|
|
|
p={3} // Reduced padding
|
2025-03-06 13:50:35 +05:30
|
|
|
bgSize={'md'}
|
2025-02-12 13:25:22 +05:30
|
|
|
>
|
2025-03-06 13:50:35 +05:30
|
|
|
<DialogHeader bg="white" >
|
|
|
|
|
<DialogTitle alignSelf="center" color="black" fontSize="14px">Add</DialogTitle>
|
2025-02-12 13:25:22 +05:30
|
|
|
</DialogHeader>
|
|
|
|
|
|
|
|
|
|
<DialogBody bg="white">
|
|
|
|
|
<Stack py={3}>
|
2025-03-06 13:50:35 +05:30
|
|
|
|
2025-02-12 13:25:22 +05:30
|
|
|
<Field.Root>
|
2025-03-06 13:50:35 +05:30
|
|
|
<Field.Label color="black" pt={1} fontSize="12px">Title</Field.Label>
|
2025-02-12 13:25:22 +05:30
|
|
|
<Input
|
2025-03-06 13:50:35 +05:30
|
|
|
placeholder="Enter Title"
|
2025-02-12 13:25:22 +05:30
|
|
|
bgColor="#EEEEEE"
|
|
|
|
|
color="black"
|
|
|
|
|
border="none"
|
|
|
|
|
pl={1}
|
|
|
|
|
fontSize="12px"
|
|
|
|
|
height="30px"
|
2025-03-06 13:50:35 +05:30
|
|
|
value={title}
|
|
|
|
|
onChange={(e) => setTitle(e.target.value)}
|
2025-02-12 13:25:22 +05:30
|
|
|
/>
|
2025-03-06 13:50:35 +05:30
|
|
|
</Field.Root>
|
2025-02-12 13:25:22 +05:30
|
|
|
|
2025-03-06 13:50:35 +05:30
|
|
|
<Field.Root>
|
|
|
|
|
<Field.Label color="black" pt={1} fontSize="12px">Subtitle</Field.Label>
|
|
|
|
|
<Input
|
|
|
|
|
placeholder="Enter subtitle"
|
2025-02-12 13:25:22 +05:30
|
|
|
bgColor="#EEEEEE"
|
2025-03-06 13:50:35 +05:30
|
|
|
color="black"
|
2025-02-12 13:25:22 +05:30
|
|
|
border="none"
|
2025-03-06 13:50:35 +05:30
|
|
|
pl={1}
|
|
|
|
|
fontSize="12px"
|
|
|
|
|
height="30px"
|
|
|
|
|
value={subTitle}
|
|
|
|
|
onChange={(e) => setSubTitle(e.target.value)}
|
|
|
|
|
/>
|
|
|
|
|
</Field.Root>
|
|
|
|
|
|
|
|
|
|
<Field.Root>
|
|
|
|
|
<Field.Label color="black" pt={1} fontSize="12px">Select User Type</Field.Label>
|
|
|
|
|
<Box bgColor="#EEEEEE" borderRadius="md" p={1}>
|
|
|
|
|
<select
|
|
|
|
|
style={{
|
|
|
|
|
width: "100%",
|
|
|
|
|
background: "transparent",
|
|
|
|
|
color: "black",
|
|
|
|
|
border: "none",
|
|
|
|
|
fontSize: "12px",
|
|
|
|
|
height: "30px",
|
|
|
|
|
outline: "none",
|
|
|
|
|
}}
|
|
|
|
|
value={userType}
|
|
|
|
|
onChange={(e) => setUserType(Number(e.target.value))}
|
|
|
|
|
>
|
|
|
|
|
<option value="">Select User Type</option>
|
|
|
|
|
<option value="2">Recruiter</option>
|
|
|
|
|
<option value="3">Jobseeker</option>
|
|
|
|
|
</select>
|
|
|
|
|
</Box>
|
|
|
|
|
</Field.Root>
|
|
|
|
|
|
|
|
|
|
<Field.Root>
|
|
|
|
|
<Field.Label color="black" pt={1} fontSize="12px">Images</Field.Label>
|
|
|
|
|
<Box display="flex" alignItems="center" justifyContent="space-between" px={3} bgColor="#EEEEEE" border="none" width="100%" height="50px" cursor="pointer" position="relative">
|
|
|
|
|
<Input type="file" accept="image/*" opacity={0} position="absolute" bgColor="#EEEEEE" border="none" pl={1} width="100%" height="100%" cursor="pointer" onChange={handleImageChange} />
|
2025-02-12 13:25:22 +05:30
|
|
|
<Box display="flex" gap={2} overflow="hidden">
|
|
|
|
|
{images.length > 0 ? (
|
|
|
|
|
images.map((img, index) => (
|
|
|
|
|
<img
|
|
|
|
|
key={index}
|
2025-03-06 13:50:35 +05:30
|
|
|
src={img instanceof File ? URL.createObjectURL(img) : img}
|
2025-02-12 13:25:22 +05:30
|
|
|
alt={`Uploaded ${index}`}
|
2025-03-06 13:50:35 +05:30
|
|
|
style={{ maxHeight: "40px", maxWidth: "70px", objectFit: "contain" }}
|
2025-02-12 13:25:22 +05:30
|
|
|
/>
|
|
|
|
|
))
|
|
|
|
|
) : (
|
|
|
|
|
<Box width="70px" height="40px" /> // Placeholder to maintain layout
|
|
|
|
|
)}
|
|
|
|
|
</Box>
|
|
|
|
|
<FiUpload color="#000" />
|
|
|
|
|
</Box>
|
|
|
|
|
|
|
|
|
|
{/* <Input placeholder="" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" /> */}
|
2025-03-06 13:50:35 +05:30
|
|
|
|
2025-02-12 13:25:22 +05:30
|
|
|
</Field.Root>
|
|
|
|
|
</Stack>
|
2025-03-06 13:50:35 +05:30
|
|
|
|
2025-02-12 13:25:22 +05:30
|
|
|
</DialogBody>
|
|
|
|
|
<DialogFooter display="flex" justifyContent="center" pt={"2"}>
|
2025-03-06 13:50:35 +05:30
|
|
|
<Button w="100%" bg="#02A0A0" color={"#fff"} onClick={handleSubmit}>
|
2025-02-12 13:25:22 +05:30
|
|
|
Save
|
|
|
|
|
</Button>
|
|
|
|
|
</DialogFooter>
|
|
|
|
|
|
2025-03-06 13:50:35 +05:30
|
|
|
<DialogCloseTrigger color="black" onClick={() => setIsOpen(false)} />
|
2025-02-12 13:25:22 +05:30
|
|
|
</DialogContent>
|
2025-03-06 13:50:35 +05:30
|
|
|
<Toaster />
|
|
|
|
|
</DialogRoot >
|
2025-02-12 13:25:22 +05:30
|
|
|
);
|
2025-02-07 16:38:38 +05:30
|
|
|
}
|
|
|
|
|
|
2025-02-12 13:25:22 +05:30
|
|
|
export default EditTemplateModel;
|