Compare commits
45 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
da9fc08a24 | ||
|
|
e2c17a3d4a | ||
|
|
0ecc030f20 | ||
|
|
5b37c9da1e | ||
|
|
9bfbf5ddb8 | ||
|
|
2e8f8d5a77 | ||
|
|
248980d24b | ||
|
|
8966295260 | ||
|
|
df62dcda64 | ||
|
|
44f34490a0 | ||
|
|
8efb309fa9 | ||
|
|
171a92a3dc | ||
|
|
ec021ee33c | ||
|
|
3aa9ebf619 | ||
|
|
8f19a41c57 | ||
|
|
638a68ff03 | ||
|
|
e5361a5d77 | ||
|
|
71c23a2125 | ||
|
|
abaae9603e | ||
|
|
7a3e76aa35 | ||
|
|
eaf8e77b79 | ||
|
|
2488ab98c0 | ||
|
|
6648cd3bf3 | ||
| d1cc504397 | |||
|
|
1e7b7347e4 | ||
|
|
32ccea4917 | ||
|
|
1fafdfe54d | ||
|
|
20a92a60ab | ||
|
|
284b5f3099 | ||
|
|
901dfb93a6 | ||
|
|
2805528ba3 | ||
|
|
a8a0e2ffef | ||
|
|
897572c1f1 | ||
|
|
03ab1dcd6f | ||
|
|
9d8278900d | ||
|
|
f65b5f9b2d | ||
|
|
ffda4cf04b | ||
|
|
f2d101ef16 | ||
|
|
b91c97c6c2 | ||
|
|
2a0517d8dc | ||
|
|
0c6238c843 | ||
|
|
49e8e5531f | ||
|
|
15c9cc1d94 | ||
|
|
cb7bdcdeb3 | ||
|
|
8106d505a0 |
15
.env
15
.env
@@ -1,15 +0,0 @@
|
||||
# VITE_API_URL='https://ssa.betadelivery.com/apia/v1'
|
||||
# # VITE_API_URL='http://192.16.50.44/seo-backend/apia/v1'
|
||||
# VITE_USER_NAME="Admin"
|
||||
# VITE_PASSWORD="71%@L%es^bUX94`J9XT*@bh,._WWM{$%^^&&"
|
||||
# VITE_APP_NAME=MyViteApp
|
||||
# VITE_IMG_TEMPLATES='https://ssa.betadelivery.com/storage/app/public/uploads/post_templates/'
|
||||
VITE_API_URL='https://ssa.betadelivery.com/testing/apia/v1'
|
||||
# VITE_API_URL='https://ssa.betadelivery.com/apia/v1'
|
||||
VITE_USER_NAME="Admin"
|
||||
VITE_PASSWORD="71%@L%es^bUX94`J9XT*@bh,._WWM{$%^^&&"
|
||||
# VITE_PASSWORD="71%@L%es^bUX94`J9XT*%4&^%tUU^%Q^ffgt"
|
||||
VITE_APP_NAME=MyViteApp
|
||||
VITE_IMG_TEMPLATES='https://ssa.betadelivery.com/testing/storage/app/public/uploads/post_templates/'
|
||||
VITE_MAIN_URL='https://ssa.betadelivery.com/testing'
|
||||
VITE_POST_IMG=`${VITE_MAIN_URL}/storage/app/public/uploads/post/`
|
||||
12
.env.testing
12
.env.testing
@@ -1,5 +1,7 @@
|
||||
# VITE_API_URL='https://ssa.betadelivery.com/testing/apia/'
|
||||
# VITE_USER_NAME="Admin"
|
||||
# VITE_PASSWORD="71%@L%es^bUX94`J9XT*@bh,._WWM{$%^^&&"
|
||||
# VITE_APP_NAME=MyViteApp
|
||||
# VITE_IMG_TEMPLATES='https://ssa.betadelivery.com/storage/app/public/uploads/post_templates/'
|
||||
VITE_API_URL='https://ssa.betadelivery.com/testing/apia/v1'
|
||||
VITE_USER_NAME="Admin"
|
||||
VITE_PASSWORD="71%@L%es^bUX94`J9XT*@bh,._WWM{$%^^&&"
|
||||
VITE_APP_NAME=MyViteApp
|
||||
VITE_IMG_TEMPLATES='https://ssa.betadelivery.com/storage/app/public/uploads/post_templates/'
|
||||
VITE_MAIN_URL='https://ssa.betadelivery.com/testing'
|
||||
VITE_POST_IMG=`${VITE_MAIN_URL}/storage/app/public/uploads/post/`
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -22,4 +22,4 @@ dist-ssr
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
.env
|
||||
*.env
|
||||
|
||||
@@ -82,7 +82,7 @@ define(['./workbox-54d0af47'], (function (workbox) { 'use strict';
|
||||
"revision": "3ca0b8505b4bec776b69afdba2768812"
|
||||
}, {
|
||||
"url": "index.html",
|
||||
"revision": "0.p75md0vraj"
|
||||
"revision": "0.73grfmd27h8"
|
||||
}], {});
|
||||
workbox.cleanupOutdatedCaches();
|
||||
workbox.registerRoute(new workbox.NavigationRoute(workbox.createHandlerBoundToURL("index.html"), {
|
||||
|
||||
@@ -7,6 +7,8 @@ export interface GlobalStateContextType {
|
||||
setIsAuthenticate: Dispatch<SetStateAction<boolean>>;
|
||||
isBarLoading: boolean;
|
||||
setIsBarLoading: Dispatch<SetStateAction<boolean>>;
|
||||
userAccess: string[];
|
||||
setUserAccess: Dispatch<SetStateAction<string[]>>;
|
||||
}
|
||||
// Create the context with a default value of `undefined`
|
||||
const GlobalStateContext = createContext<GlobalStateContextType | undefined>(undefined);
|
||||
|
||||
@@ -6,6 +6,10 @@ import GlobalStateContext from "./GlobalStateContext";
|
||||
const GlobalStateProvider = ({ children }: { children: ReactNode }) => {
|
||||
const [isAuthenticate, setIsAuthenticate] = useState<boolean>(true);
|
||||
const [isBarLoading, setIsBarLoading] = useState<boolean>(false); // ✅ Fixed typo
|
||||
const [userAccess, setUserAccess] = useState<string[]>(() => {
|
||||
const stored = sessionStorage.getItem('userAccess');
|
||||
return stored ? JSON.parse(stored) : [];
|
||||
});
|
||||
|
||||
|
||||
|
||||
@@ -15,6 +19,8 @@ const GlobalStateProvider = ({ children }: { children: ReactNode }) => {
|
||||
setIsAuthenticate,
|
||||
isBarLoading,
|
||||
setIsBarLoading, // ✅ Fixed typo
|
||||
userAccess,
|
||||
setUserAccess
|
||||
}}>
|
||||
{children}
|
||||
</GlobalStateContext.Provider>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { HStack, Image, Text, VStack } from "@chakra-ui/react";
|
||||
import React, { FC, useContext } from "react";
|
||||
import { RiNotificationLine } from "react-icons/ri";
|
||||
// import { RiNotificationLine } from "react-icons/ri";
|
||||
import { NavLink, useLocation, useNavigate } from "react-router-dom";
|
||||
import { nav } from "../Routes/Nav";
|
||||
import logo from '../assets/logo.svg';
|
||||
@@ -14,6 +14,8 @@ import { useLogOutMutation } from "../Redux/Service/apiSlice";
|
||||
import ProgressBar from "../components/ProgressBar/ProgressBar";
|
||||
import { useGetProfileQuery } from "../Redux/Service/profile.password";
|
||||
|
||||
const PROFILEIMGURL = import.meta.env.VITE_IMG_PROFILE
|
||||
|
||||
const DefaultLayout: FC<{ children: React.ReactNode }> = ({ children }) => {
|
||||
const { data } = useGetProfileQuery()
|
||||
const dispatch = useDispatch()
|
||||
@@ -25,9 +27,13 @@ const DefaultLayout: FC<{ children: React.ReactNode }> = ({ children }) => {
|
||||
if (!context) {
|
||||
throw new Error('App must be used within a GlobalStateProvider');
|
||||
}
|
||||
const { setIsAuthenticate, isBarLoading } = context;
|
||||
const { setIsAuthenticate, isBarLoading, userAccess } = context;
|
||||
const [logOutAdmin] = useLogOutMutation()
|
||||
|
||||
const filteredNav = nav.filter(item =>
|
||||
userAccess.includes('*') || !item.resourceTitle || userAccess.includes(item.resourceTitle)
|
||||
);
|
||||
|
||||
|
||||
// Logout function
|
||||
const handleLogout = async () => {
|
||||
@@ -57,7 +63,7 @@ const DefaultLayout: FC<{ children: React.ReactNode }> = ({ children }) => {
|
||||
<Image w={55} src={logo} />
|
||||
</HStack>
|
||||
<VStack w={'100%'} p={2} pt={0}>
|
||||
{nav?.map(({ title, path, Icon, type, children, initPath }, index) => type === 'single' ?
|
||||
{filteredNav?.map(({ title, path, Icon, type, children, initPath }, index) => type === 'single' ?
|
||||
<NavLink className="link" key={index} to={path || ''} style={{ cursor: 'pointer', borderRadius: '8px', padding: '6px', width: '100%', display: 'flex', alignItems: 'center', gap: 6, border: '1px solid #ffffff', backgroundColor: '#fff', color: '#000', boxShadow: 'rgba(99, 99, 99, 0.2) 0px 2px 8px 0px' }} ><Icon style={{ fontSize: '20px' }} /> <Text fontSize={'xs'} w={'100%'}>{title}</Text></NavLink> :
|
||||
<AccordionRoot border={location?.pathname.startsWith(initPath ?? path) ? "1px solid #02A0A0" : '1px'} key={index} bg={'#fff'} rounded={'lg'} collapsible>
|
||||
<AccordionItem rounded={'lg'} bg={'#fff'} boxShadow={'rgba(99, 99, 99, 0.2) 0px 2px 8px 0px'} borderBottom={'none'} p={0} key={index} value={title}>
|
||||
@@ -74,12 +80,12 @@ const DefaultLayout: FC<{ children: React.ReactNode }> = ({ children }) => {
|
||||
|
||||
<HStack h={'11%'} w={'100%'} justifyContent={'flex-end'} pe={3} gap={6}>
|
||||
|
||||
<NavLink to={'/manage-notification'}><RiNotificationLine color="#013e3e" cursor={'pointer'} style={{ fontSize: '22px' }} /></NavLink>
|
||||
{/* <NavLink to={'/manage-notification'}><RiNotificationLine color="#013e3e" cursor={'pointer'} style={{ fontSize: '22px' }} /></NavLink> */}
|
||||
<HStack cursor={'pointer'} onClick={() => navigate('/profile')} >
|
||||
<Avatar size={'sm'} src="https://i.pinimg.com/736x/d6/cd/0f/d6cd0ffd4634b0763d3958a7325ce26e.jpg" />
|
||||
<Avatar size={'sm'} src={`${PROFILEIMGURL}${data?.data.profile_photo}`} />
|
||||
<VStack color={'#013e3e'} gap={0} alignItems={'flex-start'}>
|
||||
<Text fontSize={'sm'} fontWeight={'bold'}>{`${data?.data?.first_name.charAt(0).toUpperCase()}${data?.data.first_name.slice(1)}`}</Text>
|
||||
<Text fontSize={'xs'} >{data?.data?.phone_number}</Text>
|
||||
<Text fontSize={'sm'} fontWeight={'bold'}>{data?.data?.first_name ? `${data?.data?.first_name.charAt(0).toUpperCase()}${data?.data.first_name.slice(1)}` : ''}</Text>
|
||||
<Text fontSize={'xs'} >{data?.data?.phone_number ? data?.data?.phone_number : ''}</Text>
|
||||
</VStack>
|
||||
</HStack>
|
||||
</HStack>
|
||||
|
||||
@@ -1,61 +1,68 @@
|
||||
import { Box, HStack, Image, Input, Stack, Text } from "@chakra-ui/react";
|
||||
import React, { useState, useEffect } from "react";
|
||||
import {
|
||||
Box,
|
||||
HStack,
|
||||
// Image, Input, Stack,
|
||||
Text
|
||||
} from "@chakra-ui/react";
|
||||
// import React, { useState, useEffect } from "react";
|
||||
import { Button } from "../../components/ui/button";
|
||||
import { IoAddSharp } from "react-icons/io5";
|
||||
import delateIcon from "../../assets/deleteIcon.png";
|
||||
import { FaClockRotateLeft } from "react-icons/fa6";
|
||||
// import { IoAddSharp } from "react-icons/io5";
|
||||
// import delateIcon from "../../assets/deleteIcon.png";
|
||||
// import { FaClockRotateLeft } from "react-icons/fa6";
|
||||
import { Link } from "react-router-dom";
|
||||
import { AgencyList } from "../../Redux/Service/dashBoard";
|
||||
|
||||
interface Todo {
|
||||
id: number;
|
||||
text: string;
|
||||
completed: boolean;
|
||||
timestamp: string;
|
||||
}
|
||||
// interface Todo {
|
||||
// id: number;
|
||||
// text: string;
|
||||
// completed: boolean;
|
||||
// timestamp: string;
|
||||
// }
|
||||
|
||||
const AgencyName: React.FC = () => {
|
||||
const [todos, setTodos] = useState<Todo[]>([]);
|
||||
const [input, setInput] = useState<string>("");
|
||||
|
||||
|
||||
const getCurrentTime = () => {
|
||||
const now = new Date();
|
||||
return now.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" });
|
||||
};
|
||||
const AgencyName = ({ agencyList }: { agencyList: AgencyList }) => {
|
||||
// const [todos, setTodos] = useState<Todo[]>([]);
|
||||
// const [input, setInput] = useState<string>("");
|
||||
|
||||
|
||||
const addTodo = () => {
|
||||
if (input.trim() === "") return;
|
||||
setTodos([...todos, { id: Date.now(), text: input, completed: false, timestamp: getCurrentTime() }]);
|
||||
setInput("");
|
||||
};
|
||||
// const getCurrentTime = () => {
|
||||
// const now = new Date();
|
||||
// return now.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" });
|
||||
// };
|
||||
|
||||
|
||||
// const addTodo = () => {
|
||||
// if (input.trim() === "") return;
|
||||
// setTodos([...todos, { id: Date.now(), text: input, completed: false, timestamp: getCurrentTime() }]);
|
||||
// setInput("");
|
||||
// };
|
||||
|
||||
// Delete a task
|
||||
const deleteTodo = (id: number) => {
|
||||
setTodos(todos.filter((todo) => todo.id !== id));
|
||||
};
|
||||
// const deleteTodo = (id: number) => {
|
||||
// setTodos(todos.filter((todo) => todo.id !== id));
|
||||
// };
|
||||
|
||||
useEffect(() => {
|
||||
const savedTodos = localStorage.getItem("todos");
|
||||
if (savedTodos) {
|
||||
setTodos(JSON.parse(savedTodos));
|
||||
}
|
||||
}, []); // Runs only on mount
|
||||
// useEffect(() => {
|
||||
// const savedTodos = localStorage.getItem("todos");
|
||||
// if (savedTodos) {
|
||||
// setTodos(JSON.parse(savedTodos));
|
||||
// }
|
||||
// }, []); // Runs only on mount
|
||||
|
||||
// 🔹 Save todos to localStorage whenever they change
|
||||
useEffect(() => {
|
||||
if (todos.length > 0) {
|
||||
localStorage.setItem("todos", JSON.stringify(todos));
|
||||
}
|
||||
}, [todos]); // Runs when `todos` changes
|
||||
// // 🔹 Save todos to localStorage whenever they change
|
||||
// useEffect(() => {
|
||||
// if (todos.length > 0) {
|
||||
// localStorage.setItem("todos", JSON.stringify(todos));
|
||||
// }
|
||||
// }, [todos]); // Runs when `todos` changes
|
||||
|
||||
|
||||
return (
|
||||
<Box p={"10px"}>
|
||||
<HStack justifyContent={"space-between"} mb={5}>
|
||||
<Text fontSize={"xs"} fontWeight={500}>
|
||||
Add Agency Name
|
||||
Agency List
|
||||
</Text>
|
||||
<Button
|
||||
{/* <Button
|
||||
bg={"#fff"}
|
||||
color={"#222222CC"}
|
||||
px={3}
|
||||
@@ -64,9 +71,18 @@ const AgencyName: React.FC = () => {
|
||||
onClick={addTodo}
|
||||
>
|
||||
<IoAddSharp /> Add
|
||||
</Button> */}
|
||||
<Button
|
||||
bg={"#fff"}
|
||||
color={"#222222CC"}
|
||||
px={3}
|
||||
fontSize={"12px"}
|
||||
h={"28px"}
|
||||
>
|
||||
<Link to="/master-module/agency-master">View ALL</Link>
|
||||
</Button>
|
||||
</HStack>
|
||||
<Input
|
||||
{/* <Input
|
||||
type="text"
|
||||
value={input}
|
||||
onChange={(e) => setInput(e.target.value)}
|
||||
@@ -76,14 +92,14 @@ const AgencyName: React.FC = () => {
|
||||
w={"100%"}
|
||||
p={2}
|
||||
mb={4}
|
||||
/>
|
||||
{todos.map((todo) => (
|
||||
/> */}
|
||||
{agencyList?.data.map((todo) => (
|
||||
<HStack key={todo.id} backgroundColor={"#fff"} rounded={5} mb={3} p={4} justifyContent={'space-between'} alignItems={'inherit'}>
|
||||
<Text fontSize={'sm'} color={'#222222bd'} fontWeight={400}>{todo.text}</Text>
|
||||
<Stack display={'flex'} alignItems={'end'} w={'130px'}>
|
||||
<Text fontSize={'sm'} color={'#222222bd'} fontWeight={400}>{todo.name}</Text>
|
||||
{/* <Stack display={'flex'} alignItems={'end'} w={'130px'}>
|
||||
<Box display={'flex'} alignItems={'center'} gap={2}>
|
||||
<FaClockRotateLeft fontSize={'10px'} style={{fontSize:'13px',color:'#222222bd'}} />
|
||||
<Text fontSize={"xs"} color={"#222222bd"}>{todo.timestamp}</Text>
|
||||
<FaClockRotateLeft fontSize={'10px'} style={{ fontSize: '13px', color: '#222222bd' }} />
|
||||
<Text fontSize={"xs"} color={"#222222bd"}>{todo.timestamp}</Text>
|
||||
</Box>
|
||||
<Box
|
||||
onClick={() => deleteTodo(todo.id)}
|
||||
@@ -93,7 +109,7 @@ const AgencyName: React.FC = () => {
|
||||
>
|
||||
<Image w={"16px"} src={delateIcon} />
|
||||
</Box>
|
||||
</Stack>
|
||||
</Stack> */}
|
||||
</HStack>
|
||||
))}
|
||||
</Box>
|
||||
|
||||
@@ -26,8 +26,31 @@ import {
|
||||
SelectValueText
|
||||
} from "../../components/ui/select";
|
||||
import AgencyName from "./AgencyName";
|
||||
import { useGetAgencyListQuery, useGetFaqListQuery, useGetNewUserQuery, useGetPastUserQuery, useGetTotalUserQuery } from "../../Redux/Service/dashBoard";
|
||||
import { useEffect, useState } from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
|
||||
const Dashboard = () => {
|
||||
const { data: totalUsers } = useGetTotalUserQuery()
|
||||
const { data: pastUsers } = useGetPastUserQuery()
|
||||
const { data: newUsers } = useGetNewUserQuery()
|
||||
const {data: agencyList} = useGetAgencyListQuery()
|
||||
const { data: faqList } = useGetFaqListQuery()
|
||||
const [activeTab, setActiveTab] = useState("tab-1");
|
||||
const [totalUser, setTotalUser] = useState<any>(null);
|
||||
|
||||
console.log("data", totalUser)
|
||||
|
||||
useEffect(() => {
|
||||
if (activeTab === "tab-1") {
|
||||
setTotalUser( pastUsers?.data)
|
||||
} else if (activeTab === "tab-2") {
|
||||
setTotalUser(totalUsers?.data)
|
||||
} else if (activeTab === "tab-3") {
|
||||
setTotalUser(newUsers?.data)
|
||||
}
|
||||
}, [totalUsers?.data, pastUsers?.data, newUsers?.data, activeTab]);
|
||||
|
||||
const frameworks = createListCollection({
|
||||
items: [
|
||||
{ label: "Today", value: "Today" },
|
||||
@@ -37,35 +60,35 @@ const Dashboard = () => {
|
||||
],
|
||||
});
|
||||
|
||||
const accItems = [
|
||||
{
|
||||
value: "1",
|
||||
title: "How to create new account?",
|
||||
text: "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since. Lorem Ipsum has been the industry's standard dummy text ever since.",
|
||||
},
|
||||
{
|
||||
value: "2",
|
||||
title: "How to create new account?",
|
||||
text: "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since. Lorem Ipsum has been the industry's standard dummy text ever since.",
|
||||
},
|
||||
{
|
||||
value: "3",
|
||||
title: "How to create new account?",
|
||||
text: "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since. Lorem Ipsum has been the industry's standard dummy text ever since.",
|
||||
},
|
||||
{
|
||||
value: "4",
|
||||
title: "How to create new account?",
|
||||
text: "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since. Lorem Ipsum has been the industry's standard dummy text ever since.",
|
||||
},
|
||||
];
|
||||
// const accItems = [
|
||||
// {
|
||||
// value: "1",
|
||||
// title: "How to create new account?",
|
||||
// text: "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since. Lorem Ipsum has been the industry's standard dummy text ever since.",
|
||||
// },
|
||||
// {
|
||||
// value: "2",
|
||||
// title: "How to create new account?",
|
||||
// text: "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since. Lorem Ipsum has been the industry's standard dummy text ever since.",
|
||||
// },
|
||||
// {
|
||||
// value: "3",
|
||||
// title: "How to create new account?",
|
||||
// text: "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since. Lorem Ipsum has been the industry's standard dummy text ever since.",
|
||||
// },
|
||||
// {
|
||||
// value: "4",
|
||||
// title: "How to create new account?",
|
||||
// text: "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since. Lorem Ipsum has been the industry's standard dummy text ever since.",
|
||||
// },
|
||||
// ];
|
||||
|
||||
return (
|
||||
<MainFrame>
|
||||
<Box display={"flex"} p={"20px"} pe={'20px'} gap={5}>
|
||||
<Box display={"flex"} p={"20px"} pe={'20px'} gap={5}>
|
||||
<Box rounded={'lg'} w={"30%"} boxShadow={"rgba(99, 99, 99, 0.2) 0px 2px 8px 0px"}>
|
||||
<Heading fontSize={"sm"} p={2}>
|
||||
Total Users
|
||||
Total Users : {totalUsers?.data?.totalUserCount ?? 0}
|
||||
</Heading>
|
||||
<Tabs.Root
|
||||
size={"sm"}
|
||||
@@ -74,6 +97,8 @@ const Dashboard = () => {
|
||||
variant="enclosed"
|
||||
fitted
|
||||
defaultValue={"tab-1"}
|
||||
value={activeTab}
|
||||
onValueChange={(details) => setActiveTab(details.value)}
|
||||
mb={6}
|
||||
>
|
||||
<Tabs.List>
|
||||
@@ -89,7 +114,7 @@ const Dashboard = () => {
|
||||
</Tabs.List>
|
||||
</Tabs.Root>
|
||||
<Box>
|
||||
<SemiDoughnutChart />
|
||||
{totalUser && <SemiDoughnutChart totalUser={totalUser} />}
|
||||
</Box>
|
||||
|
||||
<Box
|
||||
@@ -101,11 +126,11 @@ const Dashboard = () => {
|
||||
>
|
||||
<Status.Root colorPalette="blue">
|
||||
<Status.Indicator />
|
||||
Recruiter <Text fontWeight={500}>2554</Text>
|
||||
Recruiter <Text fontWeight={500}>{totalUser?.past24hourRecruiterCount ?? totalUser?.totalRecruiterCount ?? totalUser?.newRecuiterCount }</Text>
|
||||
</Status.Root>
|
||||
<Status.Root colorPalette="blue">
|
||||
<Status.Indicator />
|
||||
Customer <Text fontWeight={500}>1224</Text>
|
||||
Customer <Text fontWeight={500}>{totalUser?.past24hourCustomercount ?? totalUser?.totalCustomerCount ?? totalUser?.newCustomerCount}</Text>
|
||||
</Status.Root>
|
||||
</Box>
|
||||
</Box>
|
||||
@@ -142,8 +167,8 @@ const Dashboard = () => {
|
||||
<CircularApp />
|
||||
</Box>
|
||||
</Box>
|
||||
<Box p={"20px"} pt={0} display={"flex"} gap={5}>
|
||||
<Box w={"50%"} rounded={'lg'} bg={"#f2f2f2"} h={'100%'} p={"10px"} overflow={'auto'}>
|
||||
<Box p={"20px"} pt={0} display={"flex"} gap={5}>
|
||||
<Box w={"50%"} rounded={'lg'} bg={"#f2f2f2"} h={'100%'} p={"10px"} overflowY={'scroll'} height={'292px'}>
|
||||
<HStack justifyContent={"space-between"} mb={5}>
|
||||
<Text fontSize={"xs"} fontWeight={500}>Faqs</Text>
|
||||
<Button
|
||||
@@ -153,15 +178,15 @@ const Dashboard = () => {
|
||||
fontSize={"12px"}
|
||||
h={"28px"}
|
||||
>
|
||||
View ALL
|
||||
<Link to="/manage-cms/faq">View ALL</Link>
|
||||
</Button>
|
||||
</HStack>
|
||||
<AccordionRoot collapsible defaultValue={["b"]}>
|
||||
{accItems.map((item, index) => (
|
||||
{faqList?.data.map((item) => (
|
||||
<AccordionItem
|
||||
boxShadow={'rgba(99, 99, 99, 0.2) 0px 2px 8px 0px'}
|
||||
key={index}
|
||||
value={item.value}
|
||||
boxShadow={'rgba(99, 99, 99, 0.2) 0px 2px 8px 0px'}
|
||||
key={item.id}
|
||||
value={item.faqs_xid.toString()}
|
||||
bg={"#fff"}
|
||||
mb={2}
|
||||
p={"12px"}
|
||||
@@ -169,17 +194,17 @@ const Dashboard = () => {
|
||||
borderBottom={0}
|
||||
>
|
||||
<AccordionItemTrigger fontSize={"sm"} >
|
||||
{item.title}
|
||||
{item.question}
|
||||
</AccordionItemTrigger>
|
||||
<AccordionItemContent fontSize={"xs"} color={'#222222CC'} pt={2}>
|
||||
{item.text}
|
||||
{item.answer}
|
||||
</AccordionItemContent>
|
||||
</AccordionItem>
|
||||
))}
|
||||
</AccordionRoot>
|
||||
</Box>
|
||||
<Box w={"50%"} rounded={'lg'} bg={"#f2f2f2"} h={'100%'} overflow={'auto'}>
|
||||
<AgencyName />
|
||||
<Box w={"50%"} rounded={'lg'} bg={"#f2f2f2"} alignItems={'flex-start'} overflowY={'scroll'} height={'292px'}>
|
||||
{agencyList && <AgencyName agencyList={agencyList}/>}
|
||||
</Box>
|
||||
</Box>
|
||||
</MainFrame>
|
||||
|
||||
@@ -34,7 +34,7 @@ const Login = () => {
|
||||
if (!context) {
|
||||
throw new Error("App must be used within a GlobalStateProvider");
|
||||
}
|
||||
const { setIsAuthenticate } = context;
|
||||
const { setIsAuthenticate, setUserAccess } = context;
|
||||
const {
|
||||
register,
|
||||
handleSubmit,
|
||||
@@ -43,10 +43,10 @@ const Login = () => {
|
||||
|
||||
const onSubmit = handleSubmit(async (data) => {
|
||||
setIsLoading(true);
|
||||
// Encode Basic Auth Credentials
|
||||
const username = import.meta.env.VITE_USER_NAME || ""; // Replace with actual username
|
||||
const password = import.meta.env.VITE_PASSWORD || ""; // Replace with actual password
|
||||
const basicAuth = `${username}:${password}`; // Encode to Base64
|
||||
|
||||
const username = import.meta.env.VITE_USER_NAME || "";
|
||||
const password = import.meta.env.VITE_PASSWORD || "";
|
||||
const basicAuth = `${username}:${password}`;
|
||||
|
||||
try {
|
||||
const res = await axios.post(
|
||||
@@ -62,35 +62,36 @@ const Login = () => {
|
||||
},
|
||||
}
|
||||
);
|
||||
console.log("============", res);
|
||||
|
||||
const loginData = res.data?.data;
|
||||
const { principal_type_xid, role_permission } = loginData;
|
||||
|
||||
const isAdmin = principal_type_xid === 1;
|
||||
|
||||
const allowedTitles = isAdmin
|
||||
? ['*']
|
||||
: role_permission?.get_resource_action_link
|
||||
?.filter((link: unknown) => (link as any).is_active)
|
||||
.map((link: unknown) => (link as any).app_resource.app_resource_title) ?? [];
|
||||
|
||||
setIsAuthenticate(true);
|
||||
setUserAccess(allowedTitles);
|
||||
dispatch(setToken(String(loginData["access-token"])));
|
||||
sessionStorage.setItem('userAccess', JSON.stringify(allowedTitles));
|
||||
navigate("/dashboard");
|
||||
setIsLoading(false);
|
||||
|
||||
if (res.data) {
|
||||
setIsAuthenticate(true);
|
||||
console.log("====================================");
|
||||
console.log(res.data?.data);
|
||||
console.log("====================================");
|
||||
navigate("/dashboard");
|
||||
dispatch(setToken(String(res.data?.data["access-token"])));
|
||||
} else {
|
||||
console.log("====================================");
|
||||
console.log(res);
|
||||
console.log("====================================");
|
||||
}
|
||||
} catch (error: any) {
|
||||
console.log('error', error.response.data.message);
|
||||
|
||||
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);
|
||||
}
|
||||
console.log('error', error?.response?.data?.message);
|
||||
toaster.create({
|
||||
title: "Error",
|
||||
description: error?.response?.data?.message || "Login failed",
|
||||
type: "error",
|
||||
});
|
||||
setIsLoading(false);
|
||||
}
|
||||
});
|
||||
// console.log("User Access in Context:", userAccess);
|
||||
|
||||
return (
|
||||
|
||||
|
||||
@@ -16,12 +16,13 @@ import "react-quill/dist/quill.snow.css"; // Import the styles
|
||||
import { useState } from "react";
|
||||
import { useUpdateAboutUsMutation } from "../../../Redux/Service/manage.aboutus.service";
|
||||
import { useForm, Controller } from "react-hook-form"; // Import React Hook Form
|
||||
import { toaster, Toaster } from "../../../components/ui/toaster";
|
||||
|
||||
function AboutUsAddModel({ aboutUsData }: { aboutUsData: any }) {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
|
||||
// RTK Query Mutation Hook
|
||||
const [updateAboutUs] = useUpdateAboutUsMutation();
|
||||
const [updateAboutUs, { isLoading }] = useUpdateAboutUsMutation();
|
||||
|
||||
// React Hook Form
|
||||
const {
|
||||
@@ -55,87 +56,96 @@ function AboutUsAddModel({ aboutUsData }: { aboutUsData: any }) {
|
||||
}).unwrap();
|
||||
setIsOpen(false); // Close dialog on success
|
||||
reset(); // Reset the form
|
||||
} catch (error) {
|
||||
} catch (error: any) {
|
||||
console.error("Update failed:", error);
|
||||
toaster.create({
|
||||
title: "Error",
|
||||
description: `${error.data.message || "Failed to update"}`,
|
||||
type: "error",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<DialogRoot placement="center" open={isOpen}>
|
||||
<DialogTrigger asChild>
|
||||
<Button
|
||||
bgColor="#EEEEEE"
|
||||
pl={3}
|
||||
pr={3}
|
||||
size="xs"
|
||||
color="#000"
|
||||
onClick={() => handleEditClick(aboutUsData)} // Set content before opening modal
|
||||
>
|
||||
<FaRegEdit color="#000" style={{ height: "14px", width: "14px" }} />
|
||||
<Text color="#000" mt={1}>Edit</Text>
|
||||
</Button>
|
||||
</DialogTrigger>
|
||||
|
||||
<DialogContent bg="#fff" w={{ base: "90%", md: "1200px" }} height="auto" p={3}>
|
||||
<DialogHeader bg="white">
|
||||
<DialogTitle alignSelf="center" color="black" fontSize="14px">
|
||||
Edit About Us
|
||||
</DialogTitle>
|
||||
</DialogHeader>
|
||||
|
||||
<DialogBody bg="white">
|
||||
<Stack py={3} mb={8}>
|
||||
<Field.Root>
|
||||
<Field.Label color="black" pt={1} fontSize="12px">
|
||||
About Us Content
|
||||
</Field.Label>
|
||||
{/* Use Controller to integrate ReactQuill with React Hook Form */}
|
||||
<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">
|
||||
<>
|
||||
<DialogRoot placement="center" open={isOpen}>
|
||||
<DialogTrigger asChild>
|
||||
<Button
|
||||
w="100%"
|
||||
bg="#02A0A0"
|
||||
color="#fff"
|
||||
// isLoading={isLoading}
|
||||
onClick={handleSubmit(onSubmit)} // Use handleSubmit to trigger form submission
|
||||
bgColor="#EEEEEE"
|
||||
pl={3}
|
||||
pr={3}
|
||||
size="xs"
|
||||
color="#000"
|
||||
onClick={() => handleEditClick(aboutUsData)} // Set content before opening modal
|
||||
>
|
||||
Save
|
||||
<FaRegEdit color="#000" style={{ height: "14px", width: "14px" }} />
|
||||
<Text color="#000" mt={1}>Edit</Text>
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</DialogTrigger>
|
||||
|
||||
<DialogCloseTrigger color="black" onClick={() => setIsOpen(false)} />
|
||||
</DialogContent>
|
||||
</DialogRoot>
|
||||
<DialogContent bg="#fff" w={{ base: "90%", md: "1200px" }} height="auto" p={3}>
|
||||
<DialogHeader bg="white">
|
||||
<DialogTitle alignSelf="center" color="black" fontSize="14px">
|
||||
Edit About Us
|
||||
</DialogTitle>
|
||||
</DialogHeader>
|
||||
|
||||
<DialogBody bg="white">
|
||||
<Stack py={3} mb={8}>
|
||||
<Field.Root>
|
||||
<Field.Label color="black" pt={1} fontSize="12px">
|
||||
About Us Content
|
||||
</Field.Label>
|
||||
{/* Use Controller to integrate ReactQuill with React Hook Form */}
|
||||
<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"
|
||||
// isLoading={isLoading}
|
||||
disabled={isLoading}
|
||||
onClick={handleSubmit(onSubmit)} // Use handleSubmit to trigger form submission
|
||||
>
|
||||
Save
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
|
||||
<DialogCloseTrigger color="black" onClick={() => setIsOpen(false)} />
|
||||
</DialogContent>
|
||||
</DialogRoot>
|
||||
<Toaster />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ function EditDetails({ rowData, refetch }: {rowData: RowData, refetch: VoidFunct
|
||||
const [faqQuestion, setFaqQuestion] = useState(rowData?.question);
|
||||
const [faqAnswer, setFaqAnswer] = useState(rowData?.answer);
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [updateFaq] = useUpdateFaqMutation()
|
||||
const [updateFaq, { isLoading }] = useUpdateFaqMutation()
|
||||
|
||||
// console.log('ROWDATA', rowData);
|
||||
|
||||
@@ -146,7 +146,7 @@ function EditDetails({ rowData, refetch }: {rowData: RowData, refetch: VoidFunct
|
||||
</DialogBody>
|
||||
|
||||
<DialogFooter display="flex" justifyContent="center" pt={"2"}>
|
||||
<Button w="100%" bg="#02A0A0" color={"#fff"} onClick={handleSubmit}>
|
||||
<Button w="100%" bg="#02A0A0" color={"#fff"} onClick={handleSubmit} disabled={isLoading}>
|
||||
Save
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
|
||||
@@ -54,7 +54,7 @@ const tableHeadRow = [
|
||||
|
||||
const FAQ = () => {
|
||||
const [currentPage, setCurrentPage] = useState(1);
|
||||
const { data, refetch, isLoading, isFetching } = useGetFaqQuery(currentPage)
|
||||
const { data, refetch, isLoading, isFetching, isError } = useGetFaqQuery(currentPage)
|
||||
const [localData, setLocalData] = useState<any[]>([]);
|
||||
const [faqToggle] = useFaqToggleMutation()
|
||||
const [deleteFaqPost] = useDeleteFaqPostMutation()
|
||||
@@ -85,9 +85,21 @@ const FAQ = () => {
|
||||
|
||||
try {
|
||||
await faqToggle({ id: agencyId, is_active: newStatus }).unwrap();
|
||||
refetch()
|
||||
toaster.create({
|
||||
title: "Success",
|
||||
description: "Status updated successfully",
|
||||
type: "success",
|
||||
});
|
||||
setTimeout(() => {
|
||||
refetch();
|
||||
}, 500);
|
||||
} catch (error) {
|
||||
console.error("Error updating privacy policy:", error);
|
||||
toaster.create({
|
||||
title: "Error",
|
||||
description: "Someting went wrong.",
|
||||
type: "error",
|
||||
});
|
||||
setLocalData((prevData) =>
|
||||
prevData.map((agency) =>
|
||||
agency.id === agencyId ? { ...agency, is_active: currentStatus } : agency
|
||||
@@ -160,7 +172,7 @@ const FAQ = () => {
|
||||
handleDeleteFaq(selectedFaqId);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
/>
|
||||
<Box>
|
||||
<Switch
|
||||
colorPalette={'teal'}
|
||||
@@ -225,6 +237,8 @@ const FAQ = () => {
|
||||
total: data?.data.total || 0
|
||||
}}
|
||||
onPageChange={handlePageChange}
|
||||
isLoading={isFetching}
|
||||
isError={isError}
|
||||
/>)}
|
||||
</Box>
|
||||
<Toaster />
|
||||
|
||||
@@ -20,7 +20,7 @@ function FaqAddModel({ refetch }: { refetch: VoidFunction }) {
|
||||
const [faqAnswer, setFaqAnswer] = useState('');
|
||||
const [userType, setUserType] = useState("");
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [createFaqPost] = useCreateFaqPostMutation()
|
||||
const [createFaqPost, { isLoading }] = useCreateFaqPostMutation()
|
||||
|
||||
const handleOpenModal = () => {
|
||||
setIsOpen(true); // Open modal when clicking "Add"
|
||||
@@ -159,7 +159,7 @@ function FaqAddModel({ refetch }: { refetch: VoidFunction }) {
|
||||
</Stack>
|
||||
</DialogBody>
|
||||
<DialogFooter display="flex" justifyContent="center" pt={"2"}>
|
||||
<Button w="100%" bg="#02A0A0" color={"#fff"} onClick={handleSubmit}>
|
||||
<Button w="100%" bg="#02A0A0" color={"#fff"} onClick={handleSubmit} disabled={isLoading}>
|
||||
Save
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
|
||||
@@ -16,7 +16,7 @@ import ReactQuill from "react-quill";
|
||||
|
||||
function PrivacyPolicyAddModel({ policyData, refetch }: { policyData: any, refetch: VoidFunction }) {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [updatePrivacyPolicy] = useUpdatePrivacyPolicyMutation()
|
||||
const [updatePrivacyPolicy, { isLoading }] = useUpdatePrivacyPolicyMutation()
|
||||
const {
|
||||
control,
|
||||
handleSubmit,
|
||||
@@ -139,7 +139,7 @@ function PrivacyPolicyAddModel({ policyData, refetch }: { policyData: any, refet
|
||||
</Stack>
|
||||
</DialogBody>
|
||||
<DialogFooter display="flex" justifyContent="center" pt={"2"}>
|
||||
<Button w="100%" bg="#02A0A0" color={"#fff"} mt={'4'} onClick={handleSubmit(onSubmit)}>
|
||||
<Button w="100%" bg="#02A0A0" color={"#fff"} mt={'4'} onClick={handleSubmit(onSubmit)} disabled={isLoading}>
|
||||
Save
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
|
||||
@@ -18,7 +18,7 @@ import { useUpdateTermsMutation } from "../../../Redux/Service/terms.and.conditi
|
||||
|
||||
function TermsAndConditionsAddModel({ termsData, refetch }: { termsData: any, refetch: VoidFunction }) {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [updateTerms] = useUpdateTermsMutation()
|
||||
const [updateTerms, { isLoading }] = useUpdateTermsMutation()
|
||||
const {
|
||||
control,
|
||||
handleSubmit,
|
||||
@@ -136,7 +136,7 @@ function TermsAndConditionsAddModel({ termsData, refetch }: { termsData: any, re
|
||||
</Stack>
|
||||
</DialogBody>
|
||||
<DialogFooter display="flex" justifyContent="center" pt={"2"}>
|
||||
<Button w="100%" bg="#02A0A0" color={"#fff"} mt={'4'} onClick={handleSubmit(onSubmit)}>
|
||||
<Button w="100%" bg="#02A0A0" color={"#fff"} mt={'4'} onClick={handleSubmit(onSubmit)} disabled={isLoading}>
|
||||
Save
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
|
||||
@@ -1,19 +1,26 @@
|
||||
import { Box, HStack, Input, Text } from "@chakra-ui/react";
|
||||
import { Box, HStack, Text } from "@chakra-ui/react";
|
||||
import MainFrame from "../../components/MainFrame";
|
||||
import PendingRequests from "../../Pages/ManageContact/PendingRequests";
|
||||
import { InputGroup } from "../../components/ui/input-group";
|
||||
import { LuSearch } from "react-icons/lu";
|
||||
// import { InputGroup } from "../../components/ui/input-group";
|
||||
// import { LuSearch } from "react-icons/lu";
|
||||
import DataTable from "../../components/DataTable";
|
||||
import { useGetContactQuery } from "../../Redux/Service/manage.contactus.service";
|
||||
import { useEffect, useState } from "react";
|
||||
import { Spinner } from "../../components/Sipnner/Spinner";
|
||||
import { useDebounce } from "../../components/Hooks/useDebounce";
|
||||
import SearchComponent from "../../components/SearchComponent";
|
||||
|
||||
// table data
|
||||
const tableHeadRow = ["Sr. No", "Email id", "Name", "Date", "Action"];
|
||||
|
||||
const ManageContact = () => {
|
||||
const { data, isLoading, isError } = useGetContactQuery();
|
||||
const [localData, setLocalData] = useState([]);
|
||||
const [currentPage, setCurrentPage] = useState(1);
|
||||
const [localData, setLocalData] = useState<any[]>([]);
|
||||
const [searchTerm, setSearchTerm] = useState("");
|
||||
const debouncedSearchTerm = useDebounce(searchTerm, 500);
|
||||
const queryArgs = debouncedSearchTerm ? { page: currentPage, search: debouncedSearchTerm } : { page: currentPage };
|
||||
const { data, isLoading, isError, refetch, isFetching } = useGetContactQuery(queryArgs);
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
if (data) {
|
||||
@@ -21,6 +28,20 @@ const ManageContact = () => {
|
||||
}
|
||||
}, [data]);
|
||||
|
||||
const handlePageChange = (page: number) => {
|
||||
setCurrentPage(page);
|
||||
};
|
||||
|
||||
const handleSearchChange = (value: string) => {
|
||||
setSearchTerm(value);
|
||||
setCurrentPage(1);
|
||||
};
|
||||
|
||||
const filteredData = localData?.filter((agency) =>
|
||||
agency?.first_name.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
||||
agency?.email.toLowerCase().includes(searchTerm.toLowerCase())
|
||||
);
|
||||
|
||||
const formatDateOfBirth = (dob: string): string => {
|
||||
return new Date(dob).toLocaleDateString("en-GB", {
|
||||
day: "2-digit",
|
||||
@@ -29,14 +50,15 @@ const ManageContact = () => {
|
||||
});
|
||||
};
|
||||
|
||||
const managepost = localData?.map((agency: any, index: number) => ({
|
||||
const managepost = filteredData?.map((agency: any, index: number) => ({
|
||||
"Sr. No": index + 1, // Typically Sr. No starts from 1, not using id which might not be sequential
|
||||
"Email id": agency?.email || "-",
|
||||
Name: agency?.first_name || "-",
|
||||
Date: formatDateOfBirth(agency?.created_at) || "-",
|
||||
Action: (
|
||||
<HStack justifyContent="center">
|
||||
<PendingRequests />
|
||||
Action: (
|
||||
<HStack justifyContent="center" cursor={agency.response_status === 0 ? 'pointer' : 'default'}>
|
||||
{agency.response_status === 0 ? <PendingRequests data={agency} refetch={refetch} /> : 'Resolved'}
|
||||
{/* <PendingRequests data={agency} refetch={refetch} /> */}
|
||||
</HStack>
|
||||
),
|
||||
}));
|
||||
@@ -86,35 +108,25 @@ const ManageContact = () => {
|
||||
</Text>
|
||||
|
||||
<HStack>
|
||||
<InputGroup
|
||||
startElement={
|
||||
<LuSearch
|
||||
fontSize={"xs"}
|
||||
style={{ position: "relative", left: "10px" }}
|
||||
/>
|
||||
}
|
||||
color={"#000"}
|
||||
>
|
||||
<Input
|
||||
p={3}
|
||||
w={300}
|
||||
bg={"#fff"}
|
||||
colorPalette={"blue"}
|
||||
_focus={{ border: "1px solid #02A0A0" }}
|
||||
rounded={"md"}
|
||||
size={"xs"}
|
||||
fontSize={"sm"}
|
||||
placeholder="Search..."
|
||||
bgColor={"#EEEEEE"}
|
||||
ps={8}
|
||||
/>
|
||||
</InputGroup>
|
||||
<SearchComponent
|
||||
value={searchTerm}
|
||||
onChange={handleSearchChange}
|
||||
/>
|
||||
</HStack>
|
||||
</HStack>
|
||||
<DataTable
|
||||
sortableColumns={["Name", "Registration Date "]}
|
||||
tableHeadRow={tableHeadRow}
|
||||
data={managepost || []} // Ensure an empty array is passed if managepost is undefined
|
||||
paginationData={{
|
||||
current_page: (data?.data as any)?.current_page || 1,
|
||||
last_page: (data?.data as any)?.last_page || 1,
|
||||
per_page: (data?.data as any)?.per_page || 10,
|
||||
total: (data?.data as any)?.total || 0
|
||||
}}
|
||||
onPageChange={handlePageChange}
|
||||
isLoading={isFetching}
|
||||
isError={isError}
|
||||
/>
|
||||
</Box>
|
||||
</MainFrame>
|
||||
|
||||
@@ -10,95 +10,160 @@ import {
|
||||
DialogTrigger,
|
||||
} from "../../components/ui/dialog";
|
||||
import { Badge, Field, HStack, Input, Stack, Textarea } from "@chakra-ui/react";
|
||||
function PendingRequests() {
|
||||
import { usePendingRequestMutation } from "../../Redux/Service/manage.contactus.service";
|
||||
import { useState } from "react";
|
||||
import { Toaster, toaster } from "../../components/ui/toaster";
|
||||
|
||||
function PendingRequests({ data, refetch }: { data: any, refetch: VoidFunction }) {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [res, setRes] = useState({
|
||||
contact_us_xid: data.id,
|
||||
message: data.message,
|
||||
solution: '',
|
||||
})
|
||||
const [pendingRequest, { isLoading }] = usePendingRequestMutation()
|
||||
|
||||
const handleOpenModal = () => {
|
||||
setIsOpen(true);
|
||||
};
|
||||
|
||||
|
||||
const handleSubmit = async (status: string) => {
|
||||
const payload = { ...res, response_status: status };
|
||||
|
||||
if(res.solution === ''){
|
||||
toaster.create({
|
||||
title: "Error",
|
||||
description: "All fields are required",
|
||||
type: "error",
|
||||
});
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const response = await pendingRequest(payload).unwrap()
|
||||
if (response?.status === "success") {
|
||||
toaster.create({
|
||||
title: "Success",
|
||||
description: "Country updated successfully",
|
||||
type: "success",
|
||||
});
|
||||
setIsOpen(false);
|
||||
refetch()
|
||||
} else {
|
||||
toaster.create({
|
||||
title: "Error",
|
||||
description: "Failed to update Country",
|
||||
type: "error",
|
||||
});
|
||||
}
|
||||
} catch (error: any) {
|
||||
toaster.create({
|
||||
title: "Error",
|
||||
description: error?.data?.message || "Something went wrong",
|
||||
type: "error",
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<DialogRoot placement="center">
|
||||
<DialogTrigger asChild>
|
||||
<Badge fontSize={"xs"} px={2} bg={'#02a0a01f'}>
|
||||
Answer request
|
||||
</Badge>
|
||||
</DialogTrigger>
|
||||
<>
|
||||
<DialogRoot placement="center" key={data.id} open={isOpen} onOpenChange={({ open }) => setIsOpen(open)}>
|
||||
<DialogTrigger asChild>
|
||||
<Badge fontSize={"xs"} px={2} bg={'#02a0a01f'} onClick={handleOpenModal}>
|
||||
Answer request
|
||||
</Badge>
|
||||
</DialogTrigger>
|
||||
|
||||
<DialogContent
|
||||
bg={"#fff"}
|
||||
w={{ base: "90%", md: "400px" }}
|
||||
height={"auto"}
|
||||
p={3} // Reduced padding
|
||||
bgSize={"md"}
|
||||
>
|
||||
<DialogHeader bg="white">
|
||||
<DialogTitle alignSelf="center" color="black" fontSize="14px">
|
||||
Pending Requests
|
||||
</DialogTitle>
|
||||
</DialogHeader>
|
||||
|
||||
<DialogBody bg="white">
|
||||
<Stack py={3}>
|
||||
<Field.Root>
|
||||
<Field.Label color="black" pt={1} fontSize="12px">
|
||||
Request Type
|
||||
</Field.Label>
|
||||
<Input
|
||||
placeholder="Message"
|
||||
bgColor="#EEEEEE"
|
||||
color="black"
|
||||
border="none"
|
||||
pl={1}
|
||||
fontSize="12px"
|
||||
height="30px"
|
||||
/>
|
||||
|
||||
<Field.Label color="black" pt={1} fontSize="12px">
|
||||
Solution
|
||||
</Field.Label>
|
||||
<Textarea
|
||||
placeholder=""
|
||||
bgColor="#EEEEEE"
|
||||
color="black"
|
||||
border="none"
|
||||
pl={1}
|
||||
fontSize="12px"
|
||||
height="80px"
|
||||
pt={1.5}
|
||||
/>
|
||||
</Field.Root>
|
||||
</Stack>
|
||||
</DialogBody>
|
||||
<DialogFooter
|
||||
display={{ base: "block", md: "flex" }}
|
||||
justifyContent="center"
|
||||
gap={1}
|
||||
pt={2}
|
||||
<DialogContent
|
||||
bg={"#fff"}
|
||||
w={{ base: "90%", md: "400px" }}
|
||||
height={"auto"}
|
||||
p={3} // Reduced padding
|
||||
bgSize={"md"}
|
||||
>
|
||||
<HStack mt={2} mb={3} width={"100%"} justifyContent={"space-between"}>
|
||||
<Button
|
||||
width={"48%"}
|
||||
color="black"
|
||||
_hover={{ bgColor: "white" }}
|
||||
variant="outline"
|
||||
borderRadius="sm"
|
||||
border="1px solid #02A0A0"
|
||||
size={"xs"}
|
||||
>
|
||||
Unresolved
|
||||
</Button>
|
||||
<Button
|
||||
width={"48%"}
|
||||
borderRadius="sm"
|
||||
// bgColor="#007F33"
|
||||
bgColor={"#02A0A0"}
|
||||
color="white"
|
||||
// colorPalette="#007F33"
|
||||
size={"xs"}
|
||||
>
|
||||
Resolved
|
||||
</Button>
|
||||
</HStack>
|
||||
</DialogFooter>
|
||||
<DialogHeader bg="white">
|
||||
<DialogTitle alignSelf="center" color="black" fontSize="14px">
|
||||
Pending Requests
|
||||
</DialogTitle>
|
||||
</DialogHeader>
|
||||
|
||||
<DialogCloseTrigger color="black" />
|
||||
</DialogContent>
|
||||
</DialogRoot>
|
||||
<DialogBody bg="white">
|
||||
<Stack py={3}>
|
||||
<Field.Root>
|
||||
<Field.Label color="black" pt={1} fontSize="12px">
|
||||
Request Type
|
||||
</Field.Label>
|
||||
<Input
|
||||
placeholder="Message"
|
||||
bgColor="#EEEEEE"
|
||||
color="black"
|
||||
border="none"
|
||||
pl={1}
|
||||
fontSize="12px"
|
||||
height="30px"
|
||||
value={res.message}
|
||||
disabled
|
||||
// onChange={(e) => setRes({ ...res, message: e.target.value })}
|
||||
/>
|
||||
|
||||
<Field.Label color="black" pt={1} fontSize="12px">
|
||||
Solution
|
||||
</Field.Label>
|
||||
<Textarea
|
||||
placeholder=""
|
||||
bgColor="#EEEEEE"
|
||||
color="black"
|
||||
border="none"
|
||||
pl={1}
|
||||
fontSize="12px"
|
||||
height="80px"
|
||||
pt={1.5}
|
||||
onChange={(e) => setRes({ ...res, solution: e.target.value })}
|
||||
/>
|
||||
</Field.Root>
|
||||
</Stack>
|
||||
</DialogBody>
|
||||
<DialogFooter
|
||||
display={{ base: "block", md: "flex" }}
|
||||
justifyContent="center"
|
||||
gap={1}
|
||||
pt={2}
|
||||
>
|
||||
<HStack mt={2} mb={3} width={"100%"} justifyContent={"space-between"}>
|
||||
<Button
|
||||
width={"48%"}
|
||||
color="black"
|
||||
_hover={{ bgColor: "white" }}
|
||||
variant="outline"
|
||||
borderRadius="sm"
|
||||
border="1px solid #02A0A0"
|
||||
size={"xs"}
|
||||
onClick={() => handleSubmit('1')}
|
||||
disabled={isLoading}
|
||||
>
|
||||
Unresolved
|
||||
</Button>
|
||||
<Button
|
||||
width={"48%"}
|
||||
borderRadius="sm"
|
||||
// bgColor="#007F33"
|
||||
bgColor={"#02A0A0"}
|
||||
color="white"
|
||||
// colorPalette="#007F33"
|
||||
size={"xs"}
|
||||
onClick={() => handleSubmit('0')}
|
||||
disabled={isLoading}
|
||||
>
|
||||
Resolved
|
||||
</Button>
|
||||
</HStack>
|
||||
</DialogFooter>
|
||||
|
||||
<DialogCloseTrigger color="black" />
|
||||
</DialogContent>
|
||||
</DialogRoot>
|
||||
<Toaster />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -3,15 +3,14 @@ import {
|
||||
HStack,
|
||||
Image,
|
||||
// Image,
|
||||
Input,
|
||||
Text,
|
||||
} from "@chakra-ui/react";
|
||||
import { LuSearch } from "react-icons/lu";
|
||||
// import { LuSearch } from "react-icons/lu";
|
||||
// import { RiDeleteBin5Line } from "react-icons/ri";
|
||||
// import AlertDailog from "../../components/AlertDailog";
|
||||
import DataTable from "../../components/DataTable";
|
||||
import MainFrame from "../../components/MainFrame";
|
||||
import { InputGroup } from "../../components/ui/input-group";
|
||||
// import { InputGroup } from "../../components/ui/input-group";
|
||||
import ManageJobsAdd from "./ManageJobsAdd";
|
||||
import ViewManageJob from "./ViewManageJob";
|
||||
import {
|
||||
@@ -21,8 +20,10 @@ import {
|
||||
import { useEffect, useState } from "react";
|
||||
import { Spinner } from "../../components/Sipnner/Spinner";
|
||||
import Delete from "../../components/ActionIcons/Delete";
|
||||
import { toaster } from "../../components/ui/toaster";
|
||||
import { Toaster, toaster } from "../../components/ui/toaster";
|
||||
import AlertDailog from "../../components/AlertDailog";
|
||||
import { useDebounce } from "../../components/Hooks/useDebounce";
|
||||
import SearchComponent from "../../components/SearchComponent";
|
||||
// import { useState } from "react";
|
||||
// import { useGetManageJobsQuery } from "../../Redux/Service/manage.jobs.service";
|
||||
// import Delete from "../../components/ActionIcons/Delete";
|
||||
@@ -40,9 +41,12 @@ const tableHeadRow = [
|
||||
];
|
||||
|
||||
const ManageJobs = () => {
|
||||
const [currentPage] = useState(1);
|
||||
const [currentPage, setCurrentPage] = useState(1);
|
||||
const [localData, setLocalData] = useState([]);
|
||||
const { data, refetch, isLoading } = useGetManageJobsQuery(currentPage);
|
||||
const [searchTerm, setSearchTerm] = useState("");
|
||||
const debouncedSearchTerm = useDebounce(searchTerm, 500);
|
||||
const queryArgs = debouncedSearchTerm ? { page: currentPage, search: debouncedSearchTerm } : { page: currentPage };
|
||||
const { data, refetch, isLoading, isError, isFetching } = useGetManageJobsQuery(queryArgs);
|
||||
const [deleteJobsPost] = useDeleteJobsPostMutation();
|
||||
const [deleteModal, setDeleteModal] = useState(false);
|
||||
const [selectedJobsId, setSelectedJobsId] = useState<number | null>(null);
|
||||
@@ -52,7 +56,16 @@ const ManageJobs = () => {
|
||||
setLocalData((data as any)?.data?.data || []);
|
||||
}
|
||||
}, [data]);
|
||||
console.log(data?.data.data);
|
||||
// console.log(data?.data.data);
|
||||
|
||||
const handleSearchChange = (value: string) => {
|
||||
setSearchTerm(value);
|
||||
setCurrentPage(1);
|
||||
};
|
||||
|
||||
const handlePageChange = (page: number) => {
|
||||
setCurrentPage(page);
|
||||
};
|
||||
|
||||
const handleDeleteJobs = async (jobsId: number) => {
|
||||
try {
|
||||
@@ -84,8 +97,8 @@ const ManageJobs = () => {
|
||||
Salary: agency?.ctc_amount,
|
||||
Action: (
|
||||
<HStack justifyContent="center">
|
||||
<ViewManageJob />
|
||||
<ManageJobsAdd />
|
||||
<ViewManageJob data={agency} />
|
||||
<ManageJobsAdd data={agency} refetch={refetch}/>
|
||||
<AlertDailog
|
||||
isOpen={deleteModal}
|
||||
AltertTiggerIcon={() => (
|
||||
@@ -142,29 +155,10 @@ const ManageJobs = () => {
|
||||
</Text>
|
||||
|
||||
<HStack>
|
||||
<InputGroup
|
||||
startElement={
|
||||
<LuSearch
|
||||
fontSize={"xs"}
|
||||
style={{ position: "relative", left: "10px" }}
|
||||
/>
|
||||
}
|
||||
color={"#000"}
|
||||
>
|
||||
<Input
|
||||
p={3}
|
||||
w={300}
|
||||
bg={"#fff"}
|
||||
colorPalette={"blue"}
|
||||
_focus={{ border: "1px solid #02A0A0" }}
|
||||
rounded={"md"}
|
||||
size={"xs"}
|
||||
fontSize={"sm"}
|
||||
placeholder="Search..."
|
||||
bgColor={"#EEEEEE"}
|
||||
ps={8}
|
||||
/>
|
||||
</InputGroup>
|
||||
<SearchComponent
|
||||
value={searchTerm}
|
||||
onChange={handleSearchChange}
|
||||
/>
|
||||
{/* <Button bgColor={'#EEEEEE'} pl={3} pr={3}><IoMdAdd /> <Text>Add</Text></Button> */}
|
||||
</HStack>
|
||||
</HStack>
|
||||
@@ -172,8 +166,18 @@ const ManageJobs = () => {
|
||||
sortableColumns={["Name", "Registration Date "]}
|
||||
tableHeadRow={tableHeadRow}
|
||||
data={managepost}
|
||||
paginationData={{
|
||||
current_page: data?.data.current_page || 1,
|
||||
last_page: data?.data.last_page || 1,
|
||||
per_page: data?.data.per_page || 10,
|
||||
total: data?.data.total || 0
|
||||
}}
|
||||
onPageChange={handlePageChange}
|
||||
isLoading={isFetching}
|
||||
isError={isError}
|
||||
/>
|
||||
</Box>
|
||||
<Toaster />
|
||||
</MainFrame>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
import {
|
||||
Field,
|
||||
Input,
|
||||
SelectValueText,
|
||||
Span,
|
||||
Stack,
|
||||
createListCollection,
|
||||
} from "@chakra-ui/react";
|
||||
import { Button } from "../../components/ui/button";
|
||||
import {
|
||||
@@ -19,24 +17,151 @@ import {
|
||||
} from "../../components/ui/dialog";
|
||||
|
||||
// import { TbEdit } from "react-icons/tb";
|
||||
import {
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
SelectLabel,
|
||||
SelectRoot,
|
||||
SelectTrigger,
|
||||
} from "../../components/ui/select";
|
||||
import Edit from "../../components/ActionIcons/Edit";
|
||||
import { JobStatusData, useGetCountryQuery, useGetDepartmentQuery, useGetIndustryQuery, useGetManageJobTypeQuery, useGetWorkspaceModesQuery, useUpdateJobsMutation, WorkSpace } from "../../Redux/Service/manage.jobs.service";
|
||||
import { useReducer, useRef } from "react";
|
||||
import { Toaster, toaster } from "../../components/ui/toaster";
|
||||
|
||||
const reducerFunction = (state: any, action: any) => {
|
||||
switch (action.type) {
|
||||
case "SET_JOB_TITLE":
|
||||
return { ...state, jobTitle: action.payload };
|
||||
case "SET_WORKSPACE_MODE":
|
||||
return { ...state, workspaceMode: action.payload };
|
||||
case "SET_CATEGORY":
|
||||
return { ...state, category: action.payload };
|
||||
case "SET_SUB_CATEGORY":
|
||||
return { ...state, subCategory: action.payload };
|
||||
case "SET_SALARY":
|
||||
return { ...state, salary: action.payload };
|
||||
case "SET_EXPERIENCE":
|
||||
return { ...state, experience: action.payload };
|
||||
case "SET_JOB_LOCATION":
|
||||
return { ...state, jobLocation: action.payload };
|
||||
case "SET_COUNTRY_SELECTION":
|
||||
return { ...state, countrySelection: action.payload };
|
||||
case "SET_JOB_TYPE":
|
||||
return { ...state, jobType: action.payload };
|
||||
case "SET_SKILLS_REQUIRED":
|
||||
return { ...state, skillsRequired: action.payload };
|
||||
case "SET_JOB_DESCRIPTION":
|
||||
return { ...state, jobDescription: action.payload };
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
||||
|
||||
function ManageJobsAdd({ data, refetch }: { data: JobStatusData, refetch: () => void }) {
|
||||
const { data: workspaceModes } = useGetWorkspaceModesQuery({});
|
||||
const { data: industryData } = useGetIndustryQuery({});
|
||||
const { data: departmentData } = useGetDepartmentQuery({});
|
||||
const { data: countryData } = useGetCountryQuery({});
|
||||
const { data: jobTypeData } = useGetManageJobTypeQuery({});
|
||||
const [updateJobs, { isLoading}] = useUpdateJobsMutation();
|
||||
// console.log('Modes:', jobTypeData?.data.data);
|
||||
|
||||
const initialState = {
|
||||
jobTitle: data?.job_title || "",
|
||||
workspaceMode: data?.workspace_mode_xid || "",
|
||||
category: data?.industry_xid || "",
|
||||
subCategory: data?.department_xid || "",
|
||||
salary: data?.ctc_amount || "",
|
||||
experience: data?.experience || "",
|
||||
jobLocation: data?.job_location || "",
|
||||
countrySelection: data?.country_xid || "",
|
||||
jobType: data?.job_type_xid || "",
|
||||
skillsDescription: data?.skill_description || "",
|
||||
jobDescription: data?.job_description || "",
|
||||
};
|
||||
|
||||
const [state, dispatch] = useReducer(reducerFunction, initialState);
|
||||
const closeRef = useRef<HTMLButtonElement>(null);
|
||||
|
||||
const getDisplayName = (name: string, maxLength = 30) =>
|
||||
name.length > maxLength ? name.slice(0, maxLength) + "..." : name;
|
||||
|
||||
const handleSubmit = async () => {
|
||||
const {
|
||||
jobTitle,
|
||||
workspaceMode,
|
||||
category,
|
||||
subCategory,
|
||||
salary,
|
||||
experience,
|
||||
jobLocation,
|
||||
countrySelection,
|
||||
jobType,
|
||||
skillsDescription,
|
||||
jobDescription,
|
||||
} = state;
|
||||
|
||||
if (
|
||||
!jobTitle ||
|
||||
!workspaceMode ||
|
||||
!category ||
|
||||
!subCategory ||
|
||||
!salary ||
|
||||
!experience ||
|
||||
!jobLocation ||
|
||||
!countrySelection ||
|
||||
!jobType ||
|
||||
!skillsDescription ||
|
||||
!jobDescription
|
||||
) {
|
||||
toaster.create({
|
||||
title: "Missing Fields",
|
||||
description: "Please fill in all required fields before submitting.",
|
||||
type: "error",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// Only en_name is editable, so we only need to send that in the payload.
|
||||
const payload = {
|
||||
id: data?.id,
|
||||
job_title: state.jobTitle,
|
||||
workspace_mode_xid: state.workspaceMode,
|
||||
industry_xid: state.category,
|
||||
department_xid: state.subCategory,
|
||||
ctc_amount: state.salary,
|
||||
experience: state.experience,
|
||||
job_location: state.jobLocation,
|
||||
country_xid: state.countrySelection,
|
||||
job_type_xid: state.jobType,
|
||||
skill_description: state.skillsDescription,
|
||||
job_description: state.jobDescription,
|
||||
};
|
||||
|
||||
// console.log('payload', payload)
|
||||
|
||||
try {
|
||||
const response = await updateJobs(payload).unwrap();
|
||||
if (response?.status === "success") {
|
||||
toaster.create({
|
||||
title: "Success",
|
||||
description: "Country updated successfully",
|
||||
type: "success",
|
||||
});
|
||||
closeRef.current?.click();
|
||||
refetch()
|
||||
} else {
|
||||
toaster.create({
|
||||
title: "Error",
|
||||
description: "Failed to update Country",
|
||||
type: "error",
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error updating template:", error);
|
||||
// alert("Failed to update template");
|
||||
toaster.create({
|
||||
title: "Error",
|
||||
description: "Something went wrong",
|
||||
type: "error",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const frameworks = createListCollection({
|
||||
items: [
|
||||
{ label: "React.js", value: "react" },
|
||||
{ label: "Vue.js", value: "vue" },
|
||||
{ label: "Angular", value: "angular" },
|
||||
{ label: "Svelte", value: "svelte" },
|
||||
],
|
||||
});
|
||||
function ManageJobsAdd() {
|
||||
return (
|
||||
<DialogRoot placement="center">
|
||||
<DialogTrigger asChild>
|
||||
@@ -73,50 +198,182 @@ function ManageJobsAdd() {
|
||||
pl={1}
|
||||
fontSize="12px"
|
||||
height="30px"
|
||||
value={state.jobTitle}
|
||||
onChange={(e) =>
|
||||
dispatch({
|
||||
type: "SET_JOB_TITLE",
|
||||
payload: e.target.value,
|
||||
})
|
||||
}
|
||||
/>
|
||||
</Field.Root>
|
||||
<Field.Root>
|
||||
<Field.Label color="black" pt={1} fontSize="12px">
|
||||
Workspace mode
|
||||
</Field.Label>
|
||||
<Input
|
||||
placeholder="Enter the Workspace Mode"
|
||||
bgColor="#EEEEEE"
|
||||
color="black"
|
||||
border="none"
|
||||
pl={1}
|
||||
fontSize="12px"
|
||||
height="30px"
|
||||
/>
|
||||
<select
|
||||
style={{
|
||||
backgroundColor: "#EEEEEE",
|
||||
color: "black",
|
||||
border: "none",
|
||||
height: "30px",
|
||||
fontSize: "12px",
|
||||
padding: "4px",
|
||||
borderRadius: "4px",
|
||||
width: "100%",
|
||||
}}
|
||||
value={state.workspace_mode_xid}
|
||||
onChange={(e) =>
|
||||
dispatch({
|
||||
type: "SET_WORKSPACE_MODE",
|
||||
payload: Number(e.target.value),
|
||||
})
|
||||
}
|
||||
>
|
||||
<option value="" disabled>
|
||||
Select country
|
||||
</option>
|
||||
{workspaceModes && workspaceModes?.data.map((mode: WorkSpace) => (
|
||||
<option key={mode.id} value={mode.id}>
|
||||
{getDisplayName(mode.en_name)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</Field.Root>
|
||||
<Field.Root>
|
||||
<Field.Label pt={1} color="black" fontSize="12px">
|
||||
Category
|
||||
</Field.Label>
|
||||
<Input
|
||||
placeholder="Enter the Category"
|
||||
bgColor="#EEEEEE"
|
||||
color="black"
|
||||
border="none"
|
||||
pl={1}
|
||||
fontSize="12px"
|
||||
height="30px"
|
||||
/>
|
||||
<select
|
||||
style={{
|
||||
backgroundColor: "#EEEEEE",
|
||||
color: "black",
|
||||
border: "none",
|
||||
height: "30px",
|
||||
fontSize: "12px",
|
||||
padding: "4px",
|
||||
borderRadius: "4px",
|
||||
width: "100%",
|
||||
}}
|
||||
value={state.industry_xid}
|
||||
onChange={(e) =>
|
||||
dispatch({
|
||||
type: "SET_INDUSTRY",
|
||||
payload: Number(e.target.value),
|
||||
})
|
||||
}
|
||||
>
|
||||
<option value="" disabled>
|
||||
Select department
|
||||
</option>
|
||||
{industryData && industryData?.data.map((mode: WorkSpace) => (
|
||||
<option key={mode.id} value={mode.id}>
|
||||
{getDisplayName(mode.en_name)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</Field.Root>
|
||||
<Field.Root>
|
||||
<Field.Label pt={1} color="black" fontSize="12px">
|
||||
Sub-Category
|
||||
</Field.Label>
|
||||
<Input
|
||||
placeholder="Enter the Sub-Category"
|
||||
bgColor="#EEEEEE"
|
||||
color="black"
|
||||
border="none"
|
||||
pl={1}
|
||||
fontSize="12px"
|
||||
height="30px"
|
||||
/>
|
||||
<select
|
||||
style={{
|
||||
backgroundColor: "#EEEEEE",
|
||||
color: "black",
|
||||
border: "none",
|
||||
height: "30px",
|
||||
fontSize: "12px",
|
||||
padding: "4px",
|
||||
borderRadius: "4px",
|
||||
width: "100%",
|
||||
}}
|
||||
value={state.department_xid}
|
||||
onChange={(e) =>
|
||||
dispatch({
|
||||
type: "SET_DEPARTMENT",
|
||||
payload: Number(e.target.value),
|
||||
})
|
||||
}
|
||||
>
|
||||
<option value="" disabled>
|
||||
Select department
|
||||
</option>
|
||||
{departmentData && departmentData?.data.map((mode: WorkSpace) => (
|
||||
<option key={mode.id} value={mode.id}>
|
||||
{getDisplayName(mode.en_name)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</Field.Root>
|
||||
|
||||
<Field.Root>
|
||||
<Field.Label pt={1} color="black" fontSize="12px">
|
||||
Country
|
||||
</Field.Label>
|
||||
<select
|
||||
style={{
|
||||
backgroundColor: "#EEEEEE",
|
||||
color: "black",
|
||||
border: "none",
|
||||
height: "30px",
|
||||
fontSize: "12px",
|
||||
padding: "4px",
|
||||
borderRadius: "4px",
|
||||
width: "100%",
|
||||
}}
|
||||
value={state.country_xid}
|
||||
onChange={(e) =>
|
||||
dispatch({
|
||||
type: "SET_COUNTRY",
|
||||
payload: Number(e.target.value),
|
||||
})
|
||||
}
|
||||
>
|
||||
<option value="" disabled>
|
||||
Select country
|
||||
</option>
|
||||
{countryData && countryData?.data.map((mode: WorkSpace) => (
|
||||
<option key={mode.id} value={mode.id}>
|
||||
{getDisplayName(mode.en_name)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</Field.Root>
|
||||
<Field.Root>
|
||||
<Field.Label pt={1} color="black" fontSize="12px">
|
||||
Job type
|
||||
</Field.Label>
|
||||
<select
|
||||
style={{
|
||||
backgroundColor: "#EEEEEE",
|
||||
color: "black",
|
||||
border: "none",
|
||||
height: "30px",
|
||||
fontSize: "12px",
|
||||
padding: "4px",
|
||||
borderRadius: "4px",
|
||||
width: "100%",
|
||||
}}
|
||||
value={state.job_type_xid}
|
||||
onChange={(e) =>
|
||||
dispatch({
|
||||
type: "SET_JOB_TYPE",
|
||||
payload: Number(e.target.value),
|
||||
})
|
||||
}
|
||||
>
|
||||
<option value="" disabled>
|
||||
Select Job Type
|
||||
</option>
|
||||
{jobTypeData && jobTypeData?.data.data.map((mode: WorkSpace) => (
|
||||
<option key={mode.id} value={mode.id}>
|
||||
{getDisplayName(mode.en_name)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</Field.Root>
|
||||
|
||||
<Field.Root>
|
||||
<Field.Label pt={1} color="black" fontSize="12px">
|
||||
Salary
|
||||
@@ -129,6 +386,13 @@ function ManageJobsAdd() {
|
||||
pl={1}
|
||||
fontSize="12px"
|
||||
height="30px"
|
||||
value={state.salary}
|
||||
onChange={(e) =>
|
||||
dispatch({
|
||||
type: "SET_SALARY",
|
||||
payload: e.target.value,
|
||||
})
|
||||
}
|
||||
/>
|
||||
</Field.Root>
|
||||
<Field.Root>
|
||||
@@ -136,13 +400,20 @@ function ManageJobsAdd() {
|
||||
Experience
|
||||
</Field.Label>
|
||||
<Input
|
||||
placeholder="Enter the Experience"
|
||||
placeholder="Enter the Experience in years"
|
||||
bgColor="#EEEEEE"
|
||||
color="black"
|
||||
border="none"
|
||||
pl={1}
|
||||
fontSize="12px"
|
||||
height="30px"
|
||||
value={state.experience}
|
||||
onChange={(e) =>
|
||||
dispatch({
|
||||
type: "SET_EXPERIENCE",
|
||||
payload: e.target.value,
|
||||
})
|
||||
}
|
||||
/>
|
||||
</Field.Root>
|
||||
<Field.Root>
|
||||
@@ -157,71 +428,34 @@ function ManageJobsAdd() {
|
||||
pl={1}
|
||||
fontSize="12px"
|
||||
height="30px"
|
||||
/>
|
||||
</Field.Root>
|
||||
{/* <Field.Label pt={1} color="black" fontSize="12px">Country Selection</Field.Label>
|
||||
<Input placeholder="Enter the Country Selection" /> */}
|
||||
<SelectRoot collection={frameworks} size="sm" w={"100%"}>
|
||||
<SelectLabel pt={1} color="black" fontSize="12px">
|
||||
Country Selection
|
||||
</SelectLabel>
|
||||
<SelectTrigger
|
||||
bgColor="#EEEEEE"
|
||||
color="black"
|
||||
border="none"
|
||||
pl={1}
|
||||
fontSize="12px"
|
||||
height="30px"
|
||||
borderRadius={"5px"}
|
||||
>
|
||||
<SelectValueText
|
||||
placeholder="Enter the Country Selection"
|
||||
pb={"6px"}
|
||||
fontSize={"12px"}
|
||||
/>
|
||||
</SelectTrigger>
|
||||
<SelectContent position={"relative"} zIndex={"9999"} bg={"#fff"}>
|
||||
{frameworks.items.map((movie) => (
|
||||
<SelectItem
|
||||
item={movie}
|
||||
key={movie.value}
|
||||
color={"black"}
|
||||
pl={2}
|
||||
p={1}
|
||||
_hover={{ bg: "#F0F0F0" }} // Light grey background on hover
|
||||
fontSize="12px"
|
||||
>
|
||||
{movie.label}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</SelectRoot>
|
||||
<Field.Root>
|
||||
<Field.Label pt={1} color="black" fontSize="12px">
|
||||
Job type
|
||||
</Field.Label>
|
||||
<Input
|
||||
placeholder="Enter the Job Type"
|
||||
bgColor="#EEEEEE"
|
||||
color="black"
|
||||
border="none"
|
||||
pl={1}
|
||||
fontSize="12px"
|
||||
height="30px"
|
||||
value={state.jobLocation}
|
||||
onChange={(e) =>
|
||||
dispatch({
|
||||
type: "SET_JOB_LOCATION",
|
||||
payload: e.target.value,
|
||||
})
|
||||
}
|
||||
/>
|
||||
</Field.Root>
|
||||
<Field.Root>
|
||||
<Field.Label pt={1} color="black" fontSize="12px">
|
||||
Skills required
|
||||
Skills description
|
||||
</Field.Label>
|
||||
<Input
|
||||
placeholder="Enter the Skills Required"
|
||||
placeholder="Enter the Skills description"
|
||||
bgColor="#EEEEEE"
|
||||
color="black"
|
||||
border="none"
|
||||
pl={1}
|
||||
fontSize="12px"
|
||||
height="30px"
|
||||
value={state.skillsDescription}
|
||||
onChange={(e) =>
|
||||
dispatch({
|
||||
type: "SET_SKILLS_DESCRIPTION",
|
||||
payload: e.target.value,
|
||||
})
|
||||
}
|
||||
/>
|
||||
</Field.Root>
|
||||
<Field.Root>
|
||||
@@ -236,6 +470,13 @@ function ManageJobsAdd() {
|
||||
pl={1}
|
||||
fontSize="12px"
|
||||
height="30px"
|
||||
value={state.jobDescription}
|
||||
onChange={(e) =>
|
||||
dispatch({
|
||||
type: "SET_JOB_DESCRIPTION",
|
||||
payload: e.target.value,
|
||||
})
|
||||
}
|
||||
/>
|
||||
</Field.Root>
|
||||
</Stack>
|
||||
@@ -247,13 +488,16 @@ function ManageJobsAdd() {
|
||||
color={"#fff"}
|
||||
fontSize="12px"
|
||||
height="30px"
|
||||
onClick={handleSubmit}
|
||||
disabled={isLoading}
|
||||
>
|
||||
Save
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
|
||||
<DialogCloseTrigger color="black" />
|
||||
<DialogCloseTrigger color="black" ref={closeRef} />
|
||||
</DialogContent>
|
||||
<Toaster />
|
||||
</DialogRoot>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,17 +1,13 @@
|
||||
import {
|
||||
Field,
|
||||
Input,
|
||||
SelectValueText,
|
||||
Span,
|
||||
Stack,
|
||||
createListCollection,
|
||||
} from "@chakra-ui/react";
|
||||
import { Button } from "../../components/ui/button";
|
||||
import {
|
||||
DialogBody,
|
||||
DialogCloseTrigger,
|
||||
DialogContent,
|
||||
DialogFooter,
|
||||
DialogHeader,
|
||||
DialogRoot,
|
||||
DialogTitle,
|
||||
@@ -19,276 +15,290 @@ import {
|
||||
} from "../../components/ui/dialog";
|
||||
|
||||
// import { MdOutlineRemoveRedEye } from "react-icons/md";
|
||||
import {
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
SelectLabel,
|
||||
SelectRoot,
|
||||
SelectTrigger,
|
||||
} from "../../components/ui/select";
|
||||
import View from "../../components/ActionIcons/View";
|
||||
import { useLazyViewJobsQuery } from "../../Redux/Service/manage.jobs.service";
|
||||
import { JobStatusData, useLazyViewJobsQuery } from "../../Redux/Service/manage.jobs.service";
|
||||
|
||||
const frameworks = createListCollection({
|
||||
items: [
|
||||
{ label: "React.js", value: "react" },
|
||||
{ label: "Vue.js", value: "vue" },
|
||||
{ label: "Angular", value: "angular" },
|
||||
{ label: "Svelte", value: "svelte" },
|
||||
],
|
||||
});
|
||||
function ViewManageJob() {
|
||||
const [trigger, { data }] = useLazyViewJobsQuery();
|
||||
function ViewManageJob({ data }: { data: JobStatusData }) {
|
||||
const [trigger] = useLazyViewJobsQuery();
|
||||
|
||||
console.log(data);
|
||||
|
||||
// const handleView = () => {
|
||||
// trigger(id);
|
||||
// };
|
||||
const handleView = () => {
|
||||
trigger(data.id);
|
||||
};
|
||||
|
||||
const viewJobs = data;
|
||||
// const viewJobs = data;
|
||||
|
||||
console.log();
|
||||
|
||||
return (
|
||||
<DialogRoot placement="center">
|
||||
<DialogTrigger asChild>
|
||||
<Span>
|
||||
<Button
|
||||
onClick={handleView}
|
||||
bg={'transparent'}
|
||||
color={"black"}
|
||||
>
|
||||
<View />
|
||||
</Span>
|
||||
</Button>
|
||||
</DialogTrigger>
|
||||
|
||||
{/* {viewJobs?.map((data: any) => ( */}
|
||||
<DialogContent
|
||||
bg={"#fff"}
|
||||
// w={{ lg: "60%", md: "230px" }}
|
||||
w={{ base: "90%", md: "400px" }}
|
||||
height={"80vh"}
|
||||
overflow={"scroll"}
|
||||
overflowX="hidden"
|
||||
p={3} // Reduced padding
|
||||
bgSize={"md"}
|
||||
>
|
||||
<DialogHeader bg="white">
|
||||
<DialogTitle alignSelf="center" color="black" fontSize="14px">
|
||||
Add Details
|
||||
</DialogTitle>
|
||||
</DialogHeader>
|
||||
<DialogContent
|
||||
bg={"#fff"}
|
||||
// w={{ lg: "60%", md: "230px" }}
|
||||
w={{ base: "90%", md: "400px" }}
|
||||
height={"80vh"}
|
||||
overflow={"scroll"}
|
||||
overflowX="hidden"
|
||||
p={3} // Reduced padding
|
||||
bgSize={"md"}
|
||||
>
|
||||
<DialogHeader bg="white">
|
||||
<DialogTitle alignSelf="center" color="black" fontSize="14px">
|
||||
Add Details
|
||||
</DialogTitle>
|
||||
</DialogHeader>
|
||||
|
||||
<DialogBody bg="white">
|
||||
<Stack py={3}>
|
||||
<Field.Root>
|
||||
<Field.Label color="black" pt={1} fontSize="12px">
|
||||
Job title
|
||||
</Field.Label>
|
||||
<Input
|
||||
placeholder="Enter the Job Title"
|
||||
bgColor="#EEEEEE"
|
||||
color="black"
|
||||
border="none"
|
||||
pl={1}
|
||||
fontSize="12px"
|
||||
height="30px"
|
||||
/>
|
||||
</Field.Root>
|
||||
<Field.Root>
|
||||
<Field.Label color="black" pt={1} fontSize="12px">
|
||||
Workspace mode
|
||||
</Field.Label>
|
||||
<Input
|
||||
placeholder="Enter the Workspace Mode"
|
||||
bgColor="#EEEEEE"
|
||||
color="black"
|
||||
border="none"
|
||||
pl={1}
|
||||
fontSize="12px"
|
||||
height="30px"
|
||||
/>
|
||||
</Field.Root>
|
||||
<Field.Root>
|
||||
<Field.Label pt={1} color="black" fontSize="12px">
|
||||
Category
|
||||
</Field.Label>
|
||||
<Input
|
||||
placeholder="Enter the Category"
|
||||
bgColor="#EEEEEE"
|
||||
color="black"
|
||||
border="none"
|
||||
pl={1}
|
||||
fontSize="12px"
|
||||
height="30px"
|
||||
/>
|
||||
</Field.Root>
|
||||
<Field.Root>
|
||||
<Field.Label pt={1} color="black" fontSize="12px">
|
||||
Sub-Category
|
||||
</Field.Label>
|
||||
<Input
|
||||
placeholder="Enter the Sub-Category"
|
||||
bgColor="#EEEEEE"
|
||||
color="black"
|
||||
border="none"
|
||||
pl={1}
|
||||
fontSize="12px"
|
||||
height="30px"
|
||||
/>
|
||||
</Field.Root>
|
||||
<Field.Root>
|
||||
<Field.Label pt={1} color="black" fontSize="12px">
|
||||
Salary
|
||||
</Field.Label>
|
||||
<Input
|
||||
placeholder="Enter the Salary"
|
||||
bgColor="#EEEEEE"
|
||||
color="black"
|
||||
border="none"
|
||||
pl={1}
|
||||
fontSize="12px"
|
||||
height="30px"
|
||||
/>
|
||||
</Field.Root>
|
||||
<Field.Root>
|
||||
<Field.Label pt={1} color="black" fontSize="12px">
|
||||
Experience
|
||||
</Field.Label>
|
||||
<Input
|
||||
placeholder="Enter the Experience"
|
||||
bgColor="#EEEEEE"
|
||||
color="black"
|
||||
border="none"
|
||||
pl={1}
|
||||
fontSize="12px"
|
||||
height="30px"
|
||||
/>
|
||||
</Field.Root>
|
||||
<Field.Root>
|
||||
<Field.Label pt={1} color="black" fontSize="12px">
|
||||
Job Location
|
||||
</Field.Label>
|
||||
<Input
|
||||
placeholder="Enter the Job Location"
|
||||
bgColor="#EEEEEE"
|
||||
color="black"
|
||||
border="none"
|
||||
pl={1}
|
||||
fontSize="12px"
|
||||
height="30px"
|
||||
/>
|
||||
</Field.Root>
|
||||
{/* <Field.Label pt={1} color="black" fontSize="12px">Country Selection</Field.Label>
|
||||
<Input placeholder="Enter the Country Selection" /> */}
|
||||
<SelectRoot collection={frameworks} size="sm" w={"100%"}>
|
||||
<SelectLabel pt={1} color="black" fontSize="12px">
|
||||
Country Selection
|
||||
</SelectLabel>
|
||||
<SelectTrigger
|
||||
bgColor="#EEEEEE"
|
||||
color="black"
|
||||
border="none"
|
||||
pl={1}
|
||||
fontSize="12px"
|
||||
height="30px"
|
||||
borderRadius={"5px"}
|
||||
>
|
||||
<SelectValueText
|
||||
placeholder="Enter the Country Selection"
|
||||
pb={"6px"}
|
||||
fontSize={"12px"}
|
||||
/>
|
||||
</SelectTrigger>
|
||||
<SelectContent
|
||||
position={"relative"}
|
||||
zIndex={"9999"}
|
||||
bg={"#fff"}
|
||||
>
|
||||
{frameworks.items.map((movie) => (
|
||||
<SelectItem
|
||||
item={movie}
|
||||
key={movie.value}
|
||||
color={"black"}
|
||||
pl={2}
|
||||
p={1}
|
||||
_hover={{ bg: "#F0F0F0" }} // Light grey background on hover
|
||||
fontSize="12px"
|
||||
>
|
||||
{movie.label}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</SelectRoot>
|
||||
<DialogBody bg="white">
|
||||
<Stack py={3}>
|
||||
<Field.Root>
|
||||
<Field.Label color="black" pt={1} fontSize="12px">
|
||||
Job title
|
||||
</Field.Label>
|
||||
<Input
|
||||
placeholder="Enter the Job Title"
|
||||
bgColor="#EEEEEE"
|
||||
color="black"
|
||||
border="none"
|
||||
pl={1}
|
||||
fontSize="12px"
|
||||
height="30px"
|
||||
value={data?.job_title}
|
||||
/>
|
||||
</Field.Root>
|
||||
<Field.Root>
|
||||
<Field.Label color="black" pt={1} fontSize="12px">
|
||||
Workspace mode
|
||||
</Field.Label>
|
||||
<Input
|
||||
placeholder="Enter the Workspace Mode"
|
||||
bgColor="#EEEEEE"
|
||||
color="black"
|
||||
border="none"
|
||||
pl={1}
|
||||
fontSize="12px"
|
||||
height="30px"
|
||||
value={data?.workspace?.en_name}
|
||||
/>
|
||||
</Field.Root>
|
||||
<Field.Root>
|
||||
<Field.Label pt={1} color="black" fontSize="12px">
|
||||
Category
|
||||
</Field.Label>
|
||||
<Input
|
||||
placeholder="Enter the Category"
|
||||
bgColor="#EEEEEE"
|
||||
color="black"
|
||||
border="none"
|
||||
pl={1}
|
||||
fontSize="12px"
|
||||
height="30px"
|
||||
value={data?.industry?.en_name}
|
||||
/>
|
||||
</Field.Root>
|
||||
<Field.Root>
|
||||
<Field.Label pt={1} color="black" fontSize="12px">
|
||||
Sub-Category
|
||||
</Field.Label>
|
||||
<Input
|
||||
placeholder="Enter the Sub-Category"
|
||||
bgColor="#EEEEEE"
|
||||
color="black"
|
||||
border="none"
|
||||
pl={1}
|
||||
fontSize="12px"
|
||||
height="30px"
|
||||
value={data?.department?.en_name}
|
||||
/>
|
||||
</Field.Root>
|
||||
<Field.Root>
|
||||
<Field.Label pt={1} color="black" fontSize="12px">
|
||||
Salary
|
||||
</Field.Label>
|
||||
<Input
|
||||
placeholder="Enter the Salary"
|
||||
bgColor="#EEEEEE"
|
||||
color="black"
|
||||
border="none"
|
||||
pl={1}
|
||||
fontSize="12px"
|
||||
height="30px"
|
||||
value={data?.ctc_amount}
|
||||
/>
|
||||
</Field.Root>
|
||||
<Field.Root>
|
||||
<Field.Label pt={1} color="black" fontSize="12px">
|
||||
Experience
|
||||
</Field.Label>
|
||||
<Input
|
||||
placeholder="Enter the Experience"
|
||||
bgColor="#EEEEEE"
|
||||
color="black"
|
||||
border="none"
|
||||
pl={1}
|
||||
fontSize="12px"
|
||||
height="30px"
|
||||
value={data?.experience}
|
||||
/>
|
||||
</Field.Root>
|
||||
<Field.Root>
|
||||
<Field.Label pt={1} color="black" fontSize="12px">
|
||||
Job Location
|
||||
</Field.Label>
|
||||
<Input
|
||||
placeholder="Enter the Job Location"
|
||||
bgColor="#EEEEEE"
|
||||
color="black"
|
||||
border="none"
|
||||
pl={1}
|
||||
fontSize="12px"
|
||||
height="30px"
|
||||
value={data?.job_location}
|
||||
/>
|
||||
</Field.Root>
|
||||
|
||||
<Field.Root>
|
||||
<Field.Label pt={1} color="black" fontSize="12px">
|
||||
Job type
|
||||
</Field.Label>
|
||||
<Input
|
||||
placeholder="Enter the Job Type"
|
||||
bgColor="#EEEEEE"
|
||||
color="black"
|
||||
border="none"
|
||||
pl={1}
|
||||
fontSize="12px"
|
||||
height="30px"
|
||||
/>
|
||||
</Field.Root>
|
||||
<Field.Root>
|
||||
<Field.Label pt={1} color="black" fontSize="12px">
|
||||
Skills required
|
||||
</Field.Label>
|
||||
<Input
|
||||
placeholder="Enter the Skills Required"
|
||||
bgColor="#EEEEEE"
|
||||
color="black"
|
||||
border="none"
|
||||
pl={1}
|
||||
fontSize="12px"
|
||||
height="30px"
|
||||
/>
|
||||
</Field.Root>
|
||||
<Field.Root>
|
||||
<Field.Label pt={1} color="black" fontSize="12px">
|
||||
Job Description*
|
||||
</Field.Label>
|
||||
<Input
|
||||
placeholder="Enter the Job Description"
|
||||
bgColor="#EEEEEE"
|
||||
color="black"
|
||||
border="none"
|
||||
pl={1}
|
||||
fontSize="12px"
|
||||
height="30px"
|
||||
/>
|
||||
</Field.Root>
|
||||
<Field.Root>
|
||||
<Field.Label pt={1} color="black" fontSize="12px">
|
||||
Upload Image
|
||||
</Field.Label>
|
||||
<Input
|
||||
placeholder="Upload Image"
|
||||
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"}
|
||||
fontSize="12px"
|
||||
height="30px"
|
||||
>
|
||||
Save
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
<Field.Root>
|
||||
<Field.Label pt={1} color="black" fontSize="12px">
|
||||
Country
|
||||
</Field.Label>
|
||||
<Input
|
||||
placeholder="Enter the Country"
|
||||
bgColor="#EEEEEE"
|
||||
color="black"
|
||||
border="none"
|
||||
pl={1}
|
||||
fontSize="12px"
|
||||
height="30px"
|
||||
value={data?.country.en_name}
|
||||
/>
|
||||
</Field.Root>
|
||||
|
||||
<DialogCloseTrigger color="black" />
|
||||
</DialogContent>
|
||||
{/* <SelectRoot collection={frameworks} size="sm" w={"100%"}>
|
||||
<SelectLabel pt={1} color="black" fontSize="12px">
|
||||
Country Selection
|
||||
</SelectLabel>
|
||||
<SelectTrigger
|
||||
bgColor="#EEEEEE"
|
||||
color="black"
|
||||
border="none"
|
||||
pl={1}
|
||||
fontSize="12px"
|
||||
height="30px"
|
||||
borderRadius={"5px"}
|
||||
>
|
||||
<SelectValueText
|
||||
placeholder="Enter the Country Selection"
|
||||
pb={"6px"}
|
||||
fontSize={"12px"}
|
||||
/>
|
||||
</SelectTrigger>
|
||||
<SelectContent
|
||||
position={"relative"}
|
||||
zIndex={"9999"}
|
||||
bg={"#fff"}
|
||||
>
|
||||
{frameworks.items.map((movie) => (
|
||||
<SelectItem
|
||||
item={movie}
|
||||
key={movie.value}
|
||||
color={"black"}
|
||||
pl={2}
|
||||
p={1}
|
||||
_hover={{ bg: "#F0F0F0" }} // Light grey background on hover
|
||||
fontSize="12px"
|
||||
>
|
||||
{movie.label}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</SelectRoot> */}
|
||||
|
||||
<Field.Root>
|
||||
<Field.Label pt={1} color="black" fontSize="12px">
|
||||
Job type
|
||||
</Field.Label>
|
||||
<Input
|
||||
placeholder="Enter the Job Type"
|
||||
bgColor="#EEEEEE"
|
||||
color="black"
|
||||
border="none"
|
||||
pl={1}
|
||||
fontSize="12px"
|
||||
height="30px"
|
||||
value={data?.job_type?.en_name}
|
||||
/>
|
||||
</Field.Root>
|
||||
<Field.Root>
|
||||
<Field.Label pt={1} color="black" fontSize="12px">
|
||||
Skills required
|
||||
</Field.Label>
|
||||
<Input
|
||||
placeholder="Enter the Skills Required"
|
||||
bgColor="#EEEEEE"
|
||||
color="black"
|
||||
border="none"
|
||||
pl={1}
|
||||
fontSize="12px"
|
||||
height="30px"
|
||||
value={data?.skill_description}
|
||||
/>
|
||||
</Field.Root>
|
||||
<Field.Root>
|
||||
<Field.Label pt={1} color="black" fontSize="12px">
|
||||
Job Description*
|
||||
</Field.Label>
|
||||
<Input
|
||||
placeholder="Enter the Job Description"
|
||||
bgColor="#EEEEEE"
|
||||
color="black"
|
||||
border="none"
|
||||
pl={1}
|
||||
fontSize="12px"
|
||||
height="30px"
|
||||
value={data?.job_description}
|
||||
/>
|
||||
</Field.Root>
|
||||
{/* <Field.Root>
|
||||
<Field.Label pt={1} color="black" fontSize="12px">
|
||||
Upload Image
|
||||
</Field.Label>
|
||||
<Input
|
||||
placeholder="Upload Image"
|
||||
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"}
|
||||
fontSize="12px"
|
||||
height="30px"
|
||||
>
|
||||
Save
|
||||
</Button>
|
||||
</DialogFooter> */}
|
||||
|
||||
<DialogCloseTrigger color="black" />
|
||||
</DialogContent>
|
||||
{/* ))} */}
|
||||
</DialogRoot>
|
||||
);
|
||||
|
||||
@@ -14,9 +14,10 @@ import { Switch } from "../../components/ui/switch";
|
||||
import ViewDailog from "./ViewDailog";
|
||||
import { useGetManagePostsQuery, usePostStatusToggleMutation } from "../../Redux/Service/manage.post.service";
|
||||
import { useEffect, useState } from "react";
|
||||
import { toaster } from "../../components/ui/toaster";
|
||||
import { Toaster, toaster } from "../../components/ui/toaster";
|
||||
import { FaVideo } from "react-icons/fa";
|
||||
import SearchComponent from "../../components/SearchComponent";
|
||||
import { delay } from "../../components/Utils";
|
||||
// import Delete from "../../components/ActionIcons/Delete";
|
||||
// import ViewDailog from './ViewDailog'
|
||||
|
||||
@@ -71,7 +72,7 @@ const tableHeadRow = [
|
||||
|
||||
const ManagePost = () => {
|
||||
const [currentPage, setCurrentPage] = useState(1);
|
||||
const { data, refetch } = useGetManagePostsQuery(currentPage)
|
||||
const { data, refetch, isFetching, isError } = useGetManagePostsQuery(currentPage)
|
||||
const [localData, setLocalData] = useState<any[]>([]);
|
||||
const [searchTerm, setSearchTerm] = useState("");
|
||||
const [postStatusToggle] = usePostStatusToggleMutation()
|
||||
@@ -96,6 +97,12 @@ const ManagePost = () => {
|
||||
);
|
||||
try {
|
||||
await postStatusToggle({ id: agencyId, is_active: newStatus }).unwrap();
|
||||
toaster.create({
|
||||
title: "Success",
|
||||
description: "Status updated successfully",
|
||||
type: "success",
|
||||
});
|
||||
await delay(500);
|
||||
refetch()
|
||||
} catch (error) {
|
||||
console.error("Error updating:", error);
|
||||
@@ -149,36 +156,35 @@ const ManagePost = () => {
|
||||
h={50}
|
||||
src={`${APIURL}${agency.images[0].image_name}`}
|
||||
/>
|
||||
<Text fontSize="xs" color={'lightgray'}>
|
||||
<Text fontSize="xs" color={'lightgray'}>
|
||||
{`${Number(agency.images.length) > 1 ? '+' + (Number(agency.images.length) - 1) : ''}`}
|
||||
</Text>
|
||||
</Text>
|
||||
</HStack>
|
||||
) : (
|
||||
<HStack>
|
||||
<Box
|
||||
rounded={"lg"}
|
||||
w={100}
|
||||
h={50}
|
||||
bg="gray.200"
|
||||
display="flex"
|
||||
alignItems="center"
|
||||
justifyContent="center"
|
||||
>
|
||||
<Icon as={FaVideo} color="gray.500" />
|
||||
</Box>
|
||||
<Text fontSize="xs" color={'lightgray'}>
|
||||
{`${Number(agency.images.length) > 1 ? '+' + (Number(agency.images.length) - 1) : ''}`}
|
||||
</Text>
|
||||
</HStack>
|
||||
<HStack>
|
||||
<Box
|
||||
rounded={"lg"}
|
||||
w={100}
|
||||
h={50}
|
||||
bg="gray.200"
|
||||
display="flex"
|
||||
alignItems="center"
|
||||
justifyContent="center"
|
||||
>
|
||||
<Icon as={FaVideo} color="gray.500" />
|
||||
</Box>
|
||||
<Text fontSize="xs" color={'lightgray'}>
|
||||
{`${Number(agency.images.length) > 1 ? '+' + (Number(agency.images.length) - 1) : ''}`}
|
||||
</Text>
|
||||
</HStack>
|
||||
) : ''
|
||||
// <Image rounded={"lg"} w={100} h={50} src={img} />
|
||||
),
|
||||
Description: (
|
||||
<Text>
|
||||
{`${translation?.content}`.slice(
|
||||
0,
|
||||
30
|
||||
) + "..."}
|
||||
{translation?.content?.length > 30
|
||||
? `${translation.content.slice(0, 30)}...`
|
||||
: translation?.content}
|
||||
</Text>
|
||||
),
|
||||
"Publish Data": formatAPIDate(agency.created_at),
|
||||
@@ -236,8 +242,11 @@ const ManagePost = () => {
|
||||
total: data?.data.total || 0
|
||||
}}
|
||||
onPageChange={handlePageChange}
|
||||
isLoading={isFetching}
|
||||
isError={isError}
|
||||
/>
|
||||
</Box>
|
||||
<Toaster />
|
||||
</MainFrame>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,12 +1,16 @@
|
||||
import { Box, HStack, Input, Text } from "@chakra-ui/react";
|
||||
import { Box, HStack, Text } from "@chakra-ui/react";
|
||||
import MainFrame from "../../../components/MainFrame";
|
||||
import DataTable from "../../../components/DataTable";
|
||||
import { Switch } from "../../../components/ui/switch";
|
||||
import { InputGroup } from "../../../components/ui/input-group";
|
||||
import { LuSearch } from "react-icons/lu";
|
||||
import { useGetContactQuery } from "../../../Redux/Service/deactivated.account.service";
|
||||
// import { InputGroup } from "../../../components/ui/input-group";
|
||||
// import { LuSearch } from "react-icons/lu";
|
||||
// import { useGetContactQuery } from "../../../Redux/Service/deactivated.account.service";
|
||||
import { useEffect, useState } from "react";
|
||||
import { Spinner } from "../../../components/Sipnner/Spinner";
|
||||
import { useGetDeactivateUserQuery, useUserDeactivateToggleMutation } from "../../../Redux/Service/manage.user";
|
||||
import SearchComponent from "../../../components/SearchComponent";
|
||||
import { Toaster, toaster } from "../../../components/ui/toaster";
|
||||
import { delay } from "../../../components/Utils";
|
||||
|
||||
const tableHeadRow = [
|
||||
"Sr. No",
|
||||
@@ -17,8 +21,11 @@ const tableHeadRow = [
|
||||
];
|
||||
|
||||
const DeactivatedAccounts = () => {
|
||||
const { data ,isLoading} = useGetContactQuery();
|
||||
const [localData, setLocalData] = useState([]);
|
||||
const [currentPage, setCurrentPage] = useState(1);
|
||||
const { data, isLoading, refetch, isError, isFetching } = useGetDeactivateUserQuery(currentPage);
|
||||
const [localData, setLocalData] = useState<any[]>([]);
|
||||
const [searchTerm, setSearchTerm] = useState("");
|
||||
const [userDeactivateToggle] = useUserDeactivateToggleMutation()
|
||||
|
||||
useEffect(() => {
|
||||
if (data) {
|
||||
@@ -26,8 +33,47 @@ const DeactivatedAccounts = () => {
|
||||
}
|
||||
}, [data]);
|
||||
|
||||
const handlePageChange = (page: number) => {
|
||||
setCurrentPage(page);
|
||||
}
|
||||
|
||||
const manageUser = localData?.map((agency: any, index: number) => ({
|
||||
const filteredData = localData?.filter((agency) => {
|
||||
const searchLower = searchTerm.toLowerCase();
|
||||
const firstName = agency.first_name?.toLowerCase().includes(searchLower);
|
||||
const lastName = agency.last_name?.toLowerCase().includes(searchLower);
|
||||
// const email = agency.capital?.toLowerCase().includes(searchLower);
|
||||
return firstName || lastName;
|
||||
});
|
||||
|
||||
const handleToggle = async (agencyId: number, currentStatus: string) => {
|
||||
const newStatus = currentStatus === '1' ? '0' : '1';
|
||||
|
||||
setLocalData((prevData) =>
|
||||
prevData.map((agency) =>
|
||||
agency.id === agencyId ? { ...agency, is_active: newStatus } : agency
|
||||
)
|
||||
);
|
||||
|
||||
try {
|
||||
await userDeactivateToggle({ id: agencyId, is_active: newStatus }).unwrap();
|
||||
toaster.create({
|
||||
title: "Success",
|
||||
description: "Status updated successfully",
|
||||
type: "success",
|
||||
});
|
||||
await delay(500);
|
||||
refetch()
|
||||
} catch (error) {
|
||||
console.error("Error updating privacy policy:", error);
|
||||
setLocalData((prevData) =>
|
||||
prevData.map((agency) =>
|
||||
agency.id === agencyId ? { ...agency, is_active: currentStatus } : agency
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const manageUser = filteredData?.map((agency: any, index: number) => ({
|
||||
"Sr. No": index + 1,
|
||||
"First Name": agency?.first_name,
|
||||
"Last Name": agency?.last_name,
|
||||
@@ -38,13 +84,13 @@ const DeactivatedAccounts = () => {
|
||||
size={"sm"}
|
||||
colorPalette={"teal"}
|
||||
checked={agency.is_active === true}
|
||||
// onChange={() => handleToggle(agency.id, agency.is_active ? "1" : "0")}
|
||||
onChange={() => handleToggle(agency.id, agency.is_active ? "1" : "0")}
|
||||
/>
|
||||
</Box>
|
||||
),
|
||||
}));
|
||||
|
||||
if (isLoading) {
|
||||
if (isLoading) {
|
||||
return (
|
||||
<MainFrame>
|
||||
<Box
|
||||
@@ -89,37 +135,32 @@ const DeactivatedAccounts = () => {
|
||||
</Text>
|
||||
|
||||
<HStack>
|
||||
<InputGroup
|
||||
startElement={
|
||||
<LuSearch
|
||||
fontSize={"xs"}
|
||||
style={{ position: "relative", left: "10px" }}
|
||||
/>
|
||||
}
|
||||
color={"#000"}
|
||||
>
|
||||
<Input
|
||||
p={4}
|
||||
w={300}
|
||||
bg={"#fff"}
|
||||
colorPalette={"blue"}
|
||||
_focus={{ border: "1px solid #02A0A0" }}
|
||||
rounded={"md"}
|
||||
size={"2xs"}
|
||||
fontSize={"sm"}
|
||||
placeholder="Search..."
|
||||
bgColor={"#EEEEEE"}
|
||||
ps={8}
|
||||
/>
|
||||
</InputGroup>
|
||||
<SearchComponent
|
||||
value={searchTerm}
|
||||
onChange={(value) => {
|
||||
setSearchTerm(value);
|
||||
// setCurrentPage(1);
|
||||
refetch()
|
||||
}}
|
||||
/>
|
||||
</HStack>
|
||||
</HStack>
|
||||
<DataTable
|
||||
sortableColumns={["Name", "Registration Date "]}
|
||||
tableHeadRow={tableHeadRow}
|
||||
data={manageUser}
|
||||
paginationData={{
|
||||
current_page: data?.data.current_page || 1,
|
||||
last_page: data?.data.last_page || 1,
|
||||
per_page: data?.data.per_page || 10,
|
||||
total: data?.data.total || 0
|
||||
}}
|
||||
onPageChange={handlePageChange}
|
||||
isLoading={isFetching}
|
||||
isError={isError}
|
||||
/>
|
||||
</Box>
|
||||
<Toaster />
|
||||
</MainFrame>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Field, Input, Stack } from "@chakra-ui/react";
|
||||
import { Box, Field, Input, Stack } from "@chakra-ui/react";
|
||||
import {
|
||||
DialogActionTrigger,
|
||||
DialogBody,
|
||||
@@ -12,8 +12,32 @@ import {
|
||||
} from "../../../components/ui/dialog";
|
||||
import { Button } from "../../../components/ui/button";
|
||||
import { IoMdAdd } from "react-icons/io";
|
||||
import { useState } from "react";
|
||||
// import { useCreateUserMutation } from "../../../Redux/Service/manage.user";
|
||||
// import { useState } from "react";
|
||||
|
||||
function AddRegisterUsers() {
|
||||
// const [createUser] = useCreateUserMutation();
|
||||
const [userType, setUserType] = useState<number | "">("");
|
||||
|
||||
const [user, setUser] = useState<{
|
||||
principal_type_xid: number;
|
||||
principal_source_xid: number | "";
|
||||
first_name: string;
|
||||
last_name: string;
|
||||
gender: string;
|
||||
date_of_birth: string;
|
||||
language_name: string[];
|
||||
}>({
|
||||
principal_type_xid: 1,
|
||||
principal_source_xid: userType,
|
||||
first_name: '',
|
||||
last_name: '',
|
||||
gender: '',
|
||||
date_of_birth: '',
|
||||
language_name: [],
|
||||
});
|
||||
|
||||
return (
|
||||
<DialogRoot placement="center">
|
||||
<DialogTrigger asChild>
|
||||
@@ -23,13 +47,13 @@ function AddRegisterUsers() {
|
||||
</DialogTrigger>
|
||||
|
||||
<DialogContent
|
||||
bg={"#fff"}
|
||||
w={{ base: '90%', md: '400px' }}
|
||||
height={'80vh'}
|
||||
overflow={'scroll'}
|
||||
overflowX="hidden"
|
||||
p={3} // Reduced padding
|
||||
bgSize={'md'}
|
||||
bg={"#fff"}
|
||||
w={{ base: '90%', md: '400px' }}
|
||||
height={'80vh'}
|
||||
overflow={'scroll'}
|
||||
overflowX="hidden"
|
||||
p={3} // Reduced padding
|
||||
bgSize={'md'}
|
||||
>
|
||||
<DialogHeader bg="white" >
|
||||
<DialogTitle alignSelf="center" color="black" fontSize="14px">
|
||||
@@ -44,42 +68,110 @@ function AddRegisterUsers() {
|
||||
First Name
|
||||
</Field.Label>
|
||||
<Input
|
||||
bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px"
|
||||
bgColor="#EEEEEE"
|
||||
color="black"
|
||||
border="none"
|
||||
pl={1}
|
||||
fontSize="12px"
|
||||
height="30px"
|
||||
value={user.first_name}
|
||||
onChange={(e) => setUser({ ...user, first_name: e.target.value })}
|
||||
/>
|
||||
|
||||
<Field.Label color="black" pt={1} fontSize="12px">
|
||||
Last Name
|
||||
</Field.Label>
|
||||
<Input
|
||||
bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px"
|
||||
bgColor="#EEEEEE"
|
||||
color="black"
|
||||
border="none"
|
||||
pl={1}
|
||||
fontSize="12px"
|
||||
height="30px"
|
||||
value={user.last_name}
|
||||
onChange={(e) => setUser({ ...user, last_name: e.target.value })}
|
||||
/>
|
||||
|
||||
<Field.Label color="black" pt={1} fontSize="12px">
|
||||
Gender
|
||||
</Field.Label>
|
||||
<Input
|
||||
bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px"
|
||||
bgColor="#EEEEEE"
|
||||
color="black"
|
||||
border="none"
|
||||
pl={1}
|
||||
fontSize="12px"
|
||||
height="30px"
|
||||
value={user.gender}
|
||||
onChange={(e) => setUser({ ...user, gender: e.target.value })}
|
||||
/>
|
||||
|
||||
<Field.Label color="black" pt={1} fontSize="12px">
|
||||
DOB
|
||||
</Field.Label>
|
||||
<Input
|
||||
bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px"
|
||||
bgColor="#EEEEEE"
|
||||
color="black"
|
||||
border="none"
|
||||
pl={1}
|
||||
fontSize="12px"
|
||||
height="30px"
|
||||
type="date"
|
||||
value={user.date_of_birth}
|
||||
onChange={(e) => setUser({ ...user, date_of_birth: e.target.value })}
|
||||
/>
|
||||
|
||||
<Field.Label color="black" pt={1} fontSize="12px">
|
||||
<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.Label color="black" pt={1} fontSize="12px">
|
||||
OTP Verified
|
||||
</Field.Label>
|
||||
<Input
|
||||
bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px"
|
||||
/>
|
||||
/> */}
|
||||
|
||||
<Field.Label color="black" pt={1} fontSize="12px">
|
||||
Language
|
||||
</Field.Label>
|
||||
<Input
|
||||
bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px"
|
||||
bgColor="#EEEEEE"
|
||||
color="black"
|
||||
border="none"
|
||||
pl={1}
|
||||
fontSize="12px"
|
||||
height="30px"
|
||||
value={user.language_name.join(", ")} // display as comma-separated string
|
||||
onChange={(e) =>
|
||||
setUser({
|
||||
...user,
|
||||
language_name: e.target.value
|
||||
.split(",")
|
||||
.map(lang => lang.trim())
|
||||
.filter(Boolean), // remove empty strings
|
||||
})
|
||||
}
|
||||
|
||||
/>
|
||||
</Field.Root>
|
||||
</Stack>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
// import { MdOutlineRemoveRedEye } from "react-icons/md";
|
||||
import { Field, Input, Span, Stack } from "@chakra-ui/react";
|
||||
import { Box, Field, HStack, Input, Stack } from "@chakra-ui/react";
|
||||
import {
|
||||
DialogActionTrigger,
|
||||
DialogBody,
|
||||
DialogCloseTrigger,
|
||||
DialogContent,
|
||||
@@ -15,118 +14,332 @@ import {
|
||||
import { Button } from "../../../components/ui/button";
|
||||
// import { TbEdit } from "react-icons/tb";
|
||||
import Edit from "../../../components/ActionIcons/Edit";
|
||||
import { UserData, useUpdateUserMutation } from "../../../Redux/Service/manage.user";
|
||||
import { useState } from "react";
|
||||
import { Toaster, toaster } from "../../../components/ui/toaster";
|
||||
|
||||
interface UserPayload {
|
||||
id: number;
|
||||
principal_type_xid: number;
|
||||
principal_source_xid: number;
|
||||
first_name: string;
|
||||
last_name: string;
|
||||
gender: string;
|
||||
date_of_birth: string | null;
|
||||
language_xid: number; // ✅ Always an array
|
||||
}
|
||||
|
||||
export interface UserFormData {
|
||||
id: number;
|
||||
principal_type_xid: number;
|
||||
first_name: string;
|
||||
last_name: string;
|
||||
phone_number: string;
|
||||
gender: string;
|
||||
date_of_birth: string;
|
||||
is_active: boolean;
|
||||
principal_type: {
|
||||
id: number;
|
||||
principal_type_title: string;
|
||||
};
|
||||
principle_language_linkss: {
|
||||
id?: number;
|
||||
iam_principal_xid?: number;
|
||||
language_xid: number;
|
||||
};
|
||||
}
|
||||
|
||||
function EditRegisterUsers({ data, refetch }: { data: UserData, refetch: () => void }) {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const transformToFormData = (data: UserData): UserFormData => ({
|
||||
...data,
|
||||
principle_language_linkss: {
|
||||
...data.principle_language_linkss,
|
||||
language_xid: data.principle_language_linkss.language_xid, // wrap in array
|
||||
},
|
||||
});
|
||||
const [formData, setFormData] = useState<UserFormData>(transformToFormData(data));
|
||||
// const [formData, setFormData] = useState<UserData>({
|
||||
// id: data?.id,
|
||||
// first_name: data?.first_name || '',
|
||||
// last_name: data?.last_name || '',
|
||||
// principal_type_xid: data?.principal_type_xid,
|
||||
// phone_number: data?.phone_number || '',
|
||||
// gender: data?.gender || '',
|
||||
// date_of_birth: data?.date_of_birth || '',
|
||||
// principal_type: data?.principal_type,
|
||||
// is_active: data?.is_active ?? true,
|
||||
// principle_language_linkss: {
|
||||
// ...data?.principle_language_linkss,
|
||||
// language_xid: Array.isArray(data?.principle_language_linkss?.language_xid)
|
||||
// ? data.principle_language_linkss.language_xid
|
||||
// : [data?.principle_language_linkss?.language_xid].filter(Boolean),
|
||||
// },
|
||||
// // principle_language_linkss: data?.principle_language_linkss ?? [],
|
||||
// });
|
||||
const [updateUser, { isLoading }] = useUpdateUserMutation();
|
||||
|
||||
const handleOpenModal = () => {
|
||||
setIsOpen(true);
|
||||
};
|
||||
|
||||
const handleSubmit = async (event: React.FormEvent) => {
|
||||
event.preventDefault();
|
||||
if (formData.first_name === '' || formData.last_name === '' || formData.phone_number === '' || formData.gender === '' || formData.date_of_birth === '') {
|
||||
toaster.create({
|
||||
title: "Error",
|
||||
description: "Input fields cannot be empty",
|
||||
type: "error",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// const languageData = formData?.principle_language_linkss?.language_xid;
|
||||
|
||||
const payload: UserPayload = {
|
||||
id: formData?.id,
|
||||
principal_type_xid: formData?.principal_type_xid,
|
||||
principal_source_xid: formData?.id,
|
||||
first_name: formData?.first_name,
|
||||
last_name: formData?.last_name,
|
||||
gender: formData?.gender,
|
||||
date_of_birth: formData?.date_of_birth,
|
||||
// language_xid: languageData,
|
||||
language_xid: formData.principle_language_linkss?.language_xid
|
||||
? formData.principle_language_linkss.language_xid
|
||||
: formData.principle_language_linkss?.language_xid,
|
||||
|
||||
};
|
||||
|
||||
// console.log('payload', payload)
|
||||
|
||||
try {
|
||||
const response = await updateUser(payload).unwrap();
|
||||
if (response?.status === "success") {
|
||||
toaster.create({
|
||||
title: "Success",
|
||||
description: "Country updated successfully",
|
||||
type: "success",
|
||||
});
|
||||
setIsOpen(false);
|
||||
refetch()
|
||||
} else {
|
||||
toaster.create({
|
||||
title: "Error",
|
||||
description: "Failed to update Country",
|
||||
type: "error",
|
||||
});
|
||||
}
|
||||
} catch (error: any) {
|
||||
console.error("Error updating template:", error);
|
||||
// alert("Failed to update template");
|
||||
toaster.create({
|
||||
title: "Error",
|
||||
description: error ? `${error?.data.message}` : "Something went wrong",
|
||||
type: "error",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
function EditRegisterUsers() {
|
||||
return (
|
||||
<DialogRoot placement="center">
|
||||
<DialogTrigger asChild>
|
||||
<Span>
|
||||
<>
|
||||
<DialogRoot placement="center" key={formData.id} open={isOpen} onOpenChange={({ open }) => setIsOpen(open)}>
|
||||
<DialogTrigger asChild>
|
||||
{/* <Span>
|
||||
<Edit />
|
||||
</Span>
|
||||
</DialogTrigger>
|
||||
</Span> */}
|
||||
<Button bg="transparent" color={"black"} h={"18px"} onClick={handleOpenModal}><Edit /></Button>
|
||||
</DialogTrigger>
|
||||
|
||||
<DialogContent
|
||||
bg={"#fff"}
|
||||
w={{ base: "90%", md: "400px" }}
|
||||
height={"80vh"}
|
||||
overflow={"scroll"}
|
||||
overflowX="hidden"
|
||||
p={3} // Reduced padding
|
||||
bgSize={"md"}
|
||||
>
|
||||
<DialogHeader bg="white" p={0}>
|
||||
<DialogTitle alignSelf="center" color="black" fontSize="14px">
|
||||
Edit user Accounts
|
||||
</DialogTitle>
|
||||
</DialogHeader>
|
||||
<DialogContent
|
||||
bg={"#fff"}
|
||||
w={{ base: "90%", md: "400px" }}
|
||||
height={"80vh"}
|
||||
overflow={"scroll"}
|
||||
overflowX="hidden"
|
||||
p={3} // Reduced padding
|
||||
bgSize={"md"}
|
||||
>
|
||||
<DialogHeader bg="white" p={0}>
|
||||
<DialogTitle alignSelf="center" color="black" fontSize="14px">
|
||||
Edit user Accounts
|
||||
</DialogTitle>
|
||||
</DialogHeader>
|
||||
|
||||
<DialogBody bg="white">
|
||||
<Stack py={3}>
|
||||
<Field.Root>
|
||||
<Field.Label color="black" pt={1} fontSize="12px">
|
||||
First Name
|
||||
</Field.Label>
|
||||
<Input
|
||||
bgColor="#EEEEEE"
|
||||
color="black"
|
||||
border="none"
|
||||
pl={1}
|
||||
fontSize="12px"
|
||||
height="30px"
|
||||
/>
|
||||
<DialogBody bg="white">
|
||||
<Stack py={3}>
|
||||
<Field.Root>
|
||||
<Field.Label color="black" pt={1} fontSize="12px">
|
||||
First Name
|
||||
</Field.Label>
|
||||
<Input
|
||||
bgColor="#EEEEEE"
|
||||
color="black"
|
||||
border="none"
|
||||
pl={1}
|
||||
fontSize="12px"
|
||||
height="30px"
|
||||
value={formData.first_name}
|
||||
onChange={(e) => setFormData({ ...formData, first_name: e.target.value })}
|
||||
/>
|
||||
|
||||
<Field.Label color="black" pt={1} fontSize="12px">
|
||||
Last Name
|
||||
</Field.Label>
|
||||
<Input
|
||||
bgColor="#EEEEEE"
|
||||
color="black"
|
||||
border="none"
|
||||
pl={1}
|
||||
fontSize="12px"
|
||||
height="30px"
|
||||
/>
|
||||
<Field.Label color="black" pt={1} fontSize="12px">
|
||||
Last Name
|
||||
</Field.Label>
|
||||
<Input
|
||||
bgColor="#EEEEEE"
|
||||
color="black"
|
||||
border="none"
|
||||
pl={1}
|
||||
fontSize="12px"
|
||||
height="30px"
|
||||
value={formData.last_name}
|
||||
onChange={(e) => setFormData({ ...formData, last_name: e.target.value })}
|
||||
/>
|
||||
|
||||
<Field.Label color="black" pt={1} fontSize="12px">
|
||||
Gender
|
||||
</Field.Label>
|
||||
<Input
|
||||
bgColor="#EEEEEE"
|
||||
color="black"
|
||||
border="none"
|
||||
pl={1}
|
||||
fontSize="12px"
|
||||
height="30px"
|
||||
/>
|
||||
<Field.Label color="black" pt={1} fontSize="12px">
|
||||
Gender
|
||||
</Field.Label>
|
||||
<Input
|
||||
bgColor="#EEEEEE"
|
||||
color="black"
|
||||
border="none"
|
||||
pl={1}
|
||||
fontSize="12px"
|
||||
height="30px"
|
||||
value={formData.gender}
|
||||
onChange={(e) => setFormData({ ...formData, gender: e.target.value })}
|
||||
/>
|
||||
|
||||
<Field.Label color="black" pt={1} fontSize="12px">
|
||||
DOB
|
||||
</Field.Label>
|
||||
<Input
|
||||
bgColor="#EEEEEE"
|
||||
color="black"
|
||||
border="none"
|
||||
pl={1}
|
||||
fontSize="12px"
|
||||
height="30px"
|
||||
/>
|
||||
<Field.Label color="black" pt={1} fontSize="12px">
|
||||
DOB
|
||||
</Field.Label>
|
||||
<Input
|
||||
bgColor="#EEEEEE"
|
||||
color="black"
|
||||
border="none"
|
||||
pl={1}
|
||||
fontSize="12px"
|
||||
height="30px"
|
||||
value={formData.date_of_birth ? new Date(formData.date_of_birth).toLocaleDateString('en-GB').replace(/\//g, '-') : 'N/A'}
|
||||
onChange={(e) => setFormData({ ...formData, date_of_birth: e.target.value })}
|
||||
disabled={formData.principal_type_xid === 2 ? true : false}
|
||||
/>
|
||||
|
||||
<Field.Label color="black" pt={1} fontSize="12px">
|
||||
OTP Verified
|
||||
</Field.Label>
|
||||
<Input
|
||||
bgColor="#EEEEEE"
|
||||
color="black"
|
||||
border="none"
|
||||
pl={1}
|
||||
fontSize="12px"
|
||||
height="30px"
|
||||
/>
|
||||
<Field.Label color="black" pt={1} fontSize="12px">
|
||||
Mobile Number
|
||||
</Field.Label>
|
||||
<Input
|
||||
bgColor="#EEEEEE"
|
||||
color="black"
|
||||
border="none"
|
||||
pl={1}
|
||||
fontSize="12px"
|
||||
height="30px"
|
||||
value={formData.phone_number || ''}
|
||||
onChange={(e) => setFormData({ ...formData, phone_number: e.target.value })}
|
||||
/>
|
||||
|
||||
<Field.Label color="black" pt={1} fontSize="12px">
|
||||
Language
|
||||
</Field.Label>
|
||||
<Input
|
||||
bgColor="#EEEEEE"
|
||||
color="black"
|
||||
border="none"
|
||||
pl={1}
|
||||
fontSize="12px"
|
||||
height="30px"
|
||||
/>
|
||||
</Field.Root>
|
||||
</Stack>
|
||||
</DialogBody>
|
||||
<DialogFooter mt={5}>
|
||||
<DialogActionTrigger asChild>
|
||||
<Button rounded={"md"} w={"100%"} size={"sm"} bg={"#02A0A0"}>
|
||||
<Field.Label color="black" pt={1} fontSize="12px">
|
||||
Type Of User
|
||||
</Field.Label>
|
||||
{/* <Input
|
||||
bgColor="#EEEEEE"
|
||||
color="black"
|
||||
border="none"
|
||||
pl={1}
|
||||
fontSize="12px"
|
||||
height="30px"
|
||||
value={formData.principal_type?.principal_type_title || 'N/A'}
|
||||
onChange={(e) => setFormData({ ...formData, principal_type: { ...formData.principal_type, principal_type_title: e.target.value } })}
|
||||
/> */}
|
||||
|
||||
<Box>
|
||||
<select
|
||||
style={{
|
||||
width: "100%",
|
||||
background: "transparent",
|
||||
color: "black",
|
||||
border: "none",
|
||||
fontSize: "12px",
|
||||
height: "30px",
|
||||
outline: "none",
|
||||
}}
|
||||
value={formData.principal_type_xid?.toString() || 'N/A'}
|
||||
onChange={(e) => setFormData({ ...formData, principal_type_xid: Number(e.target.value) })}
|
||||
>
|
||||
{/* <option value="">Select User Type</option> */}
|
||||
<option value="2">Recruiter</option>
|
||||
<option value="3">Jobseeker</option>
|
||||
</select>
|
||||
</Box>
|
||||
|
||||
<Field.Label color="black" pt={1} fontSize="12px">
|
||||
Default Language
|
||||
</Field.Label>
|
||||
{/* <Input
|
||||
bgColor="#EEEEEE"
|
||||
color="black"
|
||||
border="none"
|
||||
pl={1}
|
||||
fontSize="12px"
|
||||
height="30px"
|
||||
value={formData?.principle_language_linkss?.language_xid || 'N/A'}
|
||||
onChange={(e) => setFormData({
|
||||
...formData, principle_language_linkss: {
|
||||
...formData?.principle_language_linkss, language_xid: e.target.value
|
||||
.split(",")
|
||||
.map(lang => lang.trim())
|
||||
.filter(Boolean)
|
||||
}
|
||||
})}
|
||||
/> */}
|
||||
|
||||
<HStack>
|
||||
<select
|
||||
style={{
|
||||
width: "100%",
|
||||
background: "transparent",
|
||||
color: "black",
|
||||
border: "none",
|
||||
fontSize: "12px",
|
||||
height: "30px",
|
||||
outline: "none",
|
||||
}}
|
||||
value={formData?.principle_language_linkss?.language_xid || ""}
|
||||
onChange={(e) => {
|
||||
const value = Number(e.target.value);
|
||||
setFormData({
|
||||
...formData,
|
||||
principle_language_linkss: {
|
||||
...formData?.principle_language_linkss,
|
||||
language_xid: value,
|
||||
},
|
||||
});
|
||||
}}
|
||||
>
|
||||
<option value="1">English</option>
|
||||
<option value="2">Hindi</option>
|
||||
<option value="3">Marathi</option>
|
||||
<option value="4">Telgu</option>
|
||||
<option value="5">Tamil</option>
|
||||
<option value="6">Bengali</option>
|
||||
<option value="7">Odia</option>
|
||||
</select>
|
||||
</HStack>
|
||||
</Field.Root>
|
||||
</Stack>
|
||||
</DialogBody>
|
||||
<DialogFooter mt={5}>
|
||||
<Button rounded={"md"} w={"100%"} size={"sm"} bg={"#02A0A0"} onClick={handleSubmit} disabled={isLoading}>
|
||||
Save
|
||||
</Button>
|
||||
</DialogActionTrigger>
|
||||
</DialogFooter>
|
||||
<DialogCloseTrigger color="black" />
|
||||
</DialogContent>
|
||||
</DialogRoot>
|
||||
</DialogFooter>
|
||||
<DialogCloseTrigger color="black" />
|
||||
</DialogContent>
|
||||
</DialogRoot >
|
||||
<Toaster />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import {
|
||||
Box, HStack,
|
||||
Image,
|
||||
// Image,
|
||||
Text
|
||||
Text,
|
||||
} from "@chakra-ui/react";
|
||||
import MainFrame from "../../../components/MainFrame";
|
||||
// import AlertDailog from "../../../components/AlertDailog";
|
||||
@@ -10,21 +11,26 @@ import DataTable from "../../../components/DataTable";
|
||||
import { Switch } from "../../../components/ui/switch";
|
||||
import ViewRegisterUsers from "./ViewRegisterUsers";
|
||||
import EditRegisterUsers from "./EditRegisterUsers";
|
||||
import AddRegisterUsers from "./AddRegisterUsers";
|
||||
// import AddRegisterUsers from "./AddRegisterUsers";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useGetManageUserQuery, UserData, useUserToggleMutation } from "../../../Redux/Service/manage.user";
|
||||
import { useDeleteUserMutation, useGetManageUserQuery, UserData, useUserToggleMutation } from "../../../Redux/Service/manage.user";
|
||||
import SearchComponent from "../../../components/SearchComponent";
|
||||
import AlertDailog from "../../../components/AlertDailog";
|
||||
import { toaster } from "../../../components/ui/toaster";
|
||||
import Delete from "../../../components/ActionIcons/Delete";
|
||||
import { delay } from "../../../components/Utils";
|
||||
// import Delete from "../../../components/ActionIcons/Delete";
|
||||
|
||||
const tableHeadRow = [
|
||||
"Sr. No",
|
||||
"First Name",
|
||||
"Last Name",
|
||||
"Mobile Number",
|
||||
"Gender",
|
||||
"DOB",
|
||||
"Type Of User",
|
||||
"Language",
|
||||
"Activate/Deactivate",
|
||||
"Default Language",
|
||||
"Active/Deactive",
|
||||
"Action",
|
||||
];
|
||||
|
||||
@@ -63,10 +69,14 @@ const tableHeadRow = [
|
||||
|
||||
const RegisterUsers = () => {
|
||||
const [currentPage, setCurrentPage] = useState(1);
|
||||
const { data, refetch } = useGetManageUserQuery(currentPage)
|
||||
const { data, refetch, isFetching, isError } = useGetManageUserQuery(currentPage)
|
||||
const [localData, setLocalData] = useState<any[]>([]);
|
||||
const [searchTerm, setSearchTerm] = useState("");
|
||||
const [userToggle] = useUserToggleMutation()
|
||||
const [deleteFaqPost] = useDeleteUserMutation()
|
||||
const [deleteModal, setDeleteModal] = useState(false)
|
||||
const [selectedFaqId, setSelectedFaqId] = useState<number | null>(null);
|
||||
|
||||
console.log("Register Users Data", data?.data.data);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -97,9 +107,20 @@ const RegisterUsers = () => {
|
||||
|
||||
try {
|
||||
await userToggle({ id: agencyId, is_active: newStatus }).unwrap();
|
||||
toaster.create({
|
||||
title: "Success",
|
||||
description: "Status updated successfully",
|
||||
type: "success",
|
||||
});
|
||||
await delay(500);
|
||||
refetch()
|
||||
} catch (error) {
|
||||
console.error("Error updating privacy policy:", error);
|
||||
toaster.create({
|
||||
title: "Error",
|
||||
description: "Someting went wrong.",
|
||||
type: "error",
|
||||
});
|
||||
setLocalData((prevData) =>
|
||||
prevData.map((agency) =>
|
||||
agency.id === agencyId ? { ...agency, is_active: currentStatus } : agency
|
||||
@@ -108,21 +129,46 @@ const RegisterUsers = () => {
|
||||
}
|
||||
}
|
||||
|
||||
const handleDeleteFaq = async (faqId: number) => {
|
||||
try {
|
||||
const response = await deleteFaqPost({ id: faqId }).unwrap();
|
||||
if (response?.status === "success") {
|
||||
toaster.create({
|
||||
title: "Success",
|
||||
description: "User deleted successfully",
|
||||
type: "success",
|
||||
});
|
||||
refetch()
|
||||
console.log("User deleted successfully:", response);
|
||||
}
|
||||
// Optionally, refetch data or update state after deletion
|
||||
} catch (error) {
|
||||
console.error("Error deleting User:", error);
|
||||
toaster.create({
|
||||
title: "Error",
|
||||
description: "Something went wrong",
|
||||
type: "error",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const managepost = filteredData?.flatMap((agency: UserData, index: number) => ({
|
||||
"Sr. No": (currentPage - 1) * (data?.data.per_page ?? 0) + index + 1,
|
||||
"First Name": agency.first_name,
|
||||
"Last Name": agency.last_name,
|
||||
"Mobile Number": agency.phone_number,
|
||||
"Gender": agency.gender,
|
||||
"DOB": agency.date_of_birth ? new Date(agency.date_of_birth).toLocaleDateString('en-GB').replace(/\//g, '-') : 'N/A',
|
||||
"Type Of User": agency.principal_type?.principal_type_title || 'N/A',
|
||||
// "Language": agency.principle_language_links.map(lang => lang.language_name).join(', ') || 'N/A',
|
||||
"Action": (
|
||||
"Default Language": agency?.principle_language_linkss?.language?.language_name,
|
||||
"Active/Deactive": agency.is_active === true ? 'Active' : 'Inactive',
|
||||
"Action": (
|
||||
<HStack justifyContent="center">
|
||||
<EditRegisterUsers
|
||||
// rowData={{ id: agency.id, en_name: agency.en_name, country_code: agency.country_code, phonecode: agency.phonecode, capital: agency.capital, currency: agency.currency, currency_name: agency.currency_name, currency_symbol: agency.currency_symbol }}
|
||||
// refetch={refetch}
|
||||
data={agency}
|
||||
refetch={refetch}
|
||||
/>
|
||||
<ViewRegisterUsers />
|
||||
<ViewRegisterUsers data={agency} />
|
||||
<Box>
|
||||
<Switch
|
||||
colorPalette={'teal'}
|
||||
@@ -131,6 +177,24 @@ const RegisterUsers = () => {
|
||||
onChange={() => handleToggle(agency.id, agency.is_active ? '1' : '0')}
|
||||
/>
|
||||
</Box>
|
||||
<AlertDailog
|
||||
isOpen={deleteModal}
|
||||
AltertTiggerIcon={() => <Delete onClick={() => {
|
||||
setSelectedFaqId(agency.id);
|
||||
setDeleteModal(true)
|
||||
}} />}
|
||||
alertText="Do you want to delete user?"
|
||||
alertIcon={<Image src={"DeleteIcon"} h={"39px"} />}
|
||||
alertCaption="are you sure you want to delete ?"
|
||||
onClose={() => setDeleteModal(false)}
|
||||
onConfirm={() => {
|
||||
// console.log("Deleting FAQ with ID:", selectedFaqId); // Correct ID
|
||||
if (selectedFaqId) {
|
||||
setDeleteModal(false);
|
||||
handleDeleteFaq(selectedFaqId);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</HStack>
|
||||
),
|
||||
}))
|
||||
@@ -158,7 +222,7 @@ const RegisterUsers = () => {
|
||||
refetch()
|
||||
}}
|
||||
/>
|
||||
<AddRegisterUsers />
|
||||
{/* <AddRegisterUsers /> */}
|
||||
</HStack>
|
||||
</HStack>
|
||||
<DataTable
|
||||
@@ -172,6 +236,8 @@ const RegisterUsers = () => {
|
||||
total: data?.data.total || 0
|
||||
}}
|
||||
onPageChange={handlePageChange}
|
||||
isLoading={isFetching}
|
||||
isError={isError}
|
||||
/>
|
||||
</Box>
|
||||
</MainFrame>
|
||||
|
||||
@@ -9,8 +9,9 @@ import {
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "../../../components/ui/dialog";
|
||||
import { UserData } from "../../../Redux/Service/manage.user";
|
||||
|
||||
function ViewRegisterUsers() {
|
||||
function ViewRegisterUsers({ data }: { data: UserData }) {
|
||||
return (
|
||||
<DialogRoot placement="center">
|
||||
<DialogTrigger asChild>
|
||||
@@ -18,13 +19,13 @@ function ViewRegisterUsers() {
|
||||
</DialogTrigger>
|
||||
|
||||
<DialogContent
|
||||
bg={"#fff"}
|
||||
w={{ base: '90%', md: '400px' }}
|
||||
height={'80vh'}
|
||||
overflow={'scroll'}
|
||||
overflowX="hidden"
|
||||
p={3} // Reduced padding
|
||||
bgSize={'md'}
|
||||
bg={"#fff"}
|
||||
w={{ base: '90%', md: '400px' }}
|
||||
height={'80vh'}
|
||||
overflow={'scroll'}
|
||||
overflowX="hidden"
|
||||
p={3} // Reduced padding
|
||||
bgSize={'md'}
|
||||
>
|
||||
<DialogHeader bg="white">
|
||||
<DialogTitle alignSelf="center" color="black" fontSize="14px">
|
||||
@@ -39,14 +40,24 @@ function ViewRegisterUsers() {
|
||||
First Name
|
||||
</Field.Label>
|
||||
<Input
|
||||
bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px"
|
||||
bgColor="#EEEEEE"
|
||||
color="black"
|
||||
border="none"
|
||||
pl={1}
|
||||
fontSize="12px"
|
||||
height="30px"
|
||||
value={data?.first_name || ''}
|
||||
/>
|
||||
|
||||
<Field.Label color="black" pt={1} fontSize="12px">
|
||||
Last Name
|
||||
</Field.Label>
|
||||
<Input
|
||||
bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px"
|
||||
bgColor="#EEEEEE"
|
||||
color="black"
|
||||
border="none" pl={1}
|
||||
fontSize="12px" height="30px"
|
||||
value={data?.last_name || ''}
|
||||
/>
|
||||
|
||||
<Field.Label color="black" pt={1} fontSize="12px">
|
||||
@@ -54,6 +65,7 @@ function ViewRegisterUsers() {
|
||||
</Field.Label>
|
||||
<Input
|
||||
bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px"
|
||||
value={data?.gender || ''}
|
||||
/>
|
||||
|
||||
<Field.Label color="black" pt={1} fontSize="12px">
|
||||
@@ -61,20 +73,41 @@ function ViewRegisterUsers() {
|
||||
</Field.Label>
|
||||
<Input
|
||||
bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px"
|
||||
value={data?.date_of_birth ? new Date(data.date_of_birth).toLocaleDateString('en-GB').replace(/\//g, '-') : 'N/A'}
|
||||
/>
|
||||
|
||||
<Field.Label color="black" pt={1} fontSize="12px">
|
||||
OTP Verified
|
||||
Mobile Number
|
||||
</Field.Label>
|
||||
<Input
|
||||
bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px"
|
||||
bgColor="#EEEEEE"
|
||||
color="black"
|
||||
border="none"
|
||||
pl={1}
|
||||
fontSize="12px"
|
||||
height="30px"
|
||||
value={data?.phone_number || ''}
|
||||
/>
|
||||
|
||||
<Field.Label color="black" pt={1} fontSize="12px">
|
||||
Language
|
||||
Type Of User
|
||||
</Field.Label>
|
||||
<Input
|
||||
bgColor="#EEEEEE"
|
||||
color="black"
|
||||
border="none"
|
||||
pl={1}
|
||||
fontSize="12px"
|
||||
height="30px"
|
||||
value={data?.principal_type?.principal_type_title || 'N/A'}
|
||||
/>
|
||||
|
||||
<Field.Label color="black" pt={1} fontSize="12px">
|
||||
Default Language
|
||||
</Field.Label>
|
||||
<Input
|
||||
bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px"
|
||||
value={data?.principle_language_linkss?.language?.language_name || 'N/A'}
|
||||
/>
|
||||
</Field.Root>
|
||||
</Stack>
|
||||
|
||||
@@ -2,12 +2,15 @@ import { Box, HStack, Text } from "@chakra-ui/react";
|
||||
import MainFrame from "../../../components/MainFrame"
|
||||
import DataTable from "../../../components/DataTable";
|
||||
import { Switch } from "../../../components/ui/switch";
|
||||
// import EditAgencyMaster from "./EditAgencyMaster";
|
||||
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";
|
||||
import SearchComponent from "../../../components/SearchComponent";
|
||||
import { useDebounce } from "../../../components/Hooks/useDebounce";
|
||||
import { toaster, Toaster } from "../../../components/ui/toaster";
|
||||
import { delay } from "../../../components/Utils";
|
||||
|
||||
// table data
|
||||
|
||||
@@ -20,6 +23,7 @@ const tableHeadRow = [
|
||||
"Registered Office Address",
|
||||
"Website/Domain",
|
||||
"GST no.",
|
||||
"Agency Status",
|
||||
"Action"
|
||||
|
||||
];
|
||||
@@ -48,10 +52,12 @@ const tableHeadRow = [
|
||||
|
||||
const AgencyMaster = () => {
|
||||
const [currentPage, setCurrentPage] = useState(1);
|
||||
const { data, refetch } = useGetAgencyMasterQuery(currentPage)
|
||||
const [agencyMasterToggle] = useAgencyMasterToggleMutation()
|
||||
const [localData, setLocalData] = useState<any[]>([]);
|
||||
const [searchTerm, setSearchTerm] = useState("");
|
||||
const debouncedSearchTerm = useDebounce(searchTerm, 500);
|
||||
const queryArgs = debouncedSearchTerm ? { page: currentPage, search: debouncedSearchTerm } : { page: currentPage };
|
||||
const { data, refetch, isError, isFetching } = useGetAgencyMasterQuery(queryArgs)
|
||||
|
||||
const handleToggle = async (agencyId: string, currentStatus: number) => {
|
||||
const newStatus = currentStatus ? 0 : 1;
|
||||
@@ -62,6 +68,12 @@ const AgencyMaster = () => {
|
||||
);
|
||||
try {
|
||||
await agencyMasterToggle({ id: agencyId, is_active: newStatus }).unwrap();
|
||||
toaster.create({
|
||||
title: "Success",
|
||||
description: "Status updated successfully",
|
||||
type: "success",
|
||||
});
|
||||
await delay(500);
|
||||
refetch()
|
||||
} catch (error) {
|
||||
console.error("Error updating privacy policy:", error);
|
||||
@@ -70,6 +82,11 @@ const AgencyMaster = () => {
|
||||
agency.id === agencyId ? { ...agency, is_active: currentStatus } : agency
|
||||
)
|
||||
);
|
||||
toaster.create({
|
||||
title: "Error",
|
||||
description: "Please try again later",
|
||||
type: "error",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@@ -77,36 +94,55 @@ const AgencyMaster = () => {
|
||||
setCurrentPage(page);
|
||||
};
|
||||
|
||||
const handleSearchChange = (value: string) => {
|
||||
setSearchTerm(value);
|
||||
setCurrentPage(1);
|
||||
};
|
||||
|
||||
const filteredData = localData?.filter((agency) =>
|
||||
agency?.name.toLowerCase().includes(searchTerm.toLowerCase())
|
||||
agency?.name.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
||||
agency?.rc_number.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
||||
agency?.state.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
||||
agency?.registered_office.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
||||
agency?.domain_name.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
||||
agency?.gst_number.toLowerCase().includes(searchTerm.toLowerCase())
|
||||
);
|
||||
|
||||
const managepost = filteredData?.map((agency: any, index: number) => ({
|
||||
'id': agency.id,
|
||||
"Sr. No": (currentPage - 1) * (data?.data.per_page ?? 0) + 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 agency={localData} id={agency.id} />
|
||||
{/* <EditAgencyMaster editData={{ id: agency.id, name: agency.name, domain_name: agency.domain_name, gst_number: agency.gst_number, rc_number: agency.rc_number, rc_status: agency.rc_status, registered_office: agency.registered_office, state: agency.state }} refetch={refetch} /> */}
|
||||
<Box>
|
||||
<Switch
|
||||
colorPalette={"teal"}
|
||||
size={"xs"}
|
||||
onChange={() => handleToggle(agency.id.toString(), Number(agency.is_active))}
|
||||
checked={Boolean(Number(agency.is_active))}
|
||||
/>
|
||||
</Box>
|
||||
</HStack>
|
||||
),
|
||||
}));
|
||||
// const activeCount = filteredData?.filter((a: any) => a.is_active === 1).length ?? 0;
|
||||
|
||||
const managepost = filteredData?.map((agency: any, index: number) => {
|
||||
// const isOnlyActive = activeCount === 1 && agency.is_active === 1;
|
||||
|
||||
return {
|
||||
id: agency.id,
|
||||
"Sr. No": (currentPage - 1) * (data?.data.per_page ?? 0) + 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,
|
||||
"Agency Status": agency.is_domain_verified ? "Verified" : "Unverified",
|
||||
"is_active": agency.is_active,
|
||||
Action: (
|
||||
<HStack justifyContent="center">
|
||||
<ViewAgencyMaster agency={localData} id={agency.id} />
|
||||
<EditAgencyMaster editData={agency} refetch={refetch} />
|
||||
<Box>
|
||||
<Switch
|
||||
colorPalette={"teal"}
|
||||
size={"xs"}
|
||||
onChange={() => handleToggle(agency.id.toString(), Number(agency.is_active))}
|
||||
checked={Boolean(Number(agency.is_active))}
|
||||
// disabled={isOnlyActive}
|
||||
/>
|
||||
</Box>
|
||||
</HStack>
|
||||
),
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
if (data?.data?.data) {
|
||||
@@ -158,7 +194,7 @@ const AgencyMaster = () => {
|
||||
</InputGroup> */}
|
||||
<SearchComponent
|
||||
value={searchTerm}
|
||||
onChange={setSearchTerm}
|
||||
onChange={handleSearchChange}
|
||||
/>
|
||||
{/* <ViewAgencyAddModel refetch={refetch} /> */}
|
||||
</HStack>
|
||||
@@ -174,8 +210,11 @@ const AgencyMaster = () => {
|
||||
total: data?.data.total || 0
|
||||
}}
|
||||
onPageChange={handlePageChange}
|
||||
isLoading={isFetching}
|
||||
isError={isError}
|
||||
/>
|
||||
</Box>
|
||||
</Box>
|
||||
<Toaster />
|
||||
</MainFrame>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -15,34 +15,47 @@ import { useEffect, useState } from "react";
|
||||
import { useUpdateAgencyMasterMutation } from "../../../Redux/Service/agency.master.module.service";
|
||||
import { Toaster, toaster } from "../../../components/ui/toaster";
|
||||
|
||||
interface Organization {
|
||||
id: number;
|
||||
raid?: string;
|
||||
// interface Organization {
|
||||
// id: number;
|
||||
// raid?: string;
|
||||
// name: string;
|
||||
// auth_signatory?: string;
|
||||
// state: string;
|
||||
// district?: string;
|
||||
// rc_number: number;
|
||||
// contact_details?: string;
|
||||
// registered_office: string;
|
||||
// branch_office?: string;
|
||||
// registered_email?: string;
|
||||
// other_email?: string;
|
||||
// registered_contact?: string;
|
||||
// website?: string;
|
||||
// domain_name: string;
|
||||
// staff_domain_name?: string;
|
||||
// gst_number: string;
|
||||
// rc_status?: "Active" | "Inactive"; // Assuming it's a status with limited values
|
||||
// }
|
||||
|
||||
type AgencyFormData = {
|
||||
id: string;
|
||||
name: string;
|
||||
auth_signatory?: string;
|
||||
state: string;
|
||||
district?: string;
|
||||
rc_number: number;
|
||||
contact_details?: string;
|
||||
rc_number: string;
|
||||
registered_office: string;
|
||||
branch_office?: string;
|
||||
registered_email?: string;
|
||||
other_email?: string;
|
||||
registered_contact?: string;
|
||||
website?: string;
|
||||
domain_name: string;
|
||||
staff_domain_name?: string;
|
||||
gst_number: string;
|
||||
rc_status?: "Active" | "Inactive"; // Assuming it's a status with limited values
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
function EditAgencyMaster({ editData, refetch }: { editData: Organization, refetch: VoidFunction }) {
|
||||
|
||||
function EditAgencyMaster<T extends AgencyFormData>({ editData, refetch }: { editData: T, refetch: VoidFunction }) {
|
||||
|
||||
const [formData, setFormData] = useState(editData);
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [updateAgencyMaster] = useUpdateAgencyMasterMutation()
|
||||
const [updateAgencyMaster, { isLoading }] = useUpdateAgencyMasterMutation()
|
||||
|
||||
console.log("Edit Data", editData);
|
||||
|
||||
useEffect(() => {
|
||||
setFormData(editData);
|
||||
}, [editData]);
|
||||
@@ -104,11 +117,11 @@ function EditAgencyMaster({ editData, refetch }: { editData: Organization, refet
|
||||
type: "error",
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
} catch (error: any) {
|
||||
console.error("Error updating template:", error);
|
||||
toaster.create({
|
||||
title: "Error",
|
||||
description: "Something went wrong.",
|
||||
description: `${error.data.message || "Failed to update"}`,
|
||||
type: "error",
|
||||
});
|
||||
// alert("Failed to update template");
|
||||
@@ -254,6 +267,7 @@ function EditAgencyMaster({ editData, refetch }: { editData: Organization, refet
|
||||
fontSize="12px"
|
||||
height="30px"
|
||||
onClick={handleSubmit}
|
||||
disabled={isLoading}
|
||||
>
|
||||
Save
|
||||
</Button>
|
||||
|
||||
@@ -70,7 +70,7 @@ function ViewAgencyAddModel({ refetch }: { refetch: VoidFunction }) {
|
||||
console.error("Error updating template:", error);
|
||||
toaster.create({
|
||||
title: "Error",
|
||||
description: "Something went wrong",
|
||||
description: "Please try again later",
|
||||
type: "error",
|
||||
});
|
||||
|
||||
|
||||
@@ -7,6 +7,9 @@ import EditCountryModel from "./EditCountryModel";
|
||||
import { CountryData, useCountryToggleMutation, useGetCountryMasterQuery } from "../../../Redux/Service/country.master";
|
||||
import { useEffect, useState } from "react";
|
||||
import SearchComponent from "../../../components/SearchComponent";
|
||||
import { useDebounce } from "../../../components/Hooks/useDebounce";
|
||||
import { toaster, Toaster } from "../../../components/ui/toaster";
|
||||
import { delay } from "../../../components/Utils";
|
||||
|
||||
|
||||
|
||||
@@ -36,10 +39,13 @@ const tableHeadRow = [
|
||||
|
||||
const Country = () => {
|
||||
const [currentPage, setCurrentPage] = useState(1);
|
||||
const { data, refetch } = useGetCountryMasterQuery(currentPage)
|
||||
// const { data, refetch } = useGetCountryMasterQuery(currentPage)
|
||||
const [countryToggle] = useCountryToggleMutation()
|
||||
const [localData, setLocalData] = useState<any[]>([]);
|
||||
const [searchTerm, setSearchTerm] = useState("");
|
||||
const debouncedSearchTerm = useDebounce(searchTerm, 500);
|
||||
const queryArgs = debouncedSearchTerm ? { page: currentPage, search: debouncedSearchTerm } : { page: currentPage };
|
||||
const { data, refetch, isError, isFetching } = useGetCountryMasterQuery(queryArgs);
|
||||
console.log("Country Data", data?.data.data)
|
||||
|
||||
useEffect(() => {
|
||||
@@ -52,6 +58,11 @@ const Country = () => {
|
||||
setCurrentPage(page);
|
||||
};
|
||||
|
||||
const handleSearchChange = (value: string) => {
|
||||
setSearchTerm(value);
|
||||
setCurrentPage(1);
|
||||
};
|
||||
|
||||
const filteredData = localData?.filter((agency) => {
|
||||
const searchLower = searchTerm.toLowerCase();
|
||||
const countryName = agency.en_name?.toLowerCase().includes(searchLower);
|
||||
@@ -70,9 +81,20 @@ const Country = () => {
|
||||
|
||||
try {
|
||||
await countryToggle({ id: agencyId, is_active: newStatus }).unwrap();
|
||||
toaster.create({
|
||||
title: "Success",
|
||||
description: "Status updated successfully",
|
||||
type: "success",
|
||||
});
|
||||
await delay(500);
|
||||
refetch()
|
||||
} catch (error) {
|
||||
console.error("Error updating privacy policy:", error);
|
||||
toaster.create({
|
||||
title: "Error",
|
||||
description: "Please try again later.",
|
||||
type: "error",
|
||||
});
|
||||
setLocalData((prevData) =>
|
||||
prevData.map((agency) =>
|
||||
agency.id === agencyId ? { ...agency, is_active: currentStatus } : agency
|
||||
@@ -99,6 +121,7 @@ const Country = () => {
|
||||
),
|
||||
}))
|
||||
|
||||
|
||||
return (
|
||||
|
||||
<MainFrame>
|
||||
@@ -137,14 +160,15 @@ const Country = () => {
|
||||
</InputGroup> */}
|
||||
<SearchComponent
|
||||
value={searchTerm}
|
||||
onChange={(value) => {
|
||||
setSearchTerm(value);
|
||||
// setCurrentPage(1);
|
||||
refetch()
|
||||
}}
|
||||
// onChange={(value) => {
|
||||
// setSearchTerm(value);
|
||||
// // setCurrentPage(1);
|
||||
// refetch()
|
||||
// }}
|
||||
onChange={handleSearchChange}
|
||||
/>
|
||||
{/* <Button bgColor={'#EEEEEE'} pl={3} pr={3}><IoMdAdd /> <Text>Add</Text></Button> */}
|
||||
<CountryAddModel />
|
||||
<CountryAddModel refetch={refetch} />
|
||||
</HStack>
|
||||
</HStack>
|
||||
<DataTable
|
||||
@@ -158,8 +182,11 @@ const Country = () => {
|
||||
total: data?.data.total || 0
|
||||
}}
|
||||
onPageChange={handlePageChange}
|
||||
isLoading={isFetching}
|
||||
isError={isError}
|
||||
/>
|
||||
</Box>
|
||||
<Toaster />
|
||||
</MainFrame>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2,12 +2,12 @@ import { DialogBody, DialogCloseTrigger, DialogContent, DialogFooter, DialogHead
|
||||
import { Field, Input, Stack, Text } from "@chakra-ui/react"
|
||||
import { IoMdAdd } from "react-icons/io"
|
||||
import { Button } from "../../../components/ui/button"
|
||||
import { useState } from "react";
|
||||
import { useEffect, useState } from "react";
|
||||
import { PostCountry, useCreateCountryPostMutation } from "../../../Redux/Service/country.master";
|
||||
import { Toaster, toaster } from "../../../components/ui/toaster";
|
||||
|
||||
function CountryAddModel() {
|
||||
const [createCountryPost] = useCreateCountryPostMutation()
|
||||
function CountryAddModel({refetch}: { refetch: VoidFunction }) {
|
||||
const [createCountryPost, { isLoading }] = useCreateCountryPostMutation()
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [countryName, setCountryName] = useState<PostCountry>({
|
||||
en_name: '',
|
||||
@@ -19,12 +19,26 @@ function CountryAddModel() {
|
||||
currency_symbol: '',
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (!isOpen) {
|
||||
setCountryName({
|
||||
en_name: '',
|
||||
country_code: '',
|
||||
phonecode: '',
|
||||
capital: '',
|
||||
currency: '',
|
||||
currency_name: '',
|
||||
currency_symbol: '',
|
||||
});
|
||||
}
|
||||
}, [isOpen]);
|
||||
|
||||
const handleOpenModal = () => {
|
||||
setIsOpen(true); // Open modal when clicking "Add"
|
||||
};
|
||||
|
||||
const handleSubmit = async () => {
|
||||
if (countryName.en_name === "") {
|
||||
if (countryName.en_name === "" || countryName.country_code === "" || countryName.phonecode === "" || countryName.capital === "" || countryName.currency === "" || countryName.currency_name === "" || countryName.currency_symbol === "") {
|
||||
toaster.create({
|
||||
title: "Error",
|
||||
description: "Input fields cannot be empty",
|
||||
@@ -52,6 +66,7 @@ function CountryAddModel() {
|
||||
type: "success",
|
||||
});
|
||||
setIsOpen(false);
|
||||
refetch();
|
||||
} else {
|
||||
toaster.create({
|
||||
title: "Error",
|
||||
@@ -98,7 +113,7 @@ function CountryAddModel() {
|
||||
<Field.Root>
|
||||
<Field.Label color="black" pt={1} fontSize="12px">Country</Field.Label>
|
||||
<Input
|
||||
placeholder=""
|
||||
placeholder="Enter Country Name"
|
||||
bgColor="#EEEEEE"
|
||||
color="black"
|
||||
border="none"
|
||||
@@ -111,7 +126,7 @@ function CountryAddModel() {
|
||||
|
||||
<Field.Label color="black" pt={1} fontSize="12px">Country Code</Field.Label>
|
||||
<Input
|
||||
placeholder=""
|
||||
placeholder="Please enter country code ex: IN, US"
|
||||
bgColor="#EEEEEE"
|
||||
color="black"
|
||||
border="none"
|
||||
@@ -124,7 +139,7 @@ function CountryAddModel() {
|
||||
|
||||
<Field.Label color="black" pt={1} fontSize="12px">Phone Code</Field.Label>
|
||||
<Input
|
||||
placeholder=""
|
||||
placeholder="Please enter phone code ex: +91, +1"
|
||||
bgColor="#EEEEEE"
|
||||
color="black"
|
||||
border="none"
|
||||
@@ -136,7 +151,7 @@ function CountryAddModel() {
|
||||
/>
|
||||
<Field.Label color="black" pt={1} fontSize="12px">Capital</Field.Label>
|
||||
<Input
|
||||
placeholder=""
|
||||
placeholder="Enter Capital City"
|
||||
bgColor="#EEEEEE"
|
||||
color="black"
|
||||
border="none"
|
||||
@@ -148,7 +163,7 @@ function CountryAddModel() {
|
||||
/>
|
||||
<Field.Label color="black" pt={1} fontSize="12px">Currency</Field.Label>
|
||||
<Input
|
||||
placeholder=""
|
||||
placeholder="Enter Currency"
|
||||
bgColor="#EEEEEE"
|
||||
color="black"
|
||||
border="none"
|
||||
@@ -160,7 +175,7 @@ function CountryAddModel() {
|
||||
/>
|
||||
<Field.Label color="black" pt={1} fontSize="12px">Currency name</Field.Label>
|
||||
<Input
|
||||
placeholder=""
|
||||
placeholder="Enter Currency Name"
|
||||
bgColor="#EEEEEE"
|
||||
color="black"
|
||||
border="none"
|
||||
@@ -172,7 +187,7 @@ function CountryAddModel() {
|
||||
/>
|
||||
<Field.Label color="black" pt={1} fontSize="12px">Currency Symbol</Field.Label>
|
||||
<Input
|
||||
placeholder=""
|
||||
placeholder="Enter Currency Symbol"
|
||||
bgColor="#EEEEEE"
|
||||
color="black"
|
||||
border="none"
|
||||
@@ -187,7 +202,7 @@ function CountryAddModel() {
|
||||
|
||||
</DialogBody>
|
||||
<DialogFooter display="flex" justifyContent="center" pt={"2"}>
|
||||
<Button w="100%" bg="#02A0A0" color={"#fff"} onClick={handleSubmit}>
|
||||
<Button w="100%" bg="#02A0A0" color={"#fff"} onClick={handleSubmit} disabled={isLoading}>
|
||||
Save
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
|
||||
@@ -36,7 +36,7 @@ export interface EditCountryModelProps {
|
||||
|
||||
|
||||
function EditCountryModel({ rowData, refetch }: { rowData: EditCountryModelProps, refetch: VoidFunction }) {
|
||||
const [updateCountry] = useUpdateCountryMutation()
|
||||
const [updateCountry, { isLoading }] = useUpdateCountryMutation()
|
||||
const [editData, setEditData] = useState(rowData)
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
|
||||
@@ -145,7 +145,7 @@ function EditCountryModel({ rowData, refetch }: { rowData: EditCountryModelProps
|
||||
</Stack>
|
||||
</DialogBody>
|
||||
<DialogFooter display="flex" justifyContent="center" pt={"2"}>
|
||||
<Button w="100%" bg="#02A0A0" color={"#fff"} onClick={handleSubmit}>
|
||||
<Button w="100%" bg="#02A0A0" color={"#fff"} onClick={handleSubmit} disabled={isLoading}>
|
||||
Save
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
|
||||
@@ -9,7 +9,7 @@ import { useCreateDepartmentPostMutation, useGetDepartmentMasterDropDownQuery }
|
||||
function AddDepartmentMaster({ refetch }: { refetch: VoidFunction }) {
|
||||
const [jobType, setJobType] = useState("");
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [createDepartmentPost] = useCreateDepartmentPostMutation()
|
||||
const [createDepartmentPost, { isLoading }] = useCreateDepartmentPostMutation()
|
||||
const { data } = useGetDepartmentMasterDropDownQuery()
|
||||
const [selectdDep, setSelectdDep] = useState<any>({
|
||||
id: '',
|
||||
@@ -140,7 +140,7 @@ function AddDepartmentMaster({ refetch }: { refetch: VoidFunction }) {
|
||||
|
||||
</DialogBody>
|
||||
<DialogFooter display="flex" justifyContent="center" pt={"2"}>
|
||||
<Button w="100%" bg="#02A0A0" color={"#fff"} onClick={handleSubmit}>
|
||||
<Button w="100%" bg="#02A0A0" color={"#fff"} onClick={handleSubmit} disabled={isLoading}>
|
||||
Save
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
|
||||
@@ -9,6 +9,9 @@ import SearchComponent from "../../../components/SearchComponent";
|
||||
import { useDepartmentToggleMutation, useGetDepartmentMasterQuery } from "../../../Redux/Service/department.master";
|
||||
import AddDepartmentMaster from "./AddDepartmentMaster";
|
||||
import EditDepartmentMaster from "./EditDepartmentMaster";
|
||||
import { useDebounce } from "../../../components/Hooks/useDebounce";
|
||||
import { Toaster, toaster } from "../../../components/ui/toaster";
|
||||
import { delay } from "../../../components/Utils";
|
||||
|
||||
|
||||
// table data
|
||||
@@ -24,12 +27,14 @@ const tableHeadRow = [
|
||||
|
||||
const DepartmentMasterList = () => {
|
||||
const [currentPage, setCurrentPage] = useState(1);
|
||||
const { data, refetch } = useGetDepartmentMasterQuery(currentPage)
|
||||
const [departmentToggle] = useDepartmentToggleMutation()
|
||||
const [localData, setLocalData] = useState<any[]>([]);
|
||||
const [searchTerm, setSearchTerm] = useState("");
|
||||
const [searchTerm, setSearchTerm] = useState("");
|
||||
const debouncedSearchTerm = useDebounce(searchTerm, 500);
|
||||
const queryArgs = debouncedSearchTerm ? { page: currentPage, search: debouncedSearchTerm } : { page: currentPage };
|
||||
const { data, refetch, isError, isFetching } = useGetDepartmentMasterQuery(queryArgs)
|
||||
|
||||
console.log("Department Data", data?.data.data)
|
||||
console.log("Department Data", data?.data.data)
|
||||
|
||||
useEffect(() => {
|
||||
if (data?.data?.data) {
|
||||
@@ -37,6 +42,11 @@ const DepartmentMasterList = () => {
|
||||
}
|
||||
}, [data]);
|
||||
|
||||
const handleSearchChange = (value: string) => {
|
||||
setSearchTerm(value);
|
||||
setCurrentPage(1);
|
||||
};
|
||||
|
||||
const handlePageChange = (page: number) => {
|
||||
setCurrentPage(page);
|
||||
};
|
||||
@@ -50,9 +60,20 @@ const DepartmentMasterList = () => {
|
||||
);
|
||||
try {
|
||||
await departmentToggle({ id: agencyId, is_active: newStatus }).unwrap();
|
||||
toaster.create({
|
||||
title: "Success",
|
||||
description: "Status updated successfully",
|
||||
type: "success",
|
||||
});
|
||||
await delay(500);
|
||||
refetch()
|
||||
} catch (error) {
|
||||
console.error("Error updating privacy policy:", error);
|
||||
toaster.create({
|
||||
title: "Error",
|
||||
description: "Someting went wrong.",
|
||||
type: "error",
|
||||
});
|
||||
setLocalData((prevData) =>
|
||||
prevData.map((agency) =>
|
||||
agency.id === agencyId ? { ...agency, is_active: currentStatus } : agency
|
||||
@@ -112,11 +133,7 @@ const DepartmentMasterList = () => {
|
||||
<HStack >
|
||||
<SearchComponent
|
||||
value={searchTerm}
|
||||
onChange={(value) => {
|
||||
setSearchTerm(value);
|
||||
// setCurrentPage(1);
|
||||
refetch()
|
||||
}}
|
||||
onChange={handleSearchChange}
|
||||
/>
|
||||
{/* <Button bgColor={'#EEEEEE'} pl={3} pr={3}><IoMdAdd /> <Text>Add</Text></Button> */}
|
||||
{/* <ViewAgencyAddModel /> */}
|
||||
@@ -134,8 +151,11 @@ const DepartmentMasterList = () => {
|
||||
total: data?.data.total || 0
|
||||
}}
|
||||
onPageChange={handlePageChange}
|
||||
isLoading={isFetching}
|
||||
isError={isError}
|
||||
/>
|
||||
</Box>
|
||||
<Toaster />
|
||||
</MainFrame>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ import { useGetDepartmentMasterDropDownQuery, useUpdateDepartmentMutation } from
|
||||
|
||||
function EditDepartmentMaster({ localData, refetch }: { localData: any, refetch: VoidFunction }) {
|
||||
const [jobtype, setJobType] = useState("");
|
||||
const [updateDepartment] = useUpdateDepartmentMutation()
|
||||
const [updateDepartment, { isLoading }] = useUpdateDepartmentMutation()
|
||||
const { data } = useGetDepartmentMasterDropDownQuery()
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [selectdDep, setSelectdDep] = useState<any>({
|
||||
@@ -145,7 +145,7 @@ function EditDepartmentMaster({ localData, refetch }: { localData: any, refetch:
|
||||
</Stack>
|
||||
</DialogBody>
|
||||
<DialogFooter display="flex" justifyContent="center" pt={"2"}>
|
||||
<Button w="100%" bg="#02A0A0" color={"#fff"} onClick={handleSubmit}>
|
||||
<Button w="100%" bg="#02A0A0" color={"#fff"} onClick={handleSubmit} disabled={isLoading}>
|
||||
Save
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
|
||||
@@ -9,7 +9,7 @@ import { useCreateIndustryMasterPostMutation } from "../../../Redux/Service/indu
|
||||
function AddIndustryMaster({ refetch }: { refetch: VoidFunction }) {
|
||||
const [jobType, setJobType] = useState("");
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [createIndustryMasterPost] = useCreateIndustryMasterPostMutation()
|
||||
const [createIndustryMasterPost, { isLoading }] = useCreateIndustryMasterPostMutation()
|
||||
|
||||
const handleOpenModal = () => {
|
||||
setIsOpen(true); // Open modal when clicking "Add"
|
||||
@@ -88,7 +88,7 @@ function AddIndustryMaster({ refetch }: { refetch: VoidFunction }) {
|
||||
|
||||
</DialogBody>
|
||||
<DialogFooter display="flex" justifyContent="center" pt={"2"}>
|
||||
<Button w="100%" bg="#02A0A0" color={"#fff"} onClick={handleSubmit}>
|
||||
<Button w="100%" bg="#02A0A0" color={"#fff"} onClick={handleSubmit} disabled={isLoading}>
|
||||
Save
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
|
||||
@@ -17,7 +17,7 @@ import { useUpdateIndustryMasterMutation } from "../../../Redux/Service/industry
|
||||
|
||||
function EditIndustryMaster({ id, localData, refetch, categories }: { id: number, localData: any, refetch: VoidFunction, categories: any }) {
|
||||
const [jobtype, setJobType] = useState("");
|
||||
const [updateIndustryMaster] = useUpdateIndustryMasterMutation()
|
||||
const [updateIndustryMaster, { isLoading }] = useUpdateIndustryMasterMutation()
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
|
||||
const handleOpenModal = () => {
|
||||
@@ -98,7 +98,7 @@ function EditIndustryMaster({ id, localData, refetch, categories }: { id: number
|
||||
</Stack>
|
||||
</DialogBody>
|
||||
<DialogFooter display="flex" justifyContent="center" pt={"2"}>
|
||||
<Button w="100%" bg="#02A0A0" color={"#fff"} onClick={handleSubmit}>
|
||||
<Button w="100%" bg="#02A0A0" color={"#fff"} onClick={handleSubmit} disabled={isLoading}>
|
||||
Save
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
|
||||
@@ -9,6 +9,9 @@ import { useGetIndustryMasterQuery, useIndustryMasterToggleMutation } from "../.
|
||||
import EditIndustryMaster from "./EditIndustryMaster";
|
||||
import AddIndustryMaster from "./AddIndustryMaster";
|
||||
import SearchComponent from "../../../components/SearchComponent";
|
||||
import { useDebounce } from "../../../components/Hooks/useDebounce";
|
||||
import { Toaster, toaster } from "../../../components/ui/toaster";
|
||||
import { delay } from "../../../components/Utils";
|
||||
|
||||
|
||||
// table data
|
||||
@@ -44,10 +47,12 @@ const tableHeadRow = [
|
||||
|
||||
const IndustryMasterList = () => {
|
||||
const [currentPage, setCurrentPage] = useState(1);
|
||||
const { data, refetch } = useGetIndustryMasterQuery(currentPage)
|
||||
const [industryMasterToggle] = useIndustryMasterToggleMutation()
|
||||
const [localData, setLocalData] = useState<any[]>([]);
|
||||
const [searchTerm, setSearchTerm] = useState("");
|
||||
const [searchTerm, setSearchTerm] = useState("");
|
||||
const debouncedSearchTerm = useDebounce(searchTerm, 500);
|
||||
const queryArgs = debouncedSearchTerm ? { page: currentPage, search: debouncedSearchTerm } : { page: currentPage };
|
||||
const { data, refetch, isError, isFetching } = useGetIndustryMasterQuery(queryArgs)
|
||||
|
||||
useEffect(() => {
|
||||
if (data?.data?.data) {
|
||||
@@ -55,6 +60,11 @@ const IndustryMasterList = () => {
|
||||
}
|
||||
}, [data]);
|
||||
|
||||
const handleSearchChange = (value: string) => {
|
||||
setSearchTerm(value);
|
||||
setCurrentPage(1);
|
||||
};
|
||||
|
||||
const handlePageChange = (page: number) => {
|
||||
setCurrentPage(page);
|
||||
};
|
||||
@@ -68,9 +78,20 @@ const IndustryMasterList = () => {
|
||||
);
|
||||
try {
|
||||
await industryMasterToggle({ id: agencyId, is_active: newStatus }).unwrap();
|
||||
toaster.create({
|
||||
title: "Success",
|
||||
description: "Status updated successfully",
|
||||
type: "success",
|
||||
});
|
||||
await delay(500);
|
||||
refetch()
|
||||
} catch (error) {
|
||||
console.error("Error updating privacy policy:", error);
|
||||
toaster.create({
|
||||
title: "Error",
|
||||
description: "Someting went wrong.",
|
||||
type: "error",
|
||||
});
|
||||
setLocalData((prevData) =>
|
||||
prevData.map((agency) =>
|
||||
agency.id === agencyId ? { ...agency, is_active: currentStatus } : agency
|
||||
@@ -130,11 +151,7 @@ const IndustryMasterList = () => {
|
||||
<HStack >
|
||||
<SearchComponent
|
||||
value={searchTerm}
|
||||
onChange={(value) => {
|
||||
setSearchTerm(value);
|
||||
// setCurrentPage(1);
|
||||
refetch()
|
||||
}}
|
||||
onChange={handleSearchChange}
|
||||
/>
|
||||
{/* <Button bgColor={'#EEEEEE'} pl={3} pr={3}><IoMdAdd /> <Text>Add</Text></Button> */}
|
||||
{/* <ViewAgencyAddModel /> */}
|
||||
@@ -152,8 +169,11 @@ const IndustryMasterList = () => {
|
||||
total: data?.data.total || 0
|
||||
}}
|
||||
onPageChange={handlePageChange}
|
||||
isLoading={isFetching}
|
||||
isError={isError}
|
||||
/>
|
||||
</Box>
|
||||
<Toaster />
|
||||
</MainFrame>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ import { Toaster, toaster } from "../../../components/ui/toaster";
|
||||
|
||||
|
||||
function EditJobStatusModel({ localData, refetch }: { localData: any, refetch: VoidFunction }) {
|
||||
const [updateJobStatus] = useUpdateJobStatusMutation()
|
||||
const [updateJobStatus, { isLoading }] = useUpdateJobStatusMutation()
|
||||
const [title, setTitle] = useState(localData.translation.title);
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
|
||||
@@ -89,7 +89,7 @@ function EditJobStatusModel({ localData, refetch }: { localData: any, refetch: V
|
||||
|
||||
</DialogBody>
|
||||
<DialogFooter display="flex" justifyContent="center" pt={"2"}>
|
||||
<Button w="100%" bg="#02A0A0" color={"#fff"} onClick={handleSubmit}>
|
||||
<Button w="100%" bg="#02A0A0" color={"#fff"} onClick={handleSubmit} disabled={isLoading}>
|
||||
Save
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
|
||||
@@ -7,7 +7,9 @@ import EditJobStatusModel from "./EditJobStatusModel";
|
||||
import { useGetJobStatusQuery, useJobStatusToggleMutation } from "../../../Redux/Service/job.status";
|
||||
import { useEffect, useState } from "react";
|
||||
import SearchComponent from "../../../components/SearchComponent";
|
||||
import { toaster } from "../../../components/ui/toaster";
|
||||
import { toaster, Toaster } from "../../../components/ui/toaster";
|
||||
import { useDebounce } from "../../../components/Hooks/useDebounce";
|
||||
import { delay } from "../../../components/Utils";
|
||||
|
||||
|
||||
|
||||
@@ -37,9 +39,11 @@ const tableHeadRow = [
|
||||
|
||||
const JobStatus = () => {
|
||||
const [currentPage, setCurrentPage] = useState(1);
|
||||
const { data, refetch } = useGetJobStatusQuery(currentPage)
|
||||
const [localData, setLocalData] = useState<any[]>([]);
|
||||
const [searchTerm, setSearchTerm] = useState("");
|
||||
const debouncedSearchTerm = useDebounce(searchTerm, 500);
|
||||
const queryArgs = debouncedSearchTerm ? { page: currentPage, search: debouncedSearchTerm } : { page: currentPage };
|
||||
const { data, refetch, isError, isFetching } = useGetJobStatusQuery(queryArgs)
|
||||
const [localData, setLocalData] = useState<any[]>([]);
|
||||
const [jobStatusToggle] = useJobStatusToggleMutation()
|
||||
console.log(data?.data.data)
|
||||
|
||||
@@ -53,6 +57,11 @@ const JobStatus = () => {
|
||||
setCurrentPage(page);
|
||||
};
|
||||
|
||||
const handleSearchChange = (value: string) => {
|
||||
setSearchTerm(value);
|
||||
setCurrentPage(1);
|
||||
};
|
||||
|
||||
const handleToggle = async (agencyId: string, currentStatus: number) => {
|
||||
const newStatus = currentStatus ? 0 : 1;
|
||||
setLocalData((prevData) =>
|
||||
@@ -62,6 +71,12 @@ const JobStatus = () => {
|
||||
);
|
||||
try {
|
||||
await jobStatusToggle({ id: agencyId, is_active: newStatus }).unwrap();
|
||||
toaster.create({
|
||||
title: "Success",
|
||||
description: "Status updated successfully",
|
||||
type: "success",
|
||||
});
|
||||
await delay(500);
|
||||
refetch()
|
||||
} catch (error) {
|
||||
console.error("Error updating:", error);
|
||||
@@ -125,11 +140,7 @@ const JobStatus = () => {
|
||||
<HStack >
|
||||
<SearchComponent
|
||||
value={searchTerm}
|
||||
onChange={(value) => {
|
||||
setSearchTerm(value);
|
||||
// setCurrentPage(1);
|
||||
refetch()
|
||||
}}
|
||||
onChange={handleSearchChange}
|
||||
/>
|
||||
{/* <Button bgColor={'#EEEEEE'} pl={3} pr={3}><IoMdAdd /> <Text>Add</Text></Button> */}
|
||||
<JobStatusAddModel refetch={refetch} />
|
||||
@@ -146,8 +157,11 @@ const JobStatus = () => {
|
||||
total: data?.data.total || 0
|
||||
}}
|
||||
onPageChange={handlePageChange}
|
||||
isLoading={isFetching}
|
||||
isError={isError}
|
||||
/>
|
||||
</Box>
|
||||
<Toaster />
|
||||
</MainFrame>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ import { useState } from "react"
|
||||
function JobStatusAddModel({ refetch }: { refetch: VoidFunction }) {
|
||||
const [title, setTitle] = useState('')
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [createJobStatusPost] = useCreateJobStatusPostMutation()
|
||||
const [createJobStatusPost, { isLoading }] = useCreateJobStatusPostMutation()
|
||||
|
||||
const handleOpenModal = () => {
|
||||
setIsOpen(true);
|
||||
@@ -88,7 +88,7 @@ function JobStatusAddModel({ refetch }: { refetch: VoidFunction }) {
|
||||
|
||||
</DialogBody>
|
||||
<DialogFooter display="flex" justifyContent="center" pt={"2"}>
|
||||
<Button w="100%" bg="#02A0A0" color={"#fff"} onClick={handleSubmit}>
|
||||
<Button w="100%" bg="#02A0A0" color={"#fff"} onClick={handleSubmit} disabled={isLoading}>
|
||||
Save
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
|
||||
@@ -17,7 +17,7 @@ import { toaster } from "../../../components/ui/toaster";
|
||||
|
||||
function EditJobeModel({ id, localData, refetch }: { id: number, localData: any, refetch: VoidFunction }) {
|
||||
const [jobtype, setJobType] = useState("");
|
||||
const [updateJobType] = useUpdateJobTypeMutation()
|
||||
const [updateJobType, { isLoading }] = useUpdateJobTypeMutation()
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
|
||||
const handleOpenModal = () => {
|
||||
@@ -97,7 +97,7 @@ function EditJobeModel({ id, localData, refetch }: { id: number, localData: any,
|
||||
</Stack>
|
||||
</DialogBody>
|
||||
<DialogFooter display="flex" justifyContent="center" pt={"2"}>
|
||||
<Button w="100%" bg="#02A0A0" color={"#fff"} onClick={handleSubmit}>
|
||||
<Button w="100%" bg="#02A0A0" color={"#fff"} onClick={handleSubmit} disabled={isLoading}>
|
||||
Save
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
|
||||
@@ -9,7 +9,7 @@ import { toaster } from "../../../components/ui/toaster";
|
||||
function JobAddModel({ refetch }: { refetch: VoidFunction }) {
|
||||
const [jobType, setJobType] = useState("");
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [createJobTypePost] = useCreateJobTypePostMutation()
|
||||
const [createJobTypePost, { isLoading }] = useCreateJobTypePostMutation()
|
||||
|
||||
const handleOpenModal = () => {
|
||||
setIsOpen(true); // Open modal when clicking "Add"
|
||||
@@ -87,7 +87,7 @@ function JobAddModel({ refetch }: { refetch: VoidFunction }) {
|
||||
|
||||
</DialogBody>
|
||||
<DialogFooter display="flex" justifyContent="center" pt={"2"}>
|
||||
<Button w="100%" bg="#02A0A0" color={"#fff"} onClick={handleSubmit}>
|
||||
<Button w="100%" bg="#02A0A0" color={"#fff"} onClick={handleSubmit} disabled={isLoading}>
|
||||
Save
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
|
||||
@@ -6,9 +6,11 @@ import DataTable from "../../../components/DataTable";
|
||||
import { Switch } from "../../../components/ui/switch";
|
||||
import JobAddModel from "./JobAddModel";
|
||||
import EditJobeModel from "./EditJobModel";
|
||||
import { JobTypeData, useGetJobTypeQuery } from "../../../Redux/Service/job.type.service";
|
||||
import { JobTypeData, useGetJobTypeQuery, useJobTypeToggleMutation } from "../../../Redux/Service/job.type.service";
|
||||
import { useEffect, useState } from "react";
|
||||
import SearchComponent from "../../../components/SearchComponent";
|
||||
import { toaster, Toaster } from "../../../components/ui/toaster";
|
||||
import { delay } from "../../../components/Utils";
|
||||
|
||||
|
||||
|
||||
@@ -38,10 +40,10 @@ const tableHeadRow = [
|
||||
|
||||
const JobType = () => {
|
||||
const [currentPage, setCurrentPage] = useState(1);
|
||||
const { data, refetch } = useGetJobTypeQuery(currentPage)
|
||||
const { data, refetch, isFetching, isError } = useGetJobTypeQuery(currentPage)
|
||||
const [localData, setLocalData] = useState<any[]>([]);
|
||||
const [searchTerm, setSearchTerm] = useState("");
|
||||
// const [templateMasterToggle] = useTemplateMasterToggleMutation()
|
||||
const [jobTypeToggle] = useJobTypeToggleMutation()
|
||||
console.log('DATA', data?.data.data);
|
||||
|
||||
|
||||
@@ -61,25 +63,36 @@ const JobType = () => {
|
||||
return title;
|
||||
});
|
||||
|
||||
// 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 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 jobTypeToggle({ id: agencyId, is_active: newStatus }).unwrap();
|
||||
toaster.create({
|
||||
title: "Success",
|
||||
description: "Status updated successfully",
|
||||
type: "success",
|
||||
});
|
||||
await delay(500);
|
||||
refetch()
|
||||
} catch (error) {
|
||||
console.error("Error updating privacy policy:", error);
|
||||
setLocalData((prevData) =>
|
||||
prevData.map((agency) =>
|
||||
agency.id === agencyId ? { ...agency, is_active: currentStatus } : agency
|
||||
)
|
||||
);
|
||||
toaster.create({
|
||||
title: "Error",
|
||||
description: "Please try again later",
|
||||
type: "error",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const managepost = filteredData?.map((agency: JobTypeData, index: number) => ({
|
||||
@@ -94,7 +107,7 @@ const JobType = () => {
|
||||
<Switch
|
||||
colorPalette={'teal'}
|
||||
size={"xs"}
|
||||
// onChange={() => handleToggle(agency.id, Number(agency.is_active))}
|
||||
onChange={() => handleToggle(agency.id.toString(), Number(agency.is_active))}
|
||||
checked={Boolean(Number(agency.is_active))}
|
||||
/>
|
||||
</Box>
|
||||
@@ -142,8 +155,11 @@ const JobType = () => {
|
||||
total: data?.data.total || 0
|
||||
}}
|
||||
onPageChange={handlePageChange}
|
||||
isLoading={isFetching}
|
||||
isError={isError}
|
||||
/>
|
||||
</Box>
|
||||
<Toaster />
|
||||
</MainFrame>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ import { useState } from "react";
|
||||
// import { FaRegEdit } from "react-icons/fa";
|
||||
import Edit from "../../../components/ActionIcons/Edit";
|
||||
import { Toaster, toaster } from "../../../components/ui/toaster";
|
||||
import { Template } from "../../../Redux/Service/template.master.service";
|
||||
// import { Template } from "../../../Redux/Service/template.master.service";
|
||||
import axios from "axios";
|
||||
|
||||
const IMGURL = import.meta.env.VITE_IMG_TEMPLATES
|
||||
@@ -30,13 +30,14 @@ function EditTemplateModel({ id, localData, refetch }: { id: number, localData:
|
||||
const [subTitle, setSubTitle] = useState("");
|
||||
const [userType, setUserType] = useState<number | "">("");
|
||||
const [images, setImages] = useState<(File | string)[]>([]);
|
||||
const [loading, setLoading] = useState(false);
|
||||
// const [objectURLs, setObjectURLs] = useState<string[]>([]); // Store object URLs separately
|
||||
// const [updateTemplateMaster] = useUpdateTemplateMasterMutation()
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [selectedTemplate, setSelectedTemplate] = useState<Template | null>(null);
|
||||
// const [selectedTemplate, setSelectedTemplate] = useState<Template | null>(null);
|
||||
const token = localStorage.getItem("token");
|
||||
|
||||
console.log(selectedTemplate);
|
||||
console.log(images);
|
||||
|
||||
const handleImageChange = async (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
if (event.target.files) {
|
||||
@@ -50,14 +51,17 @@ function EditTemplateModel({ id, localData, refetch }: { id: number, localData:
|
||||
return;
|
||||
}
|
||||
|
||||
setImages((prevImages) => [...prevImages, file]);
|
||||
// setImages((prevImages) => [...prevImages, file]);
|
||||
if (file) {
|
||||
setImages([file])
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const handleOpenModal = () => {
|
||||
const template = localData?.find((item: any) => item.id === id);
|
||||
if (template) {
|
||||
setSelectedTemplate(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() || "");
|
||||
@@ -90,9 +94,9 @@ function EditTemplateModel({ id, localData, refetch }: { id: number, localData:
|
||||
return;
|
||||
}
|
||||
|
||||
const newImages = images.filter((image) => image instanceof File);
|
||||
// const newImages = images.filter((image) => image instanceof File);
|
||||
|
||||
if (newImages.length === 0) {
|
||||
if (images.length === 0) {
|
||||
toaster.create({
|
||||
title: "Error",
|
||||
description: "Please upload at least one image.",
|
||||
@@ -101,14 +105,18 @@ function EditTemplateModel({ id, localData, refetch }: { id: number, localData:
|
||||
return;
|
||||
}
|
||||
|
||||
setLoading(true);
|
||||
|
||||
const formData = new FormData();
|
||||
formData.append("id", `${id}`);
|
||||
formData.append("principle_type_xid", `${userType}`);
|
||||
formData.append("title", title);
|
||||
formData.append("sub_title", subTitle);
|
||||
|
||||
newImages.forEach((image, index) => {
|
||||
formData.append(`image_name[${index}]`, image, image.name);
|
||||
images.forEach((image, index) => {
|
||||
if (image instanceof File) {
|
||||
formData.append(`image_name[${index}]`, image, image.name);
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
@@ -123,12 +131,14 @@ function EditTemplateModel({ id, localData, refetch }: { id: number, localData:
|
||||
});
|
||||
}
|
||||
setIsOpen(false);
|
||||
setLoading(false);
|
||||
refetch()
|
||||
} catch (error) {
|
||||
} catch (error: any) {
|
||||
console.error("Error updating template:", error);
|
||||
setLoading(false);
|
||||
toaster.create({
|
||||
title: "Error",
|
||||
description: "Failed to update template. Please try again.",
|
||||
description: `${error.response?.data?.message || "Please try again later."}`,
|
||||
type: "error",
|
||||
});
|
||||
}
|
||||
@@ -294,7 +304,7 @@ function EditTemplateModel({ id, localData, refetch }: { id: number, localData:
|
||||
|
||||
</DialogBody>
|
||||
<DialogFooter display="flex" justifyContent="center" pt={"2"}>
|
||||
<Button w="100%" bg="#02A0A0" color={"#fff"} onClick={handleSubmit}>
|
||||
<Button w="100%" bg="#02A0A0" color={"#fff"} onClick={handleSubmit} disabled={loading}>
|
||||
Save
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
|
||||
@@ -3,7 +3,7 @@ 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 { useEffect, useState } from "react";
|
||||
// import { useCreateTemplatePostMutation } from "../../../Redux/Service/template.master.service";
|
||||
import { Toaster, toaster } from "../../../components/ui/toaster"
|
||||
import axios from "axios";
|
||||
@@ -17,12 +17,23 @@ function TemplateAddModel({ refetch }: { refetch: VoidFunction }) {
|
||||
const [images, setImages] = useState<(File | string)[]>([]);
|
||||
// const [createTemplatePost] = useCreateTemplatePostMutation()
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const token = localStorage.getItem("token");
|
||||
|
||||
useEffect(() => {
|
||||
if (!isOpen) {
|
||||
setTitle("");
|
||||
setSubTitle("");
|
||||
setUserType("");
|
||||
setImages([]);
|
||||
}
|
||||
}, [isOpen]);
|
||||
|
||||
if (!token) {
|
||||
console.error("No token found in localStorage!");
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
const handleOpenModal = () => {
|
||||
setIsOpen(true); // Open modal when clicking "Add"
|
||||
};
|
||||
@@ -40,7 +51,10 @@ function TemplateAddModel({ refetch }: { refetch: VoidFunction }) {
|
||||
return;
|
||||
}
|
||||
|
||||
setImages((prevImages) => [...prevImages, file]);
|
||||
// setImages((prevImages) => [...prevImages, file]);
|
||||
if(file){
|
||||
setImages([file])
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -72,6 +86,7 @@ function TemplateAddModel({ refetch }: { refetch: VoidFunction }) {
|
||||
// image_name: images.filter((img) => typeof img === "string"), // Send only Base64 strings
|
||||
// };
|
||||
|
||||
setIsLoading(true);
|
||||
|
||||
const formData = new FormData();
|
||||
formData.append("principle_type_xid", `${userType}`);
|
||||
@@ -106,13 +121,19 @@ function TemplateAddModel({ refetch }: { refetch: VoidFunction }) {
|
||||
setUserType("");
|
||||
setImages([]);
|
||||
setIsOpen(false)
|
||||
} catch (error) {
|
||||
setIsLoading(false);
|
||||
} catch (error: any) {
|
||||
console.error("Error creating template:", error);
|
||||
// alert("Failed to create template");
|
||||
toaster.create({
|
||||
title: "Error",
|
||||
description: `${error.response?.data?.message || "Please try again later."}`,
|
||||
type: "error",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// console.log("Token stored:", window.localStorage.getItem("token"));
|
||||
// console.log("Token stored:", window.localStorage.getItem("token"))
|
||||
|
||||
|
||||
return (
|
||||
@@ -226,7 +247,7 @@ function TemplateAddModel({ refetch }: { refetch: VoidFunction }) {
|
||||
|
||||
</DialogBody>
|
||||
<DialogFooter display="flex" justifyContent="center" pt={"2"}>
|
||||
<Button w="100%" bg="#02A0A0" color={"#fff"} onClick={handleSubmit}>
|
||||
<Button w="100%" bg="#02A0A0" color={"#fff"} onClick={handleSubmit} disabled={isLoading}>
|
||||
Save
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
|
||||
@@ -9,6 +9,8 @@ import EditTemplateModel from "./EditTemplateModel";
|
||||
import { Template, useGetTemplateMasterQuery, useTemplateMasterToggleMutation } from "../../../Redux/Service/template.master.service";
|
||||
import { useEffect, useState } from "react";
|
||||
import SearchComponent from "../../../components/SearchComponent";
|
||||
import { toaster, Toaster } from "../../../components/ui/toaster";
|
||||
import { delay } from "../../../components/Utils";
|
||||
|
||||
const APIURL = import.meta.env.VITE_IMG_TEMPLATES
|
||||
|
||||
@@ -17,6 +19,7 @@ const APIURL = import.meta.env.VITE_IMG_TEMPLATES
|
||||
const tableHeadRow = [
|
||||
"Sr. No",
|
||||
"Title",
|
||||
"User Type",
|
||||
"Images",
|
||||
"Action"
|
||||
];
|
||||
@@ -46,7 +49,7 @@ const tableHeadRow = [
|
||||
|
||||
const TemplateMaster = () => {
|
||||
const [currentPage, setCurrentPage] = useState(1);
|
||||
const { data, refetch } = useGetTemplateMasterQuery(currentPage)
|
||||
const { data, refetch, isFetching, isError } = useGetTemplateMasterQuery(currentPage)
|
||||
const [localData, setLocalData] = useState<any[]>([]);
|
||||
const [templateMasterToggle] = useTemplateMasterToggleMutation();
|
||||
const [searchTerm, setSearchTerm] = useState("");
|
||||
@@ -71,6 +74,12 @@ const TemplateMaster = () => {
|
||||
);
|
||||
try {
|
||||
await templateMasterToggle({ id: agencyId, is_active: newStatus }).unwrap();
|
||||
toaster.create({
|
||||
title: "Success",
|
||||
description: "Status updated successfully",
|
||||
type: "success",
|
||||
});
|
||||
await delay(500);
|
||||
refetch()
|
||||
} catch (error) {
|
||||
console.error("Error updating privacy policy:", error);
|
||||
@@ -79,6 +88,11 @@ const TemplateMaster = () => {
|
||||
agency.id === agencyId ? { ...agency, is_active: currentStatus } : agency
|
||||
)
|
||||
);
|
||||
toaster.create({
|
||||
title: "Error",
|
||||
description: "Please try again later",
|
||||
type: "error",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@@ -86,37 +100,45 @@ const TemplateMaster = () => {
|
||||
agency.post_template_translate[0].title.toLowerCase().includes(searchTerm.toLowerCase())
|
||||
);
|
||||
|
||||
const managepost = filteredData?.map((agency: Template, index: number) => ({
|
||||
'id': agency.id,
|
||||
"Sr. No": (currentPage - 1) * (data?.data.per_page ?? 0) + index + 1,
|
||||
"Title": agency.post_template_translate.length > 0
|
||||
? agency.post_template_translate[0].title
|
||||
: "N/A",
|
||||
"Images": (
|
||||
// <Image w={50} src={img} />
|
||||
<HStack key={agency.id}>
|
||||
{agency.post_template_image.map((img) => (
|
||||
<Image rounded={'lg'} w={100} h={50} src={`${APIURL}${img.image_name}`} />
|
||||
))}
|
||||
const activeCount = filteredData?.filter((a: any) => a.is_active === 1).length ?? 0;
|
||||
|
||||
{/* <Image rounded={'lg'} w={100} h={50} src={Templateimg} /> */}
|
||||
</HStack>
|
||||
),
|
||||
const managepost = filteredData?.map((agency: Template, index: number) => {
|
||||
const isOnlyActive = activeCount === 1 && Number(agency.is_active) === 1;
|
||||
|
||||
"Action": (
|
||||
<HStack justifyContent="center">
|
||||
<EditTemplateModel id={agency.id} localData={localData} refetch={refetch} />
|
||||
<Box>
|
||||
<Switch
|
||||
colorPalette={'teal'}
|
||||
size={"xs"}
|
||||
onChange={() => handleToggle(agency.id.toString(), Number(agency.is_active ?? 0))}
|
||||
checked={Boolean(Number(agency.is_active))}
|
||||
/>
|
||||
</Box>
|
||||
</HStack>
|
||||
),
|
||||
}));
|
||||
return {
|
||||
'id': agency.id,
|
||||
"Sr. No": (currentPage - 1) * (data?.data.per_page ?? 0) + index + 1,
|
||||
"Title": agency.post_template_translate.length > 0
|
||||
? agency.post_template_translate[0].title
|
||||
: "N/A",
|
||||
"User Type": agency.principle_type_xid === 2 ? 'Recruiter' : 'Job Seeker',
|
||||
"Images": (
|
||||
// <Image w={50} src={img} />
|
||||
<HStack>
|
||||
{agency.post_template_image.map((img) => (
|
||||
<Image key={img.id} 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 id={agency.id} localData={localData} refetch={refetch} />
|
||||
<Box>
|
||||
<Switch
|
||||
colorPalette={'teal'}
|
||||
size={"xs"}
|
||||
onChange={() => handleToggle(agency.id.toString(), Number(agency.is_active ?? 0))}
|
||||
checked={Boolean(Number(agency.is_active))}
|
||||
disabled={isOnlyActive}
|
||||
/>
|
||||
</Box>
|
||||
</HStack>
|
||||
)
|
||||
}
|
||||
});
|
||||
|
||||
return (
|
||||
|
||||
@@ -172,8 +194,11 @@ const TemplateMaster = () => {
|
||||
total: data?.data.total || 0
|
||||
}}
|
||||
onPageChange={handlePageChange}
|
||||
isLoading={isFetching}
|
||||
isError={isError}
|
||||
/>
|
||||
</Box>
|
||||
<Toaster />
|
||||
</MainFrame>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ import { useUpdateWorkSpaceMutation } from "../../../Redux/Service/workspace.mod
|
||||
function EditWorkModel({ localData, refetch }: {localData: any, refetch: VoidFunction}) {
|
||||
const [title, setTitle] = useState(localData?.en_name);
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [updateWorkSpace] = useUpdateWorkSpaceMutation()
|
||||
const [updateWorkSpace, { isLoading }] = useUpdateWorkSpaceMutation()
|
||||
console.log("localData", localData)
|
||||
|
||||
const handleOpenModal = () => {
|
||||
@@ -104,7 +104,7 @@ function EditWorkModel({ localData, refetch }: {localData: any, refetch: VoidFun
|
||||
</Stack>
|
||||
</DialogBody>
|
||||
<DialogFooter display="flex" justifyContent="center" pt={"2"}>
|
||||
<Button w="100%" bg="#02A0A0" color={"#fff"} onClick={handleSubmit}>
|
||||
<Button w="100%" bg="#02A0A0" color={"#fff"} onClick={handleSubmit} disabled={isLoading}>
|
||||
Save
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
|
||||
@@ -2,14 +2,14 @@ import { DialogBody, DialogCloseTrigger, DialogContent, DialogFooter, DialogHead
|
||||
import { Field, Input, Stack, Text } from "@chakra-ui/react"
|
||||
import { IoMdAdd } from "react-icons/io"
|
||||
import { Button } from "../../../components/ui/button"
|
||||
import { useState } from "react";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useCreateWorkspacePostMutation } from "../../../Redux/Service/workspace.mode";
|
||||
import { Toaster, toaster } from "../../../components/ui/toaster";
|
||||
|
||||
function WorkAddModel({ refetch }: { refetch: VoidFunction }) {
|
||||
const [title, setTitle] = useState('')
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [createWorkspacePost] = useCreateWorkspacePostMutation()
|
||||
const [createWorkspacePost, { isLoading }] = useCreateWorkspacePostMutation()
|
||||
|
||||
const handleOpenModal = () => {
|
||||
setIsOpen(true);
|
||||
@@ -40,6 +40,12 @@ function WorkAddModel({ refetch }: { refetch: VoidFunction }) {
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (!isOpen) {
|
||||
setTitle("");
|
||||
}
|
||||
}, [isOpen]);
|
||||
|
||||
return (
|
||||
|
||||
<DialogRoot placement="center" open={isOpen}>
|
||||
@@ -88,7 +94,7 @@ function WorkAddModel({ refetch }: { refetch: VoidFunction }) {
|
||||
|
||||
</DialogBody>
|
||||
<DialogFooter display="flex" justifyContent="center" pt={"2"}>
|
||||
<Button w="100%" bg="#02A0A0" color={"#fff"} onClick={handleSubmit}>
|
||||
<Button w="100%" bg="#02A0A0" color={"#fff"} onClick={handleSubmit} disabled={isLoading}>
|
||||
Save
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
|
||||
@@ -37,7 +37,7 @@ const tableHeadRow = [
|
||||
|
||||
const WorkspaceMode = () => {
|
||||
const [currentPage, setCurrentPage] = useState(1);
|
||||
const { data, refetch } = useGetWorkSpaceModeQuery(currentPage)
|
||||
const { data, refetch, isError, isFetching } = useGetWorkSpaceModeQuery(currentPage)
|
||||
const [localData, setLocalData] = useState<any[]>([]);
|
||||
const [searchTerm, setSearchTerm] = useState("");
|
||||
const [workspaceToggle] = useWorkspaceToggleMutation()
|
||||
@@ -63,12 +63,17 @@ const WorkspaceMode = () => {
|
||||
);
|
||||
try {
|
||||
await workspaceToggle({ id: agencyId, is_active: newStatus }).unwrap();
|
||||
toaster.create({
|
||||
title: "Success",
|
||||
description: "Status updated successfully",
|
||||
type: "success",
|
||||
});
|
||||
refetch()
|
||||
} catch (error) {
|
||||
console.error("Error updating privacy policy:", error);
|
||||
toaster.create({
|
||||
title: "Error",
|
||||
description: "Someting went wrong.",
|
||||
description: "Please try again later.",
|
||||
type: "error",
|
||||
});
|
||||
setLocalData((prevData) =>
|
||||
@@ -88,7 +93,9 @@ const WorkspaceMode = () => {
|
||||
const managepost = filteredData?.map((agency: any, index: number) => ({
|
||||
'id': agency.id,
|
||||
"Sr. No": (currentPage - 1) * (data?.data.per_page ?? 0) + index + 1,
|
||||
"Title": agency.en_name,
|
||||
"Title": agency.en_name.length > 12
|
||||
? agency.en_name.slice(0, 12) + '...'
|
||||
: agency.en_name,
|
||||
"is_active": agency.is_active,
|
||||
"Action": (
|
||||
<HStack justifyContent="center">
|
||||
@@ -131,7 +138,7 @@ const WorkspaceMode = () => {
|
||||
}}
|
||||
/>
|
||||
{/* <Button bgColor={'#EEEEEE'} pl={3} pr={3}><IoMdAdd /> <Text>Add</Text></Button> */}
|
||||
<WorkAddModel refetch={refetch}/>
|
||||
<WorkAddModel refetch={refetch} />
|
||||
</HStack>
|
||||
</HStack>
|
||||
<DataTable
|
||||
@@ -145,6 +152,8 @@ const WorkspaceMode = () => {
|
||||
total: data?.data.total || 0
|
||||
}}
|
||||
onPageChange={handlePageChange}
|
||||
isLoading={isFetching}
|
||||
isError={isError}
|
||||
/>
|
||||
</Box>
|
||||
<Toaster />
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
|
||||
import { DialogCloseTrigger, Field, IconButton, Input, Stack, Text } from "@chakra-ui/react";
|
||||
import { Button } from "../../components/ui/button";
|
||||
import { DialogBody, DialogContent, DialogFooter, DialogHeader, DialogRoot, DialogTitle, DialogTrigger } from "../../components/ui/dialog";
|
||||
import { DialogBody, DialogContent, DialogFooter, DialogHeader, DialogRoot, DialogTitle } from "../../components/ui/dialog";
|
||||
// import EnterPassword from "./EnterPassword";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { useEffect, useState } from "react";
|
||||
import { toaster } from "../../components/ui/toaster";
|
||||
import { toaster, Toaster } from "../../components/ui/toaster";
|
||||
import { useNewPasswordSetMutation } from "../../Redux/Service/profile.password";
|
||||
import { LuEye, LuEyeOff } from "react-icons/lu";
|
||||
import { InputGroup } from "../../components/ui/input-group";
|
||||
@@ -114,11 +114,11 @@ function Changepassword({ onClose, isOpen }: EnterPasswordProps) {
|
||||
onOpenChange={(open) => !open && onClose()}
|
||||
>
|
||||
|
||||
<DialogTrigger asChild>
|
||||
{/* <DialogTrigger asChild>
|
||||
<Button bg="#02A0A0" size={'2xs'} color={"#fff"} px={2} >
|
||||
Change Password
|
||||
</Button>
|
||||
</DialogTrigger>
|
||||
</DialogTrigger> */}
|
||||
|
||||
<DialogContent
|
||||
bg={"#fff"}
|
||||
@@ -203,7 +203,7 @@ function Changepassword({ onClose, isOpen }: EnterPasswordProps) {
|
||||
pl={1}
|
||||
fontSize="12px"
|
||||
height="30px"
|
||||
type= {showNewPassword ? "password" : "Text"}
|
||||
type={showNewPassword ? "text" : "password"}
|
||||
border={errors.confirm_password ? "1px solid red" : "1px solid grey"}
|
||||
{...register("confirm_password", {
|
||||
required: "Please confirm your password",
|
||||
@@ -240,6 +240,7 @@ function Changepassword({ onClose, isOpen }: EnterPasswordProps) {
|
||||
<DialogCloseTrigger color="black" />
|
||||
</DialogContent>
|
||||
</DialogRoot >
|
||||
<Toaster />
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -6,9 +6,78 @@ import { Field } from "../../components/ui/field";
|
||||
// import Changepassword from "./ChangePassword";
|
||||
import EnterPassword from "./EnterPassword";
|
||||
import { useGetProfileQuery } from "../../Redux/Service/profile.password";
|
||||
// import { useUpdateImageMutation } from "../../Redux/Service/myprofie.service";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { Toaster, toaster } from "../../components/ui/toaster";
|
||||
import axios from "axios";
|
||||
|
||||
const APIURL = import.meta.env.VITE_API_URL
|
||||
const PROFILEIMGURL = import.meta.env.VITE_IMG_PROFILE
|
||||
|
||||
const Profile = () => {
|
||||
const { data } = useGetProfileQuery()
|
||||
const { data, refetch } = useGetProfileQuery()
|
||||
const fileInputRef = useRef<HTMLInputElement>(null);
|
||||
const [avatarSrc, setAvatarSrc] = useState<string>("");
|
||||
// const [updateImage] = useUpdateImageMutation();
|
||||
|
||||
useEffect(() => {
|
||||
if (data?.data.profile_photo) {
|
||||
setAvatarSrc(data.data.profile_photo);
|
||||
}
|
||||
}, [data?.data.profile_photo]);
|
||||
|
||||
|
||||
const handleClick = () => {
|
||||
fileInputRef.current?.click();
|
||||
};
|
||||
|
||||
const handleFileChange = async (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const file = e.target.files?.[0];
|
||||
if (!file) return;
|
||||
|
||||
if (file.size > 2 * 1024 * 1024) {
|
||||
alert("File size exceeds 2MB limit.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Preview the image
|
||||
const previewUrl = URL.createObjectURL(file);
|
||||
setAvatarSrc(previewUrl);
|
||||
|
||||
// Prepare FormData
|
||||
const formData = new FormData();
|
||||
formData.append("profile_photo", file, file.name);
|
||||
|
||||
const token = localStorage.getItem("token");
|
||||
|
||||
try {
|
||||
if (token) {
|
||||
await axios.post(`${APIURL}/profile-image-edit`, formData, {
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data',
|
||||
'access-token': `${token}`,
|
||||
},
|
||||
// withCredentials: true,
|
||||
});
|
||||
|
||||
toaster.create({
|
||||
title: "Success",
|
||||
description: "Updated successfully",
|
||||
type: "success",
|
||||
});
|
||||
refetch();
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error updating image:", error);
|
||||
toaster.create({
|
||||
title: "Error",
|
||||
description: "Something went wrong",
|
||||
type: "error",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
console.log('PROFILE DATA:', data?.data);
|
||||
|
||||
return (
|
||||
@@ -20,10 +89,11 @@ const Profile = () => {
|
||||
<HStack shadow={'md'} rounded={'lg'} justifyContent={'space-between'} alignItems={'flex-end'} w={'100%'} px={3} py={3} >
|
||||
<VStack w={'100%'} alignItems={'flex-start'} gap={0}>
|
||||
<Box mb={2} position="relative" width="fit-content"
|
||||
cursor="pointer" onClick={() => alert("Avatar clicked!")}>
|
||||
<Avatar.Root size={"2xl"} style={{ display: "inline-block", width: "auto" }}>
|
||||
cursor="pointer" onClick={handleClick}>
|
||||
<Avatar.Root size={"2xl"} style={{ display: "flex", width: "50px", height: '50px', justifyContent: 'center' }}>
|
||||
<Avatar.Fallback />
|
||||
<Avatar.Image src="https://i.pinimg.com/736x/d6/cd/0f/d6cd0ffd4634b0763d3958a7325ce26e.jpg" />
|
||||
{/* <Avatar.Image src="https://i.pinimg.com/736x/d6/cd/0f/d6cd0ffd4634b0763d3958a7325ce26e.jpg" /> */}
|
||||
{avatarSrc && <Avatar.Image src={`${PROFILEIMGURL}${avatarSrc}`} />}
|
||||
</Avatar.Root>
|
||||
<Box
|
||||
position="absolute"
|
||||
@@ -33,6 +103,13 @@ const Profile = () => {
|
||||
>
|
||||
<FaCamera color="#ccc" size={16} />
|
||||
</Box>
|
||||
<input
|
||||
type="file"
|
||||
accept="image/*"
|
||||
ref={fileInputRef}
|
||||
style={{ display: "none" }}
|
||||
onChange={handleFileChange}
|
||||
/>
|
||||
</Box>
|
||||
<Text color={"black"} as={'span'} fontSize={'sm'} fontWeight={"bold"}>{`${data?.data?.first_name.charAt(0).toUpperCase()}${data?.data.first_name.slice(1)}`}
|
||||
</Text>
|
||||
@@ -63,7 +140,7 @@ const Profile = () => {
|
||||
</VStack>
|
||||
|
||||
</HStack>
|
||||
|
||||
<Toaster />
|
||||
</MainFrame >
|
||||
)
|
||||
}
|
||||
|
||||
@@ -123,7 +123,7 @@ const SetNewPassword = () => {
|
||||
height={"fit-content"}
|
||||
mr={2}
|
||||
>
|
||||
{showOldPassword ? <LuEye /> : <LuEyeOff />}
|
||||
{showOldPassword ? <LuEyeOff /> : <LuEye />}
|
||||
</IconButton>
|
||||
}
|
||||
>
|
||||
@@ -158,7 +158,7 @@ const SetNewPassword = () => {
|
||||
color={"#000"}
|
||||
mr={2}
|
||||
>
|
||||
{showNewPassword ? <LuEye /> : <LuEyeOff />}
|
||||
{showNewPassword ? <LuEyeOff /> : <LuEye />}
|
||||
</IconButton>
|
||||
}
|
||||
>
|
||||
|
||||
@@ -12,26 +12,54 @@ import {
|
||||
import { Field, Grid, Heading, Input, Stack, Text } from "@chakra-ui/react";
|
||||
import { IoMdAdd } from "react-icons/io";
|
||||
import { Checkbox } from "../../components/ui/checkbox";
|
||||
import { useCreateSubAdminPostMutation } from "../../Redux/Service/manage.subadmin.service";
|
||||
import { toaster } from "../../components/ui/toaster";
|
||||
import { useState } from "react";
|
||||
import { PermissionResponse, useCreateSubAdminPostMutation } from "../../Redux/Service/manage.subadmin.service";
|
||||
import { toaster, Toaster } from "../../components/ui/toaster";
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
function AddModel({ refetch }: { refetch: VoidFunction }) {
|
||||
const [createSubAdminPost] = useCreateSubAdminPostMutation();
|
||||
function AddModel({ refetch, allPermissions }: { refetch: VoidFunction, allPermissions?: PermissionResponse }) {
|
||||
const [createSubAdminPost, { isLoading }] = useCreateSubAdminPostMutation();
|
||||
|
||||
// State fields
|
||||
const [firstName, setFirstName] = useState("");
|
||||
const [lastName, setLastName] = useState("");
|
||||
const [userName, setUserName] = useState("");
|
||||
// const [userName, setUserName] = useState("");
|
||||
const [dateOfBirth, setDateOfBirth] = useState("");
|
||||
const [gender, setGender] = useState("");
|
||||
const [ setIsOpen] = useState(false);
|
||||
const [email, setEmail] = useState("");
|
||||
const [phonenumber, setPhonenumber] = useState("");
|
||||
const [permissions, setPermission] = useState<number[]>([]);
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
// const [ setIsOpen] = useState(false);
|
||||
|
||||
const handleOpenModal = () => {
|
||||
setIsOpen(true);
|
||||
};
|
||||
|
||||
const handleCheckboxToggle = (permissionId: number) => {
|
||||
setPermission((prevData) =>
|
||||
prevData.includes(permissionId)
|
||||
? prevData.filter((id) => id !== permissionId)
|
||||
: [...prevData, permissionId]
|
||||
);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (!isOpen) {
|
||||
setFirstName("");
|
||||
setLastName("");
|
||||
// setUserName("");
|
||||
setDateOfBirth("");
|
||||
setGender("");
|
||||
setEmail("");
|
||||
setPhonenumber("");
|
||||
setPermission([]);
|
||||
}
|
||||
}, [isOpen]);
|
||||
|
||||
const handleSubmit = async () => {
|
||||
if (
|
||||
!firstName.trim() ||
|
||||
!lastName.trim() ||
|
||||
!userName.trim() ||
|
||||
!dateOfBirth.trim() ||
|
||||
!gender.trim()
|
||||
) {
|
||||
@@ -43,17 +71,35 @@ function AddModel({ refetch }: { refetch: VoidFunction }) {
|
||||
return;
|
||||
}
|
||||
|
||||
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||||
if (!emailRegex.test(email)) {
|
||||
toaster.create({
|
||||
title: "Invalid Email",
|
||||
description: "Please enter a valid email address",
|
||||
type: "error",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (phonenumber.length !== 10) {
|
||||
toaster.create({
|
||||
title: "Invalid Phone Number",
|
||||
description: "Phone number must be exactly 10 digits",
|
||||
type: "error",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const payload = {
|
||||
principal_type_xid: 4,
|
||||
principal_source_xid: 1,
|
||||
user_name: userName,
|
||||
// user_name: userName,
|
||||
first_name: firstName,
|
||||
last_name: lastName,
|
||||
date_of_birth: dateOfBirth,
|
||||
gender: gender,
|
||||
email_address: "example@yopmail.com", // Hardcoded
|
||||
phone_number: "9876543210", // Hardcoded
|
||||
created_by: 1,
|
||||
email_address: email,
|
||||
phone_number: phonenumber,
|
||||
permission: permissions.filter((id) => typeof id === "number"),
|
||||
// created_by: 1,
|
||||
};
|
||||
|
||||
try {
|
||||
@@ -65,27 +111,33 @@ function AddModel({ refetch }: { refetch: VoidFunction }) {
|
||||
type: "success",
|
||||
});
|
||||
refetch();
|
||||
setIsOpen(false);
|
||||
setFirstName("");
|
||||
setLastName("");
|
||||
setUserName("");
|
||||
// setUserName("");
|
||||
setDateOfBirth("");
|
||||
setGender("");
|
||||
setIsOpen(false);
|
||||
}
|
||||
} catch (error) {
|
||||
} catch (error:any) {
|
||||
console.error("Error creating sub-admin:", error);
|
||||
toaster.create({
|
||||
title: "Error",
|
||||
description: "Failed to create sub-admin",
|
||||
description: error ? error.data.message : "Failed to create sub-admin",
|
||||
type: "error",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<DialogRoot placement="center">
|
||||
<DialogRoot placement="center" open={isOpen} onOpenChange={({ open }) => setIsOpen(open)}>
|
||||
<DialogTrigger asChild>
|
||||
<Button rounded={"md"} px={4} py={2} size={"xs"} bg={"#02A0A0"}>
|
||||
|
||||
<Button
|
||||
rounded={"md"}
|
||||
px={4} py={2}
|
||||
size={"xs"}
|
||||
bg={"#02A0A0"}
|
||||
onClick={handleOpenModal}>
|
||||
<IoMdAdd /> Add
|
||||
</Button>
|
||||
</DialogTrigger>
|
||||
@@ -138,7 +190,7 @@ function AddModel({ refetch }: { refetch: VoidFunction }) {
|
||||
onChange={(e) => setLastName(e.target.value)}
|
||||
/>
|
||||
|
||||
<Field.Label color="black" pt={1} fontSize="12px">
|
||||
{/* <Field.Label color="black" pt={1} fontSize="12px">
|
||||
Username
|
||||
</Field.Label>
|
||||
<Input
|
||||
@@ -151,7 +203,7 @@ function AddModel({ refetch }: { refetch: VoidFunction }) {
|
||||
height="30px"
|
||||
value={userName}
|
||||
onChange={(e) => setUserName(e.target.value)}
|
||||
/>
|
||||
/> */}
|
||||
|
||||
<Field.Label color="black" pt={1} fontSize="12px">
|
||||
DOB
|
||||
@@ -184,30 +236,63 @@ function AddModel({ refetch }: { refetch: VoidFunction }) {
|
||||
onChange={(e) => setGender(e.target.value)}
|
||||
/>
|
||||
|
||||
<Field.Label color="black" pt={1} fontSize="12px">
|
||||
Email Address
|
||||
</Field.Label>
|
||||
<Input
|
||||
placeholder="Enter Email address"
|
||||
bgColor="#EEEEEE"
|
||||
color="black"
|
||||
border="none"
|
||||
pl={1}
|
||||
type="email"
|
||||
fontSize="12px"
|
||||
height="30px"
|
||||
value={email}
|
||||
onChange={(e) => setEmail(e.target.value)}
|
||||
/>
|
||||
|
||||
<Field.Label color="black" pt={1} fontSize="12px">
|
||||
Phone Number
|
||||
</Field.Label>
|
||||
<Input
|
||||
placeholder="Enter phone number"
|
||||
bgColor="#EEEEEE"
|
||||
color="black"
|
||||
border="none"
|
||||
type="tel"
|
||||
pl={1}
|
||||
fontSize="12px"
|
||||
height="30px"
|
||||
value={phonenumber}
|
||||
onChange={(e) => {
|
||||
const value = e.target.value;
|
||||
if (/^\d*$/.test(value)) { // Only allow digits
|
||||
setPhonenumber(value);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
|
||||
<Heading mt={5} color={"#000"} fontSize={"sm"}>
|
||||
Permissions
|
||||
</Heading>
|
||||
</Field.Root>
|
||||
|
||||
<Grid templateColumns="repeat(2, 1fr)" gap={4}>
|
||||
{[
|
||||
"Dashboard",
|
||||
"Manage contact us",
|
||||
"manage User",
|
||||
"Manage CMS",
|
||||
"Manage Post",
|
||||
"Manage Reports",
|
||||
"manage Sub-Admin",
|
||||
"My profile",
|
||||
"Manage Jobs",
|
||||
"manage feedbacks",
|
||||
"Manage community",
|
||||
"Notification",
|
||||
].map((permission) => (
|
||||
<Checkbox size="sm" color="black" key={permission}>
|
||||
<Text fontSize={12}>{permission}</Text>
|
||||
</Checkbox>
|
||||
))}
|
||||
{Array.isArray(allPermissions?.data?.permission)
|
||||
? allPermissions.data.permission.map((permission: any) => (
|
||||
<Checkbox
|
||||
size="sm"
|
||||
color="black"
|
||||
key={permission.id}
|
||||
checked={permissions.includes(permission.id)}
|
||||
onChange={() => handleCheckboxToggle(permission.id)}
|
||||
>
|
||||
<Text fontSize={12}>{permission.app_resource_title}</Text>
|
||||
</Checkbox>
|
||||
))
|
||||
: <Text fontSize={12} color="gray.500">Loading permissions...</Text>
|
||||
}
|
||||
</Grid>
|
||||
</Stack>
|
||||
</DialogBody>
|
||||
@@ -219,13 +304,14 @@ function AddModel({ refetch }: { refetch: VoidFunction }) {
|
||||
bg="#02A0A0"
|
||||
color={"#fff"}
|
||||
onClick={handleSubmit}
|
||||
disabled={isLoading}
|
||||
>
|
||||
Save
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
|
||||
<DialogCloseTrigger color="black" />
|
||||
<DialogCloseTrigger color="black" onClick={() => setIsOpen(false)} />
|
||||
</DialogContent>
|
||||
<Toaster />
|
||||
</DialogRoot>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Field, Grid, Heading, Input, Stack, Text } from "@chakra-ui/react";
|
||||
// import { TbEdit } from "react-icons/tb";
|
||||
import { Button } from "./ui/button";
|
||||
import { Checkbox } from "./ui/checkbox";
|
||||
import { Button } from "../../components/ui/button";
|
||||
import { Checkbox } from "../../components/ui/checkbox";
|
||||
import {
|
||||
DialogBody,
|
||||
DialogCloseTrigger,
|
||||
@@ -11,25 +11,23 @@ import {
|
||||
DialogRoot,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "./ui/dialog";
|
||||
import Edit from "./ActionIcons/Edit";
|
||||
import { useLazyViewSubAdminQuery, useUpdateSubAdminMutation } from "../Redux/Service/manage.subadmin.service";
|
||||
} from "../../components/ui/dialog";
|
||||
import Edit from "../../components/ActionIcons/Edit";
|
||||
import { PermissionResponse, useLazyViewSubAdminQuery, useUpdateSubAdminMutation } from "../../Redux/Service/manage.subadmin.service";
|
||||
import { useEffect, useState } from "react";
|
||||
import { toaster } from "./ui/toaster";
|
||||
import { Toaster, toaster } from "../../components/ui/toaster";
|
||||
|
||||
const resourceIdToLabel: { [key: number]: string } = {
|
||||
1: 'Dashboard',
|
||||
2: 'Manage contact us',
|
||||
3: 'Manage User',
|
||||
4: 'Manage CMS',
|
||||
5: 'Manage Post',
|
||||
6: 'Manage Reports',
|
||||
7: 'Manage Sub-Admin',
|
||||
8: 'My profile',
|
||||
9: 'Manage Jobs',
|
||||
10: 'Manage feedbacks',
|
||||
11: 'Manage community',
|
||||
12: 'Notification',
|
||||
2: 'Manage User',
|
||||
3: 'Manage Post',
|
||||
4: 'Manage Subadmin',
|
||||
5: 'Manage Jobs',
|
||||
6: 'Manage Groups',
|
||||
7: 'Manage Contact Us',
|
||||
8: 'Manage CMS',
|
||||
9: 'My Profile',
|
||||
10: 'Master Module',
|
||||
};
|
||||
|
||||
|
||||
@@ -37,11 +35,15 @@ interface ResourceActionLink {
|
||||
id: number;
|
||||
app_resource_xid: number;
|
||||
is_active: boolean;
|
||||
app_resource: {
|
||||
id: number,
|
||||
app_resource_title: string
|
||||
}
|
||||
}
|
||||
|
||||
function EditSubAdmin({ id, refetch }: { id: number, refetch: VoidFunction }) {
|
||||
function EditSubAdmin({ id, refetch, allPermissions }: { id: number, refetch: VoidFunction, allPermissions?: PermissionResponse }) {
|
||||
const [trigger, { data }] = useLazyViewSubAdminQuery();
|
||||
const [updateSubAdmin] = useUpdateSubAdminMutation()
|
||||
const [updateSubAdmin, {isLoading}] = useUpdateSubAdminMutation()
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [editData, setEditData] = useState<{
|
||||
id: string;
|
||||
@@ -62,8 +64,23 @@ function EditSubAdmin({ id, refetch }: { id: number, refetch: VoidFunction }) {
|
||||
})
|
||||
|
||||
useEffect(() => {
|
||||
if (data?.data && data.data.length > 0) {
|
||||
const subAdmin = data.data[0]; // Extract the first item from the array
|
||||
if (data?.data?.length && allPermissions?.data?.permission?.length) {
|
||||
const subAdmin = data.data[0];
|
||||
|
||||
const activePermissionIds = subAdmin.get_resource_action_link
|
||||
.filter((perm: any) => perm.is_active)
|
||||
.map((perm: any) => perm.app_resource_xid);
|
||||
|
||||
const mergedPermissions: ResourceActionLink[] = allPermissions.data.permission.map((perm) => ({
|
||||
id: perm.id,
|
||||
app_resource_xid: perm.id,
|
||||
is_active: activePermissionIds.includes(perm.id),
|
||||
app_resource: {
|
||||
id: perm.id,
|
||||
app_resource_title: perm.app_resource_title,
|
||||
},
|
||||
}));
|
||||
|
||||
|
||||
// Map the API response to editData
|
||||
setEditData({
|
||||
@@ -73,10 +90,10 @@ function EditSubAdmin({ id, refetch }: { id: number, refetch: VoidFunction }) {
|
||||
last_name: subAdmin.last_name,
|
||||
date_of_birth: formatDateOfBirth(subAdmin.date_of_birth),
|
||||
gender: subAdmin.gender,
|
||||
permission: subAdmin.get_resource_action_link,
|
||||
permission: mergedPermissions,
|
||||
});
|
||||
}
|
||||
}, [data]);
|
||||
}, [data, allPermissions]);
|
||||
|
||||
const formatDateOfBirth = (dob: string): string => {
|
||||
// Convert the date to the desired format with slashes
|
||||
@@ -99,7 +116,7 @@ function EditSubAdmin({ id, refetch }: { id: number, refetch: VoidFunction }) {
|
||||
setEditData((prevData) => ({
|
||||
...prevData,
|
||||
permission: prevData.permission.map((permission) =>
|
||||
permission.id === permissionId
|
||||
permission.app_resource_xid === permissionId
|
||||
? { ...permission, is_active: !permission.is_active }
|
||||
: permission
|
||||
),
|
||||
@@ -113,12 +130,14 @@ function EditSubAdmin({ id, refetch }: { id: number, refetch: VoidFunction }) {
|
||||
|
||||
const payload = {
|
||||
id: Number(editData.id),
|
||||
unique_id: editData.unique_id,
|
||||
// unique_id: editData.unique_id,
|
||||
first_name: editData.first_name,
|
||||
last_name: editData.last_name,
|
||||
date_of_birth: editData.date_of_birth,
|
||||
gender: editData.gender,
|
||||
permission: editData.permission
|
||||
.filter((p) => p.is_active)
|
||||
.map((p) => p.app_resource_xid),
|
||||
};
|
||||
|
||||
try {
|
||||
@@ -171,7 +190,7 @@ function EditSubAdmin({ id, refetch }: { id: number, refetch: VoidFunction }) {
|
||||
<DialogBody bg="white">
|
||||
<Stack py={3}>
|
||||
<Field.Root>
|
||||
<Field.Label color="black" pt={1} fontSize="12px">
|
||||
{/* <Field.Label color="black" pt={1} fontSize="12px">
|
||||
ID
|
||||
</Field.Label>
|
||||
<Input
|
||||
@@ -184,7 +203,7 @@ function EditSubAdmin({ id, refetch }: { id: number, refetch: VoidFunction }) {
|
||||
height="30px"
|
||||
value={editData.unique_id}
|
||||
onChange={(e) => setEditData({ ...editData, unique_id: e.target.value })}
|
||||
/>
|
||||
/> */}
|
||||
|
||||
<Field.Label color="black" pt={1} fontSize="12px">
|
||||
First Name
|
||||
@@ -248,44 +267,6 @@ function EditSubAdmin({ id, refetch }: { id: number, refetch: VoidFunction }) {
|
||||
Permissions
|
||||
</Heading>
|
||||
</Field.Root>
|
||||
{/* <Grid templateColumns="repeat(2, 1fr)" gap={4}>
|
||||
<Checkbox size={"sm"} color={"black"}>
|
||||
<Text fontSize={12}>Dashboard</Text>
|
||||
</Checkbox>
|
||||
<Checkbox size={"sm"} color={"black"}>
|
||||
<Text fontSize={12}>Manage contact us</Text>
|
||||
</Checkbox>
|
||||
<Checkbox size={"sm"} color={"black"}>
|
||||
<Text fontSize={12}>manage User</Text>
|
||||
</Checkbox>
|
||||
<Checkbox size={"sm"} color={"black"}>
|
||||
<Text fontSize={12}>Manage CMS</Text>
|
||||
</Checkbox>
|
||||
<Checkbox size={"sm"} color={"black"}>
|
||||
<Text fontSize={12}>Manage Post</Text>
|
||||
</Checkbox>
|
||||
<Checkbox size={"sm"} color={"black"}>
|
||||
<Text fontSize={12}>Manage Reports</Text>
|
||||
</Checkbox>
|
||||
<Checkbox size={"sm"} color={"black"}>
|
||||
<Text fontSize={12}>manage Sub-Admin</Text>
|
||||
</Checkbox>
|
||||
<Checkbox size={"sm"} color={"black"}>
|
||||
<Text fontSize={12}>My profile</Text>
|
||||
</Checkbox>
|
||||
<Checkbox size={"sm"} color={"black"}>
|
||||
<Text fontSize={12}>Manage Jobs</Text>{" "}
|
||||
</Checkbox>
|
||||
<Checkbox size={"sm"} color={"black"}>
|
||||
<Text fontSize={12}> manage feedbacks</Text>
|
||||
</Checkbox>
|
||||
<Checkbox size={"sm"} color={"black"}>
|
||||
<Text fontSize={12}>Manage community</Text>{" "}
|
||||
</Checkbox>
|
||||
<Checkbox size={"sm"} color={"black"}>
|
||||
<Text fontSize={12}> Notification</Text>
|
||||
</Checkbox>
|
||||
</Grid> */}
|
||||
<Grid templateColumns="repeat(2, 1fr)" gap={4}>
|
||||
{editData.permission.map((permission) => {
|
||||
const label = resourceIdToLabel[permission.app_resource_xid];
|
||||
@@ -295,7 +276,7 @@ function EditSubAdmin({ id, refetch }: { id: number, refetch: VoidFunction }) {
|
||||
size="sm"
|
||||
color="black"
|
||||
checked={permission.is_active}
|
||||
onChange={() => handleCheckboxToggle(permission.id)}
|
||||
onChange={() => handleCheckboxToggle(permission.app_resource_xid)}
|
||||
cursor={'pointer'}
|
||||
>
|
||||
<Text fontSize={12}>{label}</Text>
|
||||
@@ -306,12 +287,13 @@ function EditSubAdmin({ id, refetch }: { id: number, refetch: VoidFunction }) {
|
||||
</Stack>
|
||||
</DialogBody>
|
||||
<DialogFooter display="flex" justifyContent="center" pt={"2"}>
|
||||
<Button size={"xs"} w="100%" bg="#02A0A0" color={"#fff"} onClick={handleSubmit}>
|
||||
<Button size={"xs"} w="100%" bg="#02A0A0" color={"#fff"} onClick={handleSubmit} disabled={isLoading}>
|
||||
Save
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
<DialogCloseTrigger color="black" onClick={() => setIsOpen(false)} />
|
||||
</DialogContent>
|
||||
<Toaster />
|
||||
</DialogRoot>
|
||||
);
|
||||
}
|
||||
@@ -1,24 +1,26 @@
|
||||
import { Box, HStack, Image, Input, Text } from "@chakra-ui/react"
|
||||
import { Box, HStack, Image, Text } from "@chakra-ui/react"
|
||||
import MainFrame from "../../components/MainFrame"
|
||||
import { InputGroup } from "../../components/ui/input-group"
|
||||
import { LuSearch } from "react-icons/lu"
|
||||
// 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 AddModel from "./AddModel"
|
||||
import EditSubAdmin from "../../components/EditSubAdmin"
|
||||
import EditSubAdmin from "./EditSubAdmin"
|
||||
import ViewSubAdmin from "./ViewSubAdmin"
|
||||
import Delete from "../../components/ActionIcons/Delete"
|
||||
import { useDeleteSubAdminPostMutation, useGetSubAdminQuery } from "../../Redux/Service/manage.subadmin.service"
|
||||
import { PermissionResponse, useDeleteSubAdminPostMutation, useGetPermissionQuery, useGetSubAdminQuery } from "../../Redux/Service/manage.subadmin.service"
|
||||
import { useEffect, useState } from "react"
|
||||
import { toaster } from "../../components/ui/toaster"
|
||||
import { Toaster, toaster } from "../../components/ui/toaster"
|
||||
import { useDebounce } from "../../components/Hooks/useDebounce"
|
||||
import SearchComponent from "../../components/SearchComponent"
|
||||
|
||||
|
||||
// table data
|
||||
|
||||
const tableHeadRow = [
|
||||
"Sr. No",
|
||||
"Id",
|
||||
"Emp ID",
|
||||
"First Name",
|
||||
"last Name",
|
||||
"DOB",
|
||||
@@ -55,37 +57,52 @@ const tableHeadRow = [
|
||||
// ];
|
||||
|
||||
const SubAdmin = () => {
|
||||
const { data, refetch } = useGetSubAdminQuery()
|
||||
const [currentPage, setCurrentPage] = useState(1);
|
||||
// const { data, refetch } = useGetSubAdminQuery()
|
||||
const { data: permissions } = useGetPermissionQuery()
|
||||
const [localData, setLocalData] = useState<any[]>([]);
|
||||
const [allPermissions, setAllPermissions] = useState<PermissionResponse>();
|
||||
const [deleteModal, setDeleteModal] = useState(false)
|
||||
const [deleteSubAdminPost] = useDeleteSubAdminPostMutation()
|
||||
|
||||
console.log("============================",data);
|
||||
|
||||
const [searchTerm, setSearchTerm] = useState("");
|
||||
const debouncedSearchTerm = useDebounce(searchTerm, 500);
|
||||
const queryArgs = debouncedSearchTerm ? { page: currentPage, search: debouncedSearchTerm } : { page: currentPage };
|
||||
const { data, refetch, isError, isFetching } = useGetSubAdminQuery(queryArgs);
|
||||
|
||||
useEffect(() => {
|
||||
if (data?.data.data) {
|
||||
setLocalData(data?.data.data);
|
||||
setAllPermissions(permissions);
|
||||
}
|
||||
}, [data]);
|
||||
}, [data, permissions]);
|
||||
|
||||
console.log("============================", allPermissions);
|
||||
console.log('localData', localData);
|
||||
|
||||
const handleDeleteFaq = async (faqId: number) => {
|
||||
const handlePageChange = (page: number) => {
|
||||
setCurrentPage(page);
|
||||
};
|
||||
|
||||
const handleSearchChange = (value: string) => {
|
||||
setSearchTerm(value);
|
||||
setCurrentPage(1);
|
||||
};
|
||||
|
||||
const handleDeleteAdmin = async (faqId: number) => {
|
||||
try {
|
||||
const response = await deleteSubAdminPost(faqId).unwrap();
|
||||
if (response.success) {
|
||||
toaster.create({
|
||||
title: "Success",
|
||||
description: "FAQ deleted successfully",
|
||||
description: "Sub Admin deleted successfully",
|
||||
type: "success",
|
||||
});
|
||||
refetch()
|
||||
console.log("FAQ deleted successfully:", response);
|
||||
console.log("Sub Admin deleted successfully:", response);
|
||||
}
|
||||
// Optionally, refetch data or update state after deletion
|
||||
} catch (error) {
|
||||
console.error("Error deleting FAQ:", error);
|
||||
console.error("Error deleting Sub Admin:", error);
|
||||
toaster.create({
|
||||
title: "Error",
|
||||
description: "Something went wrong",
|
||||
@@ -102,10 +119,18 @@ const SubAdmin = () => {
|
||||
});
|
||||
};
|
||||
|
||||
const managepost = localData?.map((agency: any, index: number) => ({
|
||||
const filteredData = localData?.filter((agency) => {
|
||||
const searchLower = searchTerm.toLowerCase();
|
||||
const userName = agency.user_name?.toLowerCase().includes(searchLower);
|
||||
const firstName = agency.first_name?.toLowerCase().includes(searchLower);
|
||||
const lastName = agency.last_name?.toLowerCase().includes(searchLower);
|
||||
return userName || firstName || lastName;
|
||||
});
|
||||
|
||||
const managepost = filteredData?.map((agency: any, index: number) => ({
|
||||
'id': agency.id,
|
||||
"Sr. No": index + 1,
|
||||
"Id": agency.unique_id,
|
||||
"Emp ID": agency.unique_id,
|
||||
"First Name": agency.first_name,
|
||||
"last Name": agency.last_name,
|
||||
"DOB": formatDateOfBirth(agency.date_of_birth),
|
||||
@@ -114,20 +139,20 @@ const SubAdmin = () => {
|
||||
"Action": (
|
||||
<HStack justifyContent="center">
|
||||
{/* <EditDetails rowData={{ id: agency.id, question: agency.question, answer: agency.answer }} refetch={refetch} /> */}
|
||||
<ViewSubAdmin id={agency.id}/>
|
||||
<EditSubAdmin id={agency.id} refetch={refetch} />
|
||||
<ViewSubAdmin id={agency.id} />
|
||||
<EditSubAdmin id={agency.id} refetch={refetch} allPermissions={permissions} />
|
||||
|
||||
<AlertDailog
|
||||
isOpen={deleteModal}
|
||||
AltertTiggerIcon={() => <Delete onClick={() => setDeleteModal(prev => !prev)} />}
|
||||
alertText="Delete FAQ"
|
||||
alertText="Delete sub admin"
|
||||
alertIcon={<Image src={"DeleteIcon"} h={"39px"} />}
|
||||
alertCaption="are you sure you want to delete ?"
|
||||
onClose={() => setDeleteModal(false)}
|
||||
onConfirm={() => {
|
||||
// console.log("User deleted:", index + 1);
|
||||
setDeleteModal(false);
|
||||
handleDeleteFaq(agency.id)
|
||||
handleDeleteAdmin(agency.id)
|
||||
}}
|
||||
/>
|
||||
</HStack>
|
||||
@@ -150,38 +175,31 @@ const SubAdmin = () => {
|
||||
</Text>
|
||||
|
||||
<HStack>
|
||||
<InputGroup
|
||||
startElement={
|
||||
<LuSearch fontSize={"xs"} style={{ position: 'relative', left: '10px' }} />
|
||||
}
|
||||
color={"#000"}
|
||||
>
|
||||
<Input
|
||||
p={3}
|
||||
w={300}
|
||||
bg={"#fff"}
|
||||
colorPalette={"cyan"}
|
||||
_focus={{ border: "1px solid #02A0A0" }}
|
||||
rounded={"md"}
|
||||
size={"xs"}
|
||||
fontSize={"sm"}
|
||||
placeholder="Search..."
|
||||
bgColor={'#EEEEEE'}
|
||||
ps={8}
|
||||
/>
|
||||
</InputGroup>
|
||||
<SearchComponent
|
||||
value={searchTerm}
|
||||
onChange={handleSearchChange}
|
||||
/>
|
||||
{/* <Button bgColor={'#EEEEEE'} pl={3} pr={3}><IoMdAdd /> <Text>Add</Text></Button> */}
|
||||
<AddModel />
|
||||
<AddModel refetch={refetch} allPermissions={permissions} />
|
||||
</HStack>
|
||||
</HStack>
|
||||
<DataTable
|
||||
sortableColumns={["Name", "Registration Date "]}
|
||||
tableHeadRow={tableHeadRow}
|
||||
data={managepost}
|
||||
// paginationData={data?.data}
|
||||
// refetch={refetch}
|
||||
paginationData={{
|
||||
current_page: data?.data.current_page || 1,
|
||||
last_page: data?.data.last_page || 1,
|
||||
per_page: data?.data.per_page || 10,
|
||||
total: data?.data.total || 0
|
||||
}}
|
||||
onPageChange={handlePageChange}
|
||||
isLoading={isFetching}
|
||||
isError={isError}
|
||||
/>
|
||||
</Box> </MainFrame>
|
||||
</Box>
|
||||
<Toaster />
|
||||
</MainFrame>
|
||||
)
|
||||
}
|
||||
export default SubAdmin
|
||||
@@ -22,9 +22,9 @@ import { Checkbox } from "../../components/ui/checkbox";
|
||||
// import { FaRegEdit } from "react-icons/fa";
|
||||
import View from "../../components/ActionIcons/View";
|
||||
import { Button } from "../../components/ui/button";
|
||||
import { useLazyViewSubAdminQuery } from "../../Redux/Service/manage.subadmin.service";
|
||||
import {useLazyViewSubAdminQuery } from "../../Redux/Service/manage.subadmin.service";
|
||||
|
||||
function ViewSubAdmin({ id }: { id: number }) {
|
||||
function ViewSubAdmin({ id, }: { id: number}) {
|
||||
const [trigger, { data }] = useLazyViewSubAdminQuery();
|
||||
|
||||
const handleView = () => {
|
||||
@@ -64,6 +64,7 @@ function ViewSubAdmin({ id }: { id: number }) {
|
||||
overflowX="hidden"
|
||||
p={3} // Reduced padding
|
||||
bgSize={"md"}
|
||||
key={data.id}
|
||||
>
|
||||
<DialogHeader bg="white">
|
||||
<DialogTitle alignSelf="center" color="black" fontSize="14px">
|
||||
@@ -149,8 +150,8 @@ function ViewSubAdmin({ id }: { id: number }) {
|
||||
</Field.Root>
|
||||
<Grid templateColumns="repeat(2, 1fr)" gap={4}>
|
||||
{data.get_resource_action_link.map((check: any) => (
|
||||
<Checkbox size={"sm"} color={"black"} checked={check.is_active}>
|
||||
<Text fontSize={12}>{check.app_resource_xid}</Text>
|
||||
<Checkbox size={"sm"} color={"black"} checked={check.is_active} key={check.id}>
|
||||
<Text fontSize={12}>{check?.app_resource.app_resource_title}</Text>
|
||||
</Checkbox>
|
||||
// <>
|
||||
// <Checkbox size={"sm"} color={"black"}>
|
||||
|
||||
@@ -70,8 +70,18 @@ export const agencyMasterModule = createApi({
|
||||
}),
|
||||
}),
|
||||
|
||||
getAgencyMaster: builder.query<AgencyResponse, number>({
|
||||
query: (page = 1) => `/agency-master?page=${page}`
|
||||
// getAgencyMaster: builder.query<AgencyResponse, number>({
|
||||
// query: (page = 1) => `/agency-master?page=${page}`
|
||||
// }),
|
||||
|
||||
getAgencyMaster: builder.query<AgencyResponse, { page?: number; search?: string }>({
|
||||
query: ({ page, search }) => {
|
||||
const params = new URLSearchParams();
|
||||
if (page) params.append("page", page.toString());
|
||||
if (search) params.append("search", search);
|
||||
|
||||
return `/agency-master?${params.toString()}`;
|
||||
},
|
||||
}),
|
||||
|
||||
agencyMasterToggle: builder.mutation({
|
||||
|
||||
@@ -65,8 +65,18 @@ export const countryMaster = createApi({
|
||||
}),
|
||||
}),
|
||||
// 🔹 GET: Fetch all posts
|
||||
getCountryMaster: builder.query<ApiResponse, number>({
|
||||
query: (page = 1) => `/country-list?page=${page}`,
|
||||
// getCountryMaster: builder.query<ApiResponse, number>({
|
||||
// query: (page = 1) => `/country-list?page=${page}`,
|
||||
// }),
|
||||
|
||||
getCountryMaster: builder.query<ApiResponse, { page?: number; search?: string }>({
|
||||
query: ({ page, search }) => {
|
||||
const params = new URLSearchParams();
|
||||
if (page) params.append("page", page.toString());
|
||||
if (search) params.append("search", search);
|
||||
|
||||
return `/country-list?${params.toString()}`;
|
||||
},
|
||||
}),
|
||||
|
||||
getCountryMasterEdit: builder.query<CountryEdit, number>({
|
||||
|
||||
77
src/Redux/Service/dashBoard.ts
Normal file
77
src/Redux/Service/dashBoard.ts
Normal file
@@ -0,0 +1,77 @@
|
||||
import { createApi } from "@reduxjs/toolkit/query/react";
|
||||
import { baseQueryWithReauth } from "./apiSlice";
|
||||
|
||||
export type TotalUser = {
|
||||
data: {
|
||||
totalRecruiterCount: number;
|
||||
totalCustomerCount: string;
|
||||
totalUserCount: string;
|
||||
recruitersByMonth: Record<string, number>;
|
||||
customersByMonth: Record<string, number>;
|
||||
};
|
||||
};
|
||||
|
||||
export type PastUser = {
|
||||
data: {
|
||||
past24hourRecruiterCount: number;
|
||||
past24hourCustomercount: number;
|
||||
};
|
||||
};
|
||||
|
||||
export type NewUser = {
|
||||
data: {
|
||||
newRecuiterCount: number;
|
||||
newCustomerCount: number;
|
||||
newTotalUserCount: number;
|
||||
};
|
||||
};
|
||||
|
||||
export type AgencyList = {
|
||||
data: [
|
||||
{
|
||||
id: number;
|
||||
name: string;
|
||||
created_at: string;
|
||||
is_active: boolean
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
export type FaqList = {
|
||||
data: [
|
||||
{
|
||||
id: number;
|
||||
faqs_xid: number;
|
||||
language_master_xid: number;
|
||||
question: string;
|
||||
answer: string;
|
||||
is_active: boolean
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
|
||||
export const dashBoard = createApi({
|
||||
reducerPath: "dashBoard",
|
||||
baseQuery: baseQueryWithReauth, // Use enhanced baseQuery with error handling
|
||||
endpoints: (builder) => ({
|
||||
|
||||
getTotalUser: builder.query<TotalUser, void>({ query: () => "/dashboard-total-user" }),
|
||||
getPastUser: builder.query<PastUser, void>({ query: () => "/dashboard-past-user" }),
|
||||
getNewUser: builder.query<NewUser, void>({ query: () => "/dashboard-new-user" }),
|
||||
getAgencyList: builder.query<AgencyList, void>({ query: () => "/dashboard-agency-list" }),
|
||||
getFaqList: builder.query<FaqList, void>({ query: () => "/dashboard-faq-list" }),
|
||||
|
||||
|
||||
|
||||
|
||||
}),
|
||||
});
|
||||
|
||||
export const {
|
||||
useGetTotalUserQuery,
|
||||
useGetPastUserQuery,
|
||||
useGetNewUserQuery,
|
||||
useGetAgencyListQuery,
|
||||
useGetFaqListQuery,
|
||||
} = dashBoard;
|
||||
@@ -64,8 +64,18 @@ export const departmentMaster = createApi({
|
||||
}),
|
||||
}),
|
||||
// 🔹 GET: Fetch all posts
|
||||
getDepartmentMaster: builder.query<ApiResponse, number>({
|
||||
query: (page = 1) => `/department-master-list?page=${page}`,
|
||||
// getDepartmentMaster: builder.query<ApiResponse, number>({
|
||||
// query: (page = 1) => `/department-master-list?page=${page}`,
|
||||
// }),
|
||||
|
||||
getDepartmentMaster: builder.query<ApiResponse, { page?: number; search?: string }>({
|
||||
query: ({ page, search }) => {
|
||||
const params = new URLSearchParams();
|
||||
if (page) params.append("page", page.toString());
|
||||
if (search) params.append("search", search);
|
||||
|
||||
return `/department-master-list?${params.toString()}`;
|
||||
},
|
||||
}),
|
||||
|
||||
getDepartmentMasterDropDown: builder.query<DropDown, void>({
|
||||
|
||||
@@ -61,8 +61,18 @@ export const industryMaster = createApi({
|
||||
}),
|
||||
}),
|
||||
// 🔹 GET: Fetch all posts
|
||||
getIndustryMaster: builder.query<IndustryMasterResponse, number>({
|
||||
query: (page = 1) => `/industry-master-list?page=${page}`,
|
||||
// getIndustryMaster: builder.query<IndustryMasterResponse, number>({
|
||||
// query: (page = 1) => `/industry-master-list?page=${page}`,
|
||||
// }),
|
||||
|
||||
getIndustryMaster: builder.query<IndustryMasterResponse, { page?: number; search?: string }>({
|
||||
query: ({ page, search }) => {
|
||||
const params = new URLSearchParams();
|
||||
if (page) params.append("page", page.toString());
|
||||
if (search) params.append("search", search);
|
||||
|
||||
return `/industry-master-list?${params.toString()}`;
|
||||
},
|
||||
}),
|
||||
|
||||
updateIndustryMaster: builder.mutation({
|
||||
|
||||
@@ -51,8 +51,18 @@ export const jobStatus = createApi({
|
||||
}),
|
||||
}),
|
||||
// 🔹 GET: Fetch all posts
|
||||
getJobStatus: builder.query<ApiResponse, number>({
|
||||
query: (page = 1) => `/job-status-list?page=${page}`,
|
||||
// getJobStatus: builder.query<ApiResponse, number>({
|
||||
// query: (page = 1) => `/job-status-list?page=${page}`,
|
||||
// }),
|
||||
|
||||
getJobStatus: builder.query<ApiResponse, { page?: number; search?: string }>({
|
||||
query: ({ page, search }) => {
|
||||
const params = new URLSearchParams();
|
||||
if (page) params.append("page", page.toString());
|
||||
if (search) params.append("search", search);
|
||||
|
||||
return `/job-status-list?${params.toString()}`;
|
||||
},
|
||||
}),
|
||||
|
||||
updateJobStatus: builder.mutation({
|
||||
|
||||
@@ -71,9 +71,9 @@ export const jobType = createApi({
|
||||
}),
|
||||
}),
|
||||
|
||||
templateMasterToggle: builder.mutation({
|
||||
jobTypeToggle: builder.mutation({
|
||||
query: ({ id, is_active }) => ({
|
||||
url: `/template-status`,
|
||||
url: `/job-type-status`,
|
||||
method: "POST",
|
||||
body: { id, is_active },
|
||||
}),
|
||||
@@ -86,5 +86,5 @@ export const {
|
||||
useGetJobTypeQuery,
|
||||
useCreateJobTypePostMutation,
|
||||
useUpdateJobTypeMutation,
|
||||
useTemplateMasterToggleMutation,
|
||||
useJobTypeToggleMutation,
|
||||
} = jobType;
|
||||
|
||||
@@ -20,14 +20,26 @@ export const manageContactUs = createApi({
|
||||
tagTypes: ["Contact"],
|
||||
endpoints: (builder) => ({
|
||||
|
||||
|
||||
getContact: builder.query<ApiResponse, void>({
|
||||
query: () => "/contact-us",
|
||||
|
||||
getContact: builder.query<ApiResponse, { page?: number; search?: string }>({
|
||||
query: ({ page, search }) => {
|
||||
const params = new URLSearchParams();
|
||||
if (page) params.append("page", page.toString());
|
||||
if (search) params.append("search", search);
|
||||
return `/contact-us?${params.toString()}`;
|
||||
},
|
||||
providesTags: ["Contact"],
|
||||
}),
|
||||
|
||||
|
||||
pendingRequest: builder.mutation({
|
||||
query: (body) => ({
|
||||
url: `/contact-us-response`,
|
||||
method: "POST",
|
||||
body,
|
||||
}),
|
||||
invalidatesTags: ["Contact"],
|
||||
}),
|
||||
}),
|
||||
});
|
||||
|
||||
export const { useGetContactQuery } = manageContactUs;
|
||||
export const { useGetContactQuery, usePendingRequestMutation } = manageContactUs;
|
||||
|
||||
@@ -66,17 +66,40 @@ export type PostJobStatus = {
|
||||
title: string
|
||||
};
|
||||
|
||||
export type WorkSpace = {
|
||||
id: number;
|
||||
en_name: string;
|
||||
};
|
||||
|
||||
export const manageJobs = createApi({
|
||||
reducerPath: "manageJobs",
|
||||
baseQuery: baseQueryWithReauth, // Use enhanced baseQuery with error handling
|
||||
endpoints: (builder) => ({
|
||||
|
||||
getManageJobs: builder.query<ApiResponse, number>({
|
||||
query: (page = 1) => `/manage-jobs-list?page=${page}`,
|
||||
// getManageJobs: builder.query<ApiResponse, number>({
|
||||
// query: (page = 1) => `/manage-jobs-list?page=${page}`,
|
||||
// }),
|
||||
|
||||
getManageJobs: builder.query<ApiResponse, { page?: number; search?: string }>({
|
||||
query: ({ page, search }) => {
|
||||
const params = new URLSearchParams();
|
||||
if (page) params.append("page", page.toString());
|
||||
if (search) params.append("search", search);
|
||||
|
||||
return `/manage-jobs-list?${params.toString()}`;
|
||||
},
|
||||
}),
|
||||
|
||||
updateJobs: builder.mutation({
|
||||
query: (updatedData) => ({
|
||||
url: "/manage-jobs-update",
|
||||
method: "POST",
|
||||
body: updatedData,
|
||||
}),
|
||||
}),
|
||||
|
||||
viewJobs: builder.query<ApiResponse, number>({
|
||||
query: (id) => `/manage-jobs-list/${id}`,
|
||||
query: () => `/manage-jobs-list`,
|
||||
}),
|
||||
|
||||
deleteJobsPost: builder.mutation<{ status: string; message: string }, { id: number }>({
|
||||
@@ -87,10 +110,38 @@ export const manageJobs = createApi({
|
||||
}),
|
||||
}),
|
||||
|
||||
|
||||
// Modes
|
||||
getWorkspaceModes: builder.query({
|
||||
query: () => `/manage-jobs-get-workspace`,
|
||||
}),
|
||||
|
||||
getIndustry: builder.query({
|
||||
query: () => `/manage-jobs-get-industry`,
|
||||
}),
|
||||
|
||||
getDepartment: builder.query({
|
||||
query: () => `/manage-jobs-get-department`,
|
||||
}),
|
||||
|
||||
getCountry: builder.query({
|
||||
query: () => `/manage-jobs-get-country`,
|
||||
}),
|
||||
|
||||
getManageJobType: builder.query({
|
||||
query: () => `/job-type`,
|
||||
}),
|
||||
|
||||
}),
|
||||
});
|
||||
|
||||
export const { useGetManageJobsQuery,useLazyViewJobsQuery,useDeleteJobsPostMutation } = manageJobs;
|
||||
export const {
|
||||
useGetManageJobsQuery,
|
||||
useLazyViewJobsQuery,
|
||||
useDeleteJobsPostMutation,
|
||||
useUpdateJobsMutation,
|
||||
useGetWorkspaceModesQuery,
|
||||
useGetIndustryQuery,
|
||||
useGetDepartmentQuery,
|
||||
useGetCountryQuery,
|
||||
useGetManageJobTypeQuery
|
||||
} = manageJobs;
|
||||
|
||||
@@ -40,6 +40,25 @@ interface ApiResponse {
|
||||
data: PaginatedData;
|
||||
}
|
||||
|
||||
export type Permission = {
|
||||
id: number;
|
||||
app_resource_title: string;
|
||||
is_active: boolean;
|
||||
created_by: string | null;
|
||||
modified_by: string | null;
|
||||
deleted_at: string | null;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
};
|
||||
|
||||
export type PermissionResponse = {
|
||||
status: string;
|
||||
status_code: number;
|
||||
message: string;
|
||||
data: {
|
||||
permission: Permission[];
|
||||
};
|
||||
};
|
||||
// export type SubAdminPost = {
|
||||
// id: number;
|
||||
// first_name: string,
|
||||
@@ -60,6 +79,10 @@ interface ResourceActionLink {
|
||||
deleted_at: string | null;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
app_resource: {
|
||||
id: number;
|
||||
app_resource_title: string
|
||||
}
|
||||
}
|
||||
|
||||
interface SubAdmin {
|
||||
@@ -80,16 +103,14 @@ interface SubAdminView {
|
||||
}
|
||||
|
||||
interface CreateSubAdminPayload {
|
||||
principal_type_xid: number;
|
||||
principal_source_xid: number;
|
||||
user_name: string;
|
||||
// user_name: string;
|
||||
first_name: string;
|
||||
last_name: string;
|
||||
date_of_birth: string;
|
||||
gender: string;
|
||||
email_address: string;
|
||||
phone_number: string;
|
||||
created_by: number;
|
||||
// created_by: number;
|
||||
}
|
||||
|
||||
interface CreateSubAdminResponse {
|
||||
@@ -112,9 +133,18 @@ export const manageSubAdmin = createApi({
|
||||
body: data,
|
||||
}),
|
||||
}),
|
||||
|
||||
getSubAdmin: builder.query<ApiResponse, void>({
|
||||
query: () => `/sub-admin`,
|
||||
|
||||
getSubAdmin: builder.query<ApiResponse, { page?: number; search?: string }>({
|
||||
query: ({ page, search }) => {
|
||||
const params = new URLSearchParams();
|
||||
if (page) params.append("page", page.toString());
|
||||
if (search) params.append("search", search);
|
||||
return `/sub-admin?${params.toString()}`
|
||||
}
|
||||
}),
|
||||
|
||||
getPermission: builder.query<PermissionResponse, void>({
|
||||
query: () => `/resources`,
|
||||
}),
|
||||
|
||||
viewSubAdmin: builder.query<SubAdminView, number>({
|
||||
@@ -151,8 +181,9 @@ export const manageSubAdmin = createApi({
|
||||
|
||||
deleteSubAdminPost: builder.mutation<{ success: boolean }, number>({
|
||||
query: (id) => ({
|
||||
url: `/faq-delete/${id}`,
|
||||
method: "DELETE",
|
||||
url: `/sub-admin-delete`,
|
||||
method: "POST",
|
||||
body: { id },
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
@@ -160,6 +191,7 @@ export const manageSubAdmin = createApi({
|
||||
|
||||
export const {
|
||||
useGetSubAdminQuery,
|
||||
useGetPermissionQuery,
|
||||
useLazyViewSubAdminQuery,
|
||||
useUpdateSubAdminMutation,
|
||||
useDeleteSubAdminPostMutation,
|
||||
|
||||
@@ -10,11 +10,19 @@ export interface UserData {
|
||||
gender: string;
|
||||
date_of_birth: string;
|
||||
is_active: boolean;
|
||||
principal_type:{
|
||||
principal_type: {
|
||||
id: number;
|
||||
principal_type_title: string;
|
||||
},
|
||||
principle_language_links:[]
|
||||
principle_language_linkss: {
|
||||
id: number;
|
||||
language_xid: number;
|
||||
iam_principal_xid: number;
|
||||
language: {
|
||||
id: number,
|
||||
language_name: string;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
interface ApiResponse {
|
||||
@@ -55,9 +63,9 @@ export const registerUser = createApi({
|
||||
reducerPath: "registerUser",
|
||||
baseQuery: baseQueryWithReauth, // Use enhanced baseQuery with error handling
|
||||
endpoints: (builder) => ({
|
||||
createCountryPost: builder.mutation<PostCountry, Partial<PostCountry>>({
|
||||
createUser: builder.mutation<PostCountry, Partial<PostCountry>>({
|
||||
query: (data) => ({
|
||||
url: "/country-add",
|
||||
url: "/manage-user-store",
|
||||
method: "POST",
|
||||
body: data,
|
||||
}),
|
||||
@@ -67,13 +75,13 @@ export const registerUser = createApi({
|
||||
query: (page = 1) => `/manage-user-list?page=${page}`,
|
||||
}),
|
||||
|
||||
getCountryMasterEdit: builder.query<CountryEdit, number>({
|
||||
query: (id) => `/country-edit/${id}`,
|
||||
getDeactivateUser: builder.query<ApiResponse, number>({
|
||||
query: (page = 1) => `/manage-user-deactivate-list?page=${page}`,
|
||||
}),
|
||||
|
||||
updateCountry: builder.mutation({
|
||||
updateUser: builder.mutation({
|
||||
query: (updatedData) => ({
|
||||
url: "/country-update",
|
||||
url: "/manage-user-update",
|
||||
method: "POST",
|
||||
body: updatedData,
|
||||
}),
|
||||
@@ -87,22 +95,31 @@ export const registerUser = createApi({
|
||||
}),
|
||||
}),
|
||||
|
||||
// deleteFaqPost: builder.mutation<{ status: string; message: string }, { id: number }>({
|
||||
// query: ({ id }) => ({
|
||||
// url: `/faq-delete`,
|
||||
// method: "POST",
|
||||
// body: { id },
|
||||
// }),
|
||||
// }),
|
||||
userDeactivateToggle: builder.mutation({
|
||||
query: ({ id, is_active }) => ({
|
||||
url: `/manage-user-deactivate-status`,
|
||||
method: "POST",
|
||||
body: { id, is_active },
|
||||
}),
|
||||
}),
|
||||
|
||||
deleteUser: builder.mutation({
|
||||
query: ({ id }) => ({
|
||||
url: `/manage-user-delete`,
|
||||
method: "POST",
|
||||
body: { id },
|
||||
}),
|
||||
}),
|
||||
|
||||
}),
|
||||
});
|
||||
|
||||
export const {
|
||||
useGetManageUserQuery,
|
||||
useGetCountryMasterEditQuery,
|
||||
useCreateCountryPostMutation,
|
||||
useUpdateCountryMutation,
|
||||
useCreateUserMutation,
|
||||
useUpdateUserMutation,
|
||||
useUserToggleMutation,
|
||||
// useDeleteFaqPostMutation
|
||||
useGetDeactivateUserQuery,
|
||||
useUserDeactivateToggleMutation,
|
||||
useDeleteUserMutation
|
||||
} = registerUser;
|
||||
@@ -1,26 +1,37 @@
|
||||
import { createApi } from "@reduxjs/toolkit/query";
|
||||
import { createApi } from "@reduxjs/toolkit/query/react";
|
||||
import { baseQueryWithReauth } from "./apiSlice";
|
||||
|
||||
export const myProfile = createApi({
|
||||
reducerPath: "myProfile",
|
||||
baseQuery: baseQueryWithReauth, // Use enhanced baseQuery with error handling
|
||||
endpoints: (builder) => ({
|
||||
|
||||
|
||||
|
||||
getPosts: builder.query<Post[], void>({ query: () => "/posts" }),
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}),
|
||||
});
|
||||
|
||||
export const { } = myProfile;
|
||||
|
||||
export type Post = {
|
||||
id: number;
|
||||
title: string;
|
||||
body: string;
|
||||
};
|
||||
reducerPath: "myProfile",
|
||||
baseQuery: baseQueryWithReauth, // Use enhanced baseQuery with error handling
|
||||
endpoints: (builder) => ({
|
||||
|
||||
|
||||
|
||||
// getPosts: builder.query<Post[], void>({ query: () => "/profile-image-edit" }),
|
||||
|
||||
updateImage: builder.mutation({
|
||||
query: (formData: FormData) => {
|
||||
const token = localStorage.getItem("token");
|
||||
|
||||
return {
|
||||
url: "/profile-image-edit",
|
||||
method: "POST",
|
||||
body: formData,
|
||||
headers: {
|
||||
"access-token": `${token}`,
|
||||
},
|
||||
};
|
||||
},
|
||||
}),
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}),
|
||||
});
|
||||
|
||||
export const {
|
||||
useUpdateImageMutation,
|
||||
} = myProfile;
|
||||
|
||||
@@ -27,6 +27,7 @@ interface PaginationData {
|
||||
export interface Template {
|
||||
id: number;
|
||||
is_active: boolean;
|
||||
principle_type_xid: number;
|
||||
post_template_translate: PostTemplateTranslate[];
|
||||
post_template_image: PostTemplateImage[];
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ export const workspaceMode = createApi({
|
||||
endpoints: (builder) => ({
|
||||
createWorkspacePost: builder.mutation<PostDepartment, Partial<PostDepartment>>({
|
||||
query: (data) => ({
|
||||
url: "/department-master-store",
|
||||
url: "/workspace-create",
|
||||
method: "POST",
|
||||
body: data,
|
||||
}),
|
||||
|
||||
@@ -23,6 +23,7 @@ import { workspaceMode } from "./Service/workspace.mode";
|
||||
import { jobStatus } from "./Service/job.status";
|
||||
import { managePosts } from "./Service/manage.post.service";
|
||||
import { registerUser } from "./Service/manage.user";
|
||||
import { dashBoard } from "./Service/dashBoard";
|
||||
|
||||
export const store = configureStore({
|
||||
reducer: {
|
||||
@@ -49,6 +50,7 @@ export const store = configureStore({
|
||||
[jobStatus.reducerPath]: jobStatus.reducer,
|
||||
[managePosts.reducerPath]: managePosts.reducer,
|
||||
[registerUser.reducerPath]: registerUser.reducer,
|
||||
[dashBoard.reducerPath]: dashBoard.reducer,
|
||||
auth: authReducer,
|
||||
},
|
||||
middleware: (getDefaultMiddleware) =>
|
||||
@@ -76,6 +78,7 @@ export const store = configureStore({
|
||||
jobStatus.middleware,
|
||||
managePosts.middleware,
|
||||
registerUser.middleware,
|
||||
dashBoard.middleware,
|
||||
),
|
||||
});
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { LuBriefcaseBusiness} from "react-icons/lu";
|
||||
import { MdHeadsetMic, MdOutlineDashboard} from "react-icons/md";
|
||||
import { LuBriefcaseBusiness } from "react-icons/lu";
|
||||
import { MdHeadsetMic, MdOutlineDashboard } from "react-icons/md";
|
||||
import { GoDotFill } from "react-icons/go";
|
||||
import { HiOutlinePencilSquare } from "react-icons/hi2";
|
||||
import { BiUser, BiUserPin } from "react-icons/bi";
|
||||
@@ -8,146 +8,156 @@ import { BsBoxes, BsPersonBadge } from "react-icons/bs";
|
||||
import { AiOutlineFileText } from "react-icons/ai";
|
||||
|
||||
export const nav = [
|
||||
|
||||
{
|
||||
title: "Dashboard",
|
||||
path: "/",
|
||||
Icon: MdOutlineDashboard,
|
||||
type:'single'
|
||||
},
|
||||
{
|
||||
title: "Manage Users",
|
||||
initPath: "/manage-users",
|
||||
Icon: BiUserPin,
|
||||
type:'multiple',
|
||||
children: [
|
||||
{
|
||||
title: "Register Users",
|
||||
path: "/manage-users/register-users",
|
||||
Icon: GoDotFill,
|
||||
},
|
||||
{
|
||||
title: "Deactivated Accounts",
|
||||
path: "/manage-users/deactivated-accounts",
|
||||
Icon: GoDotFill,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Manage Post",
|
||||
path: "/manage-post",
|
||||
Icon: HiOutlinePencilSquare,
|
||||
type:'single'
|
||||
},
|
||||
{
|
||||
title: "Manage Sub-Admin",
|
||||
path: "/sub-admin",
|
||||
Icon: BiUser,
|
||||
type:'single'
|
||||
},
|
||||
{
|
||||
title: "Manage Jobs",
|
||||
path: "/manage-jobs",
|
||||
Icon: LuBriefcaseBusiness,
|
||||
type:'single'
|
||||
},
|
||||
{
|
||||
title: "Manage Groups",
|
||||
path: "/manage-groups",
|
||||
Icon: PiUsersThree,
|
||||
type:'single'
|
||||
},
|
||||
{
|
||||
title: "Manage Contact Us",
|
||||
path: "/manage-contact",
|
||||
Icon: MdHeadsetMic ,
|
||||
type:'single'
|
||||
},
|
||||
{
|
||||
title: "Manage CMS",
|
||||
initPath: "/manage-cms",
|
||||
Icon: AiOutlineFileText,
|
||||
type:'multiple',
|
||||
children: [
|
||||
{
|
||||
title: "FAQs",
|
||||
path: "/manage-cms/faq",
|
||||
Icon: GoDotFill,
|
||||
},
|
||||
{
|
||||
title: "About Us",
|
||||
path: "/manage-cms/about-us",
|
||||
Icon: GoDotFill,
|
||||
},
|
||||
{
|
||||
title: "Privacy Policy",
|
||||
path: "/manage-cms/privacy-policy",
|
||||
Icon: GoDotFill,
|
||||
},
|
||||
{
|
||||
title: "Terms And Conditions",
|
||||
path: "/manage-cms/terms-conditions",
|
||||
Icon: GoDotFill,
|
||||
},
|
||||
// {
|
||||
// title: "Privacy",
|
||||
// path: "/manage-cms/privacy",
|
||||
// Icon: GoDotFill,
|
||||
// },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "My Profile",
|
||||
path: "/profile",
|
||||
Icon: BsPersonBadge,
|
||||
type:'single'
|
||||
},
|
||||
{
|
||||
title: "Master Module",
|
||||
initPath: "/master-module",
|
||||
Icon: BsBoxes,
|
||||
type:'multiple',
|
||||
children: [
|
||||
{
|
||||
title: "Agency Master",
|
||||
path: "/master-module/agency-master",
|
||||
Icon: GoDotFill,
|
||||
},
|
||||
{
|
||||
title: "Template Master",
|
||||
path: "/master-module/template-master",
|
||||
Icon: GoDotFill,
|
||||
},
|
||||
{
|
||||
title: "Job Type",
|
||||
path: "/master-module/job-type",
|
||||
Icon: GoDotFill,
|
||||
},
|
||||
{
|
||||
title: "Workspace Mode",
|
||||
path: "/master-module/workspace-mode",
|
||||
Icon: GoDotFill,
|
||||
},
|
||||
{
|
||||
title: "Country",
|
||||
path: "/master-module/country",
|
||||
Icon: GoDotFill,
|
||||
},
|
||||
{
|
||||
title: "Job Status",
|
||||
path: "/master-module/job-status",
|
||||
Icon: GoDotFill,
|
||||
},
|
||||
{
|
||||
title: "Industry Master",
|
||||
path: "/master-module/industry-master",
|
||||
Icon: GoDotFill,
|
||||
},
|
||||
{
|
||||
title: "Department Master",
|
||||
path: "/master-module/department-master",
|
||||
Icon: GoDotFill,
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
{
|
||||
title: "Dashboard",
|
||||
path: "/",
|
||||
Icon: MdOutlineDashboard,
|
||||
type: 'single',
|
||||
resourceTitle: 'Dashboard'
|
||||
},
|
||||
{
|
||||
title: "Manage Users",
|
||||
initPath: "/manage-users",
|
||||
Icon: BiUserPin,
|
||||
type: 'multiple',
|
||||
resourceTitle: 'Manage User',
|
||||
children: [
|
||||
{
|
||||
title: "Register Users",
|
||||
path: "/manage-users/register-users",
|
||||
Icon: GoDotFill,
|
||||
},
|
||||
{
|
||||
title: "Deactivated Accounts",
|
||||
path: "/manage-users/deactivated-accounts",
|
||||
Icon: GoDotFill,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Manage Post",
|
||||
path: "/manage-post",
|
||||
Icon: HiOutlinePencilSquare,
|
||||
type: 'single',
|
||||
resourceTitle: 'Manage Post'
|
||||
},
|
||||
{
|
||||
title: "Manage Sub-Admin",
|
||||
path: "/sub-admin",
|
||||
Icon: BiUser,
|
||||
type: 'single',
|
||||
resourceTitle: 'Manage Subadmin'
|
||||
},
|
||||
{
|
||||
title: "Manage Jobs",
|
||||
path: "/manage-jobs",
|
||||
Icon: LuBriefcaseBusiness,
|
||||
type: 'single',
|
||||
resourceTitle: 'Manage Jobs'
|
||||
},
|
||||
{
|
||||
title: "Manage Groups",
|
||||
path: "/manage-groups",
|
||||
Icon: PiUsersThree,
|
||||
type: 'single',
|
||||
resourceTitle: 'Manage Groups'
|
||||
},
|
||||
{
|
||||
title: "Manage Contact Us",
|
||||
path: "/manage-contact",
|
||||
Icon: MdHeadsetMic,
|
||||
type: 'single',
|
||||
resourceTitle: 'Manage Contact Us'
|
||||
},
|
||||
{
|
||||
title: "Manage CMS",
|
||||
initPath: "/manage-cms",
|
||||
Icon: AiOutlineFileText,
|
||||
type: 'multiple',
|
||||
resourceTitle: 'Manage CMS',
|
||||
children: [
|
||||
{
|
||||
title: "FAQs",
|
||||
path: "/manage-cms/faq",
|
||||
Icon: GoDotFill,
|
||||
},
|
||||
{
|
||||
title: "About Us",
|
||||
path: "/manage-cms/about-us",
|
||||
Icon: GoDotFill,
|
||||
},
|
||||
{
|
||||
title: "Privacy Policy",
|
||||
path: "/manage-cms/privacy-policy",
|
||||
Icon: GoDotFill,
|
||||
},
|
||||
{
|
||||
title: "Terms And Conditions",
|
||||
path: "/manage-cms/terms-conditions",
|
||||
Icon: GoDotFill,
|
||||
},
|
||||
// {
|
||||
// title: "Privacy",
|
||||
// path: "/manage-cms/privacy",
|
||||
// Icon: GoDotFill,
|
||||
// },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "My Profile",
|
||||
path: "/profile",
|
||||
Icon: BsPersonBadge,
|
||||
type: 'single',
|
||||
resourceTitle: 'My Profile'
|
||||
},
|
||||
{
|
||||
title: "Master Module",
|
||||
initPath: "/master-module",
|
||||
Icon: BsBoxes,
|
||||
type: 'multiple',
|
||||
resourceTitle: 'Master Module',
|
||||
children: [
|
||||
{
|
||||
title: "Agency Master",
|
||||
path: "/master-module/agency-master",
|
||||
Icon: GoDotFill,
|
||||
},
|
||||
{
|
||||
title: "Template Master",
|
||||
path: "/master-module/template-master",
|
||||
Icon: GoDotFill,
|
||||
},
|
||||
{
|
||||
title: "Job Type",
|
||||
path: "/master-module/job-type",
|
||||
Icon: GoDotFill,
|
||||
},
|
||||
{
|
||||
title: "Workspace Mode",
|
||||
path: "/master-module/workspace-mode",
|
||||
Icon: GoDotFill,
|
||||
},
|
||||
{
|
||||
title: "Country",
|
||||
path: "/master-module/country",
|
||||
Icon: GoDotFill,
|
||||
},
|
||||
{
|
||||
title: "Job Status",
|
||||
path: "/master-module/job-status",
|
||||
Icon: GoDotFill,
|
||||
},
|
||||
{
|
||||
title: "Industry Master",
|
||||
path: "/master-module/industry-master",
|
||||
Icon: GoDotFill,
|
||||
},
|
||||
{
|
||||
title: "Department Master",
|
||||
path: "/master-module/department-master",
|
||||
Icon: GoDotFill,
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
@@ -11,19 +11,35 @@ import { FaUser } from "react-icons/fa";
|
||||
// ✅ Register required components
|
||||
ChartJS.register(ArcElement, Tooltip, Legend);
|
||||
|
||||
const SemiDoughnutChart = () => {
|
||||
const SemiDoughnutChart = ({ totalUser }: { totalUser: any }) => {
|
||||
const dataSource = totalUser ?? {}
|
||||
|
||||
const recruiterCount =
|
||||
dataSource.past24hourRecruiterCount ??
|
||||
dataSource.totalRecruiterCount ??
|
||||
dataSource.newRecuiterCount ??
|
||||
0;
|
||||
|
||||
const customerCount =
|
||||
dataSource.past24hourCustomercount ??
|
||||
dataSource.totalCustomerCount ??
|
||||
dataSource.newCustomerCount ??
|
||||
0;
|
||||
|
||||
|
||||
|
||||
// 📊 Chart Data
|
||||
const data = {
|
||||
labels: ["Recruiter", "Customer"],
|
||||
datasets: [
|
||||
{
|
||||
data: [2554, 2800], // Values
|
||||
data: [recruiterCount, customerCount], // Values
|
||||
backgroundColor: ["#E0E0E0", "#3D5AFE"], // Grey and Blue
|
||||
borderWidth: 0, // No border
|
||||
cutout: "90%", // Makes it a doughnut shape
|
||||
circumference: 270, // Semi-circle
|
||||
rotation: 225, // Starts from the top
|
||||
|
||||
|
||||
},
|
||||
],
|
||||
};
|
||||
@@ -50,9 +66,9 @@ const SemiDoughnutChart = () => {
|
||||
fontSize: "20px",
|
||||
fontWeight: "bold",
|
||||
color: "#3D5AFE",
|
||||
backgroundColor:'#ECEAF8',
|
||||
padding:'15px',
|
||||
borderRadius:'50%'
|
||||
backgroundColor: '#ECEAF8',
|
||||
padding: '15px',
|
||||
borderRadius: '50%'
|
||||
}}
|
||||
>
|
||||
<FaUser />
|
||||
|
||||
@@ -25,6 +25,8 @@ interface TableProps {
|
||||
total: number;
|
||||
};
|
||||
onPageChange?: (page: number) => void;
|
||||
isLoading?: boolean;
|
||||
isError?: boolean;
|
||||
}
|
||||
|
||||
const DataTable: React.FC<TableProps> = ({
|
||||
@@ -33,6 +35,8 @@ const DataTable: React.FC<TableProps> = ({
|
||||
sortableColumns = [],
|
||||
paginationData,
|
||||
onPageChange,
|
||||
isLoading,
|
||||
isError
|
||||
}: TableProps) => {
|
||||
const { current_page = 1, last_page = 1 } = paginationData || {};
|
||||
const [sortConfig, setSortConfig] = useState<{
|
||||
@@ -103,47 +107,65 @@ const DataTable: React.FC<TableProps> = ({
|
||||
))}
|
||||
</Table.Row>
|
||||
</Table.Header>
|
||||
{data?.length === 0 ? (
|
||||
<Box>
|
||||
<Box textAlign={"center"} py={20} position={'absolute'} w={'84%'}>
|
||||
<Image src={EmptyFile} alt="No data" maxW="65px" mx="auto" />
|
||||
<Text fontSize={"18px"} fontWeight={500} mt={2}>
|
||||
We do not have any records
|
||||
</Text>
|
||||
</Box>
|
||||
{isLoading ? (
|
||||
<Box textAlign={"center"} py={20} position="absolute" w="84%">
|
||||
<Text fontSize={"18px"} fontWeight={500} mt={2}>
|
||||
Loading...
|
||||
</Text>
|
||||
</Box>
|
||||
) : isError ? (
|
||||
<Box textAlign={"center"} py={20} position="absolute" w="84%">
|
||||
<Image src={EmptyFile} alt="No data" maxW="65px" mx="auto" />
|
||||
<Text fontSize={"18px"} fontWeight={500} mt={2}>
|
||||
No records found — they’ll appear here if available.
|
||||
</Text>
|
||||
</Box>
|
||||
) : (
|
||||
<Table.Body h={"100%"}>
|
||||
<Table.Body h="100%">
|
||||
{data.length === 0 && (
|
||||
<Box textAlign={"center"} py={20} position="absolute" w="84%">
|
||||
<Image src={EmptyFile} alt="No data" maxW="65px" mx="auto" />
|
||||
<Text fontSize={"18px"} fontWeight={500} mt={2}>
|
||||
No records found — they’ll appear here if available.
|
||||
</Text>
|
||||
</Box>
|
||||
)}
|
||||
{data.map((item: any, index) => (
|
||||
<Table.Row
|
||||
key={index}
|
||||
bg={index % 2 === 0 ? "#fff" : "#007F3310"}
|
||||
>
|
||||
{tableHeadRow.map((heading, colIndex) => (
|
||||
<Table.Cell
|
||||
px={4}
|
||||
p={2}
|
||||
key={`${index}-${colIndex}`}
|
||||
fontSize={"xs"}
|
||||
fontWeight={500}
|
||||
border={"none"}
|
||||
>
|
||||
{(() => {
|
||||
const words =
|
||||
item[heading]?.toString().split(" ") || [];
|
||||
return words.length > 5
|
||||
? `${words.slice(0, 5).join(" ")}...`
|
||||
: item[heading];
|
||||
})()}
|
||||
</Table.Cell>
|
||||
))}
|
||||
{tableHeadRow.map((heading, colIndex) => {
|
||||
const cellContent = item[heading];
|
||||
const words = typeof cellContent === 'string'
|
||||
? cellContent.split(" ")
|
||||
: cellContent?.toString().split(" ") || [];
|
||||
|
||||
const truncated = words.length > 15
|
||||
? `${words.slice(0, 15).join(" ")}...`
|
||||
: cellContent;
|
||||
|
||||
return (
|
||||
<Table.Cell
|
||||
px={4}
|
||||
p={2}
|
||||
key={`${index}-${colIndex}`}
|
||||
fontSize="xs"
|
||||
fontWeight={500}
|
||||
border="none"
|
||||
>
|
||||
{truncated}
|
||||
</Table.Cell>
|
||||
);
|
||||
})}
|
||||
</Table.Row>
|
||||
))}
|
||||
</Table.Body>
|
||||
)}
|
||||
|
||||
</Table.Root>
|
||||
</Table.ScrollArea>
|
||||
{last_page > 1 && (
|
||||
{last_page > 1 && !isLoading && !isError && (
|
||||
<PaginationRoot
|
||||
count={paginationData?.total ?? 0}
|
||||
pageSize={paginationData?.per_page ?? 0}
|
||||
|
||||
16
src/components/Hooks/useDebounce.ts
Normal file
16
src/components/Hooks/useDebounce.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
// hooks/useDebounce.ts
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
export function useDebounce<T>(value: T, delay = 500): T {
|
||||
const [debounced, setDebounced] = useState(value);
|
||||
|
||||
useEffect(() => {
|
||||
const handler = setTimeout(() => {
|
||||
setDebounced(value);
|
||||
}, delay);
|
||||
|
||||
return () => clearTimeout(handler); // cleanup on unmount or value change
|
||||
}, [value, delay]);
|
||||
|
||||
return debounced;
|
||||
}
|
||||
3
src/components/Utils.ts
Normal file
3
src/components/Utils.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
|
||||
|
||||
export const delay = (ms: number) => new Promise(res => setTimeout(res, ms));
|
||||
@@ -44,7 +44,7 @@ export const DialogCloseTrigger = React.forwardRef<
|
||||
{...props}
|
||||
asChild
|
||||
>
|
||||
<CloseButton size="sm" ref={ref}>
|
||||
<CloseButton size="sm" ref={ref} _hover={{ color: "gray.200" }}>
|
||||
{props.children}
|
||||
</CloseButton>
|
||||
</ChakraDialog.CloseTrigger>
|
||||
|
||||
@@ -183,4 +183,23 @@ input:focus-visible {
|
||||
|
||||
.css-1ilznyv {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.custom-checkbox {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
border: 2px solid black;
|
||||
background-color: white;
|
||||
appearance: none;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.custom-checkbox:checked::after {
|
||||
content: "✔";
|
||||
color: black;
|
||||
font-size: 16px;
|
||||
position: absolute;
|
||||
top: -2px;
|
||||
left: 0px;
|
||||
}
|
||||
Reference in New Issue
Block a user