Fixed Template modal button

This commit is contained in:
rockyeverlast
2025-03-06 13:50:35 +05:30
parent 346af173b2
commit ff651461a1
2 changed files with 178 additions and 66 deletions

View File

@@ -6,116 +6,225 @@ import {
DialogHeader,
DialogRoot,
DialogTitle,
DialogTrigger,
} from "../../../components/ui/dialog";
import {
Box,
Field,
IconButton,
Input,
Span,
Stack,
Text,
Textarea,
} from "@chakra-ui/react";
import { Button } from "../../../components/ui/button";
import { FiUpload } from "react-icons/fi";
import { useState } from "react";
import { FaRegEdit } from "react-icons/fa";
// import { FaRegEdit } from "react-icons/fa";
import Edit from "../../../components/ActionIcons/Edit";
import { Toaster, toaster } from "../../../components/ui/toaster";
import { Template, useUpdateTemplateMasterMutation } from "../../../Redux/Service/template.master.service";
function EditTemplateModel() {
const [images, setImages] = useState<string[]>([]);
const APIURL = import.meta.env.VITE_IMG_TEMPLATES
const handleImageChange = (event: React.ChangeEvent<HTMLInputElement>) => {
if (event.target.files) {
const selectedFiles = Array.from(event.target.files);
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);
const newImages = selectedFiles.map((file) => {
return URL.createObjectURL(file); // Convert to preview URL
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;
}
setImages((prevImages) => [...prevImages, ...newImages]); // Append new images
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",
});
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[];
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");
}
};
return (
<DialogRoot placement="center">
<DialogTrigger asChild>
<Span><Edit /></Span>
</DialogTrigger>
<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>
<DialogContent
bg={"#fff"}
// w={{ lg: "60%", md: "230px" }}
w={{ base: "90%", md: "400px" }}
height={"auto"}
w={{ base: '90%', md: '400px' }}
height={'auto'}
overflowX="hidden"
p={3} // Reduced padding
bgSize={"md"}
bgSize={'md'}
>
<DialogHeader bg="white">
<DialogTitle alignSelf="center" color="black" fontSize="14px">
Add
</DialogTitle>
<DialogHeader bg="white" >
<DialogTitle alignSelf="center" color="black" fontSize="14px">Add</DialogTitle>
</DialogHeader>
<DialogBody bg="white">
<Stack py={3}>
<Field.Root>
<Field.Label color="black" pt={1} fontSize="12px">
Template Name
</Field.Label>
<Field.Label color="black" pt={1} fontSize="12px">Title</Field.Label>
<Input
placeholder=""
placeholder="Enter Title"
bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
value={title}
onChange={(e) => setTitle(e.target.value)}
/>
</Field.Root>
<Field.Label color="black" pt={1} fontSize="12px">
Images
</Field.Label>
<Box
display="flex"
alignItems="center"
justifyContent="space-between"
px={3}
<Field.Root>
<Field.Label color="black" pt={1} fontSize="12px">Subtitle</Field.Label>
<Input
placeholder="Enter subtitle"
bgColor="#EEEEEE"
color="black"
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}
/>
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} />
<Box display="flex" gap={2} overflow="hidden">
{images.length > 0 ? (
images.map((img, index) => (
<img
key={index}
src={img}
src={img instanceof File ? URL.createObjectURL(img) : img}
alt={`Uploaded ${index}`}
style={{
maxHeight: "40px",
maxWidth: "70px",
objectFit: "contain",
}}
style={{ maxHeight: "40px", maxWidth: "70px", objectFit: "contain" }}
/>
))
) : (
@@ -126,18 +235,21 @@ function EditTemplateModel() {
</Box>
{/* <Input placeholder="" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" /> */}
</Field.Root>
</Stack>
</DialogBody>
<DialogFooter display="flex" justifyContent="center" pt={"2"}>
<Button w="100%" bg="#02A0A0" color={"#fff"}>
<Button w="100%" bg="#02A0A0" color={"#fff"} onClick={handleSubmit}>
Save
</Button>
</DialogFooter>
<DialogCloseTrigger color="black" />
<DialogCloseTrigger color="black" onClick={() => setIsOpen(false)} />
</DialogContent>
</DialogRoot>
<Toaster />
</DialogRoot >
);
}

View File

@@ -9,7 +9,7 @@ import { Toaster, toaster } from "../../../components/ui/toaster"
import axios from "axios";
function TemplateAddModel({ id }: { id: number }) {
function TemplateAddModel({refetch}:{refetch: VoidFunction}) {
const [title, setTitle] = useState("");
const [subTitle, setSubTitle] = useState("");
const [userType, setUserType] = useState<number | "">("");
@@ -64,7 +64,6 @@ function TemplateAddModel({ id }: { id: number }) {
const formData = new FormData();
formData.append("id", `${id}`);
formData.append("principle_type_xid", `${userType}`);
formData.append("title", title);
formData.append("sub_title", subTitle);
@@ -91,6 +90,7 @@ function TemplateAddModel({ id }: { id: number }) {
// withCredentials: true,
});
}
refetch();
setTitle("");
setSubTitle("");
setUserType("");