Fixed Template modal button
This commit is contained in:
@@ -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 >
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -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("");
|
||||
|
||||
Reference in New Issue
Block a user