This commit is contained in:
YasinShaikh123
2025-06-03 13:41:24 +05:30
44 changed files with 2644 additions and 614 deletions

14
.env
View File

@@ -1,7 +1,15 @@
VITE_API_URL='https://ssa.betadelivery.com/apia/v1'
# VITE_API_URL='http://192.16.50.44/seo-backend/apia/v1'
# 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/storage/app/public/uploads/post_templates/'
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/`

View File

@@ -82,7 +82,7 @@ define(['./workbox-54d0af47'], (function (workbox) { 'use strict';
"revision": "3ca0b8505b4bec776b69afdba2768812"
}, {
"url": "index.html",
"revision": "0.4sre1e6vpfo"
"revision": "0.bma87cujt8g"
}], {});
workbox.cleanupOutdatedCaches();
workbox.registerRoute(new workbox.NavigationRoute(workbox.createHandlerBoundToURL("index.html"), {

View File

@@ -12,9 +12,10 @@ import { useDispatch } from "react-redux";
import GlobalStateContext from "../Contexts/GlobalStateContext";
import { useLogOutMutation } from "../Redux/Service/apiSlice";
import ProgressBar from "../components/ProgressBar/ProgressBar";
import { useGetProfileQuery } from "../Redux/Service/profile.password";
const DefaultLayout: FC<{ children: React.ReactNode }> = ({ children }) => {
const { data } = useGetProfileQuery()
const dispatch = useDispatch()
const navigate = useNavigate()
const location = useLocation()
@@ -25,20 +26,20 @@ const DefaultLayout: FC<{ children: React.ReactNode }> = ({ children }) => {
throw new Error('App must be used within a GlobalStateProvider');
}
const { setIsAuthenticate, isBarLoading } = context;
const [ logOutAdmin ] = useLogOutMutation()
const [logOutAdmin] = useLogOutMutation()
// Logout function
const handleLogout = async () => {
try {
// ✅ Call mutation and wait for the response
const res = await logOutAdmin().unwrap();
const res = await logOutAdmin().unwrap();
console.log("Logout Success:", res);
// ✅ Clear local storage & update authentication state
dispatch(logout());
localStorage.removeItem("token");
setIsAuthenticate(false);
localStorage.removeItem("token");
setIsAuthenticate(false);
// ✅ Redirect to login page
navigate("/login");
} catch (error) {
@@ -48,43 +49,43 @@ const DefaultLayout: FC<{ children: React.ReactNode }> = ({ children }) => {
return (
<VStack gap={0} w="100%" h="100vh" bg="#F2F2F2">
<ProgressBar isLoading={isBarLoading} />
<HStack overflow={'hidden'} position={'relative'} bg="#F2F2F2" backgroundPosition="center" backgroundRepeat="repeat" backgroundSize="cover" gap={0} w="100%" h="calc(100% - 4px)" p={0}>
<VStack pt={0} zIndex={1} gap={0} rounded={'lg'} h="100%" w="15%" overflow={'auto'} >
<HStack w={'100%'} p={3} h={'7%'} justifyContent={'center'}>
<Image w={55} src={logo} />
</HStack>
<VStack w={'100%'} p={2} pt={0}>
{nav?.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}>
<AccordionItemTrigger className="Oxygen" color={'#fff'} onClick={() => navigate(path||'')} gap={0} style={{ cursor: 'pointer', borderRadius: '8px', padding: '5px', width: '100%', display: 'flex', alignItems: 'center', border: '1px solid #ffffff', backgroundColor:'#fff',color:'#000', fontSize: '14px', }}> <Text fontSize={'xs'} gap={1} display={'flex'} alignItems={'center'} ><Icon style={{ fontSize: '20px' }} />{title}</Text></AccordionItemTrigger>
{children?.map(({ title, path, Icon }, index) => <AccordionItemContent className={`linkChild Oxygen ${location?.pathname === path && 'activeChild'}`} key={index} onClick={()=>navigate(path)} style={{ marginTop: 6, cursor: 'pointer', borderRadius: '8px', padding: '6px', width: '100%', display: 'flex', alignItems: 'center', gap: 6, border: '1px solid #ffffff', backgroundColor:'#fff',color:'#919198' }} ><Icon style={{ fontSize: '20px' }} /> <Text fontSize={'xs'} w={'100%'}>{title}</Text></AccordionItemContent>)}
</AccordionItem>
</AccordionRoot>)}
</VStack>
<VStack w={'100%'} p={3} pt={0}>
<HStack onClick={handleLogout} className="link" 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'}} ><LuLogOut style={{ fontSize: '20px' }} /> <Text fontSize={'xs'} w={'100%'}>Logout</Text></HStack>
</VStack>
</VStack>
<VStack gap={0} h="100%" w="85%" >
<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>
<HStack cursor={'pointer'} onClick={() => navigate('/profile')} >
<Avatar size={'sm'} src="https://i.pinimg.com/736x/d6/cd/0f/d6cd0ffd4634b0763d3958a7325ce26e.jpg" />
<VStack color={'#013e3e'} gap={0} alignItems={'flex-start'}>
<Text fontSize={'sm'} fontWeight={'bold'}>Ritesh Pandey</Text>
<Text fontSize={'xs'} >ritesh.pandey@wdimails.com</Text>
</VStack>
<ProgressBar isLoading={isBarLoading} />
<HStack overflow={'hidden'} position={'relative'} bg="#F2F2F2" backgroundPosition="center" backgroundRepeat="repeat" backgroundSize="cover" gap={0} w="100%" h="calc(100% - 4px)" p={0}>
<VStack pt={0} zIndex={1} gap={0} rounded={'lg'} h="100%" w="15%" overflow={'auto'} >
<HStack w={'100%'} p={3} h={'7%'} justifyContent={'center'}>
<Image w={55} src={logo} />
</HStack>
</HStack>
{children}
</VStack>
</HStack>
<VStack w={'100%'} p={2} pt={0}>
{nav?.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}>
<AccordionItemTrigger className="Oxygen" color={'#fff'} onClick={() => navigate(path || '')} gap={0} style={{ cursor: 'pointer', borderRadius: '8px', padding: '5px', width: '100%', display: 'flex', alignItems: 'center', border: '1px solid #ffffff', backgroundColor: '#fff', color: '#000', fontSize: '14px', }}> <Text fontSize={'xs'} gap={1} display={'flex'} alignItems={'center'} ><Icon style={{ fontSize: '20px' }} />{title}</Text></AccordionItemTrigger>
{children?.map(({ title, path, Icon }, index) => <AccordionItemContent className={`linkChild Oxygen ${location?.pathname === path && 'activeChild'}`} key={index} onClick={() => navigate(path)} style={{ marginTop: 6, cursor: 'pointer', borderRadius: '8px', padding: '6px', width: '100%', display: 'flex', alignItems: 'center', gap: 6, border: '1px solid #ffffff', backgroundColor: '#fff', color: '#919198' }} ><Icon style={{ fontSize: '20px' }} /> <Text fontSize={'xs'} w={'100%'}>{title}</Text></AccordionItemContent>)}
</AccordionItem>
</AccordionRoot>)}
</VStack>
<VStack w={'100%'} p={3} pt={0}>
<HStack onClick={handleLogout} className="link" 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' }} ><LuLogOut style={{ fontSize: '20px' }} /> <Text fontSize={'xs'} w={'100%'}>Logout</Text></HStack>
</VStack>
</VStack>
<VStack gap={0} h="100%" w="85%" >
<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>
<HStack cursor={'pointer'} onClick={() => navigate('/profile')} >
<Avatar size={'sm'} src="https://i.pinimg.com/736x/d6/cd/0f/d6cd0ffd4634b0763d3958a7325ce26e.jpg" />
<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>
</VStack>
</HStack>
</HStack>
{children}
</VStack>
</HStack>
</VStack>
);
};

View File

@@ -77,13 +77,13 @@ const Login = () => {
console.log(res);
console.log("====================================");
}
} catch (error) {
console.log('error', error);
} catch (error: any) {
console.log('error', error.response.data.message);
if (error) {
toaster.create({
// title: error?.response?.data?.message,
title: "Something Went Wrong",
title: error?.response?.data?.message,
// title: "Something Went Wrong",
type: "info",
})
// console.log("Login failed", error?.response?.data?.message);

View File

@@ -53,7 +53,8 @@ const tableHeadRow = [
// ];
const FAQ = () => {
const { data, refetch, isLoading, isFetching } = useGetFaqQuery()
const [currentPage, setCurrentPage] = useState(1);
const { data, refetch, isLoading, isFetching } = useGetFaqQuery(currentPage)
const [localData, setLocalData] = useState<any[]>([]);
const [faqToggle] = useFaqToggleMutation()
const [deleteFaqPost] = useDeleteFaqPostMutation()
@@ -69,6 +70,10 @@ const FAQ = () => {
}
}, [data]);
const handlePageChange = (page: number) => {
setCurrentPage(page);
};
const handleToggle = async (agencyId: number, currentStatus: string) => {
const newStatus = currentStatus === '1' ? '0' : '1';
@@ -129,10 +134,10 @@ const FAQ = () => {
const managepost = filteredData?.flatMap((agency: FaqData, index: number) =>
agency.translations.map((translation: any) => ({
'id': translation.id,
"Sr. No": index + 1,
"Sr. No": (currentPage - 1) * (data?.data.per_page ?? 0) + index + 1,
"Question": translation.question,
"Answer": translation.answer,
'Category': agency.principal_type_xid === 2 ? "Job Seeker" : "Recruiter",
'Category': agency.principal_type_xid === 2 ? "Recruiter" : "Job Seeker",
"Action": (
<HStack justifyContent="center">
@@ -178,7 +183,7 @@ const FAQ = () => {
py={0}
px={3}
>
<Spinner color={'teal'}/>
<Spinner color={'teal'} />
</HStack>
)
}
@@ -208,13 +213,18 @@ const FAQ = () => {
</HStack>
{isFetching && <Spinner />}
{!isLoading && !data?.data ? (
<NoData message={'No data found'} text={'Please add new data'}/>
<NoData message={'No data found'} text={'Please add new data'} />
) : (<DataTable
sortableColumns={["Name"]}
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}
/>)}
</Box>
<Toaster />

View File

@@ -1,6 +1,8 @@
import { Box, HStack,
import {
Box, HStack,
// Image,
Input, Text } from "@chakra-ui/react";
Input, Text
} from "@chakra-ui/react";
import { LuSearch } from "react-icons/lu";
// import { RiDeleteBin5Line } from "react-icons/ri";
// import AlertDailog from "../../components/AlertDailog";
@@ -9,6 +11,8 @@ import MainFrame from "../../components/MainFrame";
import { InputGroup } from "../../components/ui/input-group";
import ManageJobsAdd from "./ManageJobsAdd";
import ViewManageJob from "./ViewManageJob";
// import { useState } from "react";
// import { useGetManageJobsQuery } from "../../Redux/Service/manage.jobs.service";
// import Delete from "../../components/ActionIcons/Delete";
// table data
@@ -50,6 +54,10 @@ const managepost: any[] = [
];
const ManageJobs = () => {
// const [currentPage, setCurrentPage] = useState(1);
// const { data, refetch } = useGetManageJobsQuery(currentPage)
// console.log(data?.data.data);
return (
<MainFrame>
<Box>

View File

@@ -1,67 +1,205 @@
import { Box, HStack, Image, Input,
import {
Box, HStack, Icon, Image,
// Span,
Text } from "@chakra-ui/react";
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 { Switch } from "../../components/ui/switch";
import img from "../../assets/waterfall.jpg";
// import img from "../../assets/waterfall.jpg";
// import { RiDeleteBin5Line } from "react-icons/ri";
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 { FaVideo } from "react-icons/fa";
import SearchComponent from "../../components/SearchComponent";
// import Delete from "../../components/ActionIcons/Delete";
// import ViewDailog from './ViewDailog'
// table data
const APIURL = import.meta.env.VITE_POST_IMG
const tableHeadRow = [
"Sr. No",
"Images",
"Description",
"Publish Data",
"Activate/Deactivate",
// "Activate/Deactivate",
"Action",
];
const managepost: any[] = [
...Array.from({ length: 12 }, (_, i) => ({
"Sr. No": i + 1,
// const managepost: any[] = [
// ...Array.from({ length: 12 }, (_, i) => ({
// "Sr. No": i + 1,
// Images: (
// // <Image w={50} src={img} />
// <Image rounded={"lg"} w={100} h={50} src={img} />
// ),
// Description: (
// <Text>
// {`Lorem ipsum dolor, sit amet consectetur adipisicing elit.}`.slice(
// 0,
// 30
// ) + "..."}
// </Text>
// ),
// "Publish Data": "12/01/2025",
// "Activate/Deactivate": (
// <Box w={"100%"}>
// <Switch size={"sm"} colorPalette={"teal"} />
// </Box>
// ),
// Action: (
// <HStack justifyContent="center">
// <ViewDailog />
// {/* <AlertDailog
// AltertTiggerIcon={() => <Span><Delete /> </Span>}
// alertText="Delete Users"
// alertIcon={<Image src={"DeleteIcon"} h={"39px"} />}
// alertCaption="are you sure you want to delete ?"
// onConfirm={() => {
// console.log("User deleted:", i + 1);
// }}
// /> */}
// </HStack>
// ),
// })),
// ];
const ManagePost = () => {
const [currentPage, setCurrentPage] = useState(1);
const { data, refetch } = useGetManagePostsQuery(currentPage)
const [localData, setLocalData] = useState<any[]>([]);
const [searchTerm, setSearchTerm] = useState("");
const [postStatusToggle] = usePostStatusToggleMutation()
console.log('POSTS', data?.data.data);
useEffect(() => {
if (data?.data?.data) {
setLocalData(data?.data.data);
}
}, [data]);
const handlePageChange = (page: number) => {
setCurrentPage(page);
};
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 postStatusToggle({ id: agencyId, is_active: newStatus }).unwrap();
refetch()
} catch (error) {
console.error("Error updating:", error);
toaster.create({
title: "Error",
description: "Someting went wrong.",
type: "error",
});
setLocalData((prevData) =>
prevData.map((agency) =>
agency.id === agencyId ? { ...agency, is_active: currentStatus } : agency
)
);
}
};
function formatAPIDate(apiDateString: any) {
const date = new Date(apiDateString);
// Get month, day, and year
const month = date.getMonth() + 1; // Months are 0-indexed
const day = date.getDate();
const year = date.getFullYear();
// Pad with leading zeros if needed
const formattedMonth = month.toString().padStart(2, '0');
const formattedDay = day.toString().padStart(2, '0');
return `${formattedMonth}/${formattedDay}/${year}`;
}
const filteredData = localData?.filter((agency) => {
return (agency.post_content_translation.some((item: any) => {
const searchLower = searchTerm.toLowerCase();
const title = item.content?.toLowerCase().includes(searchLower);
return title;
}))
});
const managepost = filteredData?.flatMap((agency: any, index: number) => (agency.post_content_translation.map((translation: any) => ({
'id': agency.id,
"Sr. No": (currentPage - 1) * (data?.data.per_page ?? 0) + index + 1,
Images: (
// <Image w={50} src={img} />
<Image rounded={"lg"} w={100} h={50} src={img} />
agency.images.length > 0 ?
agency.images[0].type === "image" ? (
<HStack>
<Image
rounded={"lg"}
w={100}
h={50}
src={`${APIURL}${agency.images[0].image_name}`}
/>
<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>
{`Lorem ipsum dolor, sit amet consectetur adipisicing elit.}`.slice(
{`${translation?.content}`.slice(
0,
30
) + "..."}
</Text>
),
"Publish Data": "12/01/2025",
"Activate/Deactivate": (
<Box w={"100%"}>
<Switch size={"sm"} colorPalette={"teal"} />
</Box>
),
Action: (
"Publish Data": formatAPIDate(agency.created_at),
"is_active": agency.is_active,
"Action": (
<HStack justifyContent="center">
<ViewDailog />
{/* <AlertDailog
AltertTiggerIcon={() => <Span><Delete /> </Span>}
alertText="Delete Users"
alertIcon={<Image src={"DeleteIcon"} h={"39px"} />}
alertCaption="are you sure you want to delete ?"
onConfirm={() => {
console.log("User deleted:", i + 1);
}}
/> */}
{/* <ViewAgencyMaster agency={localData} id={agency.id} /> */}
<ViewDailog localData={{ ...agency, translation }} refetch={refetch} />
<Box>
<Switch
colorPalette={"teal"}
size={"xs"}
onChange={() => handleToggle(agency.id, Number(agency.is_active))}
checked={Boolean(Number(agency.is_active))}
/>
</Box>
</HStack>
),
})),
];
const ManagePost = () => {
}))));
return (
<MainFrame>
<Box>
@@ -77,35 +215,27 @@ const ManagePost = () => {
</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={(value) => {
setSearchTerm(value);
// setCurrentPage(1);
refetch()
}}
/>
</HStack>
</HStack>
<DataTable
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}
/>
</Box>
</MainFrame>

View File

@@ -1,15 +1,18 @@
import { Field, Image, Input, Span, Stack } from "@chakra-ui/react"
import { Field, HStack, Image, Input, Stack } from "@chakra-ui/react"
// import { TbEdit } from "react-icons/tb"
import img from "../../assets/waterfall.jpg"
// import img from "../../assets/waterfall.jpg"
import { DialogBody, DialogCloseTrigger, DialogContent, DialogHeader, DialogRoot, DialogTitle, DialogTrigger } from "../../components/ui/dialog"
import Edit from "../../components/ActionIcons/Edit"
// import Edit from "../../components/ActionIcons/Edit"
import { LuEye } from "react-icons/lu"
function ViewDailog() {
const APIURL = import.meta.env.VITE_POST_IMG
function ViewDailog({ localData }: { localData: any, refetch: VoidFunction }) {
return (
<DialogRoot placement="center">
<DialogTrigger asChild>
<Span><Edit /></Span>
{/* <Span><Edit /></Span> */}
<LuEye fontSize={"xm"} cursor={'pointer'} />
</DialogTrigger>
<DialogContent
@@ -25,17 +28,49 @@ function ViewDailog() {
<DialogBody bg="white">
<Stack py={3} >
<Field.Root>
<Field.Label color="black" pt={1} fontSize="12px">Title</Field.Label>
<Input placeholder="Enter the Title" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" readOnly />
<Field.Label color="black" pt={1} fontSize="12px">Subtitle</Field.Label>
<Input placeholder="Enter the Subtitle" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" readOnly />
<Field.Label color="black" pt={1} fontSize="12px">Description</Field.Label>
<Input placeholder="Enter the Description" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" readOnly />
<Input
// placeholder="Enter the Title"
value={localData.translation.content}
bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
readOnly
/>
{/* <Field.Label color="black" pt={1} fontSize="12px">Subtitle</Field.Label>
<Input placeholder="Enter the Subtitle" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" readOnly /> */}
{/* <Field.Label color="black" pt={1} fontSize="12px">Description</Field.Label>
<Input placeholder="Enter the Description" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" readOnly /> */}
<Field.Label color="black" pt={1} fontSize="12px">Image</Field.Label>
<Image src={img} w="100%" maxH="150px" objectFit="contain" />
<HStack w="fit-content" flexWrap={'wrap'}>
{localData.images.map((img: any) => (
img.type === 'image' ? (
<Image
key={img.id}
src={`${APIURL}${img.image_name}`}
w="30%"
maxH="150px"
objectFit="contain"
/>
) : (
<video
key={img.id}
width="45%"
height="50"
controls
>
<source src={`${APIURL}${img.image_name}`} type="video/mp4" />
</video>
)
))}
</HStack>
{/* <Image src={img} w="100%" maxH="150px" objectFit="contain" /> */}
</Field.Root>
</Stack>
</DialogBody>

View File

@@ -1,16 +1,19 @@
import { Box, HStack,
import {
Box, HStack,
// Image,
Input, Text } from "@chakra-ui/react";
Text
} from "@chakra-ui/react";
import MainFrame from "../../../components/MainFrame";
// import AlertDailog from "../../../components/AlertDailog";
// import { RiDeleteBin5Line } from "react-icons/ri";
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 ViewRegisterUsers from "./ViewRegisterUsers";
import EditRegisterUsers from "./EditRegisterUsers";
import AddRegisterUsers from "./AddRegisterUsers";
import { useEffect, useState } from "react";
import { useGetManageUserQuery, UserData, useUserToggleMutation } from "../../../Redux/Service/manage.user";
import SearchComponent from "../../../components/SearchComponent";
// import Delete from "../../../components/ActionIcons/Delete";
const tableHeadRow = [
@@ -25,40 +28,113 @@ const tableHeadRow = [
"Action",
];
const registerUser: any[] = [
...Array.from({ length: 12 }, (_, i) => ({
"Sr. No": i + 1,
"First Name": "Ritesh",
"Mobile Number": "akanksha@gmail.com",
"Gender": "9876543210",
"DOB": "Female",
"Type Of User": "15-01-1990",
"Language": "Mumbai",
"Activate/Deactivate": (
<Box>
<Switch size={'sm'} colorPalette={'teal'} />
</Box>
),
"Action": (
<HStack justifyContent="center">
<ViewRegisterUsers />
<EditRegisterUsers />
{/* <RiDeleteBin5Line style={{ cursor: "pointer" }} /> */}
{/* <AlertDailog
AltertTiggerIcon={() =><Delete /> } // Pass as function
alertText="Delete Users"
alertIcon={<Image src={"DeleteIcon"} h={"39px"} />}
alertCaption="Are You Sure You Want To Delete This User ?"
onConfirm={() => {
console.log("User deleted:", i + 1);
}}
/> */}
</HStack>
),
})),
];
// const registerUser: any[] = [
// ...Array.from({ length: 12 }, (_, i) => ({
// "Sr. No": i + 1,
// "First Name": "Ritesh",
// "Mobile Number": "akanksha@gmail.com",
// "Gender": "9876543210",
// "DOB": "Female",
// "Type Of User": "15-01-1990",
// "Language": "Mumbai",
// "Activate/Deactivate": (
// <Box>
// <Switch size={'sm'} colorPalette={'teal'} />
// </Box>
// ),
// "Action": (
// <HStack justifyContent="center">
// <ViewRegisterUsers />
// <EditRegisterUsers />
// {/* <RiDeleteBin5Line style={{ cursor: "pointer" }} /> */}
// {/* <AlertDailog
// AltertTiggerIcon={() =><Delete /> } // Pass as function
// alertText="Delete Users"
// alertIcon={<Image src={"DeleteIcon"} h={"39px"} />}
// alertCaption="Are You Sure You Want To Delete This User ?"
// onConfirm={() => {
// console.log("User deleted:", i + 1);
// }}
// /> */}
// </HStack>
// ),
// })),
// ];
const RegisterUsers = () => {
const [currentPage, setCurrentPage] = useState(1);
const { data, refetch } = useGetManageUserQuery(currentPage)
const [localData, setLocalData] = useState<any[]>([]);
const [searchTerm, setSearchTerm] = useState("");
const [userToggle] = useUserToggleMutation()
console.log("Register Users Data", data?.data.data);
useEffect(() => {
if (data) {
setLocalData(data?.data.data);
}
}, [data]);
const handlePageChange = (page: number) => {
setCurrentPage(page);
}
const filteredData = localData?.filter((agency) => {
const searchLower = searchTerm.toLowerCase();
const firstName = agency.first_name?.toLowerCase().includes(searchLower);
// const email = agency.capital?.toLowerCase().includes(searchLower);
return firstName;
});
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 userToggle({ id: agencyId, is_active: newStatus }).unwrap();
refetch()
} catch (error) {
console.error("Error updating privacy policy:", error);
setLocalData((prevData) =>
prevData.map((agency) =>
agency.id === agencyId ? { ...agency, is_active: currentStatus } : agency
)
);
}
}
const managepost = filteredData?.flatMap((agency: UserData, index: number) => ({
"Sr. No": (currentPage - 1) * (data?.data.per_page ?? 0) + index + 1,
"First Name": agency.first_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": (
<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}
/>
<ViewRegisterUsers />
<Box>
<Switch
colorPalette={'teal'}
size={"xs"}
checked={agency.is_active === true}
onChange={() => handleToggle(agency.id, agency.is_active ? '1' : '0')}
/>
</Box>
</HStack>
),
}))
return (
<MainFrame>
<Box>
@@ -73,34 +149,29 @@ const RegisterUsers = () => {
Register Users
</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>
<HStack>
<SearchComponent
value={searchTerm}
onChange={(value) => {
setSearchTerm(value);
// setCurrentPage(1);
refetch()
}}
/>
<AddRegisterUsers />
</HStack>
</HStack>
<DataTable
sortableColumns={["Name", "Registration Date "]}
tableHeadRow={tableHeadRow}
data={registerUser}
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}
/>
</Box>
</MainFrame>

View File

@@ -47,7 +47,8 @@ const tableHeadRow = [
// ];
const AgencyMaster = () => {
const { data, refetch } = useGetAgencyMasterQuery()
const [currentPage, setCurrentPage] = useState(1);
const { data, refetch } = useGetAgencyMasterQuery(currentPage)
const [agencyMasterToggle] = useAgencyMasterToggleMutation()
const [localData, setLocalData] = useState<any[]>([]);
const [searchTerm, setSearchTerm] = useState("");
@@ -72,13 +73,17 @@ const AgencyMaster = () => {
}
};
const handlePageChange = (page: number) => {
setCurrentPage(page);
};
const filteredData = localData?.filter((agency) =>
agency?.name.toLowerCase().includes(searchTerm.toLowerCase())
);
const managepost = filteredData?.map((agency: any, index: number) => ({
'id': agency.id,
"Sr. No": index + 1,
"Sr. No": (currentPage - 1) * (data?.data.per_page ?? 0) + index + 1,
"Agency Name": agency.name,
"RC no.": agency.rc_number,
"State": agency.state,
@@ -162,8 +167,13 @@ const AgencyMaster = () => {
sortableColumns={["Name", "Registration Date "]}
tableHeadRow={tableHeadRow}
data={managepost || []}
paginationData={data?.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}
/>
</Box>
</MainFrame>

View File

@@ -1,11 +1,12 @@
import { Box, HStack, Input, Text } from "@chakra-ui/react";
import { Box, HStack, Text } from "@chakra-ui/react";
import MainFrame from "../../../components/MainFrame"
import { InputGroup } from "../../../components/ui/input-group";
import { LuSearch } from "react-icons/lu";
import DataTable from "../../../components/DataTable";
import { Switch } from "../../../components/ui/switch";
import CountryAddModel from "./CountryAddModel";
import EditCountryModel from "./EditCountryModel";
import { CountryData, useCountryToggleMutation, useGetCountryMasterQuery } from "../../../Redux/Service/country.master";
import { useEffect, useState } from "react";
import SearchComponent from "../../../components/SearchComponent";
@@ -15,25 +16,89 @@ const tableHeadRow = [
"Sr. No",
"Title",
"Action"
];
const managepost: any[] = [
...Array.from({ length: 12 }, (_, i) => ({
"Sr. No": i + 1,
"Title": "Lorem Ipsum",
// const managepost: any[] = [
// ...Array.from({ length: 12 }, (_, i) => ({
// "Sr. No": i + 1,
// "Title": "Lorem Ipsum",
// "Action": (
// <HStack justifyContent="center">
// <EditCountryModel />
// <Box>
// <Switch colorPalette={'teal'} size={"xs"} />
// </Box>
// </HStack>
// ),
// })),
// ];
const Country = () => {
const [currentPage, setCurrentPage] = useState(1);
const { data, refetch } = useGetCountryMasterQuery(currentPage)
const [countryToggle] = useCountryToggleMutation()
const [localData, setLocalData] = useState<any[]>([]);
const [searchTerm, setSearchTerm] = useState("");
console.log("Country Data", data?.data.data)
useEffect(() => {
if (data) {
setLocalData(data?.data.data);
}
}, [data]);
const handlePageChange = (page: number) => {
setCurrentPage(page);
};
const filteredData = localData?.filter((agency) => {
const searchLower = searchTerm.toLowerCase();
const countryName = agency.en_name?.toLowerCase().includes(searchLower);
const capitalName = agency.capital?.toLowerCase().includes(searchLower);
return countryName || capitalName;
});
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 countryToggle({ id: agencyId, is_active: newStatus }).unwrap();
refetch()
} catch (error) {
console.error("Error updating privacy policy:", error);
setLocalData((prevData) =>
prevData.map((agency) =>
agency.id === agencyId ? { ...agency, is_active: currentStatus } : agency
)
);
}
}
const managepost = filteredData?.flatMap((agency: CountryData, index: number) => ({
"Sr. No": (currentPage - 1) * (data?.data.per_page ?? 0) + index + 1,
"Title": agency.en_name,
"Action": (
<HStack justifyContent="center">
<EditCountryModel />
<EditCountryModel 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} />
<Box>
<Switch colorPalette={'teal'} size={"xs"}/>
<Switch
colorPalette={'teal'}
size={"xs"}
checked={agency.is_active === '1'}
onChange={() => handleToggle(agency.id, agency.is_active)}
/>
</Box>
</HStack>
),
})),
];
}))
const Country = () => {
return (
<MainFrame>
@@ -46,11 +111,11 @@ const Country = () => {
px={3}
>
<Text as={"span"} fontSize={"sm"} fontWeight={500} color={"#000"}>
Country
Country
</Text>
<HStack >
<InputGroup
{/* <InputGroup
startElement={
<LuSearch fontSize={"xs"} style={{ position: 'relative', left: '10px' }} />
}
@@ -69,7 +134,15 @@ const Country = () => {
bgColor={'#EEEEEE'}
ps={8}
/>
</InputGroup>
</InputGroup> */}
<SearchComponent
value={searchTerm}
onChange={(value) => {
setSearchTerm(value);
// setCurrentPage(1);
refetch()
}}
/>
{/* <Button bgColor={'#EEEEEE'} pl={3} pr={3}><IoMdAdd /> <Text>Add</Text></Button> */}
<CountryAddModel />
</HStack>
@@ -78,8 +151,15 @@ const Country = () => {
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}
/>
</Box>
</Box>
</MainFrame>
)
}

View File

@@ -2,55 +2,201 @@ 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 { PostCountry, useCreateCountryPostMutation } from "../../../Redux/Service/country.master";
import { Toaster, toaster } from "../../../components/ui/toaster";
function CountryAddModel() {
return (
const [createCountryPost] = useCreateCountryPostMutation()
const [isOpen, setIsOpen] = useState(false);
const [countryName, setCountryName] = useState<PostCountry>({
en_name: '',
country_code: '',
phonecode: '',
capital: '',
currency: '',
currency_name: '',
currency_symbol: '',
});
<DialogRoot placement="center">
<DialogTrigger asChild>
{/* <Button bg={"transparent"} size="sm">
const handleOpenModal = () => {
setIsOpen(true); // Open modal when clicking "Add"
};
const handleSubmit = async () => {
if (countryName.en_name === "") {
toaster.create({
title: "Error",
description: "Input fields cannot be empty",
type: "error",
});
return;
}
const payload: PostCountry = {
en_name: countryName.en_name,
country_code: countryName.country_code,
phonecode: countryName.phonecode,
capital: countryName.capital,
currency: countryName.currency,
currency_name: countryName.currency_name,
currency_symbol: countryName.currency_symbol,
};
try {
const response = await createCountryPost(payload).unwrap();
if (response) {
toaster.create({
title: "Success",
description: "Country added successfully",
type: "success",
});
setIsOpen(false);
} else {
toaster.create({
title: "Error",
description: "Failed to add Country",
type: "error",
});
}
} catch (error) {
console.error("Error updating template:", error);
// alert("Failed to update template");
}
};
return (
<>
<DialogRoot placement="center" open={isOpen} onOpenChange={({ open }) => setIsOpen(open)}>
<DialogTrigger asChild>
{/* <Button bg={"transparent"} size="sm">
<MdOutlineRemoveRedEye style={{ cursor: "pointer", fontSize: "16px" }} />
</Button> */}
<Button px={5} size={"xs"} bg={"#02A0A0"}>
<IoMdAdd /> <Text>Add</Text>
</Button>
</DialogTrigger>
<DialogContent
bg={"#fff"}
// w={{ lg: "60%", md: "230px" }}
w={{ base: '90%', md: '400px' }}
height={'auto'}
overflowX="hidden"
p={3} // Reduced padding
bgSize={'md'}
>
<DialogHeader bg="white" >
<DialogTitle alignSelf="center" color="black" fontSize="14px">Add</DialogTitle>
</DialogHeader>
<DialogBody bg="white">
<Stack py={3}>
<Field.Root>
<Field.Label color="black" pt={1} fontSize="12px">Country</Field.Label>
<Input placeholder="" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" />
</Field.Root>
</Stack>
</DialogBody>
<DialogFooter display="flex" justifyContent="center" pt={"2"}>
<Button w="100%" bg="#02A0A0" color={"#fff"}>
Save
<Button px={5} size={"xs"} bg={"#02A0A0"} onClick={handleOpenModal}>
<IoMdAdd /> <Text>Add</Text>
</Button>
</DialogFooter>
<DialogCloseTrigger color="black" />
</DialogContent>
</DialogRoot >
</DialogTrigger>
<DialogContent
bg={"#fff"}
// w={{ lg: "60%", md: "230px" }}
w={{ base: '90%', md: '400px' }}
height={'auto'}
overflowX="hidden"
p={3} // Reduced padding
bgSize={'md'}
>
<DialogHeader bg="white" >
<DialogTitle alignSelf="center" color="black" fontSize="14px">Add</DialogTitle>
</DialogHeader>
<DialogBody bg="white">
<Stack py={3}>
<Field.Root>
<Field.Label color="black" pt={1} fontSize="12px">Country</Field.Label>
<Input
placeholder=""
bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
value={countryName.en_name}
onChange={(e) => setCountryName({ ...countryName, en_name: e.target.value })}
/>
<Field.Label color="black" pt={1} fontSize="12px">Country Code</Field.Label>
<Input
placeholder=""
bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
value={countryName.country_code}
onChange={(e) => setCountryName({ ...countryName, country_code: e.target.value })}
/>
<Field.Label color="black" pt={1} fontSize="12px">Phone Code</Field.Label>
<Input
placeholder=""
bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
value={countryName.phonecode}
onChange={(e) => setCountryName({ ...countryName, phonecode: e.target.value })}
/>
<Field.Label color="black" pt={1} fontSize="12px">Capital</Field.Label>
<Input
placeholder=""
bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
value={countryName.capital}
onChange={(e) => setCountryName({ ...countryName, capital: e.target.value })}
/>
<Field.Label color="black" pt={1} fontSize="12px">Currency</Field.Label>
<Input
placeholder=""
bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
value={countryName.currency}
onChange={(e) => setCountryName({ ...countryName, currency: e.target.value })}
/>
<Field.Label color="black" pt={1} fontSize="12px">Currency name</Field.Label>
<Input
placeholder=""
bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
value={countryName.currency_name}
onChange={(e) => setCountryName({ ...countryName, currency_name: e.target.value })}
/>
<Field.Label color="black" pt={1} fontSize="12px">Currency Symbol</Field.Label>
<Input
placeholder=""
bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
value={countryName.currency_symbol}
onChange={(e) => setCountryName({ ...countryName, currency_symbol: e.target.value })}
/>
</Field.Root>
</Stack>
</DialogBody>
<DialogFooter display="flex" justifyContent="center" pt={"2"}>
<Button w="100%" bg="#02A0A0" color={"#fff"} onClick={handleSubmit}>
Save
</Button>
</DialogFooter>
<DialogCloseTrigger color="black" />
</DialogContent>
</DialogRoot >
<Toaster />
</>
)
}

View File

@@ -8,59 +8,153 @@ import {
DialogTitle,
DialogTrigger,
} from "../../../components/ui/dialog";
import { Field, Input, Span, Stack } from "@chakra-ui/react";
import { Field, Input, Stack } from "@chakra-ui/react";
import { Button } from "../../../components/ui/button";
import Edit from "../../../components/ActionIcons/Edit";
import { useUpdateCountryMutation } from "../../../Redux/Service/country.master";
import { Toaster, toaster } from "../../../components/ui/toaster";
import { useEffect, useState } from "react";
export interface EditCountryModelProps {
id?: number;
en_name?: string;
hi_name?: string;
mr_name?: string;
te_name?: string;
ta_name?: string;
bn_name?: string;
or_name?: string;
country_code?: string;
phonecode?: string;
capital?: string;
currency?: string;
currency_name?: string;
currency_symbol?: string;
}
function EditCountryModel({ rowData, refetch }: { rowData: EditCountryModelProps, refetch: VoidFunction }) {
const [updateCountry] = useUpdateCountryMutation()
const [editData, setEditData] = useState(rowData)
const [isOpen, setIsOpen] = useState(false);
useEffect(() => {
if(rowData){
setEditData(rowData)
}
}, [rowData])
const handleOpenModal = () => {
setIsOpen(true);
};
const handleSubmit = async () => {
if (editData?.en_name === '') {
toaster.create({
title: "Error",
description: "Input fields cannot be empty",
type: "error",
});
return;
}
// Only en_name is editable, so we only need to send that in the payload.
const payload = {
id: rowData?.id,
en_name: editData?.en_name,
country_code: rowData?.country_code,
phonecode: rowData?.phonecode,
capital: rowData?.capital,
currency: rowData?.currency,
currency_name: rowData?.currency_name,
currency_symbol: rowData?.currency_symbol,
};
// console.log('payload', payload)
try {
const response = await updateCountry(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) {
console.error("Error updating template:", error);
// alert("Failed to update template");
toaster.create({
title: "Error",
description: "Something went wrong",
type: "error",
});
}
};
function EditCountryModel() {
return (
<DialogRoot placement="center">
<DialogTrigger asChild>
<Span><Edit /></Span>
</DialogTrigger>
<>
<DialogRoot placement="center" key={editData.id} open={isOpen} onOpenChange={({ open }) => setIsOpen(open)}>
<DialogTrigger asChild>
<Button bg="transparent" color={"black"} h={"18px"} onClick={handleOpenModal}><Edit /></Button>
</DialogTrigger>
<DialogContent
bg={"#fff"}
// w={{ lg: "60%", md: "230px" }}
w={{ base: "90%", md: "400px" }}
height={"auto"}
overflowX="hidden"
p={3} // Reduced padding
bgSize={"md"}
>
<DialogHeader bg="white">
<DialogTitle alignSelf="center" color="black" fontSize="14px">
Edit
</DialogTitle>
</DialogHeader>
<DialogContent
bg={"#fff"}
// w={{ lg: "60%", md: "230px" }}
w={{ base: "90%", md: "400px" }}
height={"auto"}
overflowX="hidden"
p={3} // Reduced padding
bgSize={"md"}
>
<DialogHeader bg="white">
<DialogTitle alignSelf="center" color="black" fontSize="14px">
Edit
</DialogTitle>
</DialogHeader>
<DialogBody bg="white">
<Stack py={3}>
<Field.Root>
<Field.Label color="black" pt={1} fontSize="12px">
Country
</Field.Label>
<Input
value={editData.en_name}
onChange={(e) => setEditData({ ...editData, en_name: e.target.value })}
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"} onClick={handleSubmit}>
Save
</Button>
</DialogFooter>
<DialogBody bg="white">
<Stack py={3}>
<Field.Root>
<Field.Label color="black" pt={1} fontSize="12px">
Country
</Field.Label>
<Input
value="Lorem Ipsum"
bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
/>
</Field.Root>
</Stack>
</DialogBody>
<DialogFooter display="flex" justifyContent="center" pt={"2"}>
<Button w="100%" bg="#02A0A0" color={"#fff"}>
Save
</Button>
</DialogFooter>
<DialogCloseTrigger color="black" />
</DialogContent>
</DialogRoot>
<DialogCloseTrigger color="black" />
</DialogContent>
</DialogRoot>
<Toaster />
</>
);
}

View File

@@ -0,0 +1,155 @@
import { DialogBody, DialogCloseTrigger, DialogContent, DialogFooter, DialogHeader, DialogRoot, DialogTitle, DialogTrigger } from "../../../components/ui/dialog"
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 { toaster } from "../../../components/ui/toaster";
import { useCreateDepartmentPostMutation, useGetDepartmentMasterDropDownQuery } from "../../../Redux/Service/department.master";
function AddDepartmentMaster({ refetch }: { refetch: VoidFunction }) {
const [jobType, setJobType] = useState("");
const [isOpen, setIsOpen] = useState(false);
const [createDepartmentPost] = useCreateDepartmentPostMutation()
const { data } = useGetDepartmentMasterDropDownQuery()
const [selectdDep, setSelectdDep] = useState<any>({
id: '',
en_name: '',
});
const handleOpenModal = () => {
setIsOpen(true); // Open modal when clicking "Add"
};
const handleSubmit = async () => {
if (!jobType.trim() || !selectdDep.id) {
toaster.create({
title: "Error",
description: "Title and Subtitle cannot be empty.",
type: "error",
});
return;
}
const payload = {
en_name: jobType,
industry_masters_xid: selectdDep.id,
};
try {
await createDepartmentPost(payload);
refetch()
setIsOpen(false);
setJobType("");
setSelectdDep({
id: '',
en_name: '',
})
} catch (error) {
console.error("Error updating template:", error);
alert("Failed to update template");
}
};
console.log("Selected Department", selectdDep);
return (
<DialogRoot placement="center" open={isOpen}>
<DialogTrigger asChild>
{/* <Button bg={"transparent"} size="sm">
<MdOutlineRemoveRedEye style={{ cursor: "pointer", fontSize: "16px" }} />
</Button> */}
<Button px={5} size={"xs"} bg={"#02A0A0"} onClick={handleOpenModal}>
<IoMdAdd /> <Text>Add</Text>
</Button>
</DialogTrigger>
<DialogContent
bg={"#fff"}
// w={{ lg: "60%", md: "230px" }}
w={{ base: '90%', md: '400px' }}
height={'auto'}
overflowX="hidden"
p={3} // Reduced padding
bgSize={'md'}
>
<DialogHeader bg="white" >
<DialogTitle alignSelf="center" color="black" fontSize="14px">Add</DialogTitle>
</DialogHeader>
<DialogBody bg="white">
<Stack py={3}>
<Field.Root>
<Field.Label color="black" pt={1} fontSize="12px">
Select Industry
</Field.Label>
<select
value={selectdDep.id}
onChange={(e) => {
const selectedId = e.target.value;
const selectedIndustry = data?.data.find((item: any) => item.id.toString() === selectedId);
if (selectedIndustry) {
setSelectdDep({
id: selectedIndustry.id,
en_name: selectedIndustry.en_name,
});
}
}}
style={{
backgroundColor: "#EEEEEE",
color: "black",
border: "none",
height: "30px",
fontSize: "12px",
padding: "4px",
borderRadius: "4px",
width: "100%",
}}
>
<option value="" disabled>
Select department
</option>
{data?.data.map((item: any) => (
<option value={item.id} key={item.id}>
{item.en_name}
</option>
))}
</select>
</Field.Root>
<Field.Root>
<Field.Label color="black" pt={1} fontSize="12px">Department</Field.Label>
<Input
placeholder=""
bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
value={jobType}
onChange={(e) => setJobType(e.target.value)}
/>
</Field.Root>
</Stack>
</DialogBody>
<DialogFooter display="flex" justifyContent="center" pt={"2"}>
<Button w="100%" bg="#02A0A0" color={"#fff"} onClick={handleSubmit}>
Save
</Button>
</DialogFooter>
<DialogCloseTrigger color="black" onClick={() => setIsOpen(false)} />
</DialogContent>
</DialogRoot >
)
}
export default AddDepartmentMaster

View File

@@ -0,0 +1,142 @@
import { Box, HStack, Text } from "@chakra-ui/react";
import MainFrame from "../../../components/MainFrame"
// import { InputGroup } from "../../../components/ui/input-group";
// import { LuSearch } from "react-icons/lu";
import DataTable from "../../../components/DataTable";
import { Switch } from "../../../components/ui/switch";
import { useEffect, useState } from "react";
import SearchComponent from "../../../components/SearchComponent";
import { useDepartmentToggleMutation, useGetDepartmentMasterQuery } from "../../../Redux/Service/department.master";
import AddDepartmentMaster from "./AddDepartmentMaster";
import EditDepartmentMaster from "./EditDepartmentMaster";
// table data
const tableHeadRow = [
"Sr. No",
"Title",
"Action"
];
const DepartmentMasterList = () => {
const [currentPage, setCurrentPage] = useState(1);
const { data, refetch } = useGetDepartmentMasterQuery(currentPage)
const [departmentToggle] = useDepartmentToggleMutation()
const [localData, setLocalData] = useState<any[]>([]);
const [searchTerm, setSearchTerm] = useState("");
console.log("Department Data", data?.data.data)
useEffect(() => {
if (data?.data?.data) {
setLocalData(data?.data.data);
}
}, [data]);
const handlePageChange = (page: number) => {
setCurrentPage(page);
};
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 departmentToggle({ 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 filteredData = localData?.filter((agency) => {
const searchLower = searchTerm.toLowerCase();
const title = agency.en_name?.toLowerCase().includes(searchLower);
return title;
});
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,
"is_active": agency.is_active,
"Action": (
<HStack justifyContent="center">
{/* <ViewAgencyMaster agency={localData} id={agency.id} /> */}
<EditDepartmentMaster localData={agency} refetch={refetch} />
<Box>
<Switch
colorPalette={"teal"}
size={"xs"}
onChange={() => handleToggle(agency.id, Number(agency.is_active))}
checked={Boolean(Number(agency.is_active))}
/>
</Box>
</HStack>
),
}));
// useEffect(() => {
// console.log("Fetched data:", data);
// console.log("Local data:", localData);
// console.log("Managepost data:", managepost);
// }, [data, localData, managepost]);
return (
<MainFrame>
<Box>
<HStack
w={"100%"}
justifyContent={"space-between"}
mb={4}
py={0}
px={3}
>
<Text as={"span"} fontSize={"sm"} fontWeight={500} color={"#000"}>
Department Master
</Text>
<HStack >
<SearchComponent
value={searchTerm}
onChange={(value) => {
setSearchTerm(value);
// setCurrentPage(1);
refetch()
}}
/>
{/* <Button bgColor={'#EEEEEE'} pl={3} pr={3}><IoMdAdd /> <Text>Add</Text></Button> */}
{/* <ViewAgencyAddModel /> */}
<AddDepartmentMaster refetch={refetch} />
</HStack>
</HStack>
<DataTable
sortableColumns={["Name"]}
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}
/>
</Box>
</MainFrame>
)
}
export default DepartmentMasterList

View File

@@ -0,0 +1,160 @@
import {
DialogBody,
DialogCloseTrigger,
DialogContent,
DialogFooter,
DialogHeader,
DialogRoot,
DialogTitle,
DialogTrigger,
} from "../../../components/ui/dialog";
import { Box, Field, Input, Stack } from "@chakra-ui/react";
import { Button } from "../../../components/ui/button";
import Edit from "../../../components/ActionIcons/Edit";
import { useState } from "react";
import { Toaster, toaster } from "../../../components/ui/toaster";
import { useGetDepartmentMasterDropDownQuery, useUpdateDepartmentMutation } from "../../../Redux/Service/department.master";
function EditDepartmentMaster({ localData, refetch }: { localData: any, refetch: VoidFunction }) {
const [jobtype, setJobType] = useState("");
const [updateDepartment] = useUpdateDepartmentMutation()
const { data } = useGetDepartmentMasterDropDownQuery()
const [isOpen, setIsOpen] = useState(false);
const [selectdDep, setSelectdDep] = useState<any>({
id: localData.industry_master.id,
en_name: localData.industry_master.en_name,
});
const handleOpenModal = () => {
// const template = localData?.find((item: any) => item.id === id);
if (localData) {
setJobType(localData.en_name);
setSelectdDep({
id: localData.industry_master.id,
en_name: localData.industry_master.en_name,
})
setIsOpen(true);
}
};
const handleSubmit = async () => {
if (!jobtype.trim()) {
toaster.create({
title: "Error",
description: "Title and Subtitle cannot be empty.",
type: "error",
});
return;
}
const payload = {
id: localData.id,
industry_masters_xid: selectdDep.id != null ? selectdDep.id : localData.industry_master.id,
en_name: jobtype
};
try {
await updateDepartment(payload).unwrap();
refetch()
setIsOpen(false);
} catch (error) {
console.error("Error updating template:", error);
alert("Failed to update template");
}
};
console.log("Dropdown Data", selectdDep);
console.log("Dep Data", localData)
return (
<DialogRoot placement="center" open={isOpen} onOpenChange={({ open }) => setIsOpen(open)}>
<DialogTrigger asChild>
<Box bg={"transparent"} onClick={handleOpenModal}>
<Edit />
</Box>
</DialogTrigger>
<DialogContent
bg={"#fff"}
// w={{ lg: "60%", md: "230px" }}
w={{ base: "90%", md: "400px" }}
height={"auto"}
overflowX="hidden"
p={3} // Reduced padding
bgSize={"md"}
>
<DialogHeader bg="white">
<DialogTitle alignSelf="center" color="black" fontSize="14px">
Edit Title
</DialogTitle>
</DialogHeader>
<DialogBody bg="white">
<Stack py={3}>
<Field.Root>
<Field.Label color="black" pt={1} fontSize="12px">
Select Industry
</Field.Label>
<select
value={selectdDep.id}
onChange={(e) => {
const selected = data?.data.find((item: any) => item.id === Number(e.target.value));
if (selected) {
setSelectdDep({ id: selected.id, en_name: selected.en_name });
}
}}
style={{
backgroundColor: "#EEEEEE",
color: "black",
border: "none",
height: "30px",
fontSize: "12px",
padding: "4px",
borderRadius: "4px",
width: "100%",
}}
>
<option value="" disabled>
Select department
</option>
{data?.data.map((item: any) => (
<option value={item.id} key={item.id}>
{item.en_name}
</option>
))}
</select>
</Field.Root>
<Field.Root>
<Field.Label color="black" pt={1} fontSize="12px">
Department
</Field.Label>
<Input
value={jobtype}
bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
onChange={(e) => setJobType(e.target.value)}
/>
</Field.Root>
</Stack>
</DialogBody>
<DialogFooter display="flex" justifyContent="center" pt={"2"}>
<Button w="100%" bg="#02A0A0" color={"#fff"} onClick={handleSubmit}>
Save
</Button>
</DialogFooter>
<DialogCloseTrigger color="black" onClick={() => setIsOpen(false)} />
</DialogContent>
<Toaster />
</DialogRoot>
);
}
export default EditDepartmentMaster;

View File

@@ -1,13 +1,14 @@
import { Box, HStack, Input, Text } from "@chakra-ui/react";
import { Box, HStack, 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 { Switch } from "../../../components/ui/switch";
import { useEffect, useState } from "react";
import { useGetIndustryMasterQuery, useIndustryMasterToggleMutation } from "../../../Redux/Service/industry.master.service";
import EditIndustryMaster from "./EditIndustryMaster";
import AddIndustryMaster from "./AddIndustryMaster";
import SearchComponent from "../../../components/SearchComponent";
// table data
@@ -42,9 +43,11 @@ const tableHeadRow = [
// ];
const IndustryMasterList = () => {
const { data, refetch } = useGetIndustryMasterQuery()
const [currentPage, setCurrentPage] = useState(1);
const { data, refetch } = useGetIndustryMasterQuery(currentPage)
const [industryMasterToggle] = useIndustryMasterToggleMutation()
const [localData, setLocalData] = useState<any[]>([]);
const [searchTerm, setSearchTerm] = useState("");
useEffect(() => {
if (data?.data?.data) {
@@ -52,6 +55,10 @@ const IndustryMasterList = () => {
}
}, [data]);
const handlePageChange = (page: number) => {
setCurrentPage(page);
};
const handleToggle = async (agencyId: string, currentStatus: number) => {
const newStatus = currentStatus ? 0 : 1;
setLocalData((prevData) =>
@@ -72,9 +79,15 @@ const IndustryMasterList = () => {
}
};
const managepost = localData?.map((agency: any, index: number) => ({
const filteredData = localData?.filter((agency) => {
const searchLower = searchTerm.toLowerCase();
const title = agency.en_name?.toLowerCase().includes(searchLower);
return title;
});
const managepost = filteredData?.map((agency: any, index: number) => ({
'id': agency.id,
"Sr. No": index + 1,
"Sr. No": (currentPage - 1) * (data?.data.per_page ?? 0) + index + 1,
"Title": agency.en_name,
"is_active": agency.is_active,
"Action": (
@@ -93,11 +106,11 @@ const IndustryMasterList = () => {
),
}));
useEffect(() => {
console.log("Fetched data:", data);
console.log("Local data:", localData);
console.log("Managepost data:", managepost);
}, [data, localData, managepost]);
// useEffect(() => {
// console.log("Fetched data:", data);
// console.log("Local data:", localData);
// console.log("Managepost data:", managepost);
// }, [data, localData, managepost]);
return (
@@ -115,37 +128,30 @@ const IndustryMasterList = () => {
</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={(value) => {
setSearchTerm(value);
// setCurrentPage(1);
refetch()
}}
/>
{/* <Button bgColor={'#EEEEEE'} pl={3} pr={3}><IoMdAdd /> <Text>Add</Text></Button> */}
{/* <ViewAgencyAddModel /> */}
<AddIndustryMaster refetch={refetch}/>
<AddIndustryMaster refetch={refetch} />
</HStack>
</HStack>
<DataTable
sortableColumns={["Name"]}
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}
/>
</Box>
</MainFrame>

View File

@@ -1,19 +1,58 @@
import { DialogBody, DialogCloseTrigger, DialogContent, DialogFooter, DialogHeader, DialogRoot, DialogTitle, DialogTrigger } from "../../../components/ui/dialog"
import { Field, Input, Span, Stack } from "@chakra-ui/react"
import { Box, Field, Input, Stack } from "@chakra-ui/react"
import { Button } from "../../../components/ui/button"
// import { FaRegEdit } from "react-icons/fa";
import Edit from "../../../components/ActionIcons/Edit";
import { useState } from "react";
import { useUpdateJobStatusMutation } from "../../../Redux/Service/job.status";
import { Toaster, toaster } from "../../../components/ui/toaster";
function EditJobStatusModel() {
function EditJobStatusModel({ localData, refetch }: { localData: any, refetch: VoidFunction }) {
const [updateJobStatus] = useUpdateJobStatusMutation()
const [title, setTitle] = useState(localData.translation.title);
const [isOpen, setIsOpen] = useState(false);
console.log(localData);
const handleOpenModal = () => {
if (localData) {
setIsOpen(true);
}
};
const handleSubmit = async () => {
if (!title.trim()) {
toaster.create({
title: "Error",
description: "Title field cannot be empty.",
type: "error",
});
return;
}
const payload = {
id: localData?.id,
title: title
};
try {
await updateJobStatus(payload).unwrap();
refetch()
setIsOpen(false);
} catch (error) {
console.error("Error updating template:", error);
alert("Failed to update template");
}
};
return (
<DialogRoot placement="center">
<DialogRoot placement="center" open={isOpen} onOpenChange={({ open }) => setIsOpen(open)}>
<DialogTrigger asChild>
<Span><Edit /></Span>
<Box bg={"transparent"} onClick={handleOpenModal}>
<Edit />
</Box>
</DialogTrigger>
<DialogContent
@@ -35,21 +74,30 @@ function EditJobStatusModel() {
<Field.Root>
<Field.Label color="black" pt={1} fontSize="12px">Job Status</Field.Label>
<Input value="Lorem Ipsum" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" />
<Input
value={title}
bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
onChange={(e) => setTitle(e.target.value)}
/>
</Field.Root>
</Stack>
</DialogBody>
<DialogFooter display="flex" justifyContent="center" pt={"2"}>
<Button w="100%" bg="#02A0A0" color={"#fff"}>
<Button w="100%" bg="#02A0A0" color={"#fff"} onClick={handleSubmit}>
Save
</Button>
</DialogFooter>
<DialogCloseTrigger color="black" />
</DialogContent>
<Toaster />
</DialogRoot >
)
}

View File

@@ -1,11 +1,13 @@
import { Box, HStack, Input, Text } from "@chakra-ui/react";
import { Box, HStack, Text } from "@chakra-ui/react";
import MainFrame from "../../../components/MainFrame"
import { InputGroup } from "../../../components/ui/input-group";
import { LuSearch } from "react-icons/lu";
import DataTable from "../../../components/DataTable";
import { Switch } from "../../../components/ui/switch";
import JobStatusAddModel from "./JobStatusAddModel";
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";
@@ -18,22 +20,93 @@ const tableHeadRow = [
];
const managepost: any[] = [
...Array.from({ length: 12 }, (_, i) => ({
"Sr. No": i + 1,
"Title": "Lorem Ipsum",
// const managepost: any[] = [
// ...Array.from({ length: 12 }, (_, i) => ({
// "Sr. No": i + 1,
// "Title": "Lorem Ipsum",
// "Action": (
// <HStack justifyContent="center">
// <EditJobStatusModel />
// <Box>
// <Switch colorPalette={'teal'} size={"xs"} />
// </Box>
// </HStack>
// ),
// })),
// ];
const JobStatus = () => {
const [currentPage, setCurrentPage] = useState(1);
const { data, refetch } = useGetJobStatusQuery(currentPage)
const [localData, setLocalData] = useState<any[]>([]);
const [searchTerm, setSearchTerm] = useState("");
const [jobStatusToggle] = useJobStatusToggleMutation()
console.log(data?.data.data)
useEffect(() => {
if (data?.data?.data) {
setLocalData(data?.data.data);
}
}, [data]);
const handlePageChange = (page: number) => {
setCurrentPage(page);
};
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 jobStatusToggle({ id: agencyId, is_active: newStatus }).unwrap();
refetch()
} catch (error) {
console.error("Error updating:", error);
toaster.create({
title: "Error",
description: "Someting went wrong.",
type: "error",
});
setLocalData((prevData) =>
prevData.map((agency) =>
agency.id === agencyId ? { ...agency, is_active: currentStatus } : agency
)
);
}
};
const filteredData = localData?.filter((agency) => {
return (agency.job_status_translation.map((item: any) => {
const searchLower = searchTerm.toLowerCase();
const title = item.title?.toLowerCase().includes(searchLower);
return title;
}))
});
const managepost = filteredData?.flatMap((agency: any, index: number) => (agency.job_status_translation.map((translation: any) => ({
'id': agency.id,
"Sr. No": (currentPage - 1) * (data?.data.per_page ?? 0) + index + 1,
"Title": translation.title,
"is_active": agency.is_active,
"Action": (
<HStack justifyContent="center">
<EditJobStatusModel />
{/* <ViewAgencyMaster agency={localData} id={agency.id} /> */}
<EditJobStatusModel localData={{ ...agency, translation }} refetch={refetch} />
<Box>
<Switch colorPalette={'teal'} size={"xs"} />
<Switch
colorPalette={"teal"}
size={"xs"}
onChange={() => handleToggle(agency.id, Number(agency.is_active))}
checked={Boolean(Number(agency.is_active))}
/>
</Box>
</HStack>
),
})),
];
}))));
const JobStatus = () => {
return (
<MainFrame>
@@ -50,34 +123,29 @@ const JobStatus = () => {
</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={(value) => {
setSearchTerm(value);
// setCurrentPage(1);
refetch()
}}
/>
{/* <Button bgColor={'#EEEEEE'} pl={3} pr={3}><IoMdAdd /> <Text>Add</Text></Button> */}
<JobStatusAddModel />
<JobStatusAddModel refetch={refetch} />
</HStack>
</HStack>
<DataTable
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}
/>
</Box>
</MainFrame>

View File

@@ -2,31 +2,66 @@ 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 { useCreateJobStatusPostMutation } from "../../../Redux/Service/job.status"
import { toaster } from "../../../components/ui/toaster"
import { useState } from "react"
function JobStatusAddModel({ refetch }: { refetch: VoidFunction }) {
const [title, setTitle] = useState('')
const [isOpen, setIsOpen] = useState(false);
const [createJobStatusPost] = useCreateJobStatusPostMutation()
const handleOpenModal = () => {
setIsOpen(true);
};
const handleSubmit = async () => {
if (!title.trim()) {
toaster.create({
title: "Error",
description: "Title field cannot be empty.",
type: "error",
});
return;
}
const payload = {
title: title,
};
try {
await createJobStatusPost(payload).unwrap();
refetch()
setIsOpen(false);
setTitle('')
} catch (error) {
console.error("Error updating template:", error);
alert("Failed to update template");
}
};
function JobStatusAddModel() {
return (
<DialogRoot placement="center">
<DialogRoot placement="center" open={isOpen}>
<DialogTrigger asChild>
{/* <Button bg={"transparent"} size="sm">
<MdOutlineRemoveRedEye style={{ cursor: "pointer", fontSize: "16px" }} />
</Button> */}
<Button px={5} size={"xs"} bg={"#02A0A0"}>
<Button px={5} size={"xs"} bg={"#02A0A0"} onClick={handleOpenModal}>
<IoMdAdd /> <Text>Add</Text>
</Button>
</DialogTrigger>
<DialogContent
bg={"#fff"}
// w={{ lg: "60%", md: "230px" }}
w={{ base: '90%', md: '400px' }}
bg={"#fff"}
// w={{ lg: "60%", md: "230px" }}
w={{ base: '90%', md: '400px' }}
height={'auto'}
overflowX="hidden"
p={3} // Reduced padding
bgSize={'md'}
overflowX="hidden"
p={3} // Reduced padding
bgSize={'md'}
>
<DialogHeader bg="white" >
<DialogTitle alignSelf="center" color="black" fontSize="14px">Add</DialogTitle>
@@ -37,18 +72,28 @@ function JobStatusAddModel() {
<Field.Root>
<Field.Label color="black" pt={1} fontSize="12px">Job Status</Field.Label>
<Input placeholder="" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" />
<Input
placeholder=""
bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
value={title}
onChange={(e) => setTitle(e.target.value)}
/>
</Field.Root>
</Stack>
</DialogBody>
<DialogFooter display="flex" justifyContent="center" pt={"2"}>
<Button w="100%" bg="#02A0A0" color={"#fff"}>
<Button w="100%" bg="#02A0A0" color={"#fff"} onClick={handleSubmit}>
Save
</Button>
</DialogFooter>
<DialogCloseTrigger color="black" />
<DialogCloseTrigger color="black" onClick={() => setIsOpen(false)} />
</DialogContent>
</DialogRoot >

View File

@@ -1,13 +1,14 @@
import { Box, HStack, Input, Text } from "@chakra-ui/react";
import { Box, HStack, 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 { Switch } from "../../../components/ui/switch";
import JobAddModel from "./JobAddModel";
import EditJobeModel from "./EditJobModel";
import { JobTypeData, useGetJobTypeQuery } from "../../../Redux/Service/job.type.service";
import { useEffect, useState } from "react";
import SearchComponent from "../../../components/SearchComponent";
@@ -36,8 +37,10 @@ const tableHeadRow = [
// ];
const JobType = () => {
const { data, refetch } = useGetJobTypeQuery()
const [currentPage, setCurrentPage] = useState(1);
const { data, refetch } = useGetJobTypeQuery(currentPage)
const [localData, setLocalData] = useState<any[]>([]);
const [searchTerm, setSearchTerm] = useState("");
// const [templateMasterToggle] = useTemplateMasterToggleMutation()
console.log('DATA', data?.data.data);
@@ -48,6 +51,16 @@ const JobType = () => {
}
}, [data]);
const handlePageChange = (page: number) => {
setCurrentPage(page);
};
const filteredData = localData?.filter((agency) => {
const searchLower = searchTerm.toLowerCase();
const title = agency.en_name?.toLowerCase().includes(searchLower);
return title;
});
// const handleToggle = async (agencyId: string, currentStatus: number) => {
// const newStatus = currentStatus ? 0 : 1;
// setLocalData((prevData) =>
@@ -69,8 +82,8 @@ const JobType = () => {
// };
const managepost = localData?.map((agency: JobTypeData, index: number) => ({
'id': agency.id,
const managepost = filteredData?.map((agency: JobTypeData, index: number) => ({
'id': (currentPage - 1) * (data?.data.per_page ?? 0) + index + 1,
"Sr. No": index + 1,
"Title": agency.en_name,
@@ -106,26 +119,14 @@ const JobType = () => {
</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={(value) => {
setSearchTerm(value);
// setCurrentPage(1);
refetch()
}}
/>
{/* <Button bgColor={'#EEEEEE'} pl={3} pr={3}><IoMdAdd /> <Text>Add</Text></Button> */}
<JobAddModel refetch={refetch} />
</HStack>
@@ -134,8 +135,13 @@ const JobType = () => {
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}
/>
</Box>
</MainFrame>

View File

@@ -45,7 +45,8 @@ const tableHeadRow = [
// ];
const TemplateMaster = () => {
const { data, refetch } = useGetTemplateMasterQuery()
const [currentPage, setCurrentPage] = useState(1);
const { data, refetch } = useGetTemplateMasterQuery(currentPage)
const [localData, setLocalData] = useState<any[]>([]);
const [templateMasterToggle] = useTemplateMasterToggleMutation();
const [searchTerm, setSearchTerm] = useState("");
@@ -57,6 +58,10 @@ const TemplateMaster = () => {
}
}, [data]);
const handlePageChange = (page: number) => {
setCurrentPage(page);
};
const handleToggle = async (agencyId: string, currentStatus: number) => {
const newStatus = currentStatus ? 0 : 1;
setLocalData((prevData) =>
@@ -83,7 +88,7 @@ const TemplateMaster = () => {
const managepost = filteredData?.map((agency: Template, index: number) => ({
'id': agency.id,
"Sr. No": index + 1,
"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",
@@ -160,8 +165,13 @@ const TemplateMaster = () => {
sortableColumns={["Name", "Registration Date "]}
tableHeadRow={tableHeadRow}
data={managepost}
paginationData={data?.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}
/>
</Box>
</MainFrame>

View File

@@ -9,20 +9,64 @@ import {
DialogTrigger,
} from "../../../components/ui/dialog";
import {
Box,
Field,
Input,
Span,
Stack,
} from "@chakra-ui/react";
import { Button } from "../../../components/ui/button";
// import { FaRegEdit } from "react-icons/fa";
import Edit from "../../../components/ActionIcons/Edit";
import { useState } from "react";
import { toaster } from "../../../components/ui/toaster";
import { useUpdateWorkSpaceMutation } from "../../../Redux/Service/workspace.mode";
function EditWorkModel({ localData, refetch }: {localData: any, refetch: VoidFunction}) {
const [title, setTitle] = useState(localData?.en_name);
const [isOpen, setIsOpen] = useState(false);
const [updateWorkSpace] = useUpdateWorkSpaceMutation()
console.log("localData", localData)
const handleOpenModal = () => {
// const template = localData?.find((item: any) => item.id === id);
if (localData) {
setIsOpen(true);
// setTitle(localData?.localData.en_name);
}
};
const handleSubmit = async () => {
if (!title.trim()) {
toaster.create({
title: "Error",
description: "Title field cannot be empty.",
type: "error",
});
return;
}
const payload = {
id: localData?.id,
en_name: title
};
try {
await updateWorkSpace(payload).unwrap();
refetch()
setIsOpen(false);
} catch (error) {
console.error("Error updating template:", error);
alert("Failed to update template");
}
};
function EditWorkModel() {
return (
<DialogRoot placement="center">
<DialogRoot placement="center" open={isOpen} onOpenChange={({ open }) => setIsOpen(open)}>
<DialogTrigger asChild>
<Span><Edit /></Span>
<Box bg={"transparent"} onClick={handleOpenModal}>
<Edit />
</Box>
</DialogTrigger>
<DialogContent
@@ -47,19 +91,20 @@ function EditWorkModel() {
Workspace Mode
</Field.Label>
<Input
value="Lorem Ipsum"
value={title}
bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
onChange={(e) => setTitle(e.target.value)}
/>
</Field.Root>
</Stack>
</DialogBody>
<DialogFooter display="flex" justifyContent="center" pt={"2"}>
<Button w="100%" bg="#02A0A0" color={"#fff"}>
<Button w="100%" bg="#02A0A0" color={"#fff"} onClick={handleSubmit}>
Save
</Button>
</DialogFooter>

View File

@@ -1,32 +1,67 @@
import { DialogBody, DialogCloseTrigger, DialogContent, DialogFooter, DialogHeader, DialogRoot, DialogTitle, DialogTrigger } from "../../../components/ui/dialog"
import {Field, Input, Stack, Text } from "@chakra-ui/react"
import { Field, Input, Stack, Text } from "@chakra-ui/react"
import { IoMdAdd } from "react-icons/io"
import { Button } from "../../../components/ui/button"
import { 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 handleOpenModal = () => {
setIsOpen(true);
};
const handleSubmit = async () => {
if (!title.trim()) {
toaster.create({
title: "Error",
description: "Title field cannot be empty.",
type: "error",
});
return;
}
const payload = {
en_name: title,
};
try {
await createWorkspacePost(payload);
refetch()
setIsOpen(false);
setTitle('')
} catch (error) {
console.error("Error updating template:", error);
alert("Failed to update template");
}
};
function WorkAddModel() {
return (
<DialogRoot placement="center">
<DialogRoot placement="center" open={isOpen}>
<DialogTrigger asChild>
{/* <Button bg={"transparent"} size="sm">
<MdOutlineRemoveRedEye style={{ cursor: "pointer", fontSize: "16px" }} />
</Button> */}
<Button px={5} size={"xs"} bg={"#02A0A0"}>
<Button px={5} size={"xs"} bg={"#02A0A0"} onClick={handleOpenModal}>
<IoMdAdd /> <Text>Add</Text>
</Button>
</DialogTrigger>
<DialogContent
bg={"#fff"}
// w={{ lg: "60%", md: "230px" }}
w={{ base: '90%', md: '400px' }}
bg={"#fff"}
// w={{ lg: "60%", md: "230px" }}
w={{ base: '90%', md: '400px' }}
height={'auto'}
overflowX="hidden"
p={3} // Reduced padding
bgSize={'md'}
overflowX="hidden"
p={3} // Reduced padding
bgSize={'md'}
>
<DialogHeader bg="white" >
<DialogTitle alignSelf="center" color="black" fontSize="14px">Add</DialogTitle>
@@ -37,19 +72,30 @@ function WorkAddModel() {
<Field.Root>
<Field.Label color="black" pt={1} fontSize="12px">Workspace Mode</Field.Label>
<Input placeholder="" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" />
<Input
placeholder=""
bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
value={title}
onChange={(e) => setTitle(e.target.value)}
/>
</Field.Root>
</Stack>
</DialogBody>
<DialogFooter display="flex" justifyContent="center" pt={"2"}>
<Button w="100%" bg="#02A0A0" color={"#fff"}>
<Button w="100%" bg="#02A0A0" color={"#fff"} onClick={handleSubmit}>
Save
</Button>
</DialogFooter>
<DialogCloseTrigger color="black" />
<DialogCloseTrigger color="black" onClick={() => setIsOpen(false)} />
</DialogContent>
<Toaster />
</DialogRoot >
)

View File

@@ -1,11 +1,13 @@
import { Box, HStack, Input, Text } from "@chakra-ui/react";
import { Box, HStack, Text } from "@chakra-ui/react";
import MainFrame from "../../../components/MainFrame"
import { InputGroup } from "../../../components/ui/input-group";
import { LuSearch } from "react-icons/lu";
import DataTable from "../../../components/DataTable";
import { Switch } from "../../../components/ui/switch";
import WorkAddModel from "./WorkAddModel";
import EditWorkModel from "./EditWorkModel";
import { useEffect, useState } from "react";
import { useGetWorkSpaceModeQuery, useWorkspaceToggleMutation } from "../../../Redux/Service/workspace.mode";
import SearchComponent from "../../../components/SearchComponent";
import { Toaster, toaster } from "../../../components/ui/toaster";
@@ -15,25 +17,95 @@ const tableHeadRow = [
"Sr. No",
"Title",
"Action"
];
const managepost: any[] = [
...Array.from({ length: 12 }, (_, i) => ({
"Sr. No": i + 1,
"Title": "Lorem Ipsum",
// const managepost: any[] = [
// ...Array.from({ length: 12 }, (_, i) => ({
// "Sr. No": i + 1,
// "Title": "Lorem Ipsum",
// "Action": (
// <HStack justifyContent="center">
// <EditWorkModel />
// <Box>
// <Switch colorPalette={'teal'} size={"xs"} />
// </Box>
// </HStack>
// ),
// })),
// ];
const WorkspaceMode = () => {
const [currentPage, setCurrentPage] = useState(1);
const { data, refetch } = useGetWorkSpaceModeQuery(currentPage)
const [localData, setLocalData] = useState<any[]>([]);
const [searchTerm, setSearchTerm] = useState("");
const [workspaceToggle] = useWorkspaceToggleMutation()
console.log("Workspace Data", data?.data.data)
useEffect(() => {
if (data?.data?.data) {
setLocalData(data?.data.data);
}
}, [data]);
const handlePageChange = (page: number) => {
setCurrentPage(page);
};
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 workspaceToggle({ id: agencyId, is_active: newStatus }).unwrap();
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
)
);
}
};
const filteredData = localData?.filter((agency) => {
const searchLower = searchTerm.toLowerCase();
const title = agency.en_name?.toLowerCase().includes(searchLower);
return title;
});
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,
"is_active": agency.is_active,
"Action": (
<HStack justifyContent="center">
<EditWorkModel />
{/* <ViewAgencyMaster agency={localData} id={agency.id} /> */}
<EditWorkModel localData={agency} refetch={refetch} />
<Box>
<Switch colorPalette={'teal'} size={"xs"}/>
<Switch
colorPalette={"teal"}
size={"xs"}
onChange={() => handleToggle(agency.id, Number(agency.is_active))}
checked={Boolean(Number(agency.is_active))}
/>
</Box>
</HStack>
),
})),
];
}));
const WorkspaceMode = () => {
return (
<MainFrame>
@@ -46,40 +118,36 @@ const WorkspaceMode = () => {
px={3}
>
<Text as={"span"} fontSize={"sm"} fontWeight={500} color={"#000"}>
Workspace Mode
Workspace Mode
</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={(value) => {
setSearchTerm(value);
// setCurrentPage(1);
refetch()
}}
/>
{/* <Button bgColor={'#EEEEEE'} pl={3} pr={3}><IoMdAdd /> <Text>Add</Text></Button> */}
<WorkAddModel />
<WorkAddModel refetch={refetch}/>
</HStack>
</HStack>
<DataTable
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}
/>
</Box>
</Box>
<Toaster />
</MainFrame>
)
}

View File

@@ -70,8 +70,8 @@ export const agencyMasterModule = createApi({
}),
}),
getAgencyMaster: builder.query<AgencyResponse, void>({
query: () => "/agency-master"
getAgencyMaster: builder.query<AgencyResponse, number>({
query: (page = 1) => `/agency-master?page=${page}`
}),
agencyMasterToggle: builder.mutation({

View File

@@ -0,0 +1,110 @@
import { createApi } from "@reduxjs/toolkit/query/react";
import { baseQueryWithReauth } from "./apiSlice";
export interface CountryData {
id: number;
en_name: string;
hi_name: string;
mr_name: string;
te_name: string;
ta_name: string;
bn_name: string;
or_name: string;
country_code: string;
phonecode: string;
capital: string;
currency: string;
currency_name: string;
currency_symbol: string;
is_active: string;
}
interface ApiResponse {
status: string;
status_code: number;
message: string;
data: {
current_page: number,
last_page: number,
total: number,
from: number,
per_page: number,
to: number,
data: CountryData[];
};
}
export interface CountryEdit {
status: string;
status_code: number;
message: string;
data: CountryData[];
}
export type PostCountry = {
en_name: string;
country_code: string;
phonecode: string;
capital: string;
currency: string;
currency_name: string;
currency_symbol: string;
};
export const countryMaster = createApi({
reducerPath: "countryMaster",
baseQuery: baseQueryWithReauth, // Use enhanced baseQuery with error handling
endpoints: (builder) => ({
createCountryPost: builder.mutation<PostCountry, Partial<PostCountry>>({
query: (data) => ({
url: "/country-add",
method: "POST",
body: data,
}),
}),
// 🔹 GET: Fetch all posts
getCountryMaster: builder.query<ApiResponse, number>({
query: (page = 1) => `/country-list?page=${page}`,
}),
getCountryMasterEdit: builder.query<CountryEdit, number>({
query: (id) => `/country-edit/${id}`,
}),
updateCountry: builder.mutation({
query: (updatedData) => ({
url: "/country-update",
method: "POST",
body: updatedData,
}),
}),
countryToggle: builder.mutation({
query: ({ id, is_active }) => ({
url: `/country-status`,
method: "POST",
body: { id, is_active },
}),
}),
// deleteFaqPost: builder.mutation<{ status: string; message: string }, { id: number }>({
// query: ({ id }) => ({
// url: `/faq-delete`,
// method: "POST",
// body: { id },
// }),
// }),
}),
});
export const {
useGetCountryMasterQuery,
useGetCountryMasterEditQuery,
useCreateCountryPostMutation,
useUpdateCountryMutation,
useCountryToggleMutation,
// useDeleteFaqPostMutation
} = countryMaster;

View File

@@ -0,0 +1,109 @@
import { createApi } from "@reduxjs/toolkit/query/react";
import { baseQueryWithReauth } from "./apiSlice";
export interface DepartmentData {
id: number;
industry_masters_xid: number;
en_name: string;
hi_name: string;
mr_name: string;
te_name: string;
ta_name: string;
bn_name: string;
or_name: string;
is_active: string;
}
interface ApiResponse {
status: string;
status_code: number;
message: string;
data: {
current_page: number,
last_page: number,
total: number,
from: number,
per_page: number,
to: number,
data: DepartmentData[];
};
}
export interface CountryEdit {
status: string;
status_code: number;
message: string;
data: DepartmentData[];
}
export interface DropDown{
status: string;
status_code: number;
message: string;
data: {
id: number;
en_name: string;
}[]
}
export type PostDepartment = {
en_name: string;
industry_masters_xid: number;
};
export const departmentMaster = createApi({
reducerPath: "departmentMaster",
baseQuery: baseQueryWithReauth, // Use enhanced baseQuery with error handling
endpoints: (builder) => ({
createDepartmentPost: builder.mutation<PostDepartment, Partial<PostDepartment>>({
query: (data) => ({
url: "/department-master-store",
method: "POST",
body: data,
}),
}),
// 🔹 GET: Fetch all posts
getDepartmentMaster: builder.query<ApiResponse, number>({
query: (page = 1) => `/department-master-list?page=${page}`,
}),
getDepartmentMasterDropDown: builder.query<DropDown, void>({
query: () => `/industry-master-get-category`,
}),
updateDepartment: builder.mutation({
query: (updatedData) => ({
url: "/department-master-update",
method: "POST",
body: updatedData,
}),
}),
departmentToggle: builder.mutation({
query: ({ id, is_active }) => ({
url: `/department-master-status`,
method: "POST",
body: { id, is_active },
}),
}),
// deleteFaqPost: builder.mutation<{ status: string; message: string }, { id: number }>({
// query: ({ id }) => ({
// url: `/faq-delete`,
// method: "POST",
// body: { id },
// }),
// }),
}),
});
export const {
useGetDepartmentMasterQuery,
useGetDepartmentMasterDropDownQuery,
useCreateDepartmentPostMutation,
useUpdateDepartmentMutation,
useDepartmentToggleMutation,
// useDeleteFaqPostMutation
} = departmentMaster;

View File

@@ -23,6 +23,8 @@ interface ApiResponse {
last_page: number,
total: number,
from: number,
per_page: number,
to: number,
data: FaqData[];
};
}
@@ -48,8 +50,8 @@ export const faqs = createApi({
}),
}),
// 🔹 GET: Fetch all posts
getFaq: builder.query<ApiResponse, void>({
query: () => "/faq-list",
getFaq: builder.query<ApiResponse, number>({
query: (page = 1) => `/faq-list?page=${page}`,
}),
updateFaq: builder.mutation({

View File

@@ -61,8 +61,8 @@ export const industryMaster = createApi({
}),
}),
// 🔹 GET: Fetch all posts
getIndustryMaster: builder.query<IndustryMasterResponse, void>({
query: () => "/industry-master-list",
getIndustryMaster: builder.query<IndustryMasterResponse, number>({
query: (page = 1) => `/industry-master-list?page=${page}`,
}),
updateIndustryMaster: builder.mutation({

View File

@@ -0,0 +1,91 @@
import { createApi } from "@reduxjs/toolkit/query/react";
import { baseQueryWithReauth } from "./apiSlice";
export interface JobStatusData {
id: number;
is_active: string;
job_status_translation:{
job_status_xid: number,
title:string,
language_xid:number
}[],
}
interface ApiResponse {
status: string;
status_code: number;
message: string;
data: {
current_page: number,
last_page: number,
total: number,
from: number,
per_page: number,
to: number,
data: JobStatusData[];
};
}
export interface CountryEdit {
status: string;
status_code: number;
message: string;
data: JobStatusData[];
}
export type PostJobStatus = {
title: string
};
export const jobStatus = createApi({
reducerPath: "jobStatus",
baseQuery: baseQueryWithReauth, // Use enhanced baseQuery with error handling
endpoints: (builder) => ({
createJobStatusPost: builder.mutation<PostJobStatus, Partial<PostJobStatus>>({
query: (data) => ({
url: "/job-status-store",
method: "POST",
body: data,
}),
}),
// 🔹 GET: Fetch all posts
getJobStatus: builder.query<ApiResponse, number>({
query: (page = 1) => `/job-status-list?page=${page}`,
}),
updateJobStatus: builder.mutation({
query: (updatedData) => ({
url: "/job-status-update",
method: "POST",
body: updatedData,
}),
}),
jobStatusToggle: builder.mutation({
query: ({ id, is_active }) => ({
url: `/job-status-status`,
method: "POST",
body: { id, is_active },
}),
}),
// deleteFaqPost: builder.mutation<{ status: string; message: string }, { id: number }>({
// query: ({ id }) => ({
// url: `/faq-delete`,
// method: "POST",
// body: { id },
// }),
// }),
}),
});
export const {
useGetJobStatusQuery,
useCreateJobStatusPostMutation,
useUpdateJobStatusMutation,
useJobStatusToggleMutation,
// useDeleteFaqPostMutation
} = jobStatus;

View File

@@ -59,8 +59,8 @@ export const jobType = createApi({
}),
}),
// 🔹 GET: Fetch all posts
getJobType: builder.query<JobTypeResponse, void>({
query: () => "/job-type",
getJobType: builder.query<JobTypeResponse, number>({
query: (page = 1) => `/job-type?page=${page}`,
}),
updateJobType: builder.mutation({

View File

@@ -1,26 +1,84 @@
import { createApi } from "@reduxjs/toolkit/query";
import { createApi } from "@reduxjs/toolkit/query/react";
import { baseQueryWithReauth } from "./apiSlice";
export const manageJobs = createApi({
reducerPath: "manageJobs",
baseQuery: baseQueryWithReauth, // Use enhanced baseQuery with error handling
endpoints: (builder) => ({
getPosts: builder.query<Post[], void>({ query: () => "/posts" }),
}),
});
export const { } = manageJobs;
export type Post = {
export interface JobStatusData {
id: number;
job_title: string;
workspace_mode_xid: number;
industry_xid: number;
department_xid: number;
company_name: string;
ctc_currency_symbol: string;
ctc_amount: string;
experience: string;
job_location: string;
country_xid: number;
job_type_xid: number;
skill_description: string;
job_description: string;
job_image: string | null;
industry: {
id: number;
title: string;
body: string;
};
en_name: string;
};
department: {
id: number;
en_name: string;
};
workspace: {
id: number;
en_name: string;
};
country: {
id: number;
en_name: string;
};
job_type: {
id: number;
en_name: string;
};
}
interface ApiResponse {
status: string;
status_code: number;
message: string;
data: {
current_page: number,
last_page: number,
total: number,
from: number,
per_page: number,
to: number,
data: JobStatusData[];
};
}
export interface CountryEdit {
status: string;
status_code: number;
message: string;
data: JobStatusData[];
}
export type PostJobStatus = {
title: 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}`,
}),
}),
});
export const { useGetManageJobsQuery } = manageJobs;

