From 29f30f9f9849a8db200568e454306269f3677688 Mon Sep 17 00:00:00 2001 From: rockyeverlast Date: Tue, 15 Apr 2025 20:43:48 +0530 Subject: [PATCH] Api integrated for WorkSpace and JobStatus --- .../DepartmentMaster/EditDepartmentMaster.tsx | 3 +- .../JobStatus/EditJobStatusModel.tsx | 62 +++++++- .../MasterModule/JobStatus/JobStatus.tsx | 133 ++++++++++++----- .../JobStatus/JobStatusAddModel.tsx | 73 +++++++-- .../WorkspaceMode/EditWorkModel.tsx | 57 ++++++- .../WorkspaceMode/WorkAddModel.tsx | 76 ++++++++-- .../WorkspaceMode/WorkspaceMode.tsx | 139 +++++++++++++----- src/Redux/Service/job.status.ts | 69 ++++----- src/Redux/Service/workspace.mode.ts | 96 ++++++++++++ src/Redux/Store.tsx | 6 + 10 files changed, 558 insertions(+), 156 deletions(-) create mode 100644 src/Redux/Service/workspace.mode.ts diff --git a/src/Pages/MasterModule/DepartmentMaster/EditDepartmentMaster.tsx b/src/Pages/MasterModule/DepartmentMaster/EditDepartmentMaster.tsx index 13d262a..0364cec 100644 --- a/src/Pages/MasterModule/DepartmentMaster/EditDepartmentMaster.tsx +++ b/src/Pages/MasterModule/DepartmentMaster/EditDepartmentMaster.tsx @@ -12,7 +12,7 @@ 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 } from "../../../components/ui/toaster"; +import { Toaster, toaster } from "../../../components/ui/toaster"; import { useGetDepartmentMasterDropDownQuery, useUpdateDepartmentMutation } from "../../../Redux/Service/department.master"; function EditDepartmentMaster({ localData, refetch }: { localData: any, refetch: VoidFunction }) { @@ -152,6 +152,7 @@ function EditDepartmentMaster({ localData, refetch }: { localData: any, refetch: setIsOpen(false)} /> + ); } diff --git a/src/Pages/MasterModule/JobStatus/EditJobStatusModel.tsx b/src/Pages/MasterModule/JobStatus/EditJobStatusModel.tsx index 239b33b..f6d0f0a 100644 --- a/src/Pages/MasterModule/JobStatus/EditJobStatusModel.tsx +++ b/src/Pages/MasterModule/JobStatus/EditJobStatusModel.tsx @@ -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 ( - + setIsOpen(open)}> - + + + Job Status - + setTitle(e.target.value)} + /> - + - ) } diff --git a/src/Pages/MasterModule/JobStatus/JobStatus.tsx b/src/Pages/MasterModule/JobStatus/JobStatus.tsx index b99f0d3..6d465b5 100644 --- a/src/Pages/MasterModule/JobStatus/JobStatus.tsx +++ b/src/Pages/MasterModule/JobStatus/JobStatus.tsx @@ -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": ( +// +// +// +// +// +// +// ), +// })), +// ]; + +const JobStatus = () => { + const [currentPage, setCurrentPage] = useState(1); + const { data, refetch } = useGetJobStatusQuery(currentPage) + const [localData, setLocalData] = useState([]); + 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": ( - + {/* */} + - + handleToggle(agency.id, Number(agency.is_active))} + checked={Boolean(Number(agency.is_active))} + /> ), - })), -]; + })))); -const JobStatus = () => { return ( @@ -50,34 +123,28 @@ const JobStatus = () => { - - } - color={"#000"} - > - - + { + setSearchTerm(value); + setCurrentPage(1); + }} + /> {/* */} - + diff --git a/src/Pages/MasterModule/JobStatus/JobStatusAddModel.tsx b/src/Pages/MasterModule/JobStatus/JobStatusAddModel.tsx index f01b40d..095b303 100644 --- a/src/Pages/MasterModule/JobStatus/JobStatusAddModel.tsx +++ b/src/Pages/MasterModule/JobStatus/JobStatusAddModel.tsx @@ -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 ( - + {/* */} - Add @@ -37,18 +72,28 @@ function JobStatusAddModel() { Job Status - + setTitle(e.target.value)} + /> - - + setIsOpen(false)} /> diff --git a/src/Pages/MasterModule/WorkspaceMode/EditWorkModel.tsx b/src/Pages/MasterModule/WorkspaceMode/EditWorkModel.tsx index d9bcb62..a85b43f 100644 --- a/src/Pages/MasterModule/WorkspaceMode/EditWorkModel.tsx +++ b/src/Pages/MasterModule/WorkspaceMode/EditWorkModel.tsx @@ -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 ( - + setIsOpen(open)}> - + + + setTitle(e.target.value)} /> - diff --git a/src/Pages/MasterModule/WorkspaceMode/WorkAddModel.tsx b/src/Pages/MasterModule/WorkspaceMode/WorkAddModel.tsx index 84f189e..becbddd 100644 --- a/src/Pages/MasterModule/WorkspaceMode/WorkAddModel.tsx +++ b/src/Pages/MasterModule/WorkspaceMode/WorkAddModel.tsx @@ -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 ( - + {/* */} - Add @@ -37,19 +72,30 @@ function WorkAddModel() { Workspace Mode - + setTitle(e.target.value)} + /> - - + setIsOpen(false)} /> + ) diff --git a/src/Pages/MasterModule/WorkspaceMode/WorkspaceMode.tsx b/src/Pages/MasterModule/WorkspaceMode/WorkspaceMode.tsx index 99f7007..875fa2f 100644 --- a/src/Pages/MasterModule/WorkspaceMode/WorkspaceMode.tsx +++ b/src/Pages/MasterModule/WorkspaceMode/WorkspaceMode.tsx @@ -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": ( +// +// +// +// +// +// +// ), +// })), +// ]; + +const WorkspaceMode = () => { + const [currentPage, setCurrentPage] = useState(1); + const { data, refetch } = useGetWorkSpaceModeQuery(currentPage) + const [localData, setLocalData] = useState([]); + 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": ( - + {/* */} + - + handleToggle(agency.id, Number(agency.is_active))} + checked={Boolean(Number(agency.is_active))} + /> ), - })), -]; + })); -const WorkspaceMode = () => { return ( @@ -46,40 +118,35 @@ const WorkspaceMode = () => { px={3} > - Workspace Mode + Workspace Mode - - } - color={"#000"} - > - - + { + setSearchTerm(value); + setCurrentPage(1); + }} + /> {/* */} - + - + + ) } diff --git a/src/Redux/Service/job.status.ts b/src/Redux/Service/job.status.ts index f70f360..2135cc3 100644 --- a/src/Redux/Service/job.status.ts +++ b/src/Redux/Service/job.status.ts @@ -1,22 +1,14 @@ import { createApi } from "@reduxjs/toolkit/query/react"; import { baseQueryWithReauth } from "./apiSlice"; -export interface CountryData { +export interface JobStatusData { 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; + job_status_translation:{ + job_status_xid: number, + title:string, + language_xid:number + }[], } interface ApiResponse { @@ -30,7 +22,7 @@ interface ApiResponse { from: number, per_page: number, to: number, - data: CountryData[]; + data: JobStatusData[]; }; } @@ -38,52 +30,42 @@ export interface CountryEdit { status: string; status_code: number; message: string; - data: CountryData[]; + data: JobStatusData[]; } -export type PostCountry = { - en_name: string; - country_code: string; - phonecode: string; - capital: string; - currency: string; - currency_name: string; - currency_symbol: string; +export type PostJobStatus = { + title: string }; -export const countryMaster = createApi({ - reducerPath: "countryMaster", +export const jobStatus = createApi({ + reducerPath: "jobStatus", baseQuery: baseQueryWithReauth, // Use enhanced baseQuery with error handling endpoints: (builder) => ({ - createCountryPost: builder.mutation>({ + createJobStatusPost: builder.mutation>({ query: (data) => ({ - url: "/country-add", + url: "/job-status-store", method: "POST", body: data, }), }), // 🔹 GET: Fetch all posts - getCountryMaster: builder.query({ - query: (page = 1) => `/country-list?page=${page}`, + getJobStatus: builder.query({ + query: (page = 1) => `/job-status-list?page=${page}`, }), - getCountryMasterEdit: builder.query({ - query: (id) => `/country-edit/${id}`, - }), - - updateCountry: builder.mutation({ + updateJobStatus: builder.mutation({ query: (updatedData) => ({ - url: "/country-update", + url: "/job-status-update", method: "POST", body: updatedData, }), }), - countryToggle: builder.mutation({ + jobStatusToggle: builder.mutation({ query: ({ id, is_active }) => ({ - url: `/country-status`, + url: `/job-status-status`, method: "POST", body: { id, is_active }, }), @@ -101,10 +83,9 @@ export const countryMaster = createApi({ }); export const { - useGetCountryMasterQuery, - useGetCountryMasterEditQuery, - useCreateCountryPostMutation, - useUpdateCountryMutation, - useCountryToggleMutation, + useGetJobStatusQuery, + useCreateJobStatusPostMutation, + useUpdateJobStatusMutation, + useJobStatusToggleMutation, // useDeleteFaqPostMutation -} = countryMaster; \ No newline at end of file +} = jobStatus; \ No newline at end of file diff --git a/src/Redux/Service/workspace.mode.ts b/src/Redux/Service/workspace.mode.ts new file mode 100644 index 0000000..8d88c49 --- /dev/null +++ b/src/Redux/Service/workspace.mode.ts @@ -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>({ + query: (data) => ({ + url: "/department-master-store", + method: "POST", + body: data, + }), + }), + // 🔹 GET: Fetch all posts + getWorkSpaceMode: builder.query({ + 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; \ No newline at end of file diff --git a/src/Redux/Store.tsx b/src/Redux/Store.tsx index 7d17505..167c063 100644 --- a/src/Redux/Store.tsx +++ b/src/Redux/Store.tsx @@ -21,6 +21,8 @@ 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"; export const store = configureStore({ reducer: { @@ -45,6 +47,8 @@ export const store = configureStore({ [profile.reducerPath]: profile.reducer, [countryMaster.reducerPath]: countryMaster.reducer, [departmentMaster.reducerPath]: departmentMaster.reducer, + [workspaceMode.reducerPath]: workspaceMode.reducer, + [jobStatus.reducerPath]: jobStatus.reducer, auth: authReducer, }, middleware: (getDefaultMiddleware) => @@ -69,6 +73,8 @@ export const store = configureStore({ profile.middleware, countryMaster.middleware, departmentMaster.middleware, + workspaceMode.middleware, + jobStatus.middleware, ), });