Compare commits

...

2 Commits

7 changed files with 648 additions and 393 deletions

View File

@ -17,6 +17,7 @@ import ManageExpenseStatus from "./ManageExpenseStatus";
import ManageDocumentCategory from "./ManageDocumentCategory"; import ManageDocumentCategory from "./ManageDocumentCategory";
import ManageDocumentType from "./ManageDocumentType"; import ManageDocumentType from "./ManageDocumentType";
import ManageServices from "./Services/ManageServices"; import ManageServices from "./Services/ManageServices";
import ServiceGroups from "./Services/ServicesGroups";
const MasterModal = ({ modaldata, closeModal }) => { const MasterModal = ({ modaldata, closeModal }) => {
if (!modaldata?.modalType || modaldata.modalType === "delete") { if (!modaldata?.modalType || modaldata.modalType === "delete") {
@ -67,6 +68,9 @@ const MasterModal = ({ modaldata, closeModal }) => {
"Edit-Services": ( "Edit-Services": (
<ManageServices data={item} onClose={closeModal} /> <ManageServices data={item} onClose={closeModal} />
), ),
"Manage-Services": (
<ServiceGroups service={item} onClose={closeModal}/>
),
}; };
return modalComponents[modalType] || null; return modalComponents[modalType] || null;

View File

@ -0,0 +1,71 @@
import { useForm } from "react-hook-form";
import { useCreateActivityGroup } from "../../../hooks/masterHook/useMaster";
import { zodResolver } from "@hookform/resolvers/zod";
import { ActivityGroupSchema } from "./ServicesSchema";
import Label from "../../common/Label";
const ManageGroup = ({ group = null, close }) => {
const {
register,
handleSubmit,
formState: { errors },
} = useForm({
resolver: zodResolver(ActivityGroupSchema),
defaultValues: { name: "", description: "" },
});
const { mutate: createGroup, isPending } = useCreateActivityGroup();
const onSubmit = (payload) => {
console.log(payload);
// createGroup
};
return (
<form className="row px-2" onSubmit={handleSubmit(onSubmit)}>
<div className="col-12 col-md-12 text-start">
<Label className="form-label" required>
Group Name
</Label>
<input
type="text"
{...register("name")}
className={`form-control form-control-sm ${errors.name ? "is-invalids" : ""}`}
/>
{errors.name && <p className="danger-text m-0">{errors.name.message}</p>}
</div>
<div className="col-12 col-md-12 text-start mb-2">
<Label className="form-label" htmlFor="description" required>
Description
</Label>
<textarea
rows="3"
{...register("description")}
className={`form-control form-control-sm ${errors.description ? "is-invalids" : ""}`}
></textarea>
{errors.description && (
<p className="danger-text m-0">{errors.description.message}</p>
)}
</div>
<div className="col-12 text-end">
<button
className="btn btn-sm btn-label-secondary me-3"
aria-label="Close"
disabled={isPending}
onClick={close}
>
Cancel
</button>
<button
type="submit"
className="btn btn-sm btn-primary"
disabled={isPending}
>
{isPending ? "Please Wait..." : group ? "Update" : "Submit"}
</button>
</div>
</form>
);
};
export default ManageGroup;

View File

@ -0,0 +1,133 @@
import { useState } from "react";
import {
useActivitiesByGroups,
useGroups,
} from "../../../hooks/masterHook/useMaster";
import ManageGroup from "./ManageGroup";
const ServiceGroups = ({ service }) => {
const [openService, setOpenService] = useState(true);
const [activeGroupId, setActiveGroupId] = useState(null); // track selected group
const [isManageGroup,setManageGroup] = useState({isOpen:false,group:true})
const { data: groups, isLoading } = useGroups(service?.id);
const { data: activities, isLoading: actLoading } =
useActivitiesByGroups(activeGroupId);
if (isLoading) return <div>Loading groups...</div>;
return (
<div className="w-100 my-2">
<p className="fs-5 fw-semibold">Manage Service</p>
<div className="accordion" id="accordionExample">
<div className="accordion-item active shadow-none">
{/* Service Header */}
<div className="d-flex justify-content-between text-start accordion-header ga">
<p className="m-0 fw-bold fs-6 ">{service.name}</p>
<span
onClick={() => setOpenService(!openService)}
className="text-end cursor-pointer"
data-bs-toggle="collapse"
data-bs-target="#accordionOne"
aria-expanded={openService}
aria-controls="accordionOne"
>
<i
className={`bx ${
openService ? "bx-chevron-up" : "bx-chevron-down"
}`}
></i>
</span>
</div>
{/* Groups Section */}
<div
id="accordionOne"
className={`accordion-collapse collapse ${
openService ? "show" : ""
}`}
aria-labelledby="headingOne"
data-bs-parent="#accordionExample"
>
<div className="accordion-body text-start m-0 p-0">
<div className="dropdown-divider border"></div>
{groups?.data?.map((group) => {
const isOpen = activeGroupId === group.id;
return (
<div
className="accordion-item shadow-none m-0 py-2 px-2"
key={group.id}
>
<div className="d-flex justify-content-between text-start accordion-header">
<p className="m-0 fw-bold ">{group.name}</p>
<div className="d-flex flex-row gap-3">
<div className="d-flex flex-row gap-2">
<i className="bx bx-plus-circle text-primary cursor-pointer" onClick={()=>setManageGroup({isOpen:true,group:null})}></i>
<i className="bx bx-edit text-secondary cursor-pointer"></i>
<i className="bx bx-trash text-danger cursor-pointer"></i>
</div>
<span
onClick={
() => setActiveGroupId(isOpen ? null : group.id)
}
className="text-end cursor-pointer"
data-bs-toggle="collapse"
data-bs-target={`#accordionGroup${group.id}`}
aria-expanded={isOpen}
aria-controls={`accordionGroup${group.id}`}
>
<i
className={`bx bx-lg ${
isOpen ? "bx-chevron-up" : "bx-chevron-down"
}`}
></i>
</span></div>
</div>
{isManageGroup.isOpen ? <ManageGroup group={ManageGroup.group} close={()=>setManageGroup({isOpen:false,group:null})}/> : (
<div
id={`accordionGroup${group.id}`}
className={`accordion-collapse collapse ${
isOpen ? "show" : ""
}`}
aria-labelledby={group.id}
data-bs-parent="#accordionOne"
>
<div className="accordion-body">
{isOpen && actLoading && <p>Loading activities...</p>}
{isOpen && activities?.data?.length > 0 ? (
<ul class="list-group list-group-flush">
{activities.data.map((activity) => (
<div className="d-flex justify-content-between py-2">
<li className="list-group-item border-0">
{activity.name}
</li>{" "}
<div className="d-flex flex-row gap-2">
<i class="bx bx-sm bx-plus-circle text-primary cursor-pointer"></i>
<i class="bx bx-sm bx-edit text-secondary cursor-pointer"></i>
<i class="bx bx-sm bx-trash text-danger cursor-pointer"></i>
</div>
</div>
))}
</ul>
) : (
isOpen && <p>No activities found</p>
)}
</div>
</div>
) }
</div>
);
})}
</div>
</div>
</div>
</div>
</div>
);
};
export default ServiceGroups;

View File

@ -7,3 +7,11 @@ const schema = z.object({
.min(1, { message: "Description is required" }) .min(1, { message: "Description is required" })
.max(255, { message: "Description cannot exceed 255 characters" }), .max(255, { message: "Description cannot exceed 255 characters" }),
}); });
export const ActivityGroupSchema = z.object({
name: z.string().min(1, { message: "Group Name is required" }),
description: z
.string()
.min(1, { message: "Description is required" })
.max(255, { message: "Description cannot exceed 255 characters" }),
});

View File

@ -1,52 +1,75 @@
import {useState,useEffect, useCallback} from "react" import { useState, useEffect, useCallback } from "react";
import { MasterRespository } from "../../repositories/MastersRepository"; import { MasterRespository } from "../../repositories/MastersRepository";
import { cacheData, getCachedData } from "../../slices/apiDataManager"; import { cacheData, getCachedData } from "../../slices/apiDataManager";
import { useSelector } from "react-redux"; import { useSelector } from "react-redux";
import {useMutation, useQueries, useQuery, useQueryClient} from "@tanstack/react-query"; import {
useMutation,
useQueries,
useQuery,
useQueryClient,
} from "@tanstack/react-query";
import showToast from "../../services/toastService"; import showToast from "../../services/toastService";
export const useServices = () => { export const useServices = () => {
return useQuery({ return useQuery({
queryKey: ["services"], queryKey: ["services"],
queryFn:async()=> await MasterRespository.getMasterServices() queryFn: async () => await MasterRespository.getMasterServices(),
});
};
export const useGroups = (serviceId) => {
return useQuery({
queryFn: ["groups", serviceId],
queryFn: async () => await MasterRespository.getActivityGrops(serviceId),
}) })
} };
export const useActivitiesByGroups = (groupId) => {
return useQuery({
queryFn: ["activties", groupId],
queryFn: async () => await MasterRespository.getActivityGrops(groupId),
})
};
export const useGlobalServices = () => { export const useGlobalServices = () => {
return useQuery({ return useQuery({
queryKey: ["globalServices"], queryKey: ["globalServices"],
queryFn:async()=> await MasterRespository.getGlobalServices() queryFn: async () => await MasterRespository.getGlobalServices(),
}) });
} };
export const useMasterMenu = () => { export const useMasterMenu = () => {
return useQuery({ return useQuery({
queryKey: ["MasterMenu"], queryKey: ["MasterMenu"],
queryFn: async () => { queryFn: async () => {
const resp = await MasterRespository.getMasterMenus(); const resp = await MasterRespository.getMasterMenus();
return resp.data return resp.data;
} },
}) });
} };
export const useActivitiesMaster = () =>
{
const { data:activities=[],isLoading:loading,error} = useQuery( { export const useActivitiesMaster = () => {
const {
data: activities = [],
isLoading: loading,
error,
} = useQuery({
queryKey: ["ActivityMaster"], queryKey: ["ActivityMaster"],
queryFn: async() => queryFn: async () => {
{
const response = await MasterRespository.getActivites(); const response = await MasterRespository.getActivites();
return response.data return response.data;
}, },
onError: (error) => { onError: (error) => {
showToast(error?.response?.data?.message || error.message || "Failed to fetch ActivityMasters", "error"); showToast(
error?.response?.data?.message ||
error.message ||
"Failed to fetch ActivityMasters",
"error"
);
}, },
} ) });
return {activities,loading,error} return { activities, loading, error };
} };
export const useWorkCategoriesMaster = () => { export const useWorkCategoriesMaster = () => {
const { const {
data: categories = [], data: categories = [],
@ -71,22 +94,28 @@ export const useWorkCategoriesMaster = () => {
return { categories, categoryLoading, categoryError }; return { categories, categoryLoading, categoryError };
}; };
export const useContactCategory = () => {
export const useContactCategory = () => const {
{ data: contactCategory = [],
const {data:contactCategory=[],isLoading:loading,error:Error } = useQuery( { isLoading: loading,
error: Error,
} = useQuery({
queryKey: ["Contact Category"], queryKey: ["Contact Category"],
queryFn: async () => queryFn: async () => {
{
let resp = await MasterRespository.getContactCategory(); let resp = await MasterRespository.getContactCategory();
return resp.data return resp.data;
}, },
onError: (error) => { onError: (error) => {
showToast(error?.response?.data?.message || error.message || "Failed to fetch Contact categories", "error"); showToast(
error?.response?.data?.message ||
error.message ||
"Failed to fetch Contact categories",
"error"
);
}, },
} ) });
return { contactCategory,loading,Error} return { contactCategory, loading, Error };
} };
export const useContactTags = () => { export const useContactTags = () => {
const { const {
@ -112,7 +141,6 @@ export const useContactTags = () => {
return { contactTags, loading, error }; return { contactTags, loading, error };
}; };
export const useExpenseType = () => { export const useExpenseType = () => {
const { const {
data: ExpenseTypes = [], data: ExpenseTypes = [],
@ -121,7 +149,7 @@ const {
} = useQuery({ } = useQuery({
queryKey: ["Expense Type"], queryKey: ["Expense Type"],
queryFn: async () => { queryFn: async () => {
const res = await MasterRespository.getExpenseType() const res = await MasterRespository.getExpenseType();
return res.data; return res.data;
}, },
onError: (error) => { onError: (error) => {
@ -135,7 +163,7 @@ const {
}); });
return { ExpenseTypes, loading, error }; return { ExpenseTypes, loading, error };
} };
export const usePaymentMode = () => { export const usePaymentMode = () => {
const { const {
data: PaymentModes = [], data: PaymentModes = [],
@ -144,7 +172,7 @@ const {
} = useQuery({ } = useQuery({
queryKey: ["Payment Mode"], queryKey: ["Payment Mode"],
queryFn: async () => { queryFn: async () => {
const res = await MasterRespository.getPaymentMode() const res = await MasterRespository.getPaymentMode();
return res.data; return res.data;
}, },
onError: (error) => { onError: (error) => {
@ -158,7 +186,7 @@ const {
}); });
return { PaymentModes, loading, error }; return { PaymentModes, loading, error };
} };
export const useExpenseStatus = () => { export const useExpenseStatus = () => {
const { const {
data: ExpenseStatus = [], data: ExpenseStatus = [],
@ -167,7 +195,7 @@ const {
} = useQuery({ } = useQuery({
queryKey: ["Expense Status"], queryKey: ["Expense Status"],
queryFn: async () => { queryFn: async () => {
const res = await MasterRespository.getExpenseStatus() const res = await MasterRespository.getExpenseStatus();
return res.data; return res.data;
}, },
onError: (error) => { onError: (error) => {
@ -181,17 +209,17 @@ const {
}); });
return { ExpenseStatus, loading, error }; return { ExpenseStatus, loading, error };
} };
export const useDocumentTypes = (category) => { export const useDocumentTypes = (category) => {
const { const {
data: DocumentTypes = [], data: DocumentTypes = [],
error, error,
isError, isError,
isLoading isLoading,
} = useQuery({ } = useQuery({
queryKey: ["Document Type", category], queryKey: ["Document Type", category],
queryFn: async () => { queryFn: async () => {
const res = await MasterRespository.getDocumentTypes(category) const res = await MasterRespository.getDocumentTypes(category);
return res.data; return res.data;
}, },
enabled: !!category, enabled: !!category,
@ -206,17 +234,17 @@ const {
}); });
return { DocumentTypes, isError, isLoading, error }; return { DocumentTypes, isError, isLoading, error };
} };
export const useDocumentCategories = (EntityType) => { export const useDocumentCategories = (EntityType) => {
const { const {
data: DocumentCategories = [], data: DocumentCategories = [],
error, error,
isError, isError,
isLoading isLoading,
} = useQuery({ } = useQuery({
queryKey: ["Document Category", EntityType], queryKey: ["Document Category", EntityType],
queryFn: async () => { queryFn: async () => {
const res = await MasterRespository.getDocumentCategories(EntityType) const res = await MasterRespository.getDocumentCategories(EntityType);
return res.data; return res.data;
}, },
enabled: !!EntityType, enabled: !!EntityType,
@ -231,13 +259,13 @@ const {
}); });
return { DocumentCategories, isError, isLoading, error }; return { DocumentCategories, isError, isLoading, error };
} };
export const useOrganizationType = () => { export const useOrganizationType = () => {
return useQuery({ return useQuery({
queryKey: ["orgType"], queryKey: ["orgType"],
queryFn:async()=>await MasterRespository.getOrganizationType() queryFn: async () => await MasterRespository.getOrganizationType(),
}) });
} };
// ===Application Masters Query================================================= // ===Application Masters Query=================================================
const fetchMasterData = async (masterType) => { const fetchMasterData = async (masterType) => {
@ -293,8 +321,13 @@ const fetchMasterData = async (masterType) => {
}; };
const useMaster = () => { const useMaster = () => {
const selectedMaster = useSelector((store) => store.localVariables.selectedMaster); const selectedMaster = useSelector(
const queryFn = useCallback(() => fetchMasterData(selectedMaster), [selectedMaster]); (store) => store.localVariables.selectedMaster
);
const queryFn = useCallback(
() => fetchMasterData(selectedMaster),
[selectedMaster]
);
const { const {
data = [], data = [],
isLoading, isLoading,
@ -306,7 +339,12 @@ const useMaster = () => {
staleTime: 1000 * 60 * 10, staleTime: 1000 * 60 * 10,
refetchOnWindowFocus: false, refetchOnWindowFocus: false,
onError: (error) => { onError: (error) => {
showToast(error?.response?.data?.message || error.message || `Failed to fetch ${selectedMaster} Maseter`, "error"); showToast(
error?.response?.data?.message ||
error.message ||
`Failed to fetch ${selectedMaster} Maseter`,
"error"
);
}, },
}); });
@ -365,41 +403,36 @@ export const useCreateJobRole = (onSuccessCallback) => {
// Application Role------------------------------------------- // Application Role-------------------------------------------
export const useCreateApplicationRole = (onSuccessCallback) => export const useCreateApplicationRole = (onSuccessCallback) => {
{
const queryClient = useQueryClient(); const queryClient = useQueryClient();
return useMutation({ return useMutation({
mutationFn: async ( payload ) => mutationFn: async (payload) => {
{
const resp = await MasterRespository.createRole(payload); const resp = await MasterRespository.createRole(payload);
return resp.data; return resp.data;
}, },
onSuccess: ( data ) => onSuccess: (data) => {
{ queryClient.invalidateQueries({
queryClient.invalidateQueries( {queryKey:[ "masterData", "Application Role" ]} ) queryKey: ["masterData", "Application Role"],
});
showToast("Application Role added successfully", "success"); showToast("Application Role added successfully", "success");
if(onSuccessCallback) onSuccessCallback(data) if (onSuccessCallback) onSuccessCallback(data);
}, },
onError: ( error ) => onError: (error) => {
{
showToast(error.message || "Something went wrong", "error"); showToast(error.message || "Something went wrong", "error");
} },
}) });
} };
export const useUpdateApplicationRole = (onSuccessCallback) => export const useUpdateApplicationRole = (onSuccessCallback) => {
{
const queryClient = useQueryClient(); const queryClient = useQueryClient();
return useMutation({ return useMutation({
mutationFn: async ( {id, payload} ) => mutationFn: async ({ id, payload }) => {
{
const response = await MasterRespository.updateRoles(id, payload); const response = await MasterRespository.updateRoles(id, payload);
return response.data; return response.data;
}, },
onSuccess: (data, variables) => { onSuccess: (data, variables) => {
queryClient.invalidateQueries({ queryClient.invalidateQueries({
queryKey: ["masterData", "Application Role"], queryKey: ["masterData", "Application Role"],
}); });
@ -411,44 +444,37 @@ export const useUpdateApplicationRole = (onSuccessCallback) =>
showToast(error.message || "Something went wrong", "error"); showToast(error.message || "Something went wrong", "error");
}, },
}); });
} };
// Activity------------------------------ // Activity------------------------------
export const useCreateActivity = (onSuccessCallback) => export const useCreateActivity = (onSuccessCallback) => {
{
const queryClient = useQueryClient(); const queryClient = useQueryClient();
return useMutation({ return useMutation({
mutationFn: async ( payload ) => mutationFn: async (payload) => {
{
const resp = await MasterRespository.createActivity(payload); const resp = await MasterRespository.createActivity(payload);
return resp.data; return resp.data;
}, },
onSuccess: ( data ) => onSuccess: (data) => {
{ queryClient.invalidateQueries({ queryKey: ["masterData", "Activity"] });
queryClient.invalidateQueries( {queryKey:[ "masterData", "Activity" ]} )
showToast("Activity added successfully", "success"); showToast("Activity added successfully", "success");
if(onSuccessCallback) onSuccessCallback(data) if (onSuccessCallback) onSuccessCallback(data);
}, },
onError: ( error ) => onError: (error) => {
{
showToast(error.message || "Something went wrong", "error"); showToast(error.message || "Something went wrong", "error");
} },
}) });
} };
export const useUpdateActivity = (onSuccessCallback) => export const useUpdateActivity = (onSuccessCallback) => {
{
const queryClient = useQueryClient(); const queryClient = useQueryClient();
return useMutation({ return useMutation({
mutationFn: async ( {id, payload} ) => mutationFn: async ({ id, payload }) => {
{
const response = await MasterRespository.updateActivity(id, payload); const response = await MasterRespository.updateActivity(id, payload);
return response.data; return response.data;
}, },
onSuccess: (data, variables) => { onSuccess: (data, variables) => {
queryClient.invalidateQueries({ queryClient.invalidateQueries({
queryKey: ["masterData", "Activity"], queryKey: ["masterData", "Activity"],
}); });
@ -460,45 +486,39 @@ export const useUpdateActivity = (onSuccessCallback) =>
showToast(error.message || "Something went wrong", "error"); showToast(error.message || "Something went wrong", "error");
}, },
}); });
} };
//-----Create work Category------------------------------- //-----Create work Category-------------------------------
export const useCreateWorkCategory = (onSuccessCallback) => export const useCreateWorkCategory = (onSuccessCallback) => {
{
const queryClient = useQueryClient(); const queryClient = useQueryClient();
return useMutation({ return useMutation({
mutationFn: async ( payload ) => mutationFn: async (payload) => {
{
const resp = await MasterRespository.createWorkCategory(payload); const resp = await MasterRespository.createWorkCategory(payload);
return resp.data; return resp.data;
}, },
onSuccess: ( data ) => onSuccess: (data) => {
{ queryClient.invalidateQueries({
queryClient.invalidateQueries({queryKey: [ "masterData", "Work Category" ]} ) queryKey: ["masterData", "Work Category"],
});
showToast("Work Category added successfully", "success"); showToast("Work Category added successfully", "success");
if(onSuccessCallback) onSuccessCallback(data) if (onSuccessCallback) onSuccessCallback(data);
}, },
onError: ( error ) => onError: (error) => {
{
showToast(error.message || "Something went wrong", "error"); showToast(error.message || "Something went wrong", "error");
} },
}) });
} };
export const useUpdateWorkCategory = (onSuccessCallback) => export const useUpdateWorkCategory = (onSuccessCallback) => {
{
const queryClient = useQueryClient(); const queryClient = useQueryClient();
return useMutation({ return useMutation({
mutationFn: async ( {id, payload} ) => mutationFn: async ({ id, payload }) => {
{
const response = await MasterRespository.updateWorkCategory(id, payload); const response = await MasterRespository.updateWorkCategory(id, payload);
return response.data; return response.data;
}, },
onSuccess: (data, variables) => { onSuccess: (data, variables) => {
queryClient.invalidateQueries({ queryClient.invalidateQueries({
queryKey: ["masterData", "Work Category"], queryKey: ["masterData", "Work Category"],
}); });
@ -510,47 +530,43 @@ export const useUpdateWorkCategory = (onSuccessCallback) =>
showToast(error.message || "Something went wrong", "error"); showToast(error.message || "Something went wrong", "error");
}, },
}); });
} };
//-- Contact Category--------------------------- //-- Contact Category---------------------------
export const useCreateContactCategory = (onSuccessCallback) => {
export const useCreateContactCategory = (onSuccessCallback) =>
{
const queryClient = useQueryClient(); const queryClient = useQueryClient();
return useMutation({ return useMutation({
mutationFn: async ( payload ) => mutationFn: async (payload) => {
{
const resp = await MasterRespository.createContactCategory(payload); const resp = await MasterRespository.createContactCategory(payload);
return resp.data; return resp.data;
}, },
onSuccess: ( data ) => onSuccess: (data) => {
{ queryClient.invalidateQueries({
queryClient.invalidateQueries( {queryKey:[ "masterData", "Contact Category" ]} ) queryKey: ["masterData", "Contact Category"],
});
showToast("Contact Category added successfully", "success"); showToast("Contact Category added successfully", "success");
if(onSuccessCallback) onSuccessCallback(data) if (onSuccessCallback) onSuccessCallback(data);
}, },
onError: ( error ) => onError: (error) => {
{
showToast(error.message || "Something went wrong", "error"); showToast(error.message || "Something went wrong", "error");
} },
}) });
} };
export const useUpdateContactCategory = (onSuccessCallback) => {
export const useUpdateContactCategory = (onSuccessCallback) =>
{
const queryClient = useQueryClient(); const queryClient = useQueryClient();
return useMutation({ return useMutation({
mutationFn: async ( {id, payload} ) => mutationFn: async ({ id, payload }) => {
{ const response = await MasterRespository.updateContactCategory(
const response = await MasterRespository.updateContactCategory(id,payload); id,
payload
);
return response.data; return response.data;
}, },
onSuccess: (data, variables) => { onSuccess: (data, variables) => {
queryClient.invalidateQueries({ queryClient.invalidateQueries({
queryKey: ["masterData", "Contact Category"], queryKey: ["masterData", "Contact Category"],
}); });
@ -562,47 +578,41 @@ export const useUpdateContactCategory = (onSuccessCallback) =>
showToast(error.message || "Something went wrong", "error"); showToast(error.message || "Something went wrong", "error");
}, },
}); });
} };
// ---------Contact Tag------------------- // ---------Contact Tag-------------------
export const useCreateContactTag = (onSuccessCallback) => export const useCreateContactTag = (onSuccessCallback) => {
{
const queryClient = useQueryClient(); const queryClient = useQueryClient();
return useMutation({ return useMutation({
mutationFn: async ( payload ) => mutationFn: async (payload) => {
{
const resp = await MasterRespository.createContactTag(payload); const resp = await MasterRespository.createContactTag(payload);
return resp.data; return resp.data;
}, },
onSuccess: ( data ) => onSuccess: (data) => {
{ queryClient.invalidateQueries({
queryClient.invalidateQueries( {queryKey:[ "masterData", "Contact Tag" ]} ) queryKey: ["masterData", "Contact Tag"],
});
showToast("Contact Tag added successfully", "success"); showToast("Contact Tag added successfully", "success");
if(onSuccessCallback) onSuccessCallback(data) if (onSuccessCallback) onSuccessCallback(data);
}, },
onError: ( error ) => onError: (error) => {
{
showToast(error.message || "Something went wrong", "error"); showToast(error.message || "Something went wrong", "error");
} },
}) });
} };
export const useUpdateContactTag = (onSuccessCallback) => {
export const useUpdateContactTag = (onSuccessCallback) =>
{
const queryClient = useQueryClient(); const queryClient = useQueryClient();
return useMutation({ return useMutation({
mutationFn: async ( {id, payload} ) => mutationFn: async ({ id, payload }) => {
{ debugger;
debugger
const response = await MasterRespository.updateContactTag(id, payload); const response = await MasterRespository.updateContactTag(id, payload);
return response.data; return response.data;
}, },
onSuccess: (data, variables) => { onSuccess: (data, variables) => {
queryClient.invalidateQueries({ queryClient.invalidateQueries({
queryKey: ["masterData", "Contact Tag"], queryKey: ["masterData", "Contact Tag"],
}); });
@ -614,42 +624,38 @@ export const useUpdateContactTag = (onSuccessCallback) =>
showToast(error.message || "Something went wrong", "error"); showToast(error.message || "Something went wrong", "error");
}, },
}); });
} };
// ----------------------Expense Type------------------ // ----------------------Expense Type------------------
export const useCreateExpenseType = (onSuccessCallback) => { export const useCreateExpenseType = (onSuccessCallback) => {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
return useMutation({ return useMutation({
mutationFn: async ( payload ) => mutationFn: async (payload) => {
{
const resp = await MasterRespository.createExpenseType(payload); const resp = await MasterRespository.createExpenseType(payload);
return resp.data; return resp.data;
}, },
onSuccess: ( data ) => onSuccess: (data) => {
{ queryClient.invalidateQueries({
queryClient.invalidateQueries( {queryKey:[ "masterData", "Expense Type" ]} ) queryKey: ["masterData", "Expense Type"],
});
showToast("Expense Type added successfully", "success"); showToast("Expense Type added successfully", "success");
if(onSuccessCallback) onSuccessCallback(data) if (onSuccessCallback) onSuccessCallback(data);
}, },
onError: ( error ) => onError: (error) => {
{
showToast(error.message || "Something went wrong", "error"); showToast(error.message || "Something went wrong", "error");
} },
}) });
} };
export const useUpdateExpenseType = (onSuccessCallback) => export const useUpdateExpenseType = (onSuccessCallback) => {
{
const queryClient = useQueryClient(); const queryClient = useQueryClient();
return useMutation({ return useMutation({
mutationFn: async ( {id, payload} ) => mutationFn: async ({ id, payload }) => {
{
const response = await MasterRespository.updateExpenseType(id, payload); const response = await MasterRespository.updateExpenseType(id, payload);
return response.data; return response.data;
}, },
onSuccess: (data, variables) => { onSuccess: (data, variables) => {
queryClient.invalidateQueries({ queryClient.invalidateQueries({
queryKey: ["masterData", "Expense Type"], queryKey: ["masterData", "Expense Type"],
}); });
@ -661,7 +667,7 @@ export const useUpdateExpenseType = (onSuccessCallback) =>
showToast(error.message || "Something went wrong", "error"); showToast(error.message || "Something went wrong", "error");
}, },
}); });
} };
// -----------------Payment Mode ------------- // -----------------Payment Mode -------------
@ -669,46 +675,43 @@ export const useCreatePaymentMode = (onSuccessCallback)=>{
const queryClient = useQueryClient(); const queryClient = useQueryClient();
return useMutation({ return useMutation({
mutationFn: async ( payload ) => mutationFn: async (payload) => {
{
const resp = await MasterRespository.createPaymentMode(payload); const resp = await MasterRespository.createPaymentMode(payload);
return resp.data; return resp.data;
}, },
onSuccess: ( data ) => onSuccess: (data) => {
{ queryClient.invalidateQueries({
queryClient.invalidateQueries( {queryKey:[ "masterData", "Payment Mode" ]} ) queryKey: ["masterData", "Payment Mode"],
});
showToast("Payment Mode added successfully", "success"); showToast("Payment Mode added successfully", "success");
if(onSuccessCallback) onSuccessCallback(data) if (onSuccessCallback) onSuccessCallback(data);
}, },
onError: ( error ) => onError: (error) => {
{
showToast(error.message || "Something went wrong", "error"); showToast(error.message || "Something went wrong", "error");
} },
}) });
} };
export const useUpdatePaymentMode = (onSuccessCallback) => { export const useUpdatePaymentMode = (onSuccessCallback) => {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
return useMutation({ return useMutation({
mutationFn: async ( {id,payload} ) => mutationFn: async ({ id, payload }) => {
{
const resp = await MasterRespository.updatePaymentMode(id, payload); const resp = await MasterRespository.updatePaymentMode(id, payload);
return resp.data; return resp.data;
}, },
onSuccess: ( data ) => onSuccess: (data) => {
{ queryClient.invalidateQueries({
queryClient.invalidateQueries( {queryKey:[ "masterData", "Payment Mode" ]} ) queryKey: ["masterData", "Payment Mode"],
});
showToast("Payment Mode Updated successfully", "success"); showToast("Payment Mode Updated successfully", "success");
if(onSuccessCallback) onSuccessCallback(data) if (onSuccessCallback) onSuccessCallback(data);
}, },
onError: ( error ) => onError: (error) => {
{
showToast(error.message || "Something went wrong", "error"); showToast(error.message || "Something went wrong", "error");
} },
}) });
} };
// Services------------------------------- // Services-------------------------------
@ -759,7 +762,6 @@ export const useCreateService = (onSuccessCallback) => {
}); });
}; };
export const useUpdateService = (onSuccessCallback) => { export const useUpdateService = (onSuccessCallback) => {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
@ -783,154 +785,169 @@ export const useUpdateService = (onSuccessCallback) => {
}); });
}; };
export const useCreateActivityGroup =()=>{
const queryClient = useQueryClient();
return useMutation({
mutationFn: async (payload) => {
const response = await MasterRespository.createActivityGroup(payload)
return response;
},
onSuccess: (data, variables) => {
queryClient.invalidateQueries({
queryKey: ["masterData", "Services"],
});
showToast(data.message || "Activity Group created successfully.", "success");
if (onSuccessCallback) onSuccessCallback(data);
},
onError: (error) => {
showToast(error?.message || "Something went wrong", "error");
},
});
}
// -------------------Expense Status---------------------------------- // -------------------Expense Status----------------------------------
export const useCreateExpenseStatus = (onSuccessCallback) => { export const useCreateExpenseStatus = (onSuccessCallback) => {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
return useMutation({ return useMutation({
mutationFn: async ( payload ) => mutationFn: async (payload) => {
{
const resp = await MasterRespository.createExpenseStatus(payload); const resp = await MasterRespository.createExpenseStatus(payload);
return resp.data; return resp.data;
}, },
onSuccess: ( data ) => onSuccess: (data) => {
{ queryClient.invalidateQueries({
queryClient.invalidateQueries( {queryKey:[ "masterData", "Expense Status" ]} ) queryKey: ["masterData", "Expense Status"],
});
showToast("Expense Status added successfully", "success"); showToast("Expense Status added successfully", "success");
if(onSuccessCallback) onSuccessCallback(data) if (onSuccessCallback) onSuccessCallback(data);
}, },
onError: ( error ) => onError: (error) => {
{
showToast(error.message || "Something went wrong", "error"); showToast(error.message || "Something went wrong", "error");
} },
}) });
} };
export const useUpdateExpenseStatus = (onSuccessCallback) => { export const useUpdateExpenseStatus = (onSuccessCallback) => {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
return useMutation({ return useMutation({
mutationFn: async ( {id,payload} ) => mutationFn: async ({ id, payload }) => {
{
const resp = await MasterRespository.updateExepnseStatus(id, payload); const resp = await MasterRespository.updateExepnseStatus(id, payload);
return resp.data; return resp.data;
}, },
onSuccess: ( data ) => onSuccess: (data) => {
{ queryClient.invalidateQueries({
queryClient.invalidateQueries( {queryKey:[ "masterData", "Expense Status" ]} ) queryKey: ["masterData", "Expense Status"],
});
showToast("Expense Status Updated successfully", "success"); showToast("Expense Status Updated successfully", "success");
if(onSuccessCallback) onSuccessCallback(data) if (onSuccessCallback) onSuccessCallback(data);
}, },
onError: ( error ) => onError: (error) => {
{
showToast(error.message || "Something went wrong", "error"); showToast(error.message || "Something went wrong", "error");
} },
}) });
} };
// --------------------Document-Category-------------------------------- // --------------------Document-Category--------------------------------
export const useCreateDocumentCatgory = (onSuccessCallback) => { export const useCreateDocumentCatgory = (onSuccessCallback) => {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
return useMutation({ return useMutation({
mutationFn: async ( payload ) => mutationFn: async (payload) => {
{
const resp = await MasterRespository.createDocumenyCategory(payload); const resp = await MasterRespository.createDocumenyCategory(payload);
return resp.data; return resp.data;
}, },
onSuccess: ( data ) => onSuccess: (data) => {
{ queryClient.invalidateQueries({
queryClient.invalidateQueries( {queryKey:[ "masterData", "Document Category" ]} ) queryKey: ["masterData", "Document Category"],
queryClient.invalidateQueries( {queryKey:[ "Document Category" ]} ) });
queryClient.invalidateQueries({ queryKey: ["Document Category"] });
showToast("Document Category added successfully", "success"); showToast("Document Category added successfully", "success");
if(onSuccessCallback) onSuccessCallback(data) if (onSuccessCallback) onSuccessCallback(data);
}, },
onError: ( error ) => onError: (error) => {
{
showToast(error.message || "Something went wrong", "error"); showToast(error.message || "Something went wrong", "error");
} },
}) });
} };
export const useUpdateDocumentCategory = (onSuccessCallback) => { export const useUpdateDocumentCategory = (onSuccessCallback) => {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
return useMutation({ return useMutation({
mutationFn: async ( {id,payload} ) => mutationFn: async ({ id, payload }) => {
{
const resp = await MasterRespository.updateDocumentCategory(id, payload); const resp = await MasterRespository.updateDocumentCategory(id, payload);
return resp.data; return resp.data;
}, },
onSuccess: ( data ) => onSuccess: (data) => {
{ queryClient.invalidateQueries({
queryClient.invalidateQueries( {queryKey:[ "masterData", "Document Category" ]} ) queryKey: ["masterData", "Document Category"],
queryClient.invalidateQueries( {queryKey:[ "Document Category" ]} ) });
queryClient.invalidateQueries({ queryKey: ["Document Category"] });
showToast("Document Category Updated successfully", "success"); showToast("Document Category Updated successfully", "success");
if(onSuccessCallback) onSuccessCallback(data) if (onSuccessCallback) onSuccessCallback(data);
}, },
onError: ( error ) => onError: (error) => {
{
showToast(error.message || "Something went wrong", "error"); showToast(error.message || "Something went wrong", "error");
} },
}) });
} };
// ------------------------------Document-Type----------------------------------- // ------------------------------Document-Type-----------------------------------
export const useCreateDocumentType = (onSuccessCallback) => { export const useCreateDocumentType = (onSuccessCallback) => {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
return useMutation({ return useMutation({
mutationFn: async ( payload ) => mutationFn: async (payload) => {
{
const resp = await MasterRespository.createDocumentType(payload); const resp = await MasterRespository.createDocumentType(payload);
return resp.data; return resp.data;
}, },
onSuccess: ( data ) => onSuccess: (data) => {
{ queryClient.invalidateQueries({
queryClient.invalidateQueries( {queryKey:[ "masterData", "Document Type" ]} ) queryKey: ["masterData", "Document Type"],
});
showToast("Document Type added successfully", "success"); showToast("Document Type added successfully", "success");
if(onSuccessCallback) onSuccessCallback(data) if (onSuccessCallback) onSuccessCallback(data);
}, },
onError: ( error ) => onError: (error) => {
{
showToast(error.message || "Something went wrong", "error"); showToast(error.message || "Something went wrong", "error");
} },
}) });
} };
export const useUpdateDocumentType = (onSuccessCallback) => { export const useUpdateDocumentType = (onSuccessCallback) => {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
return useMutation({ return useMutation({
mutationFn: async ( {id,payload} ) => mutationFn: async ({ id, payload }) => {
{
const resp = await MasterRespository.updateDocumentType(id, payload); const resp = await MasterRespository.updateDocumentType(id, payload);
return resp.data; return resp.data;
}, },
onSuccess: ( data ) => onSuccess: (data) => {
{ queryClient.invalidateQueries({
queryClient.invalidateQueries( {queryKey:[ "masterData", "Document Type" ]} ) queryKey: ["masterData", "Document Type"],
});
showToast("Document Type Updated successfully", "success"); showToast("Document Type Updated successfully", "success");
if(onSuccessCallback) onSuccessCallback(data) if (onSuccessCallback) onSuccessCallback(data);
}, },
onError: ( error ) => onError: (error) => {
{
showToast(error.message || "Something went wrong", "error"); showToast(error.message || "Something went wrong", "error");
} },
}) });
} };
// -Delete Master -------- // -Delete Master --------
export const useDeleteMasterItem = () => { export const useDeleteMasterItem = () => {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
return useMutation({ return useMutation({
mutationFn: async ( {masterType, item} ) => mutationFn: async ({ masterType, item }) => {
{
const deleteFn = MasterRespository[masterType]; const deleteFn = MasterRespository[masterType];
if (!deleteFn) { if (!deleteFn) {
throw new Error(`No delete strategy defined for master type: ${masterType}`); throw new Error(
`No delete strategy defined for master type: ${masterType}`
);
} }
await deleteFn(item.id); await deleteFn(item.id);
@ -945,7 +962,9 @@ export const useDeleteMasterItem = () => {
onError: (error) => { onError: (error) => {
const message = const message =
error?.response?.data?.message || error?.message || "Error occurred during deletion"; error?.response?.data?.message ||
error?.message ||
"Error occurred during deletion";
showToast(message, "error"); showToast(message, "error");
}, },
}); });

View File

@ -158,6 +158,21 @@ const MasterTable = ({ data, columns, loading, handleModalData }) => {
</> </>
) : ( ) : (
<> <>
{selectedMaster === "Services" && (
<button
aria-label="View"
type="button"
className="btn p-0 dropdown-toggle hide-arrow"
onClick={() =>
handleModalData(`Manage-${selectedMaster}`, item, selectedMaster)
}
data-bs-toggle="modal"
data-bs-target="#servicesActivityTreeModal"
>
<i className="bx bx-show me-2 text-primary"></i>
</button>
)}
<button <button
aria-label="Modify" aria-label="Modify"
type="button" type="button"

View File

@ -118,6 +118,11 @@ export const MasterRespository = {
getGlobalServices:()=>api.get("/api/Master/global-service/list"), getGlobalServices:()=>api.get("/api/Master/global-service/list"),
getMasterServices:()=>api.get("/api/Master/service/list"), getMasterServices:()=>api.get("/api/Master/service/list"),
getActivityGrops:(serviceId)=>api.get(`/api/Master/activity-group/list?serviceId=${serviceId}`),
createActivityGroup:(data)=>api.post(`/api/Master/activity-group/create`),
getActivitesByGroup: (serviceId) => api.get(`api/master/activities/activityGroupId=${activityGroupId}`),
getOrganizationType:()=>api.get('/api/Master/organization-type/list') getOrganizationType:()=>api.get('/api/Master/organization-type/list')
}; };