View File

@@ -0,0 +1,82 @@
import { createApi } from "@reduxjs/toolkit/query/react";
import { baseQueryWithReauth } from "./apiSlice";
export interface JobStatusData {
id: number;
is_active: string;
created_at:string,
job_status_translation:{
job_status_xid: number,
title:string,
language_xid:number
}[],
}
interface ApiResponse {
status: string;
status_code: number;
message: string;
data: {
current_page: number,
last_page: number,
total: number,
from: number,
per_page: number,
to: number,
data: JobStatusData[];
};
}
export interface CountryEdit {
status: string;
status_code: number;
message: string;
data: JobStatusData[];
}
export type PostJobStatus = {
title: string
};
export const managePosts = createApi({
reducerPath: "managePosts",
baseQuery: baseQueryWithReauth, // Use enhanced baseQuery with error handling
endpoints: (builder) => ({
// createJobStatusPost: builder.mutation<PostJobStatus, Partial<PostJobStatus>>({
// query: (data) => ({
// url: "/job-status-store",
// method: "POST",
// body: data,
// }),
// }),
// 🔹 GET: Fetch all posts
getManagePosts: builder.query<ApiResponse, number>({
query: (page = 1) => `/manage-post-list?page=${page}`,
}),
postStatusToggle: builder.mutation({
query: ({ id, is_active }) => ({
url: `/manage-post-status`,
method: "POST",
body: { id, is_active },
}),
}),
// deleteFaqPost: builder.mutation<{ status: string; message: string }, { id: number }>({
// query: ({ id }) => ({
// url: `/faq-delete`,
// method: "POST",
// body: { id },
// }),
// }),
}),
});
export const {
useGetManagePostsQuery,
usePostStatusToggleMutation,
// useDeleteFaqPostMutation
} = managePosts;

