API implementation for CMS and Master module
This commit is contained in:
@@ -4,12 +4,15 @@ import GlobalStateContext from "./Contexts/GlobalStateContext";
|
||||
import DefaultLayout from "./Layouts/DefaultLayout";
|
||||
import Login from "./Pages/Login";
|
||||
import { RouteLink } from "./Routes/Routes";
|
||||
import ForgotPassword from "./Pages/ForgotPassword";
|
||||
import VerifyEnterOTP from "./Pages/VerifyEnterOTP";
|
||||
import SetNewPassword from "./Pages/SetNewPassword";
|
||||
|
||||
function App() {
|
||||
const context = useContext(GlobalStateContext);
|
||||
if (!context) throw new Error("App must be used within a GlobalStateProvider");
|
||||
|
||||
const { isAuthenticate, setIsAuthenticate } = context;
|
||||
const { isAuthenticate, setIsAuthenticate } = context;
|
||||
|
||||
useEffect(() => {
|
||||
const token = localStorage.getItem("token");
|
||||
@@ -23,6 +26,9 @@ function App() {
|
||||
<Routes>
|
||||
{/* Redirect logged-in users away from login */}
|
||||
<Route path="/login" element={isAuthenticate && localStorage.getItem("token") ? <Navigate to="/" /> : <Login />} />
|
||||
<Route path="/forgot-password" element={<ForgotPassword />} />
|
||||
<Route path="/forgot-password/verify-otp" element={<VerifyEnterOTP />} />
|
||||
<Route path="/forgot-password/reset-password" element={<SetNewPassword />} />
|
||||
|
||||
{/* Protected Routes */}
|
||||
<Route
|
||||
|
||||
155
src/Pages/ForgotPassword.tsx
Normal file
155
src/Pages/ForgotPassword.tsx
Normal file
@@ -0,0 +1,155 @@
|
||||
import {
|
||||
Box,
|
||||
Center,
|
||||
HStack,
|
||||
Image,
|
||||
Input,
|
||||
Text,
|
||||
VStack,
|
||||
} from "@chakra-ui/react";
|
||||
import axios from "axios";
|
||||
import { useState } from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
// import { useDispatch } from "react-redux";
|
||||
import logo from "../assets/logo.svg";
|
||||
import { Button } from "../components/ui/button";
|
||||
import { Field } from "../components/ui/field";
|
||||
import { toaster, Toaster } from "../components/ui/toaster";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
|
||||
interface FormValues {
|
||||
mobileNumber: number;
|
||||
}
|
||||
|
||||
const ForgotPassword = () => {
|
||||
const navigate = useNavigate();
|
||||
const [isLoading, setIsLoading] = useState<boolean>(false);
|
||||
const {
|
||||
register,
|
||||
handleSubmit,
|
||||
formState: { errors },
|
||||
} = useForm<FormValues>();
|
||||
|
||||
const onSubmit = handleSubmit(async (data) => {
|
||||
setIsLoading(true);
|
||||
try {
|
||||
const res = await axios.post(
|
||||
`${import.meta.env.VITE_API_URL}/send-otp`,
|
||||
{
|
||||
mobile_number: Number(data.mobileNumber),
|
||||
},
|
||||
);
|
||||
|
||||
if (res.status === 200) {
|
||||
navigate(`/forgot-password/verify?phone=${data.mobileNumber}`)
|
||||
} else {
|
||||
alert(res.data.message || "Something went wrong");
|
||||
}
|
||||
console.log("============", res);
|
||||
|
||||
} catch (error) {
|
||||
console.log('error', error);
|
||||
|
||||
if (error) {
|
||||
toaster.create({
|
||||
// title: error?.response?.data?.message,
|
||||
title: "Something Went Wrong",
|
||||
type: "info",
|
||||
})
|
||||
// console.log("Login failed", error?.response?.data?.message);
|
||||
setIsLoading(false);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return (
|
||||
|
||||
<VStack appearance={'light'} w={"100%"} h={"100vh"} bg={"#ffffff"}>
|
||||
<HStack
|
||||
boxShadow={"rgba(99, 99, 99, 0.2) 0px 2px 8px 0px"}
|
||||
w={"100%"}
|
||||
ps={8}
|
||||
h={"7%"}
|
||||
justifyContent={"flex-start"}
|
||||
>
|
||||
<Image w={50} src={logo} />
|
||||
</HStack>
|
||||
|
||||
<HStack w={"100%"} h={"93%"} p={8} gap={8}>
|
||||
<Center
|
||||
display={{ base: "none", md: "flex" }}
|
||||
bg={"#02A0A033"}
|
||||
w={"50%"}
|
||||
h={"100%"}
|
||||
rounded={"3xl"}
|
||||
>
|
||||
<Image w={250} src={logo} />
|
||||
</Center>
|
||||
|
||||
<Box
|
||||
as={"form"}
|
||||
onSubmit={onSubmit}
|
||||
p={{ base: 4, md: 16 }}
|
||||
w={{ base: "100%", md: "50%" }}
|
||||
h={"100%"}
|
||||
>
|
||||
<VStack gap={2} w={"100%"}>
|
||||
<Text
|
||||
w={"100%"}
|
||||
textAlign={"center"}
|
||||
fontSize={"24px"}
|
||||
fontWeight={"normal"}
|
||||
color={"#313039"}
|
||||
>
|
||||
Forgot Password
|
||||
</Text>
|
||||
|
||||
<Box mt={6} gap={4} w={"full"}>
|
||||
<Field
|
||||
color={"#313039"}
|
||||
label={"Enter Mobile Number"}
|
||||
w={"100%"}
|
||||
invalid={!!errors.mobileNumber}
|
||||
errorText={errors.mobileNumber?.message}
|
||||
mb={4}
|
||||
>
|
||||
<Input
|
||||
type="number"
|
||||
ps={3}
|
||||
maxLength={10}
|
||||
{...register("mobileNumber", {
|
||||
required: "Please enter a 10 digit mobile number",
|
||||
pattern: {
|
||||
value: /^[0-9]{10}$/,
|
||||
message: "Mobile number must be exactly 10 digits"
|
||||
}
|
||||
})}
|
||||
placeholder="Enter Mobile Number"
|
||||
onInput={(e) => {
|
||||
const target = e.target as HTMLInputElement;
|
||||
target.value = target.value.replace(/\D/g, "").slice(0, 10);
|
||||
}}
|
||||
/>
|
||||
</Field>
|
||||
<Button
|
||||
loading={isLoading}
|
||||
mt={4}
|
||||
size={"sm"}
|
||||
bg={"#02A0A0"}
|
||||
rounded={"md"}
|
||||
w={"100%"}
|
||||
color={"#ffffff"}
|
||||
type="submit"
|
||||
>
|
||||
Send OTP
|
||||
</Button>
|
||||
</Box>
|
||||
</VStack>
|
||||
</Box>
|
||||
<Toaster />
|
||||
</HStack>
|
||||
</VStack>
|
||||
);
|
||||
};
|
||||
|
||||
export default ForgotPassword;
|
||||
@@ -5,7 +5,6 @@ import {
|
||||
Image,
|
||||
Input,
|
||||
Text,
|
||||
Theme,
|
||||
VStack,
|
||||
} from "@chakra-ui/react";
|
||||
import axios from "axios";
|
||||
@@ -19,8 +18,8 @@ import { Button } from "../components/ui/button";
|
||||
import { Field } from "../components/ui/field";
|
||||
import { toaster, Toaster } from "../components/ui/toaster";
|
||||
import { PasswordInput } from "../components/ui/password-input";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import ForgetPassword from "./ForgetPassword";
|
||||
import { Link, useNavigate } from "react-router-dom";
|
||||
// import ForgetPassword from "./ForgetPassword";
|
||||
|
||||
interface FormValues {
|
||||
mobileNumber: number;
|
||||
@@ -63,8 +62,8 @@ const Login = () => {
|
||||
},
|
||||
}
|
||||
);
|
||||
console.log("============",res);
|
||||
|
||||
console.log("============", res);
|
||||
|
||||
|
||||
if (res.data) {
|
||||
setIsAuthenticate(true);
|
||||
@@ -80,7 +79,7 @@ const Login = () => {
|
||||
}
|
||||
} catch (error) {
|
||||
console.log('error', error);
|
||||
|
||||
|
||||
if (error) {
|
||||
toaster.create({
|
||||
// title: error?.response?.data?.message,
|
||||
@@ -182,7 +181,15 @@ const Login = () => {
|
||||
Login
|
||||
</Button>
|
||||
|
||||
<ForgetPassword />
|
||||
{/* <ForgetPassword /> */}
|
||||
<Box textAlign={"right"}>
|
||||
<Link
|
||||
to={'/forgot-password'}
|
||||
style={{ color: "black", fontSize: "18px" }}
|
||||
>
|
||||
Forgot Password
|
||||
</Link>
|
||||
</Box>
|
||||
</Box>
|
||||
</VStack>
|
||||
</Box>
|
||||
|
||||
@@ -21,7 +21,7 @@ function AboutUsAddModel({ aboutUsData }: { aboutUsData: any }) {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
|
||||
// RTK Query Mutation Hook
|
||||
const [updateAboutUs, { isLoading }] = useUpdateAboutUsMutation();
|
||||
const [updateAboutUs] = useUpdateAboutUsMutation();
|
||||
|
||||
// React Hook Form
|
||||
const {
|
||||
|
||||
@@ -91,7 +91,7 @@ import {
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "../../../components/ui/dialog";
|
||||
import { Field, Input, Span, Stack, Textarea } from "@chakra-ui/react";
|
||||
import { Field, Input, Stack, Textarea } from "@chakra-ui/react";
|
||||
import Edit from "../../../components/ActionIcons/Edit";
|
||||
|
||||
interface RowData {
|
||||
|
||||
@@ -30,7 +30,7 @@ const managepost: any[] = [
|
||||
<Switch colorPalette={'teal'} size={"xs"} />
|
||||
</Box>
|
||||
{/* <EditDetails /> */}
|
||||
<EditDetails />
|
||||
<EditDetails id={(i + 1).toString()} question="Lorem Ipsum" answer="Lorem Ipsum" />
|
||||
|
||||
<AlertDailog
|
||||
AltertTiggerIcon={() => <Delete />}
|
||||
|
||||
@@ -8,7 +8,10 @@ import { useContext, useEffect } from "react";
|
||||
|
||||
|
||||
const PrivacyPolicy = () => {
|
||||
const { data, isLoading, isFetching } = useGetPrivacyPolicyQuery();
|
||||
const { data, isLoading, isFetching, refetch } = useGetPrivacyPolicyQuery();
|
||||
|
||||
console.log('PRIVACY', data?.data);
|
||||
|
||||
|
||||
const context = useContext(GlobalStateContext);
|
||||
if (!context) throw new Error('App must be used within a GlobalStateProvider');
|
||||
@@ -35,16 +38,15 @@ const PrivacyPolicy = () => {
|
||||
Privacy Policy <Badge variant={'surface'} colorPalette="cyan" ms={2} size={'sm'} fontSize={'xs'} px={2}>🎓 {privacy_language?.language_name}</Badge>
|
||||
</Text>
|
||||
|
||||
<PrivacyPolicyAddModel />
|
||||
<PrivacyPolicyAddModel policyData={data?.data} refetch={refetch} />
|
||||
</HStack>
|
||||
<Text
|
||||
as="p"
|
||||
fontSize="sm"
|
||||
fontWeight={400}
|
||||
color="#1D1D1D"
|
||||
>
|
||||
{content}
|
||||
</Text>
|
||||
dangerouslySetInnerHTML={{ __html: content }}
|
||||
/>
|
||||
|
||||
</VStack>)}
|
||||
</VStack>
|
||||
|
||||
@@ -9,27 +9,77 @@ import {
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "../../../components/ui/dialog";
|
||||
import { Field, Stack, Text, Textarea } from "@chakra-ui/react";
|
||||
import { Field, Stack, Text } from "@chakra-ui/react";
|
||||
import { Button } from "../../../components/ui/button";
|
||||
import { useUpdatePrivacyPolicyMutation } from "../../../Redux/Service/privacy.policy.service";
|
||||
import { Controller, useForm } from "react-hook-form";
|
||||
import { useState } from "react";
|
||||
import ReactQuill from "react-quill";
|
||||
|
||||
function PrivacyPolicyAddModel({ policyData, refetch }: { policyData: any, refetch: VoidFunction }) {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [selectedId, setSelectedId] = useState(null);
|
||||
const [updatePrivacyPolicy] = useUpdatePrivacyPolicyMutation()
|
||||
const {
|
||||
control,
|
||||
handleSubmit,
|
||||
reset,
|
||||
setValue,
|
||||
} = useForm({
|
||||
defaultValues: {
|
||||
content: "",
|
||||
languageCode: "",
|
||||
},
|
||||
});
|
||||
|
||||
console.log('POLICY', policyData);
|
||||
|
||||
const handleEditClick = (data: any) => {
|
||||
setSelectedId(data?.id)
|
||||
setValue("content", data.content); // Pre-fill the content field
|
||||
setValue("languageCode", data.privacy_language.language_code); // Pre-fill the language code
|
||||
setIsOpen(true); // Open dialog
|
||||
};
|
||||
|
||||
const onSubmit = async (formData: any) => {
|
||||
if (!formData.content.trim()) return; // Prevent empty updates
|
||||
|
||||
try {
|
||||
await updatePrivacyPolicy({
|
||||
id: selectedId,
|
||||
content: formData.content,
|
||||
language_code: formData.languageCode,
|
||||
}).unwrap();
|
||||
setIsOpen(false); // Close dialog on success
|
||||
reset(); // Reset the form
|
||||
refetch()
|
||||
} catch (error) {
|
||||
console.error("Update failed:", error);
|
||||
}
|
||||
};
|
||||
|
||||
function PrivacyPolicyAddModel() {
|
||||
return (
|
||||
<DialogRoot placement="center">
|
||||
<DialogTrigger asChild>
|
||||
{/* <Button bg={"transparent"} size="sm">
|
||||
<MdOutlineRemoveRedEye style={{ cursor: "pointer", fontSize: "16px" }} />
|
||||
</Button> */}
|
||||
<Button bgColor={"#EEEEEE"} pl={3} pr={3} size={"xs"} color={"#000"}>
|
||||
{" "}
|
||||
<FaRegEdit
|
||||
color="#000"
|
||||
style={{ height: "14px", width: "14px" }}
|
||||
/>{" "}
|
||||
<Text color={"#000"} mt={1}>
|
||||
Edit
|
||||
</Text>
|
||||
</Button>
|
||||
</DialogTrigger>
|
||||
<DialogRoot placement="center" open={isOpen}>
|
||||
{policyData?.map((item: any) => (
|
||||
<DialogTrigger asChild>
|
||||
<Button
|
||||
bgColor={"#EEEEEE"}
|
||||
pl={3} pr={3}
|
||||
size={"xs"}
|
||||
color={"#000"}
|
||||
onClick={() => handleEditClick(item)}
|
||||
>
|
||||
{" "}
|
||||
<FaRegEdit
|
||||
color="#000"
|
||||
style={{ height: "14px", width: "14px" }}
|
||||
/>{" "}
|
||||
<Text color={"#000"} mt={1}>
|
||||
Edit
|
||||
</Text>
|
||||
</Button>
|
||||
</DialogTrigger>
|
||||
))}
|
||||
|
||||
<DialogContent
|
||||
bg={"#fff"}
|
||||
@@ -51,7 +101,7 @@ function PrivacyPolicyAddModel() {
|
||||
<Field.Label color="black" pt={1} fontSize="12px">
|
||||
PrivacyPolicy
|
||||
</Field.Label>
|
||||
<Textarea
|
||||
{/* <Textarea
|
||||
placeholder=""
|
||||
bgColor="#EEEEEE"
|
||||
color="black"
|
||||
@@ -59,19 +109,46 @@ function PrivacyPolicyAddModel() {
|
||||
p={2}
|
||||
fontSize="12px"
|
||||
height={'140px'}
|
||||
_focusVisible={{outline:'none'}}
|
||||
_focusVisible={{ outline: 'none' }}
|
||||
resize={'none'}
|
||||
/> */}
|
||||
<Controller
|
||||
name="content"
|
||||
control={control}
|
||||
render={({ field }) => (
|
||||
<ReactQuill
|
||||
value={field.value}
|
||||
onChange={field.onChange}
|
||||
placeholder="Enter About Us content"
|
||||
modules={{
|
||||
toolbar: [
|
||||
[{ 'header': [1, 2, false] }],
|
||||
['bold', 'italic', 'underline', 'strike'],
|
||||
['link', 'image'],
|
||||
[{ 'list': 'ordered' }, { 'list': 'bullet' }],
|
||||
['clean']
|
||||
],
|
||||
}}
|
||||
formats={[
|
||||
'header',
|
||||
'bold', 'italic', 'underline', 'strike',
|
||||
'list', 'bullet',
|
||||
'link', 'image'
|
||||
]}
|
||||
style={{ color: "black", border: "none", fontSize: "12px", height: "170px", width: "100%" }}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</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"} mt={'4'} onClick={handleSubmit(onSubmit)}>
|
||||
Save
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
|
||||
<DialogCloseTrigger color="black" />
|
||||
<DialogCloseTrigger color="black" onClick={() => setIsOpen(false)} />
|
||||
</DialogContent>
|
||||
</DialogRoot>
|
||||
);
|
||||
|
||||
@@ -2,9 +2,13 @@ import { Box, HStack, Text } from "@chakra-ui/react";
|
||||
import MainFrame from "../../../components/MainFrame"
|
||||
import { p } from "framer-motion/client";
|
||||
import TermsAndConditionsAddModel from "./TermsAndConditionsAddModel";
|
||||
import { useGetTermsQuery } from "../../../Redux/Service/terms.and.condition.service";
|
||||
|
||||
|
||||
const TermsAndConditions = () => {
|
||||
const { data, refetch } = useGetTermsQuery()
|
||||
const termsData = data?.data
|
||||
|
||||
return (
|
||||
|
||||
<MainFrame>
|
||||
@@ -17,22 +21,29 @@ const TermsAndConditions = () => {
|
||||
px={3}
|
||||
>
|
||||
<Text as={"span"} fontSize={"sm"} fontWeight={500} color={"#000"}>
|
||||
Terms And Conditions
|
||||
Terms And Conditions
|
||||
</Text>
|
||||
|
||||
<HStack >
|
||||
|
||||
<TermsAndConditionsAddModel />
|
||||
|
||||
<TermsAndConditionsAddModel termsData={termsData} refetch={refetch}/>
|
||||
</HStack>
|
||||
</HStack>
|
||||
<Text as={p} fontSize={"sm"} fontWeight={400} color={"#1D1D1D"} px={3} w={"85%"} mb={"15px"} >
|
||||
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Numquam soluta doloremque quibusdam facilis quas, unde hic eaque doloribus sed perferendis atque, eos dolores eius consectetur iure sint adipisci itaque tempora fugit quidem culpa provident possimus. Ullam, vitae in voluptatum dignissimos, quos blanditiis sequi aut repellat error eaque veritatis unde quam temporibus adipisci consectetur neque vero exercitationem dolor cum numquam maiores alias, totam minima quas. Possimus, ratione harum. Alias laboriosam nesciunt esse fugit deserunt pariatur corporis tempora quia veniam laborum aliquid enim voluptatibus asperiores minima tempore repudiandae vero quo porro, doloribus explicabo sit beatae et hic natus. Non earum nisi reiciendis?
|
||||
{data?.data.map((item) => (
|
||||
<Text
|
||||
as={p}
|
||||
fontSize={"sm"}
|
||||
fontWeight={400}
|
||||
color={"#1D1D1D"}
|
||||
px={3} w={"85%"} mb={"15px"}
|
||||
dangerouslySetInnerHTML={{ __html: item.content }}
|
||||
/>
|
||||
))}
|
||||
|
||||
<Text as={p} fontSize={"sm"} fontWeight={400} color={"#1D1D1D"} px={3} w={"85%"} >
|
||||
</Text>
|
||||
<Text as={p} fontSize={"sm"} fontWeight={400} color={"#1D1D1D"} px={3} w={"85%"} >
|
||||
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Numquam soluta doloremque quibusdam facilis quas, unde hic eaque doloribus sed perferendis atque, eos dolores eius consectetur iure sint adipisci itaque tempora fugit quidem culpa provident possimus. Ullam, vitae in voluptatum dignissimos, quos blanditiis sequi aut repellat error eaque veritatis unde quam temporibus adipisci consectetur neque vero exercitationem dolor cum numquam maiores alias, totam minima quas. Possimus, ratione harum. Alias laboriosam nesciunt esse fugit deserunt pariatur corporis tempora quia veniam laborum aliquid enim voluptatibus asperiores minima tempore repudiandae vero quo porro, doloribus explicabo sit beatae et hic natus. Non earum nisi reiciendis?
|
||||
</Text>
|
||||
</Box>
|
||||
</MainFrame>
|
||||
</Box>
|
||||
</MainFrame >
|
||||
)
|
||||
}
|
||||
export default TermsAndConditions
|
||||
@@ -9,24 +9,75 @@ import {
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "../../../components/ui/dialog";
|
||||
import { Field, Stack, Text, Textarea } from "@chakra-ui/react";
|
||||
import { Field, Stack, Text } from "@chakra-ui/react";
|
||||
import { Button } from "../../../components/ui/button";
|
||||
import { Controller, useForm } from "react-hook-form";
|
||||
import ReactQuill from "react-quill";
|
||||
import { useState } from "react";
|
||||
import { useUpdateTermsMutation } from "../../../Redux/Service/terms.and.condition.service";
|
||||
|
||||
function TermsAndConditionsAddModel({ termsData, refetch }: { termsData: any, refetch: VoidFunction}) {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [selectedId, setSelectedId] = useState(null);
|
||||
const [updateTerms] = useUpdateTermsMutation()
|
||||
const {
|
||||
control,
|
||||
handleSubmit,
|
||||
reset,
|
||||
setValue,
|
||||
} = useForm({
|
||||
defaultValues: {
|
||||
content: "",
|
||||
languageCode: "",
|
||||
},
|
||||
});
|
||||
|
||||
const handleEditClick = (data: any) => {
|
||||
setSelectedId(data?.id)
|
||||
setValue("content", data.content); // Pre-fill the content field
|
||||
setValue("languageCode", data.terms_cond_language.language_code); // Pre-fill the language code
|
||||
setIsOpen(true); // Open dialog
|
||||
};
|
||||
|
||||
const onSubmit = async (formData: any) => {
|
||||
if (!formData.content.trim()) return; // Prevent empty updates
|
||||
|
||||
try {
|
||||
await updateTerms({
|
||||
id: selectedId,
|
||||
content: formData.content,
|
||||
language_code: formData.languageCode,
|
||||
}).unwrap();
|
||||
setIsOpen(false); // Close dialog on success
|
||||
reset(); // Reset the form
|
||||
refetch()
|
||||
} catch (error) {
|
||||
console.error("Update failed:", error);
|
||||
}
|
||||
};
|
||||
|
||||
function TermsAndConditionsAddModel() {
|
||||
return (
|
||||
<DialogRoot placement="center">
|
||||
<DialogTrigger asChild>
|
||||
<Button bgColor={"#EEEEEE"} pl={3} pr={3} size={"xs"} color={"#000"}>
|
||||
{" "}
|
||||
<FaRegEdit
|
||||
color="#000"
|
||||
style={{ height: "14px", width: "14px" }}
|
||||
/>{" "}
|
||||
<Text color={"#000"} mt={1}>
|
||||
Edit
|
||||
</Text>
|
||||
</Button>
|
||||
</DialogTrigger>
|
||||
<DialogRoot placement="center" open={isOpen}>
|
||||
{termsData?.map((item: any) => (
|
||||
<DialogTrigger asChild>
|
||||
<Button
|
||||
bgColor={"#EEEEEE"}
|
||||
pl={3} pr={3}
|
||||
size={"xs"}
|
||||
color={"#000"}
|
||||
onClick={() => handleEditClick(item)}
|
||||
>
|
||||
{" "}
|
||||
<FaRegEdit
|
||||
color="#000"
|
||||
style={{ height: "14px", width: "14px" }}
|
||||
/>{" "}
|
||||
<Text color={"#000"} mt={1}>
|
||||
Edit
|
||||
</Text>
|
||||
</Button>
|
||||
</DialogTrigger>
|
||||
))}
|
||||
|
||||
<DialogContent
|
||||
bg={"#fff"}
|
||||
@@ -43,12 +94,12 @@ function TermsAndConditionsAddModel() {
|
||||
</DialogHeader>
|
||||
|
||||
<DialogBody bg="white">
|
||||
<Stack py={3}>
|
||||
<Stack py={3} mb={8}>
|
||||
<Field.Root>
|
||||
<Field.Label color="black" pt={1} fontSize="12px">
|
||||
TermsAndConditions
|
||||
</Field.Label>
|
||||
<Textarea
|
||||
{/* <Textarea
|
||||
placeholder=""
|
||||
bgColor="#EEEEEE"
|
||||
color="black"
|
||||
@@ -58,17 +109,44 @@ function TermsAndConditionsAddModel() {
|
||||
height={'140px'}
|
||||
_focusVisible={{outline:'none'}}
|
||||
resize={'none'}
|
||||
/> */}
|
||||
<Controller
|
||||
name="content"
|
||||
control={control}
|
||||
render={({ field }) => (
|
||||
<ReactQuill
|
||||
value={field.value}
|
||||
onChange={field.onChange}
|
||||
placeholder="Enter About Us content"
|
||||
modules={{
|
||||
toolbar: [
|
||||
[{ 'header': [1, 2, false] }],
|
||||
['bold', 'italic', 'underline', 'strike'],
|
||||
['link', 'image'],
|
||||
[{ 'list': 'ordered' }, { 'list': 'bullet' }],
|
||||
['clean']
|
||||
],
|
||||
}}
|
||||
formats={[
|
||||
'header',
|
||||
'bold', 'italic', 'underline', 'strike',
|
||||
'list', 'bullet',
|
||||
'link', 'image'
|
||||
]}
|
||||
style={{ color: "black", border: "none", fontSize: "12px", height: "170px", width: "100%" }}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</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"} mt={'4'} onClick={handleSubmit(onSubmit)}>
|
||||
Save
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
|
||||
<DialogCloseTrigger color="black" />
|
||||
<DialogCloseTrigger color="black" onClick={() => setIsOpen(false)} />
|
||||
</DialogContent>
|
||||
</DialogRoot>
|
||||
);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Button } from "../../components/ui/button"
|
||||
import { DialogBody, DialogCloseTrigger, DialogContent, DialogFooter, DialogHeader, DialogRoot, DialogTitle, DialogTrigger } from "../../components/ui/dialog"
|
||||
import { Avatar, Box, Field, Heading, Input, Stack, Text } from "@chakra-ui/react"
|
||||
import { Field, Heading, Input, Stack, Text } from "@chakra-ui/react"
|
||||
import { Switch } from "../../components/ui/switch";
|
||||
import { IoMdAdd } from "react-icons/io";
|
||||
function AddGroup() {
|
||||
|
||||
@@ -4,7 +4,7 @@ import { InputGroup } from "../../components/ui/input-group";
|
||||
import { LuSearch } from "react-icons/lu";
|
||||
import DataTable from "../../components/DataTable";
|
||||
import AlertDailog from "../../components/AlertDailog";
|
||||
import { RiDeleteBin5Line } from "react-icons/ri";
|
||||
// import { RiDeleteBin5Line } from "react-icons/ri";
|
||||
import ViewManageGroup from "./ViewManageGroup";
|
||||
import EditDetailGroups from "./EditDetailGroup";
|
||||
import AddGroup from "./AddGroup";
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Box, HStack, Image, Input, Text } from "@chakra-ui/react";
|
||||
import { LuSearch } from "react-icons/lu";
|
||||
import { RiDeleteBin5Line } from "react-icons/ri";
|
||||
// import { RiDeleteBin5Line } from "react-icons/ri";
|
||||
import AlertDailog from "../../components/AlertDailog";
|
||||
import DataTable from "../../components/DataTable";
|
||||
import MainFrame from "../../components/MainFrame";
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import {
|
||||
Field,
|
||||
Icon,
|
||||
Input,
|
||||
SelectValueText,
|
||||
Span,
|
||||
@@ -19,7 +18,7 @@ import {
|
||||
DialogTrigger,
|
||||
} from "../../components/ui/dialog";
|
||||
|
||||
import { TbEdit } from "react-icons/tb";
|
||||
// import { TbEdit } from "react-icons/tb";
|
||||
import {
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import {
|
||||
Field,
|
||||
Icon,
|
||||
Input,
|
||||
SelectValueText,
|
||||
Span,
|
||||
@@ -19,7 +18,7 @@ import {
|
||||
DialogTrigger,
|
||||
} from "../../components/ui/dialog";
|
||||
|
||||
import { MdOutlineRemoveRedEye } from "react-icons/md";
|
||||
// import { MdOutlineRemoveRedEye } from "react-icons/md";
|
||||
import {
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
|
||||
@@ -6,7 +6,7 @@ import DataTable from "../../components/DataTable";
|
||||
import AlertDailog from "../../components/AlertDailog";
|
||||
import { Switch } from "../../components/ui/switch";
|
||||
import img from "../../assets/waterfall.jpg";
|
||||
import { RiDeleteBin5Line } from "react-icons/ri";
|
||||
// import { RiDeleteBin5Line } from "react-icons/ri";
|
||||
import ViewDailog from "./ViewDailog";
|
||||
import Delete from "../../components/ActionIcons/Delete";
|
||||
// import ViewDailog from './ViewDailog'
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Field, Icon, Image, Input, Span, Stack } from "@chakra-ui/react"
|
||||
import { TbEdit } from "react-icons/tb"
|
||||
import { Field, Image, Input, Span, Stack } from "@chakra-ui/react"
|
||||
// import { TbEdit } from "react-icons/tb"
|
||||
import img from "../../assets/waterfall.jpg"
|
||||
import { DialogBody, DialogCloseTrigger, DialogContent, DialogHeader, DialogRoot, DialogTitle, DialogTrigger } from "../../components/ui/dialog"
|
||||
import Edit from "../../components/ActionIcons/Edit"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { MdOutlineRemoveRedEye } from "react-icons/md";
|
||||
import { Field, Icon, Input, Span, Stack } from "@chakra-ui/react";
|
||||
// import { MdOutlineRemoveRedEye } from "react-icons/md";
|
||||
import { Field, Input, Span, Stack } from "@chakra-ui/react";
|
||||
import {
|
||||
DialogActionTrigger,
|
||||
DialogBody,
|
||||
@@ -11,9 +11,9 @@ import {
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "../../../components/ui/dialog";
|
||||
import { BiEdit } from "react-icons/bi";
|
||||
// import { BiEdit } from "react-icons/bi";
|
||||
import { Button } from "../../../components/ui/button";
|
||||
import { TbEdit } from "react-icons/tb";
|
||||
// import { TbEdit } from "react-icons/tb";
|
||||
import Edit from "../../../components/ActionIcons/Edit";
|
||||
|
||||
function EditRegisterUsers() {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Box, HStack, Image, Input, Span, Text } from "@chakra-ui/react";
|
||||
import { Box, HStack, Image, Input, Text } from "@chakra-ui/react";
|
||||
import MainFrame from "../../../components/MainFrame";
|
||||
import AlertDailog from "../../../components/AlertDailog";
|
||||
import { RiDeleteBin5Line } from "react-icons/ri";
|
||||
// import { RiDeleteBin5Line } from "react-icons/ri";
|
||||
import DataTable from "../../../components/DataTable";
|
||||
import { Switch } from "../../../components/ui/switch";
|
||||
import { InputGroup } from "../../../components/ui/input-group";
|
||||
|
||||
@@ -7,6 +7,8 @@ import { Switch } from "../../../components/ui/switch";
|
||||
import EditAgencyMaster from "./EditAgencyMaster";
|
||||
import ViewAgencyAddModel from "./ViewAgencyAddModel";
|
||||
import ViewAgencyMaster from "./ViewAgencyMaster";
|
||||
import {useAgencyMasterToggleMutation, useGetAgencyMasterQuery } from "../../../Redux/Service/agency.master.module.service";
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
|
||||
// table data
|
||||
@@ -21,32 +23,95 @@ const tableHeadRow = [
|
||||
"Website/Domain",
|
||||
"GST no.",
|
||||
"Action"
|
||||
|
||||
|
||||
];
|
||||
|
||||
const managepost: any[] = [
|
||||
...Array.from({ length: 12 }, (_, i) => ({
|
||||
"Sr. No": i + 1,
|
||||
"Agency Name": "Lorem Ipsum",
|
||||
"RC no.": "Lorem Ipsum",
|
||||
"State": "Lorem Ipsum",
|
||||
"RC Status": "Active",
|
||||
"Registered Office Address": "Lorem Ipsum",
|
||||
"Website/Domain": "Lorem Ipsum",
|
||||
"GST no.": "Lorem Ipsum",
|
||||
// const managepost: any[] = [
|
||||
// ...Array.from({ length: 12 }, (_, i) => ({
|
||||
// "Sr. No": i + 1,
|
||||
// "Agency Name": "Lorem Ipsum",
|
||||
// "RC no.": "Lorem Ipsum",
|
||||
// "State": "Lorem Ipsum",
|
||||
// "RC Status": "Active",
|
||||
// "Registered Office Address": "Lorem Ipsum",
|
||||
// "Website/Domain": "Lorem Ipsum",
|
||||
// "GST no.": "Lorem Ipsum",
|
||||
// "Action": (
|
||||
// <HStack justifyContent="center">
|
||||
// <ViewAgencyMaster/>
|
||||
// <EditAgencyMaster />
|
||||
// <Box>
|
||||
// <Switch colorPalette={'teal'} size={"xs"}/>
|
||||
// </Box>
|
||||
// </HStack>
|
||||
// ),
|
||||
// })),
|
||||
// ];
|
||||
|
||||
const AgencyMaster = () => {
|
||||
const { data, refetch } = useGetAgencyMasterQuery()
|
||||
const [agencyMasterToggle] = useAgencyMasterToggleMutation()
|
||||
const [localData, setLocalData] = useState<any[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
if (data?.data?.data) {
|
||||
setLocalData(data?.data.data);
|
||||
}
|
||||
}, [data]);
|
||||
|
||||
const handleToggle = async (agencyId: string, currentStatus: number) => {
|
||||
const newStatus = currentStatus ? 0 : 1;
|
||||
setLocalData((prevData) =>
|
||||
prevData.map((agency) =>
|
||||
agency.id === agencyId ? { ...agency, is_active: newStatus } : agency
|
||||
)
|
||||
);
|
||||
try {
|
||||
await agencyMasterToggle({ id: agencyId, is_active: newStatus }).unwrap();
|
||||
refetch()
|
||||
} catch (error) {
|
||||
console.error("Error updating privacy policy:", error);
|
||||
setLocalData((prevData) =>
|
||||
prevData.map((agency) =>
|
||||
agency.id === agencyId ? { ...agency, is_active: currentStatus } : agency
|
||||
)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
const managepost = localData?.map((agency: any, index: number) => ({
|
||||
'id': agency.id,
|
||||
"Sr. No": index + 1,
|
||||
"Agency Name": agency.name,
|
||||
"RC no.": agency.rc_number,
|
||||
"State": agency.state,
|
||||
"RC Status": agency.rc_status,
|
||||
"Registered Office Address": agency.registered_office,
|
||||
"Website/Domain": agency.domain_name,
|
||||
"GST no.": agency.gst_number,
|
||||
"is_active": agency.is_active,
|
||||
"Action": (
|
||||
<HStack justifyContent="center">
|
||||
<ViewAgencyMaster/>
|
||||
<ViewAgencyMaster agency={localData} id={agency.id}/>
|
||||
<EditAgencyMaster />
|
||||
<Box>
|
||||
<Switch colorPalette={'teal'} size={"xs"}/>
|
||||
<Switch
|
||||
colorPalette={"teal"}
|
||||
size={"xs"}
|
||||
onChange={() => handleToggle(agency.id, agency.is_active ?? 0)}
|
||||
checked={agency.is_active}
|
||||
/>
|
||||
</Box>
|
||||
</HStack>
|
||||
),
|
||||
})),
|
||||
];
|
||||
}));
|
||||
|
||||
useEffect(() => {
|
||||
console.log("Fetched data:", data);
|
||||
console.log("Local data:", localData);
|
||||
console.log("Managepost data:", managepost);
|
||||
}, [data, localData, managepost]);
|
||||
|
||||
const AgencyMaster = () => {
|
||||
return (
|
||||
|
||||
<MainFrame>
|
||||
@@ -59,11 +124,11 @@ const AgencyMaster = () => {
|
||||
px={3}
|
||||
>
|
||||
<Text as={"span"} fontSize={"sm"} fontWeight={500} color={"#000"}>
|
||||
Agency Master
|
||||
Agency Master
|
||||
</Text>
|
||||
|
||||
<HStack >
|
||||
<InputGroup
|
||||
<InputGroup
|
||||
startElement={
|
||||
<LuSearch fontSize={"xs"} style={{ position: 'relative', left: '10px' }} />
|
||||
}
|
||||
@@ -90,9 +155,9 @@ const AgencyMaster = () => {
|
||||
<DataTable
|
||||
sortableColumns={["Name", "Registration Date "]}
|
||||
tableHeadRow={tableHeadRow}
|
||||
data={managepost}
|
||||
data={managepost || []}
|
||||
/>
|
||||
</Box>
|
||||
</Box>
|
||||
</MainFrame>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "../../../components/ui/dialog";
|
||||
import { Field, Icon, Input, Span, Stack } from "@chakra-ui/react";
|
||||
import { Field, Input, Span, Stack } from "@chakra-ui/react";
|
||||
import Edit from "../../../components/ActionIcons/Edit";
|
||||
|
||||
function EditAgencyMaster() {
|
||||
|
||||
@@ -2,18 +2,20 @@ import {
|
||||
DialogBody,
|
||||
DialogCloseTrigger,
|
||||
DialogContent,
|
||||
DialogFooter,
|
||||
// DialogFooter,
|
||||
DialogHeader,
|
||||
DialogRoot,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "../../../components/ui/dialog";
|
||||
import { Field, Icon, Input, Span, Stack } from "@chakra-ui/react";
|
||||
import { MdOutlineRemoveRedEye } from "react-icons/md";
|
||||
import { Button } from "../../../components/ui/button";
|
||||
import { Field, Input, Span, Stack } from "@chakra-ui/react";
|
||||
// import { MdOutlineRemoveRedEye } from "react-icons/md";
|
||||
// import { Button } from "../../../components/ui/button";
|
||||
import View from "../../../components/ActionIcons/View";
|
||||
import { Agency } from "../../../Redux/Service/agency.master.module.service";
|
||||
|
||||
function ViewAgencyMaster({ agency, id }: { agency: Agency[], id:number }) {
|
||||
|
||||
function ViewAgencyMaster() {
|
||||
return (
|
||||
<DialogRoot placement="center">
|
||||
<DialogTrigger asChild>
|
||||
@@ -32,107 +34,130 @@ function ViewAgencyMaster() {
|
||||
>
|
||||
<DialogHeader bg="white">
|
||||
<DialogTitle alignSelf="center" color="black" fontSize="14px">
|
||||
Add
|
||||
View
|
||||
</DialogTitle>
|
||||
</DialogHeader>
|
||||
{agency.map((data) => (
|
||||
<DialogBody bg="white">
|
||||
{data.id === id && <Stack py={3}>
|
||||
<Field.Root>
|
||||
<Field.Label color="black" pt={1} fontSize="12px">
|
||||
Agency name
|
||||
</Field.Label>
|
||||
<Input
|
||||
value={data.name}
|
||||
bgColor="#EEEEEE"
|
||||
color="black"
|
||||
border="none"
|
||||
pl={1}
|
||||
fontSize="12px"
|
||||
height="30px"
|
||||
disabled
|
||||
/>
|
||||
|
||||
<DialogBody bg="white">
|
||||
<Stack py={3}>
|
||||
<Field.Root>
|
||||
<Field.Label color="black" pt={1} fontSize="12px">
|
||||
Agency name
|
||||
</Field.Label>
|
||||
<Input
|
||||
value="Lorem Ipsum"
|
||||
bgColor="#EEEEEE"
|
||||
color="black"
|
||||
border="none"
|
||||
pl={1}
|
||||
fontSize="12px"
|
||||
height="30px"
|
||||
/>
|
||||
<Field.Label color="black" pt={1} fontSize="12px">
|
||||
RC No.
|
||||
</Field.Label>
|
||||
<Input
|
||||
value={data.rc_number}
|
||||
bgColor="#EEEEEE"
|
||||
color="black"
|
||||
border="none"
|
||||
pl={1}
|
||||
fontSize="12px"
|
||||
height="30px"
|
||||
disabled
|
||||
/>
|
||||
|
||||
<Field.Label color="black" pt={1} fontSize="12px">
|
||||
RC No.
|
||||
</Field.Label>
|
||||
<Input
|
||||
value="Lorem Ipsum"
|
||||
bgColor="#EEEEEE"
|
||||
color="black"
|
||||
border="none"
|
||||
pl={1}
|
||||
fontSize="12px"
|
||||
height="30px"
|
||||
/>
|
||||
<Field.Label color="black" pt={1} fontSize="12px">
|
||||
State
|
||||
</Field.Label>
|
||||
<Input
|
||||
value={data.state}
|
||||
bgColor="#EEEEEE"
|
||||
color="black"
|
||||
border="none"
|
||||
pl={1}
|
||||
fontSize="12px"
|
||||
height="30px"
|
||||
disabled
|
||||
/>
|
||||
|
||||
<Field.Label color="black" pt={1} fontSize="12px">
|
||||
State
|
||||
</Field.Label>
|
||||
<Input
|
||||
value="Lorem Ipsum"
|
||||
bgColor="#EEEEEE"
|
||||
color="black"
|
||||
border="none"
|
||||
pl={1}
|
||||
fontSize="12px"
|
||||
height="30px"
|
||||
/>
|
||||
<Field.Label color="black" pt={1} fontSize="12px">
|
||||
RC Status
|
||||
</Field.Label>
|
||||
<Input
|
||||
value={data.rc_status}
|
||||
bgColor="#EEEEEE"
|
||||
color="black"
|
||||
border="none"
|
||||
pl={1}
|
||||
fontSize="12px"
|
||||
height="30px"
|
||||
disabled
|
||||
/>
|
||||
|
||||
<Field.Label color="black" pt={1} fontSize="12px">
|
||||
Registered Office Address
|
||||
</Field.Label>
|
||||
<Input
|
||||
value="Active"
|
||||
bgColor="#EEEEEE"
|
||||
color="black"
|
||||
border="none"
|
||||
pl={1}
|
||||
fontSize="12px"
|
||||
height="30px"
|
||||
/>
|
||||
<Field.Label color="black" pt={1} fontSize="12px">
|
||||
Registered Office Address
|
||||
</Field.Label>
|
||||
<Input
|
||||
value={data.registered_office}
|
||||
bgColor="#EEEEEE"
|
||||
color="black"
|
||||
border="none"
|
||||
pl={1}
|
||||
fontSize="12px"
|
||||
height="30px"
|
||||
disabled
|
||||
/>
|
||||
|
||||
<Field.Label color="black" pt={1} fontSize="12px">
|
||||
Website/Domain
|
||||
</Field.Label>
|
||||
<Input
|
||||
value="Lorem Ipsum"
|
||||
bgColor="#EEEEEE"
|
||||
color="black"
|
||||
border="none"
|
||||
pl={1}
|
||||
fontSize="12px"
|
||||
height="30px"
|
||||
/>
|
||||
<Field.Label color="black" pt={1} fontSize="12px">
|
||||
Website/Domain
|
||||
</Field.Label>
|
||||
<Input
|
||||
value={data.domain_name}
|
||||
bgColor="#EEEEEE"
|
||||
color="black"
|
||||
border="none"
|
||||
pl={1}
|
||||
fontSize="12px"
|
||||
height="30px"
|
||||
disabled
|
||||
/>
|
||||
|
||||
<Field.Label color="black" pt={1} fontSize="12px">
|
||||
GST no.
|
||||
</Field.Label>
|
||||
<Input
|
||||
value="Lorem Ipsum"
|
||||
bgColor="#EEEEEE"
|
||||
color="black"
|
||||
border="none"
|
||||
pl={1}
|
||||
fontSize="12px"
|
||||
height="30px"
|
||||
/>
|
||||
<Field.Label color="black" pt={1} fontSize="12px">
|
||||
GST no.
|
||||
</Field.Label>
|
||||
<Input
|
||||
value={data.gst_number}
|
||||
bgColor="#EEEEEE"
|
||||
color="black"
|
||||
border="none"
|
||||
pl={1}
|
||||
fontSize="12px"
|
||||
height="30px"
|
||||
disabled
|
||||
/>
|
||||
|
||||
<Field.Label color="black" pt={1} fontSize="12px">
|
||||
Action
|
||||
</Field.Label>
|
||||
<Input
|
||||
value="Lorem Ipsum"
|
||||
bgColor="#EEEEEE"
|
||||
color="black"
|
||||
border="none"
|
||||
pl={1}
|
||||
fontSize="12px"
|
||||
height="30px"
|
||||
/>
|
||||
</Field.Root>
|
||||
</Stack>
|
||||
</DialogBody>
|
||||
<DialogFooter display="flex" justifyContent="center" pt={"2"}>
|
||||
{/* <Field.Label color="black" pt={1} fontSize="12px">
|
||||
Action
|
||||
</Field.Label>
|
||||
<Input
|
||||
value={data}
|
||||
bgColor="#EEEEEE"
|
||||
color="black"
|
||||
border="none"
|
||||
pl={1}
|
||||
fontSize="12px"
|
||||
height="30px"
|
||||
disabled
|
||||
/> */}
|
||||
</Field.Root>
|
||||
</Stack>}
|
||||
</DialogBody>
|
||||
))}
|
||||
|
||||
{/* <DialogFooter display="flex" justifyContent="center" pt={"2"}>
|
||||
<Button
|
||||
w="100%"
|
||||
bg="#02A0A0"
|
||||
@@ -142,7 +167,7 @@ function ViewAgencyMaster() {
|
||||
>
|
||||
Save
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</DialogFooter> */}
|
||||
|
||||
<DialogCloseTrigger color="black" />
|
||||
</DialogContent>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { DialogBody, DialogCloseTrigger, DialogContent, DialogFooter, DialogHeader, DialogRoot, DialogTitle, DialogTrigger } from "../../../components/ui/dialog"
|
||||
import { Box, Field, IconButton, Input, Stack, Text, Textarea } from "@chakra-ui/react"
|
||||
import { Field, Input, Stack, Text } from "@chakra-ui/react"
|
||||
import { IoMdAdd } from "react-icons/io"
|
||||
import { Button } from "../../../components/ui/button"
|
||||
|
||||
|
||||
@@ -1,30 +1,30 @@
|
||||
import { DialogBody, DialogCloseTrigger, DialogContent, DialogFooter, DialogHeader, DialogRoot, DialogTitle, DialogTrigger } from "../../../components/ui/dialog"
|
||||
import { Box, Field, IconButton, Input, Span, Stack, Text, Textarea } from "@chakra-ui/react"
|
||||
import { Field, Input, Span, Stack } from "@chakra-ui/react"
|
||||
import { Button } from "../../../components/ui/button"
|
||||
import { FaRegEdit } from "react-icons/fa";
|
||||
// import { FaRegEdit } from "react-icons/fa";
|
||||
import Edit from "../../../components/ActionIcons/Edit";
|
||||
|
||||
|
||||
function EditJobStatusModel() {
|
||||
|
||||
|
||||
|
||||
|
||||
return (
|
||||
|
||||
<DialogRoot placement="center">
|
||||
<DialogTrigger asChild>
|
||||
<Span><Edit /></Span>
|
||||
<Span><Edit /></Span>
|
||||
</DialogTrigger>
|
||||
|
||||
<DialogContent
|
||||
bg={"#fff"}
|
||||
// w={{ lg: "60%", md: "230px" }}
|
||||
w={{ base: '90%', md: '400px' }}
|
||||
bg={"#fff"}
|
||||
// w={{ lg: "60%", md: "230px" }}
|
||||
w={{ base: '90%', md: '400px' }}
|
||||
height={'auto'}
|
||||
|
||||
overflowX="hidden"
|
||||
p={3} // Reduced padding
|
||||
bgSize={'md'}
|
||||
|
||||
overflowX="hidden"
|
||||
p={3} // Reduced padding
|
||||
bgSize={'md'}
|
||||
>
|
||||
<DialogHeader bg="white" >
|
||||
<DialogTitle alignSelf="center" color="black" fontSize="14px">Edit</DialogTitle>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Box, HStack, Image, Input, Text } from "@chakra-ui/react";
|
||||
import { Box, HStack, Input, Text } from "@chakra-ui/react";
|
||||
import MainFrame from "../../../components/MainFrame"
|
||||
import { InputGroup } from "../../../components/ui/input-group";
|
||||
import { LuSearch } from "react-icons/lu";
|
||||
@@ -15,7 +15,7 @@ const tableHeadRow = [
|
||||
"Sr. No",
|
||||
"Title",
|
||||
"Action"
|
||||
|
||||
|
||||
];
|
||||
|
||||
const managepost: any[] = [
|
||||
@@ -26,7 +26,7 @@ const managepost: any[] = [
|
||||
<HStack justifyContent="center">
|
||||
<EditJobStatusModel />
|
||||
<Box>
|
||||
<Switch colorPalette={'teal'} size={"xs"}/>
|
||||
<Switch colorPalette={'teal'} size={"xs"} />
|
||||
</Box>
|
||||
</HStack>
|
||||
),
|
||||
@@ -46,11 +46,11 @@ const JobStatus = () => {
|
||||
px={3}
|
||||
>
|
||||
<Text as={"span"} fontSize={"sm"} fontWeight={500} color={"#000"}>
|
||||
Job Status
|
||||
Job Status
|
||||
</Text>
|
||||
|
||||
<HStack >
|
||||
<InputGroup
|
||||
<InputGroup
|
||||
startElement={
|
||||
<LuSearch fontSize={"xs"} style={{ position: 'relative', left: '10px' }} />
|
||||
}
|
||||
@@ -79,7 +79,7 @@ const JobStatus = () => {
|
||||
tableHeadRow={tableHeadRow}
|
||||
data={managepost}
|
||||
/>
|
||||
</Box>
|
||||
</Box>
|
||||
</MainFrame>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { DialogBody, DialogCloseTrigger, DialogContent, DialogFooter, DialogHeader, DialogRoot, DialogTitle, DialogTrigger } from "../../../components/ui/dialog"
|
||||
import { Box, Field, IconButton, Input, Stack, Text, Textarea } from "@chakra-ui/react"
|
||||
import { Field, Input, Stack, Text } from "@chakra-ui/react"
|
||||
import { IoMdAdd } from "react-icons/io"
|
||||
import { Button } from "../../../components/ui/button"
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { DialogBody, DialogCloseTrigger, DialogContent, DialogFooter, DialogHeader, DialogRoot, DialogTitle, DialogTrigger } from "../../../components/ui/dialog"
|
||||
import { Box, Field, IconButton, Input, Stack, Text, Textarea } from "@chakra-ui/react"
|
||||
import { Field, Input, Stack, Text } from "@chakra-ui/react"
|
||||
import { IoMdAdd } from "react-icons/io"
|
||||
import { Button } from "../../../components/ui/button"
|
||||
|
||||
|
||||
@@ -1,50 +1,132 @@
|
||||
import { DialogBody, DialogCloseTrigger, DialogContent, DialogFooter, DialogHeader, DialogRoot, DialogTitle, DialogTrigger } from "../../../components/ui/dialog"
|
||||
import { Box, Field, IconButton, Input, Stack, Text, Textarea } from "@chakra-ui/react"
|
||||
import { Box, Field, Input, Stack, Text } from "@chakra-ui/react"
|
||||
import { IoMdAdd } from "react-icons/io"
|
||||
import { Button } from "../../../components/ui/button"
|
||||
import { FiUpload } from "react-icons/fi";
|
||||
import { useState } from "react";
|
||||
// import { useCreateTemplatePostMutation } from "../../../Redux/Service/template.master.service";
|
||||
import { Toaster, toaster } from "../../../components/ui/toaster"
|
||||
import axios from "axios";
|
||||
|
||||
|
||||
function TemplateAddModel() {
|
||||
function TemplateAddModel({ id }: { id: number }) {
|
||||
const [title, setTitle] = useState("");
|
||||
const [subTitle, setSubTitle] = useState("");
|
||||
const [userType, setUserType] = useState<number | "">("");
|
||||
const [images, setImages] = useState<(File | string)[]>([]);
|
||||
// const [createTemplatePost] = useCreateTemplatePostMutation()
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const token = localStorage.getItem("token");
|
||||
if (!token) {
|
||||
console.error("No token found in localStorage!");
|
||||
return;
|
||||
}
|
||||
|
||||
const [images, setImages] = useState<string[]>([]);
|
||||
|
||||
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 = () => {
|
||||
setIsOpen(true); // Open modal when clicking "Add"
|
||||
};
|
||||
|
||||
|
||||
|
||||
const handleImageChange = async (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
if (event.target.files) {
|
||||
const file = event.target.files[0];
|
||||
if (!["image/jpeg", "image/jpg", "image/png"].includes(file.type)) {
|
||||
toaster.create({
|
||||
title: "Error",
|
||||
description: "Only JPEG, JPG, and PNG files are allowed.",
|
||||
type: "error",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
setImages((prevImages) => [...prevImages, file]);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const handleSubmit = async () => {
|
||||
if (!title || !subTitle || !userType || images.length === 0) {
|
||||
toaster.create({
|
||||
title: "Error",
|
||||
description: "Please fill in all required fields and upload at least one image.",
|
||||
type: "error",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// const payload = {
|
||||
// id: id,
|
||||
// principle_type_xid: userType,
|
||||
// title,
|
||||
// sub_title: subTitle,
|
||||
// image_name: images.filter((img) => typeof img === "string"), // Send only Base64 strings
|
||||
// };
|
||||
|
||||
|
||||
const formData = new FormData();
|
||||
formData.append("id", `${id}`);
|
||||
formData.append("principle_type_xid", `${userType}`);
|
||||
formData.append("title", title);
|
||||
formData.append("sub_title", subTitle);
|
||||
|
||||
images.forEach((image, index) => {
|
||||
if (image instanceof File) {
|
||||
formData.append(`image_name[${index}]`, image, image.name); // Ensure indexed naming
|
||||
}
|
||||
});
|
||||
|
||||
if (token) {
|
||||
const payload = JSON.parse(atob(token.split(".")[1]));
|
||||
console.log("Token Payload:", payload);
|
||||
}
|
||||
|
||||
try {
|
||||
// await createTemplatePost(formData)
|
||||
if (token) {
|
||||
await axios.post(`https://ssa.betadelivery.com/apia/v1/template-store`, formData, {
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data',
|
||||
'access-token': `${token}`,
|
||||
},
|
||||
// withCredentials: true,
|
||||
});
|
||||
}
|
||||
setTitle("");
|
||||
setSubTitle("");
|
||||
setUserType("");
|
||||
setImages([]);
|
||||
setIsOpen(false)
|
||||
} catch (error) {
|
||||
console.error("Error creating template:", error);
|
||||
// alert("Failed to create template");
|
||||
}
|
||||
};
|
||||
|
||||
console.log("Token stored:", window.localStorage.getItem("token"));
|
||||
|
||||
|
||||
return (
|
||||
|
||||
<DialogRoot placement="center">
|
||||
<DialogRoot placement="center" open={isOpen}>
|
||||
<DialogTrigger asChild>
|
||||
{/* <Button bg={"transparent"} size="sm">
|
||||
<MdOutlineRemoveRedEye style={{ cursor: "pointer", fontSize: "16px" }} />
|
||||
</Button> */}
|
||||
<Button px={5} size={"xs"} bg={"#02A0A0"}>
|
||||
<Button px={5} size={"xs"} bg={"#02A0A0"} onClick={handleOpenModal}>
|
||||
<IoMdAdd /> <Text>Add</Text>
|
||||
</Button>
|
||||
|
||||
</DialogTrigger>
|
||||
|
||||
<DialogContent
|
||||
bg={"#fff"}
|
||||
// w={{ lg: "60%", md: "230px" }}
|
||||
w={{ base: '90%', md: '400px' }}
|
||||
bg={"#fff"}
|
||||
// w={{ lg: "60%", md: "230px" }}
|
||||
w={{ base: '90%', md: '400px' }}
|
||||
height={'auto'}
|
||||
|
||||
overflowX="hidden"
|
||||
p={3} // Reduced padding
|
||||
bgSize={'md'}
|
||||
|
||||
overflowX="hidden"
|
||||
p={3} // Reduced padding
|
||||
bgSize={'md'}
|
||||
>
|
||||
<DialogHeader bg="white" >
|
||||
<DialogTitle alignSelf="center" color="black" fontSize="14px">Add</DialogTitle>
|
||||
@@ -54,30 +136,79 @@ function TemplateAddModel() {
|
||||
<Stack py={3}>
|
||||
|
||||
<Field.Root>
|
||||
<Field.Label color="black" pt={1} fontSize="12px">Template Name</Field.Label>
|
||||
<Input placeholder="" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" />
|
||||
<Field.Label color="black" pt={1} fontSize="12px">Title</Field.Label>
|
||||
<Input
|
||||
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.Root>
|
||||
<Field.Label color="black" pt={1} fontSize="12px">Subtitle</Field.Label>
|
||||
<Input
|
||||
placeholder="Enter subtitle"
|
||||
bgColor="#EEEEEE"
|
||||
color="black"
|
||||
border="none"
|
||||
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}
|
||||
alt={`Uploaded ${index}`}
|
||||
style={{ maxHeight: "40px", maxWidth: "70px", objectFit: "contain" }}
|
||||
/>
|
||||
))
|
||||
) : (
|
||||
<Box width="70px" height="40px" /> // Placeholder to maintain layout
|
||||
)}
|
||||
<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 instanceof File ? URL.createObjectURL(img) : img}
|
||||
alt={`Uploaded ${index}`}
|
||||
style={{ maxHeight: "40px", maxWidth: "70px", objectFit: "contain" }}
|
||||
/>
|
||||
))
|
||||
) : (
|
||||
<Box width="70px" height="40px" /> // Placeholder to maintain layout
|
||||
)}
|
||||
</Box>
|
||||
<FiUpload color="#000" />
|
||||
</Box>
|
||||
<FiUpload color="#000" />
|
||||
</Box>
|
||||
|
||||
|
||||
{/* <Input placeholder="" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" /> */}
|
||||
|
||||
</Field.Root>
|
||||
@@ -85,13 +216,14 @@ function TemplateAddModel() {
|
||||
|
||||
</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>
|
||||
<Toaster />
|
||||
</DialogRoot >
|
||||
|
||||
)
|
||||
|
||||
@@ -4,12 +4,14 @@ import { InputGroup } from "../../../components/ui/input-group";
|
||||
import { LuSearch } from "react-icons/lu";
|
||||
import DataTable from "../../../components/DataTable";
|
||||
import { Switch } from "../../../components/ui/switch";
|
||||
import img from "../../../assets/waterfall.jpg"
|
||||
import Templateimg from "../../../assets/Template_img.png"
|
||||
// import img from "../../../assets/waterfall.jpg"
|
||||
// import Templateimg from "../../../assets/Template_img.png"
|
||||
import TemplateAddModel from "./TemplateAddModel";
|
||||
import EditTemplateModel from "./EditTemplateModel";
|
||||
import { Template, useGetTemplateMasterQuery, useTemplateMasterToggleMutation } from "../../../Redux/Service/template.master.service";
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
|
||||
const APIURL = import.meta.env.VITE_IMG_TEMPLATES
|
||||
|
||||
// table data
|
||||
|
||||
@@ -18,35 +20,95 @@ const tableHeadRow = [
|
||||
"Title",
|
||||
"Images",
|
||||
"Action"
|
||||
|
||||
];
|
||||
|
||||
const managepost: any[] = [
|
||||
...Array.from({ length: 12 }, (_, i) => ({
|
||||
"Sr. No": i + 1,
|
||||
"Title": "Lorem Ipsum",
|
||||
// const managepost: any[] = [
|
||||
// ...Array.from({ length: 12 }, (_, i) => ({
|
||||
// "Sr. No": i + 1,
|
||||
// "Title": "Lorem Ipsum",
|
||||
// "Images": (
|
||||
// // <Image w={50} src={img} />
|
||||
// <HStack >
|
||||
// <Image rounded={'lg'} w={100} h={50} src={img} />
|
||||
// <Image rounded={'lg'} w={100} h={50} src={Templateimg} />
|
||||
// </HStack>
|
||||
// ),
|
||||
|
||||
// "Action": (
|
||||
// <HStack justifyContent="center">
|
||||
// <EditTemplateModel />
|
||||
// <Box>
|
||||
// <Switch colorPalette={'teal'} size={"xs"} />
|
||||
// </Box>
|
||||
// </HStack>
|
||||
// ),
|
||||
// })),
|
||||
// ];
|
||||
|
||||
const TemplateMaster = () => {
|
||||
const { data, refetch } = useGetTemplateMasterQuery()
|
||||
const [localData, setLocalData] = useState<any[]>([]);
|
||||
const [templateMasterToggle] = useTemplateMasterToggleMutation()
|
||||
console.log('DATA', data?.data.data);
|
||||
|
||||
useEffect(() => {
|
||||
if (data?.data?.data) {
|
||||
setLocalData(data?.data.data);
|
||||
}
|
||||
}, [data]);
|
||||
|
||||
const handleToggle = async (agencyId: string, currentStatus: number) => {
|
||||
const newStatus = currentStatus ? 0 : 1;
|
||||
setLocalData((prevData) =>
|
||||
prevData.map((agency) =>
|
||||
agency.id === agencyId ? { ...agency, is_active: newStatus } : agency
|
||||
)
|
||||
);
|
||||
try {
|
||||
await templateMasterToggle({ id: agencyId, is_active: newStatus }).unwrap();
|
||||
refetch()
|
||||
} catch (error) {
|
||||
console.error("Error updating privacy policy:", error);
|
||||
setLocalData((prevData) =>
|
||||
prevData.map((agency) =>
|
||||
agency.id === agencyId ? { ...agency, is_active: currentStatus } : agency
|
||||
)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
const managepost = localData?.map((agency: Template, index: number) => ({
|
||||
'id': agency.id,
|
||||
"Sr. No": index + 1,
|
||||
"Title": agency.post_template_translate.length > 0
|
||||
? agency.post_template_translate[0].title
|
||||
: "N/A",
|
||||
"Images": (
|
||||
// <Image w={50} src={img} />
|
||||
<HStack >
|
||||
<Image rounded={'lg'} w={100} h={50} src={img} />
|
||||
<Image rounded={'lg'} w={100} h={50} src={Templateimg} />
|
||||
{agency.post_template_image.map((img) => (
|
||||
<Image rounded={'lg'} w={100} h={50} src={`${APIURL}${img.image_name}`} />
|
||||
))}
|
||||
|
||||
{/* <Image rounded={'lg'} w={100} h={50} src={Templateimg} /> */}
|
||||
</HStack>
|
||||
|
||||
|
||||
),
|
||||
|
||||
|
||||
"Action": (
|
||||
<HStack justifyContent="center">
|
||||
<EditTemplateModel />
|
||||
<EditTemplateModel id={agency.id} localData={localData} />
|
||||
<Box>
|
||||
<Switch colorPalette={'teal'} size={"xs"}/>
|
||||
<Switch
|
||||
colorPalette={'teal'}
|
||||
size={"xs"}
|
||||
onChange={() => handleToggle(agency.id.toString(), Number(agency.is_active ?? 0))}
|
||||
checked={Boolean(Number(agency.is_active))}
|
||||
/>
|
||||
</Box>
|
||||
</HStack>
|
||||
),
|
||||
})),
|
||||
];
|
||||
}));
|
||||
|
||||
const TemplateMaster = () => {
|
||||
return (
|
||||
|
||||
<MainFrame>
|
||||
@@ -59,11 +121,11 @@ const TemplateMaster = () => {
|
||||
px={3}
|
||||
>
|
||||
<Text as={"span"} fontSize={"sm"} fontWeight={500} color={"#000"}>
|
||||
Template Master
|
||||
Template Master
|
||||
</Text>
|
||||
|
||||
<HStack >
|
||||
<InputGroup
|
||||
<InputGroup
|
||||
startElement={
|
||||
<LuSearch fontSize={"xs"} style={{ position: 'relative', left: '10px' }} />
|
||||
}
|
||||
@@ -84,7 +146,9 @@ const TemplateMaster = () => {
|
||||
/>
|
||||
</InputGroup>
|
||||
{/* <Button bgColor={'#EEEEEE'} pl={3} pr={3}><IoMdAdd /> <Text>Add</Text></Button> */}
|
||||
<TemplateAddModel />
|
||||
{localData?.map((item: any) => (
|
||||
<TemplateAddModel id={item.id} />
|
||||
))}
|
||||
</HStack>
|
||||
</HStack>
|
||||
<DataTable
|
||||
@@ -92,7 +156,7 @@ const TemplateMaster = () => {
|
||||
tableHeadRow={tableHeadRow}
|
||||
data={managepost}
|
||||
/>
|
||||
</Box>
|
||||
</Box>
|
||||
</MainFrame>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -9,17 +9,13 @@ import {
|
||||
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 { FaRegEdit } from "react-icons/fa";
|
||||
// import { FaRegEdit } from "react-icons/fa";
|
||||
import Edit from "../../../components/ActionIcons/Edit";
|
||||
|
||||
function EditWorkModel() {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { DialogBody, DialogCloseTrigger, DialogContent, DialogFooter, DialogHeader, DialogRoot, DialogTitle, DialogTrigger } from "../../../components/ui/dialog"
|
||||
import { Box, Field, IconButton, Input, Stack, Text, Textarea } from "@chakra-ui/react"
|
||||
import {Field, Input, Stack, Text } from "@chakra-ui/react"
|
||||
import { IoMdAdd } from "react-icons/io"
|
||||
import { Button } from "../../../components/ui/button"
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Box, HStack, Image, Input, Text } from "@chakra-ui/react";
|
||||
import { Box, HStack, Input, Text } from "@chakra-ui/react";
|
||||
import MainFrame from "../../../components/MainFrame"
|
||||
import { InputGroup } from "../../../components/ui/input-group";
|
||||
import { LuSearch } from "react-icons/lu";
|
||||
|
||||
133
src/Pages/SetNewPassword.tsx
Normal file
133
src/Pages/SetNewPassword.tsx
Normal file
@@ -0,0 +1,133 @@
|
||||
import {
|
||||
Box,
|
||||
Center,
|
||||
HStack,
|
||||
Image,
|
||||
Input,
|
||||
Stack,
|
||||
Text,
|
||||
VStack,
|
||||
} from "@chakra-ui/react";
|
||||
import axios from "axios";
|
||||
import { useState } from "react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import logo from "../assets/logo.svg";
|
||||
import { Button } from "../components/ui/button";
|
||||
import { toaster, Toaster } from "../components/ui/toaster";
|
||||
|
||||
const SetNewPassword = () => {
|
||||
const [password, setPassword] = useState("");
|
||||
const [confirmPassword, setConfirmPassword] = useState("");
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const navigate = useNavigate();
|
||||
|
||||
const handlePasswordSubmit = async () => {
|
||||
// Validation
|
||||
if (password.length < 8) {
|
||||
toaster.create({
|
||||
title: "Password must be at least 8 characters long",
|
||||
type: "error",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (password !== confirmPassword) {
|
||||
toaster.create({
|
||||
title: "Passwords do not match",
|
||||
type: "error",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
setIsLoading(true);
|
||||
|
||||
try {
|
||||
const res = await axios.post(`${import.meta.env.VITE_API_URL}/reset-password`, {
|
||||
password: password,
|
||||
confirm_password: confirmPassword,
|
||||
// id: id
|
||||
});
|
||||
|
||||
if (res.status === 200) {
|
||||
toaster.create({
|
||||
title: "Password updated successfully",
|
||||
type: "success",
|
||||
});
|
||||
navigate("/login"); // Redirect to login page
|
||||
} else {
|
||||
toaster.create({
|
||||
title: res.data.message || "Failed to update password",
|
||||
type: "error",
|
||||
});
|
||||
}
|
||||
} catch (error: any) {
|
||||
toaster.create({
|
||||
title: error.response?.data?.message || "Something went wrong",
|
||||
type: "error",
|
||||
});
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<VStack w="100%" h="100vh" bg="#ffffff">
|
||||
<HStack
|
||||
boxShadow="rgba(99, 99, 99, 0.2) 0px 2px 8px 0px"
|
||||
w="100%"
|
||||
ps={8}
|
||||
h="7%"
|
||||
justifyContent="flex-start"
|
||||
>
|
||||
<Image w={50} src={logo} />
|
||||
</HStack>
|
||||
|
||||
<Center w="100%" h="93%" p={8}>
|
||||
<Box p={8} borderWidth={1} borderRadius="lg" boxShadow="lg">
|
||||
<Text fontSize="24px" fontWeight="bold" color="#313039" textAlign="center">
|
||||
Create a Password
|
||||
</Text>
|
||||
|
||||
<Stack p={2}>
|
||||
<Text color="black" pt={1} fontSize="12px">New password</Text>
|
||||
<Input
|
||||
color="black"
|
||||
pl={1}
|
||||
fontSize="12px"
|
||||
type="password"
|
||||
border="1px solid grey"
|
||||
value={password}
|
||||
onChange={(e) => setPassword(e.target.value)}
|
||||
/>
|
||||
|
||||
<Text color="black" pt={1} fontSize="12px">Confirm password</Text>
|
||||
<Input
|
||||
color="black"
|
||||
pl={1}
|
||||
fontSize="12px"
|
||||
type="password"
|
||||
border="1px solid grey"
|
||||
value={confirmPassword}
|
||||
onChange={(e) => setConfirmPassword(e.target.value)}
|
||||
/>
|
||||
</Stack>
|
||||
|
||||
<Button
|
||||
loading={isLoading}
|
||||
mt={6}
|
||||
w="100%"
|
||||
bg="#02A0A0"
|
||||
color="white"
|
||||
onClick={handlePasswordSubmit}
|
||||
>
|
||||
Confirm Password
|
||||
</Button>
|
||||
</Box>
|
||||
</Center>
|
||||
|
||||
<Toaster />
|
||||
</VStack>
|
||||
);
|
||||
};
|
||||
|
||||
export default SetNewPassword;
|
||||
@@ -4,7 +4,7 @@ import { InputGroup } from "../../components/ui/input-group"
|
||||
import { LuSearch } from "react-icons/lu"
|
||||
import DataTable from "../../components/DataTable"
|
||||
import AlertDailog from "../../components/AlertDailog"
|
||||
import { RiDeleteBin5Line } from "react-icons/ri";
|
||||
// import { RiDeleteBin5Line } from "react-icons/ri";
|
||||
import AddModel from "./AddModel"
|
||||
import EditSubAdmin from "../../components/EditSubAdmin"
|
||||
import ViewSubAdmin from "./ViewSubAdmin"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Button } from "../../components/ui/button";
|
||||
// import { Button } from "../../components/ui/button";
|
||||
import {
|
||||
DialogBody,
|
||||
DialogCloseTrigger,
|
||||
@@ -13,17 +13,20 @@ import {
|
||||
Field,
|
||||
Grid,
|
||||
Heading,
|
||||
Icon,
|
||||
Input,
|
||||
Span,
|
||||
Stack,
|
||||
Text,
|
||||
} from "@chakra-ui/react";
|
||||
import { Checkbox } from "../../components/ui/checkbox";
|
||||
import { MdOutlineRemoveRedEye } from "react-icons/md";
|
||||
import { FaRegEdit } from "react-icons/fa";
|
||||
// import { MdOutlineRemoveRedEye } from "react-icons/md";
|
||||
// import { FaRegEdit } from "react-icons/fa";
|
||||
import View from "../../components/ActionIcons/View";
|
||||
import { useGetSubAdminQuery } from "../../Redux/Service/manage.subadmin.service";
|
||||
function ViewSubAdmin() {
|
||||
const { data} = useGetSubAdminQuery();
|
||||
console.log('data', data);
|
||||
|
||||
return (
|
||||
<DialogRoot placement="center">
|
||||
<DialogTrigger asChild>
|
||||
|
||||
155
src/Pages/VerifyEnterOTP.tsx
Normal file
155
src/Pages/VerifyEnterOTP.tsx
Normal file
@@ -0,0 +1,155 @@
|
||||
import {
|
||||
Box,
|
||||
Center,
|
||||
HStack,
|
||||
Image,
|
||||
Input,
|
||||
Text,
|
||||
VStack,
|
||||
} from "@chakra-ui/react";
|
||||
import axios from "axios";
|
||||
import { useState } from "react";
|
||||
import { useNavigate, useLocation } from "react-router-dom";
|
||||
import logo from "../assets/logo.svg";
|
||||
import { Button } from "../components/ui/button";
|
||||
import { toaster, Toaster } from "../components/ui/toaster";
|
||||
|
||||
const VerifyOTP = () => {
|
||||
const [otp, setOtp] = useState<string[]>(["", "", "", ""]);
|
||||
const navigate = useNavigate();
|
||||
const location = useLocation();
|
||||
const queryParams = new URLSearchParams(location.search);
|
||||
const phoneNumber = queryParams.get("phone");
|
||||
|
||||
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
|
||||
const handleChange = (e: React.ChangeEvent<HTMLInputElement>, index: number): void => {
|
||||
const value = e.target.value;
|
||||
|
||||
// Prevent non-numeric input
|
||||
if (/[^0-9]/.test(value)) return;
|
||||
|
||||
// Update the OTP state with the new value
|
||||
const newOtp = [...otp];
|
||||
newOtp[index] = value;
|
||||
setOtp(newOtp);
|
||||
|
||||
// Move focus to the next input automatically
|
||||
if (value && index < otp.length - 1) {
|
||||
const nextInput = document.getElementById(`otp-input-${index + 1}`) as HTMLInputElement;
|
||||
if (nextInput) nextInput.focus();
|
||||
}
|
||||
};
|
||||
|
||||
const handleOtpSubmit = async () => {
|
||||
if (otp.length !== 4) {
|
||||
toaster.create({
|
||||
title: "OTP must be 4 digits",
|
||||
type: "error",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
setIsLoading(true);
|
||||
try {
|
||||
const res = await axios.post(`${import.meta.env.VITE_API_URL}/verify-otp`, {
|
||||
mobile_number: phoneNumber,
|
||||
otp: otp,
|
||||
});
|
||||
|
||||
if (res.status === 200) {
|
||||
toaster.create({
|
||||
title: "OTP Verified Successfully",
|
||||
type: "success",
|
||||
});
|
||||
|
||||
navigate("/forgot-password/reset-password"); // Navigate to reset password page
|
||||
} else {
|
||||
toaster.create({
|
||||
title: res.data.message || "Invalid OTP",
|
||||
type: "error",
|
||||
});
|
||||
}
|
||||
} catch (error: any) {
|
||||
toaster.create({
|
||||
title: error.response?.data?.message || "Something went wrong",
|
||||
type: "error",
|
||||
});
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<VStack w="100%" h="100vh" bg="#ffffff">
|
||||
<HStack
|
||||
boxShadow="rgba(99, 99, 99, 0.2) 0px 2px 8px 0px"
|
||||
w="100%"
|
||||
ps={8}
|
||||
h="7%"
|
||||
justifyContent="flex-start"
|
||||
>
|
||||
<Image w={50} src={logo} />
|
||||
</HStack>
|
||||
|
||||
<Center w="100%" h="93%" p={8}>
|
||||
<Box p={8} borderWidth={1} borderRadius="lg" boxShadow="lg">
|
||||
<Text fontSize="24px" fontWeight="bold" color="#313039" textAlign="center">
|
||||
Enter OTP
|
||||
</Text>
|
||||
|
||||
<Text fontSize="14px" color="gray.600" textAlign="center" mt={2}>
|
||||
OTP sent to {phoneNumber}
|
||||
</Text>
|
||||
|
||||
<HStack gap={4} mt={6} justify="center">
|
||||
{otp.map((digit, index) => (
|
||||
<Input
|
||||
key={index}
|
||||
id={`otp-input-${index}`}
|
||||
value={digit}
|
||||
maxW="50px"
|
||||
color={"black"}
|
||||
textAlign="center"
|
||||
fontSize="20px"
|
||||
placeholder="0"
|
||||
border="1px solid grey"
|
||||
onChange={(e) => handleChange(e, index)}
|
||||
maxLength={1} // Only allows 1 character per input
|
||||
/>
|
||||
))}
|
||||
</HStack>
|
||||
{/* <Box textAlign="center">
|
||||
<Text
|
||||
color="#4746F4"
|
||||
textDecoration="underline"
|
||||
fontWeight="bold"
|
||||
mt={3}
|
||||
cursor="pointer"
|
||||
display="inline-block"
|
||||
px={2}
|
||||
>
|
||||
Resend OTP
|
||||
</Text>
|
||||
</Box> */}
|
||||
|
||||
<Button
|
||||
loading={isLoading}
|
||||
mt={6}
|
||||
w="100%"
|
||||
bg="#02A0A0"
|
||||
color="white"
|
||||
onClick={handleOtpSubmit}
|
||||
>
|
||||
Verify OTP
|
||||
</Button>
|
||||
</Box>
|
||||
</Center>
|
||||
|
||||
<Toaster />
|
||||
</VStack>
|
||||
);
|
||||
};
|
||||
|
||||
export default VerifyOTP;
|
||||
60
src/Redux/Service/agency.master.module.service.ts
Normal file
60
src/Redux/Service/agency.master.module.service.ts
Normal file
@@ -0,0 +1,60 @@
|
||||
import { createApi } from "@reduxjs/toolkit/query/react";
|
||||
import { baseQueryWithReauth } from "./apiSlice";
|
||||
|
||||
export interface Agency {
|
||||
id: number;
|
||||
name: string;
|
||||
state: string;
|
||||
rc_status: string;
|
||||
rc_number: string;
|
||||
domain_name: string;
|
||||
gst_number: string;
|
||||
is_active: boolean,
|
||||
registered_office:string,
|
||||
}
|
||||
|
||||
export interface AgencyData {
|
||||
current_page: number;
|
||||
data: Agency[];
|
||||
first_page_url: string;
|
||||
from: number;
|
||||
last_page: number;
|
||||
last_page_url: string;
|
||||
per_page: number;
|
||||
total: number;
|
||||
}
|
||||
|
||||
export interface AgencyResponse {
|
||||
status: "success" | "error";
|
||||
status_code: number;
|
||||
message: string;
|
||||
data: AgencyData;
|
||||
}
|
||||
|
||||
export interface UpdatePrivacyPolicyPayload {
|
||||
id: number,
|
||||
is_active: boolean,
|
||||
}
|
||||
|
||||
|
||||
export const agencyMasterModule = createApi({
|
||||
reducerPath: "agencyMasterModule",
|
||||
baseQuery: baseQueryWithReauth, // Use enhanced baseQuery with error handling
|
||||
endpoints: (builder) => ({
|
||||
|
||||
|
||||
|
||||
getAgencyMaster: builder.query<AgencyResponse, void>({ query: () => "/agency-master" }),
|
||||
|
||||
agencyMasterToggle: builder.mutation({
|
||||
query: ({ id, is_active }) => ({
|
||||
url: `/agency-status`,
|
||||
method: "POST",
|
||||
body: { id, is_active },
|
||||
}),
|
||||
}),
|
||||
|
||||
}),
|
||||
});
|
||||
|
||||
export const { useGetAgencyMasterQuery, useAgencyMasterToggleMutation } = agencyMasterModule;
|
||||
@@ -1,36 +0,0 @@
|
||||
import { createApi } from "@reduxjs/toolkit/query/react";
|
||||
import { baseQueryWithReauth } from "./apiSlice";
|
||||
|
||||
export const forgetPassword = createApi({
|
||||
reducerPath: "aboutUs",
|
||||
baseQuery: baseQueryWithReauth, // Use enhanced baseQuery with error handling
|
||||
endpoints: (builder) => ({
|
||||
|
||||
|
||||
|
||||
// 🔹 GET: Fetch all posts
|
||||
getAboutUs: builder.query<AboutUs[], void>({
|
||||
query: () => "/send-otp",
|
||||
}),
|
||||
|
||||
}),
|
||||
});
|
||||
|
||||
export const {
|
||||
useGetAboutUsQuery,
|
||||
} = forgetPassword;
|
||||
|
||||
// Define Post type
|
||||
export type Post = {
|
||||
id: number;
|
||||
title: string;
|
||||
body: string;
|
||||
};
|
||||
|
||||
|
||||
export type AboutUs = {
|
||||
id: number;
|
||||
language_master_xid: number;
|
||||
content: string;
|
||||
is_active: boolean;
|
||||
};
|
||||
97
src/Redux/Service/job.type.service.ts
Normal file
97
src/Redux/Service/job.type.service.ts
Normal file
@@ -0,0 +1,97 @@
|
||||
import { createApi } from "@reduxjs/toolkit/query/react";
|
||||
import { baseQueryWithReauth } from "./apiSlice";
|
||||
|
||||
interface JobTypeResponse {
|
||||
status: string;
|
||||
status_code: number;
|
||||
message: string;
|
||||
data: PaginationData;
|
||||
}
|
||||
|
||||
interface PaginationData {
|
||||
current_page: number;
|
||||
data: JobTypeData[];
|
||||
first_page_url: string;
|
||||
from: number;
|
||||
last_page: number;
|
||||
last_page_url: string;
|
||||
links: PaginationLink[];
|
||||
next_page_url: string | null;
|
||||
path: string;
|
||||
per_page: number;
|
||||
prev_page_url: string | null;
|
||||
to: number;
|
||||
total: number;
|
||||
}
|
||||
|
||||
export interface JobTypeData {
|
||||
id: number;
|
||||
is_active: boolean;
|
||||
en_name: string;
|
||||
hi_name: string;
|
||||
mr_name:string,
|
||||
te_name:string,
|
||||
ta_name:string,
|
||||
bn_name:string,
|
||||
or_name:string,
|
||||
}
|
||||
|
||||
|
||||
interface PaginationLink {
|
||||
url: string | null;
|
||||
label: string;
|
||||
active: boolean;
|
||||
}
|
||||
|
||||
export interface Post {
|
||||
id: number,
|
||||
principle_type_xid: number,
|
||||
title: string,
|
||||
sub_title: string,
|
||||
image_name: string[]
|
||||
}
|
||||
|
||||
export const jobType = createApi({
|
||||
reducerPath: "jobType",
|
||||
baseQuery: baseQueryWithReauth, // Use enhanced baseQuery with error handling
|
||||
endpoints: (builder) => ({
|
||||
createTemplatePost: builder.mutation<Post, FormData>({
|
||||
query: (data) => ({
|
||||
url: "/template-store",
|
||||
method: "POST",
|
||||
body: data,
|
||||
headers: {
|
||||
token_access: `Bearer ${localStorage.getItem("token")}`,
|
||||
},
|
||||
}),
|
||||
}),
|
||||
// 🔹 GET: Fetch all posts
|
||||
getJobType: builder.query<JobTypeResponse, void>({
|
||||
query: () => "/job-type",
|
||||
}),
|
||||
|
||||
updateTemplateMaster: builder.mutation({
|
||||
query: (updatedData) => ({
|
||||
url: "/template-update",
|
||||
method: "POST",
|
||||
body: updatedData,
|
||||
}),
|
||||
}),
|
||||
|
||||
templateMasterToggle: builder.mutation({
|
||||
query: ({ id, is_active }) => ({
|
||||
url: `/template-status`,
|
||||
method: "POST",
|
||||
body: { id, is_active },
|
||||
}),
|
||||
}),
|
||||
|
||||
}),
|
||||
});
|
||||
|
||||
export const {
|
||||
useGetJobTypeQuery,
|
||||
useCreateTemplatePostMutation,
|
||||
useUpdateTemplateMasterMutation,
|
||||
useTemplateMasterToggleMutation,
|
||||
} = jobType;
|
||||
@@ -14,9 +14,6 @@ export const aboutUs = createApi({
|
||||
}),
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// 🔹 GET: Fetch a single post by ID
|
||||
getPostById: builder.query<Post, number>({
|
||||
query: (id) => `/posts/${id}`,
|
||||
@@ -42,7 +39,7 @@ export const aboutUs = createApi({
|
||||
updateAboutUs: builder.mutation({
|
||||
query: (updatedData) => ({
|
||||
url: "/about-us/update", // ✅ Updated URL
|
||||
method: "POST",
|
||||
method: "PUT",
|
||||
body: updatedData,
|
||||
}),
|
||||
}),
|
||||
@@ -59,17 +56,6 @@ export const aboutUs = createApi({
|
||||
export const {
|
||||
useGetAboutUsQuery,
|
||||
useUpdateAboutUsMutation,
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
useGetPostByIdQuery,
|
||||
useCreatePostMutation,
|
||||
useDeletePostMutation
|
||||
|
||||
@@ -1,23 +1,30 @@
|
||||
import { createApi } from "@reduxjs/toolkit/query";
|
||||
import { createApi } from "@reduxjs/toolkit/query/react";
|
||||
import { baseQueryWithReauth } from "./apiSlice";
|
||||
|
||||
|
||||
|
||||
export type SubAdminPost = {
|
||||
id: number;
|
||||
first_name: string,
|
||||
last_name: string,
|
||||
unique_id:string,
|
||||
date_of_birth:string,
|
||||
gender: string,
|
||||
}
|
||||
|
||||
export const manageSubAdmin = createApi({
|
||||
reducerPath: "manageSubAdmin",
|
||||
baseQuery: baseQueryWithReauth, // Use enhanced baseQuery with error handling
|
||||
endpoints: (builder) => ({
|
||||
|
||||
|
||||
|
||||
getPosts: builder.query<Post[], void>({ query: () => "/posts" }),
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
tagTypes: ['SubAdmin'],
|
||||
endpoints: (builder) => ({
|
||||
getSubAdmin: builder.query<SubAdminPost[], void>({
|
||||
query: () => `/sub-admin-view/2` }),
|
||||
}),
|
||||
});
|
||||
|
||||
export const { } = manageSubAdmin;
|
||||
export const {
|
||||
useGetSubAdminQuery,
|
||||
} = manageSubAdmin;
|
||||
|
||||
export type Post = {
|
||||
id: number;
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
import { createApi } from "@reduxjs/toolkit/query";
|
||||
import { baseQueryWithReauth } from "./apiSlice";
|
||||
|
||||
export const masterModule = createApi({
|
||||
reducerPath: "masterModule",
|
||||
baseQuery: baseQueryWithReauth, // Use enhanced baseQuery with error handling
|
||||
endpoints: (builder) => ({
|
||||
|
||||
|
||||
|
||||
getPosts: builder.query<Post[], void>({ query: () => "/posts" }),
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}),
|
||||
});
|
||||
|
||||
export const { } = masterModule;
|
||||
|
||||
export type Post = {
|
||||
id: number;
|
||||
title: string;
|
||||
body: string;
|
||||
};
|
||||
@@ -9,8 +9,16 @@ export const privacyPolicy = createApi({
|
||||
getPrivacyPolicy: builder.query<PrivacyPolicyResponse, void>({ // Fix types here
|
||||
query: () => "/privacy-policy",
|
||||
}),
|
||||
|
||||
updatePrivacyPolicy: builder.mutation({
|
||||
query: (updatedData) => ({
|
||||
url: "/privacy-policy/update", // ✅ Updated URL
|
||||
method: "POST",
|
||||
body: updatedData,
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
});
|
||||
|
||||
// Export hook
|
||||
export const { useGetPrivacyPolicyQuery } = privacyPolicy;
|
||||
export const { useGetPrivacyPolicyQuery, useUpdatePrivacyPolicyMutation } = privacyPolicy;
|
||||
|
||||
104
src/Redux/Service/template.master.service.ts
Normal file
104
src/Redux/Service/template.master.service.ts
Normal file
@@ -0,0 +1,104 @@
|
||||
import { createApi } from "@reduxjs/toolkit/query/react";
|
||||
import { baseQueryWithReauth } from "./apiSlice";
|
||||
|
||||
interface TemplateResponse {
|
||||
status: string;
|
||||
status_code: number;
|
||||
message: string;
|
||||
data: PaginationData;
|
||||
}
|
||||
|
||||
interface PaginationData {
|
||||
current_page: number;
|
||||
data: Template[];
|
||||
first_page_url: string;
|
||||
from: number;
|
||||
last_page: number;
|
||||
last_page_url: string;
|
||||
links: PaginationLink[];
|
||||
next_page_url: string | null;
|
||||
path: string;
|
||||
per_page: number;
|
||||
prev_page_url: string | null;
|
||||
to: number;
|
||||
total: number;
|
||||
}
|
||||
|
||||
export interface Template {
|
||||
id: number;
|
||||
is_active: boolean;
|
||||
post_template_translate: PostTemplateTranslate[];
|
||||
post_template_image: PostTemplateImage[];
|
||||
}
|
||||
|
||||
export interface PostTemplateTranslate {
|
||||
id: number;
|
||||
title: string;
|
||||
sub_title: string;
|
||||
post_template_xid: number;
|
||||
}
|
||||
|
||||
interface PostTemplateImage {
|
||||
id: number;
|
||||
post_template_xid: number;
|
||||
image_name: string;
|
||||
}
|
||||
|
||||
interface PaginationLink {
|
||||
url: string | null;
|
||||
label: string;
|
||||
active: boolean;
|
||||
}
|
||||
|
||||
export interface Post {
|
||||
id: number,
|
||||
principle_type_xid: number,
|
||||
title: string,
|
||||
sub_title: string,
|
||||
image_name: string[]
|
||||
}
|
||||
|
||||
export const templateMaster = createApi({
|
||||
reducerPath: "templateMaster",
|
||||
baseQuery: baseQueryWithReauth, // Use enhanced baseQuery with error handling
|
||||
endpoints: (builder) => ({
|
||||
createTemplatePost: builder.mutation<Post, FormData>({
|
||||
query: (data) => ({
|
||||
url: "/template-store",
|
||||
method: "POST",
|
||||
body: data,
|
||||
headers: {
|
||||
Authorization: `Bearer ${localStorage.getItem("token")}`,
|
||||
},
|
||||
}),
|
||||
}),
|
||||
// 🔹 GET: Fetch all posts
|
||||
getTemplateMaster: builder.query<TemplateResponse, void>({
|
||||
query: () => "/template-master",
|
||||
}),
|
||||
|
||||
updateTemplateMaster: builder.mutation({
|
||||
query: (updatedData) => ({
|
||||
url: "/template-update",
|
||||
method: "POST",
|
||||
body: updatedData,
|
||||
}),
|
||||
}),
|
||||
|
||||
templateMasterToggle: builder.mutation({
|
||||
query: ({ id, is_active }) => ({
|
||||
url: `/template-status`,
|
||||
method: "POST",
|
||||
body: { id, is_active },
|
||||
}),
|
||||
}),
|
||||
|
||||
}),
|
||||
});
|
||||
|
||||
export const {
|
||||
useGetTemplateMasterQuery,
|
||||
useCreateTemplatePostMutation,
|
||||
useUpdateTemplateMasterMutation,
|
||||
useTemplateMasterToggleMutation,
|
||||
} = templateMaster;
|
||||
@@ -1,26 +1,40 @@
|
||||
import { createApi } from "@reduxjs/toolkit/query";
|
||||
import { createApi } from "@reduxjs/toolkit/query/react";
|
||||
import { baseQueryWithReauth } from "./apiSlice";
|
||||
|
||||
|
||||
export interface Terms {
|
||||
id: number,
|
||||
language_master_xid: number,
|
||||
content: string,
|
||||
is_active: boolean,
|
||||
terms_cond_language: {
|
||||
id: number,
|
||||
language_name: string,
|
||||
language_code: string,
|
||||
}
|
||||
}
|
||||
|
||||
export const termsAndCondition = createApi({
|
||||
reducerPath: "api",
|
||||
baseQuery: baseQueryWithReauth, // Use enhanced baseQuery with error handling
|
||||
endpoints: (builder) => ({
|
||||
|
||||
|
||||
|
||||
getPosts: builder.query<Post[], void>({ query: () => "/posts" }),
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
reducerPath: "termsAndCondition",
|
||||
baseQuery: baseQueryWithReauth, // Use enhanced baseQuery with error handling
|
||||
endpoints: (builder) => ({
|
||||
getTerms: builder.query<{ data: Terms[] }, void>({ query: () => "/term-and-condition" }),
|
||||
|
||||
updateTerms: builder.mutation({
|
||||
query: (updatedData) => ({
|
||||
url: "/term-and-condition/update", // ✅ Updated URL
|
||||
method: "POST",
|
||||
body: updatedData,
|
||||
}),
|
||||
}),
|
||||
});
|
||||
|
||||
export const { } = termsAndCondition;
|
||||
|
||||
export type Post = {
|
||||
id: number;
|
||||
title: string;
|
||||
body: string;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
}),
|
||||
});
|
||||
|
||||
export const {
|
||||
useGetTermsQuery,
|
||||
useUpdateTermsMutation,
|
||||
} = termsAndCondition;
|
||||
|
||||
@@ -13,7 +13,10 @@ import { aboutUs } from "./Service/manage.aboutus.service";
|
||||
import { privacyPolicy } from "./Service/privacy.policy.service";
|
||||
import { privacy } from "./Service/privacy.service";
|
||||
import { myProfile } from "./Service/myprofie.service";
|
||||
import { masterModule } from "./Service/master.module.service";
|
||||
import { agencyMasterModule } from "./Service/agency.master.module.service";
|
||||
import { termsAndCondition } from "./Service/terms.and.condition.service";
|
||||
import { templateMaster } from "./Service/template.master.service";
|
||||
import { jobType } from "./Service/job.type.service";
|
||||
|
||||
export const store = configureStore({
|
||||
reducer: {
|
||||
@@ -30,7 +33,10 @@ export const store = configureStore({
|
||||
[privacyPolicy.reducerPath]: privacyPolicy.reducer,
|
||||
[privacy.reducerPath]: privacy.reducer,
|
||||
[myProfile.reducerPath]: myProfile.reducer,
|
||||
[masterModule.reducerPath]: masterModule.reducer,
|
||||
[agencyMasterModule.reducerPath]: agencyMasterModule.reducer,
|
||||
[termsAndCondition.reducerPath]: termsAndCondition.reducer,
|
||||
[templateMaster.reducerPath]: templateMaster.reducer,
|
||||
[jobType.reducerPath]: jobType.reducer,
|
||||
auth: authReducer,
|
||||
},
|
||||
middleware: (getDefaultMiddleware) =>
|
||||
@@ -47,7 +53,10 @@ export const store = configureStore({
|
||||
privacyPolicy.middleware,
|
||||
privacy.middleware,
|
||||
myProfile.middleware,
|
||||
masterModule.middleware,
|
||||
agencyMasterModule.middleware,
|
||||
termsAndCondition.middleware,
|
||||
templateMaster.middleware,
|
||||
jobType.middleware,
|
||||
),
|
||||
});
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ import FAQ from "../Pages/ManageCMS/FAQ/FAQ";
|
||||
import AboutUs from "../Pages/ManageCMS/AboutUs/AboutUs";
|
||||
import PrivacyPolicy from "../Pages/ManageCMS/PrivacyPolicy/PrivacyPolicy";
|
||||
import TermsAndConditions from "../Pages/ManageCMS/TermsAndConditions/TermsAndConditions";
|
||||
import Privacy from "../Pages/ManageCMS/Privacy/Privacy";
|
||||
// import Privacy from "../Pages/ManageCMS/Privacy/Privacy";
|
||||
import MyProfile from "../Pages/MyProfile/MyProfile";
|
||||
import Notification from "../Pages/Notification/Notification";
|
||||
import AgencyMaster from "../Pages/MasterModule/AgencyMaster/AgencyMaster";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Icon, Image } from "@chakra-ui/react";
|
||||
import { Icon } from "@chakra-ui/react";
|
||||
import { Tooltip } from "../ui/tooltip";
|
||||
import { RiDeleteBin5Line } from "react-icons/ri";
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React from "react";
|
||||
|
||||
import { Bar } from "react-chartjs-2";
|
||||
import {
|
||||
Chart as ChartJS,
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
Tooltip,
|
||||
Legend,
|
||||
} from "chart.js";
|
||||
import { BiBorderRadius } from "react-icons/bi";
|
||||
// import { BiBorderRadius } from "react-icons/bi";
|
||||
|
||||
// ✅ Register the required components
|
||||
ChartJS.register(CategoryScale, LinearScale, BarElement, Title, Tooltip, Legend);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React from "react";
|
||||
|
||||
import { Doughnut } from "react-chartjs-2";
|
||||
import {
|
||||
Chart as ChartJS,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useState } from "react";
|
||||
import { useEffect, useState } from "react";
|
||||
import { HStack, Stack, Table } from "@chakra-ui/react";
|
||||
import { PaginationItems, PaginationNextTrigger, PaginationPrevTrigger, PaginationRoot } from "./ui/pagination";
|
||||
// import {
|
||||
@@ -25,6 +25,10 @@ const DataTable: React.FC<TableProps> = ({
|
||||
direction: "asc" | "desc";
|
||||
} | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
setSortedData(data);
|
||||
}, [data]);
|
||||
|
||||
const handleSort = (column: string) => {
|
||||
if (!sortableColumns.includes(column)) return;
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Field, Grid, Heading, Icon, Input, Span, Stack, Text } from "@chakra-ui/react";
|
||||
import { TbEdit } from "react-icons/tb";
|
||||
import { Field, Grid, Heading, Input, Span, Stack, Text } from "@chakra-ui/react";
|
||||
// import { TbEdit } from "react-icons/tb";
|
||||
import { Button } from "./ui/button";
|
||||
import { Checkbox } from "./ui/checkbox";
|
||||
import {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Center } from '@chakra-ui/react'
|
||||
import './Spinner.css'
|
||||
import MainFrame from '../MainFrame'
|
||||
// import MainFrame from '../MainFrame'
|
||||
export const Spinner = () =><Center boxShadow={'rgba(99, 99, 99, 0.2) 0px 2px 8px 0px'} rounded={'lg'} w={'100%'} h={'89vh'} bg={'#fff'} > <div className='loader'/></Center>
|
||||
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@ import type { ButtonProps, TextProps } from "@chakra-ui/react";
|
||||
import {
|
||||
Button,
|
||||
Pagination as ChakraPagination,
|
||||
HStack,
|
||||
IconButton,
|
||||
Text,
|
||||
createContext,
|
||||
@@ -151,7 +150,7 @@ export const PaginationNextTrigger = React.forwardRef<
|
||||
HTMLButtonElement,
|
||||
ChakraPagination.NextTriggerProps
|
||||
>(function PaginationNextTrigger(props, ref) {
|
||||
const { size, variantMap, getHref } = useRootProps();
|
||||
const { variantMap, getHref } = useRootProps();
|
||||
const { nextPage } = usePaginationContext();
|
||||
|
||||
if (getHref) {
|
||||
@@ -204,7 +203,7 @@ export const PaginationItems = (props: React.HTMLAttributes<HTMLElement>) => {
|
||||
<PaginationItem
|
||||
key={index}
|
||||
type="page"
|
||||
value={page.value}
|
||||
value={page.type === "page" ? page.value : 0}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
|
||||
27
src/components/ui/pin-input.tsx
Normal file
27
src/components/ui/pin-input.tsx
Normal file
@@ -0,0 +1,27 @@
|
||||
import { PinInput as ChakraPinInput, Group } from "@chakra-ui/react"
|
||||
import * as React from "react"
|
||||
|
||||
export interface PinInputProps extends ChakraPinInput.RootProps {
|
||||
rootRef?: React.Ref<HTMLDivElement>
|
||||
count?: number
|
||||
inputProps?: React.InputHTMLAttributes<HTMLInputElement>
|
||||
attached?: boolean
|
||||
}
|
||||
|
||||
export const PinInput = React.forwardRef<HTMLInputElement, PinInputProps>(
|
||||
function PinInput(props, ref) {
|
||||
const { count = 4, inputProps, rootRef, attached, ...rest } = props
|
||||
return (
|
||||
<ChakraPinInput.Root ref={rootRef} {...rest}>
|
||||
<ChakraPinInput.HiddenInput ref={ref} {...inputProps} />
|
||||
<ChakraPinInput.Control>
|
||||
<Group attached={attached}>
|
||||
{Array.from({ length: count }).map((_, index) => (
|
||||
<ChakraPinInput.Input key={index} index={index} />
|
||||
))}
|
||||
</Group>
|
||||
</ChakraPinInput.Control>
|
||||
</ChakraPinInput.Root>
|
||||
)
|
||||
},
|
||||
)
|
||||
@@ -10,24 +10,23 @@ import {
|
||||
} from "@chakra-ui/react"
|
||||
|
||||
export const toaster = createToaster({
|
||||
placement:'bottom',
|
||||
placement: "bottom-end",
|
||||
pauseOnPageIdle: true,
|
||||
max:1
|
||||
})
|
||||
|
||||
export const Toaster = () => {
|
||||
return (
|
||||
<Portal >
|
||||
<Portal>
|
||||
<ChakraToaster toaster={toaster} insetInline={{ mdDown: "4" }}>
|
||||
{(toast) => (
|
||||
<Toast.Root width={{ md: "sm" }}>
|
||||
<Toast.Root width={{ md: "sm" }}>
|
||||
{toast.type === "loading" ? (
|
||||
<Spinner size="sm" color="blue.solid" />
|
||||
) : (
|
||||
<Toast.Indicator />
|
||||
)}
|
||||
<Stack appearance={'light'} rounded={'full'} gap="1" flex="1" maxWidth="100%">
|
||||
{toast.title && <Toast.Title p={2} color="#02A0A0">{toast.title}</Toast.Title>}
|
||||
<Stack gap="1" flex="1" maxWidth="100%">
|
||||
{toast.title && <Toast.Title>{toast.title}</Toast.Title>}
|
||||
{toast.description && (
|
||||
<Toast.Description>{toast.description}</Toast.Description>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user