View File

@@ -1,26 +0,0 @@
import { createApi } from "@reduxjs/toolkit/query";
import { baseQueryWithReauth } from "./apiSlice";
export const managePosts = createApi({
reducerPath: "managePosts",
baseQuery: baseQueryWithReauth, // Use enhanced baseQuery with error handling
endpoints: (builder) => ({
getPosts: builder.query<Post[], void>({ query: () => "/posts" }),
}),
});
export const { } = managePosts;
export type Post = {
id: number;
title: string;
body: string;
};

View File

@@ -0,0 +1,108 @@
import { createApi } from "@reduxjs/toolkit/query/react";
import { baseQueryWithReauth } from "./apiSlice";
export interface UserData {
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_links:[]
}
interface ApiResponse {
status: string;
status_code: number;
message: string;
data: {
current_page: number,
last_page: number,
total: number,
from: number,
per_page: number,
to: number,
data: UserData[];
};
}
export interface CountryEdit {
status: string;
status_code: number;
message: string;
data: UserData[];
}
export type PostCountry = {
en_name: string;
country_code: string;
phonecode: string;
capital: string;
currency: string;
currency_name: string;
currency_symbol: string;
};
export const registerUser = createApi({
reducerPath: "registerUser",
baseQuery: baseQueryWithReauth, // Use enhanced baseQuery with error handling
endpoints: (builder) => ({
createCountryPost: builder.mutation<PostCountry, Partial<PostCountry>>({
query: (data) => ({
url: "/country-add",
method: "POST",
body: data,
}),
}),
// 🔹 GET: Fetch all posts
getManageUser: builder.query<ApiResponse, number>({
query: (page = 1) => `/manage-user-list?page=${page}`,
}),
getCountryMasterEdit: builder.query<CountryEdit, number>({
query: (id) => `/country-edit/${id}`,
}),
updateCountry: builder.mutation({
query: (updatedData) => ({
url: "/country-update",
method: "POST",
body: updatedData,
}),
}),
userToggle: builder.mutation({
query: ({ id, is_active }) => ({
url: `/manage-user-status`,
method: "POST",
body: { id, is_active },
}),
}),
// deleteFaqPost: builder.mutation<{ status: string; message: string }, { id: number }>({
// query: ({ id }) => ({
// url: `/faq-delete`,
// method: "POST",
// body: { id },
// }),
// }),
}),
});
export const {
useGetManageUserQuery,
useGetCountryMasterEditQuery,
useCreateCountryPostMutation,
useUpdateCountryMutation,
useUserToggleMutation,
// useDeleteFaqPostMutation
} = registerUser;

View File

@@ -1,26 +0,0 @@
import { createApi } from "@reduxjs/toolkit/query";
import { baseQueryWithReauth } from "./apiSlice";
export const registerUser = createApi({
reducerPath: "registerUser",
baseQuery: baseQueryWithReauth, // Use enhanced baseQuery with error handling
endpoints: (builder) => ({
getPosts: builder.query<Post[], void>({ query: () => "/posts" }),
}),
});
export const { } = registerUser;
export type Post = {
id: number;
title: string;
body: string;
};

View File

@@ -73,8 +73,8 @@ export const templateMaster = createApi({
}),
}),
// 🔹 GET: Fetch all posts
getTemplateMaster: builder.query<TemplateResponse, void>({
query: () => "/template-master",
getTemplateMaster: builder.query<TemplateResponse, number>({
query: (page = 1) => `/template-master?page=${page}`,
}),
updateTemplateMaster: builder.mutation<Post, FormData>({

View File

@@ -0,0 +1,96 @@
import { createApi } from "@reduxjs/toolkit/query/react";
import { baseQueryWithReauth } from "./apiSlice";
export interface WorkspaceData {
id: number;
en_name: string;
is_active: string;
}
interface ApiResponse {
status: string;
status_code: number;
message: string;
data: {
current_page: number,
last_page: number,
total: number,
from: number,
per_page: number,
to: number,
data: WorkspaceData[];
};
}
export interface CountryEdit {
status: string;
status_code: number;
message: string;
data: WorkspaceData[];
}
export interface DropDown {
status: string;
status_code: number;
message: string;
data: {
id: number;
en_name: string;
}[]
}
export type PostDepartment = {
en_name: string;
};
export const workspaceMode = createApi({
reducerPath: "workspaceMode",
baseQuery: baseQueryWithReauth, // Use enhanced baseQuery with error handling
endpoints: (builder) => ({
createWorkspacePost: builder.mutation<PostDepartment, Partial<PostDepartment>>({
query: (data) => ({
url: "/department-master-store",
method: "POST",
body: data,
}),
}),
// 🔹 GET: Fetch all posts
getWorkSpaceMode: builder.query<ApiResponse, number>({
query: (page = 1) => `/workspace-mode?page=${page}`,
}),
updateWorkSpace: builder.mutation({
query: (updatedData) => ({
url: "/workspace-update",
method: "POST",
body: updatedData,
}),
}),
workspaceToggle: builder.mutation({
query: ({ id, is_active }) => ({
url: `/workspace-status`,
method: "POST",
body: { id, is_active },
}),
}),
// deleteFaqPost: builder.mutation<{ status: string; message: string }, { id: number }>({
// query: ({ id }) => ({
// url: `/faq-delete`,
// method: "POST",
// body: { id },
// }),
// }),
}),
});
export const {
useGetWorkSpaceModeQuery,
useCreateWorkspacePostMutation,
useUpdateWorkSpaceMutation,
useWorkspaceToggleMutation,
// useDeleteFaqPostMutation
} = workspaceMode;

View File

@@ -1,10 +1,8 @@
import { configureStore } from "@reduxjs/toolkit";
import { dashboard } from "./Service/apiSlice";
import authReducer from "./Service/authSlice";
import { registerUser } from "./Service/register.user.service";
import { deactivatedAccounts } from "./Service/deactivated.account.service";
import { faqs } from "./Service/faqs.service";
import { managePosts } from "./Service/manage.posts.service";
import { manageSubAdmin } from "./Service/manage.subadmin.service";
import { manageJobs } from "./Service/manage.jobs.service";
import { manageGroups } from "./Service/manage.groups.service";
@@ -19,14 +17,18 @@ import { templateMaster } from "./Service/template.master.service";
import { jobType } from "./Service/job.type.service";
import { industryMaster } from "./Service/industry.master.service";
import { profile } from "./Service/profile.password";
import { countryMaster } from "./Service/country.master";
import { departmentMaster } from "./Service/department.master";
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";
export const store = configureStore({
reducer: {
[dashboard.reducerPath]: dashboard.reducer,
[registerUser.reducerPath]: registerUser.reducer,
[deactivatedAccounts.reducerPath]: deactivatedAccounts.reducer,
[faqs.reducerPath]: faqs.reducer,
[managePosts.reducerPath]: managePosts.reducer,
[manageSubAdmin.reducerPath]: manageSubAdmin.reducer,
[manageJobs.reducerPath]: manageJobs.reducer,
[manageGroups.reducerPath]: manageGroups.reducer,
@@ -41,13 +43,18 @@ export const store = configureStore({
[jobType.reducerPath]: jobType.reducer,
[industryMaster.reducerPath]: industryMaster.reducer,
[profile.reducerPath]: profile.reducer,
[countryMaster.reducerPath]: countryMaster.reducer,
[departmentMaster.reducerPath]: departmentMaster.reducer,
[workspaceMode.reducerPath]: workspaceMode.reducer,
[jobStatus.reducerPath]: jobStatus.reducer,
[managePosts.reducerPath]: managePosts.reducer,
[registerUser.reducerPath]: registerUser.reducer,
auth: authReducer,
},
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware().concat(
dashboard.middleware,
dashboard.middleware,
deactivatedAccounts.middleware,
managePosts.middleware,
faqs.middleware,
manageSubAdmin.middleware,
manageJobs.middleware,
@@ -63,7 +70,13 @@ export const store = configureStore({
jobType.middleware,
industryMaster.middleware,
profile.middleware,
),
countryMaster.middleware,
departmentMaster.middleware,
workspaceMode.middleware,
jobStatus.middleware,
managePosts.middleware,
registerUser.middleware,
),
});
export type RootState = ReturnType<typeof store.getState>;

View File

@@ -143,6 +143,11 @@ export const nav = [
path: "/master-module/industry-master",
Icon: GoDotFill,
},
{
title: "Department Master",
path: "/master-module/department-master",
Icon: GoDotFill,
},
],
},
];

View File

@@ -24,6 +24,7 @@ import RegisterUsers from "../Pages/ManageUsers/RegisterUsers/RegisterUsers";
import DeactivatedAccounts from "../Pages/ManageUsers/DeactivatedAccounts/DeactivatedAccounts";
import { Spinner } from "../components/Sipnner/Spinner";
import IndustryMasterList from "../Pages/MasterModule/IndustryMaster/IndustryMasterList";
import DepartmentMasterList from "../Pages/MasterModule/DepartmentMaster/DepartmentMasterList";
export const RouteLink = [
{ path: "/", Component: Dashboard },
@@ -63,6 +64,7 @@ export const RouteLink = [
{ path: "/master-module/country", Component: Country},
{ path: "/master-module/job-status", Component: JobStatus},
{ path: "/master-module/industry-master", Component: IndustryMasterList},
{ path: "/master-module/department-master", Component: DepartmentMasterList},
// { path: "/job-status", Component: Spinner},
]

View File

@@ -1,4 +1,4 @@
import { useEffect, useState } from "react";
import { useState } from "react";
import { HStack, Stack, Table } from "@chakra-ui/react";
import { PaginationItems, PaginationNextTrigger, PaginationPrevTrigger, PaginationRoot } from "./ui/pagination";
// import {
@@ -12,8 +12,13 @@ interface TableProps {
tableHeadRow: string[];
data: Record<string, any>[];
sortableColumns?: string[]; // Specify which columns are sortable
paginationData?: any,
refetch?: (params?: any) => void;
paginationData?: {
current_page: number;
last_page: number;
per_page: number;
total: number;
},
onPageChange?: (page: number) => void;
}
const DataTable: React.FC<TableProps> = ({
@@ -21,30 +26,18 @@ const DataTable: React.FC<TableProps> = ({
data,
sortableColumns = [],
paginationData,
refetch
}) => {
const totalCount = paginationData?.total || 0;
const pageSize = paginationData?.per_page || 10;
const currentPage = paginationData?.current_page || 1;
const lastPage = paginationData?.last_page || 1;
const [page, setPage] = useState(currentPage);
const [sortedData, setSortedData] = useState(data);
onPageChange
}: TableProps) => {
const { current_page = 1, last_page = 1 } = paginationData || {};
const [sortConfig, setSortConfig] = useState<{
key: string;
direction: "asc" | "desc";
} | null>(null);
useEffect(() => {
setSortedData(data);
}, [data]);
const handlePageChange = (newPage: any) => {
if (newPage >= 1 && newPage <= lastPage) {
setPage(newPage);
if (refetch) {
refetch({ page: newPage });
}
const handlePageChange = (details: { page: number }) => {
const newPage = details.page;
if (newPage >= 1 && newPage <= last_page) {
onPageChange?.(newPage);
}
};
@@ -60,14 +53,9 @@ const DataTable: React.FC<TableProps> = ({
direction = "desc";
}
const sortedArray = [...sortedData].sort((a, b) => {
if (a[column] < b[column]) return direction === "asc" ? -1 : 1;
if (a[column] > b[column]) return direction === "asc" ? 1 : -1;
return 0;
});
setSortedData(sortedArray);
setSortConfig({ key: column, direction });
const newSortConfig = { key: column, direction };
setSortConfig(newSortConfig);
onPageChange?.(1);
};
return (
@@ -110,7 +98,7 @@ const DataTable: React.FC<TableProps> = ({
</Table.Row>
</Table.Header>
<Table.Body>
{sortedData.map((item: any, index) => (
{data.map((item: any, index) => (
<Table.Row
key={index}
bg={index % 2 === 0 ? "#fff" : "#007F3310"}
@@ -139,22 +127,24 @@ const DataTable: React.FC<TableProps> = ({
</Table.Body>
</Table.Root>
</Table.ScrollArea>
{lastPage > 1 && <PaginationRoot
count={totalCount}
pageSize={pageSize}
defaultPage={currentPage}
{last_page > 1 && (<PaginationRoot
count={paginationData?.total ?? 0}
pageSize={paginationData?.per_page ?? 0}
page={current_page}
onPageChange={handlePageChange}
size={"xs"}
siblingCount={1}
// count={20}
// pageSize={2}
// defaultPage={1}
mb={4}
>
<HStack justifyContent="flex-end">
<PaginationPrevTrigger onClick={() => handlePageChange(page - 1)} disabled={page === 1} />
<PaginationPrevTrigger onClick={() => handlePageChange({ page: current_page - 1 })} disabled={current_page === 1} />
<PaginationItems />
<PaginationNextTrigger onClick={() => handlePageChange(page + 1)} disabled={page === lastPage} />
<PaginationNextTrigger onClick={() => handlePageChange({ page: current_page + 1 })} disabled={current_page === last_page} />
</HStack>
</PaginationRoot>}
</PaginationRoot>)}
</Stack>
);
};

View File

@@ -198,16 +198,40 @@ export const PaginationNextTrigger = React.forwardRef<
export const PaginationItems = (props: React.HTMLAttributes<HTMLElement>) => {
return (
<ChakraPagination.Context>
{({ pages }) =>
pages.map((page, index) => (
<PaginationItem
key={index}
type="page"
value={page.type === "page" ? page.value : 0}
{...props}
/>
))
}
{({ pages }) =>(
<>
{pages.map((page, index) => {
if(page.type === "ellipsis") {
return (
(
<Text
key={`ellipsis-${index}`}
mx={1}
display="inline-flex"
alignItems="center"
height="100%"
>
...
</Text>
)
)
}
if (page.type === 'page') {
return (
<PaginationItem
key={index}
type="page"
value={page.value}
{...props}
/>
);
}
// Skip rendering for other types
return null;
})}
</>
)}
</ChakraPagination.Context>
);
};