Added Document Managment feature #388

Merged
pramod.mahajan merged 124 commits from Document_Manag into main 2025-09-10 14:34:35 +00:00
7 changed files with 459 additions and 175 deletions
Showing only changes of commit a52cf0bc39 - Show all commits

View File

@ -1,70 +1,71 @@
import React, { useState } from 'react'; import React from "react";
const ConfirmModal = ({ type, onSubmit, onClose, message, loading ,header, paramData}) => { const ConfirmModal = ({
type,
const TypeofIcon = (type) => { onSubmit,
switch (type) { onClose,
case "delete": message,
return <i className='bx bx-x-circle text-danger ' style={{fontSize:"60px"}} ></i>; loading,
default: header,
return null; paramData,
isOpen = false,
}) => {
if (!isOpen) return null;
const TypeofIcon = () => {
if (type === "delete") {
return (
<i
className="bx bx-x-circle text-danger"
style={{ fontSize: "60px" }}
></i>
);
} }
return null;
}; };
const TypeofModal = (type) => { const modalSize = type === "delete" ? "sm" : "md";
switch (type) {
case "delete":
return "sm";
case "other":
return "md";
default:
return "sm";
}
};
return ( return (
<div className={`modal-dialog modal-${TypeofModal(type)} modal-simple modal-confirm`}> <div
<div className='modal-dialog modal-dialog-centered'> className="modal fade show"
style={{ display: "block", backgroundColor: "rgba(0,0,0,0.5)" }}
role="dialog"
aria-modal="true"
>
<div className={`modal-dialog modal-${modalSize} modal-dialog-top`}>
<div className="modal-content"> <div className="modal-content">
<div className="modal-body py-1 px-2"> <div className="modal-body py-1 px-2">
<div className="row"> <div className="d-flex justify-content-between mb-4">
{header && <strong className="mb-0">{header}</strong>}
<div className="text-start mb-1">
<div className=' d-flex justify-content-between mb-4'>
{header && < strong className='mb-0 font-weight-bold'>{header }</strong>}
<button <button
type="button" type="button"
className="btn-close" className="btn-close"
aria-label="Close" aria-label="Close"
onClick={onClose} onClick={onClose}
/> />
</div> </div>
<div className='row'> <div className="row">
<div className='col-4 col-sm-2'> {TypeofIcon(type)}</div> <div className="col-4 col-sm-2">{TypeofIcon()}</div>
<div className='col-8 col-sm-10 py-sm-2 py-1 text-sm-start'> <div className="col-8 col-sm-10 py-sm-2 py-1 text-sm-start">
<span className='fs-6 text'>{message}</span> <span className="fs-6">{message}</span>
<div className='d-flex justify-content-end mt-4'> <div className="d-flex justify-content-end mt-4">
<button <button
className='btn btn-primary btn-sm' className="btn btn-primary btn-sm"
onClick={()=>onSubmit(paramData)} onClick={() => onSubmit(paramData)}
disabled={loading} disabled={loading}
> >
{loading ? "Please Wait..." : "Yes"} {loading ? "Please Wait..." : "Yes"}
</button> </button>
<button <button
className='btn btn-secondary ms-4 btn-sm' className="btn btn-secondary ms-4 btn-sm"
onClick={onClose} onClick={onClose}
disabled={loading} disabled={loading}
> >
No No
</button> </button>
</div> </div>
</div>
</div>
</div> </div>
</div> </div>
</div> </div>

View File

@ -0,0 +1,223 @@
import React, { useEffect } from "react";
import { useForm, FormProvider } from "react-hook-form";
import { z } from "zod";
import { zodResolver } from "@hookform/resolvers/zod";
import { useCreateDocumentType, useDocumentCategories, useUpdateDocumentType } from "../../hooks/masterHook/useMaster";
import { DOCUMENTS_ENTITIES } from "../../utils/constants";
export const Document_Entity = Object.entries(DOCUMENTS_ENTITIES).map(
([key, value]) => ({ key, value })
);
const DocumentTypeSchema = z.object({
name: z.string().min(1, { message: "Name is required" }),
regexExpression: z.string().optional(),
allowedContentType: z.string().min(1, { message: "Allowed content type is required" }),
maxSizeAllowedInMB: z
.number({ invalid_type_error: "Must be a number" })
.min(1, { message: "Max size must be at least 1MB" }),
isValidationRequired: z.boolean().default(true),
isMandatory: z.boolean().default(true),
documentCategoryId: z.string().min(1, { message: "Document Category is required" }),
});
const ManageDocumentType = ({ data, onClose, documentCategories = [] }) => {
const methods = useForm({
resolver: zodResolver(DocumentTypeSchema),
defaultValues: {
name: "",
regexExpression: "",
allowedContentType: "",
maxSizeAllowedInMB: 25,
isValidationRequired: true,
isMandatory: true,
documentCategoryId: "",
entityTypeId:""
},
});
const {
register,
handleSubmit,
reset,watch,
formState: { errors },
} = methods;
const selectedDocumentEntity = watch("entityTypeId")
const {DocumentCategories,isLoading} = useDocumentCategories(selectedDocumentEntity)
const { mutate: createDocType, isPending: creating } = useCreateDocumentType(() =>
onClose?.()
);
const { mutate: updateDocType, isPending: updating } = useUpdateDocumentType(() =>
onClose?.()
);
const onSubmit = (payload) => {
const { entityTypeId, ...rest } = payload;
if (data) {
updateDocType({ id: data.id, payload: { ...rest, id: data.id } });
} else {
createDocType(rest);
}
};
useEffect(() => {
if (data) {
reset({
name: data.name ?? "",
regexExpression: data.regexExpression ?? "",
allowedContentType: data.allowedContentType ?? "",
maxSizeAllowedInMB: data.maxSizeAllowedInMB ?? 25,
isValidationRequired: data.isValidationRequired ?? true,
isMandatory: data.isMandatory ?? true,
documentCategoryId: data.documentCategory?.id ?? "",
entityTypeId:data.documentCategory?.entityTypeId ?? ""
});
}
}, [data]);
return (
<FormProvider {...methods}>
<form className="row g-2 text-start" onSubmit={handleSubmit(onSubmit)}>
<div className="text-center">
<p className="fw-semibold">
{data ? "Edit Document Type" : "Add Document Type"}
</p>
</div>
{/* Name */}
<div className="col-12">
<label className="form-label">Name</label>
<input
type="text"
{...register("name")}
className={`form-control form-control-sm `}
/>
{errors.name && <a className="text-danger">{errors.name.message}</a>}
</div>
{/* Regex Expression */}
<div className="col-12">
<label className="form-label">Regex Expression</label>
<input
type="text"
{...register("regexExpression")}
className="form-control form-control-sm"
/>
</div>
{/* Allowed Content Type */}
<div className="col-12">
<label className="form-label">Allowed Content Type</label>
<input
type="text"
{...register("allowedContentType")}
className={`form-control form-control form-control-sm`}
/>
{errors.allowedContentType && (
<a className="text-danger">{errors.allowedContentType.message}</a>
)}
</div>
{/* Max Size */}
<div className="col-12">
<label className="form-label">Max Size Allowed (MB)</label>
<input
type="number"
{...register("maxSizeAllowedInMB", { valueAsNumber: true })}
className={`form-control form-control-sm`}
/>
{errors.maxSizeAllowedInMB && (
<a className="text-danger">{errors.maxSizeAllowedInMB.message}</a>
)}
</div>
{/* Validation Required */}
<div className="col-6 form-check">
<input
type="checkbox"
className="form-check-input"
{...register("isValidationRequired")}
/>
<label className="form-check-label">Validation Required</label>
</div>
{/* Mandatory */}
<div className="col-6 form-check">
<input
type="checkbox"
className="form-check-input "
{...register("isMandatory")}
/>
<label className="form-check-label">Mandatory</label>
</div>
<div className="col-12">
<label className="form-label">Document Entity</label>
<select
{...register("entityTypeId")}
className={`form-select form-select-sm`}
>
<option value="">-- Select Category --</option>
{Document_Entity.map((entity) => (
<option key={entity.key} value={entity.value}>
{entity.key}
</option>
))}
</select>
{errors.entityTypeId && (
<a className="text-danger">{errors.entityTypeId.message}</a>
)}
</div>
{/* Category */}
<div className="col-12">
<label className="form-label">Document Category</label>
<select
{...register("documentCategoryId")}
className={`form-select form-select-sm`}
>
{isLoading && <option value="" disabled>Loading....</option> }
<option value="">-- Select Category --</option>
{!isLoading && DocumentCategories?.map((cat) => (
<option key={cat.id} value={cat.id}>
{cat.name}
</option>
))}
</select>
{errors.documentCategoryId && (
<a className="text-danger">{errors.documentCategoryId.message}</a>
)}
</div>
{/* Buttons */}
<div className="col-12 text-center">
<button
type="submit"
className="btn btn-sm btn-primary me-3"
disabled={creating || updating}
>
{creating || updating
? "Please Wait..."
: data
? "Update"
: "Submit"}
</button>
<button
type="button"
className="btn btn-sm btn-secondary"
onClick={onClose}
disabled={creating || updating}
>
Cancel
</button>
</div>
</form>
</FormProvider>
);
};
export default ManageDocumentType;

View File

@ -1,119 +1,68 @@
import React, { useState, useEffect } from "react"; import React from "react";
import CreateRole from "./CreateRole"; import CreateRole from "./CreateRole";
import DeleteMaster from "./DeleteMaster";
import EditRole from "./EditRole"; import EditRole from "./EditRole";
import CreateJobRole from "./CreateJobRole"; import CreateJobRole from "./CreateJobRole";
import EditJobRole from "./EditJobRole"; import EditJobRole from "./EditJobRole";
import CreateActivity from "./CreateActivity"; import CreateActivity from "./CreateActivity";
import EditActivity from "./EditActivity"; import EditActivity from "./EditActivity";
import ConfirmModal from "../common/ConfirmModal";
import { MasterRespository } from "../../repositories/MastersRepository";
import { cacheData, getCachedData } from "../../slices/apiDataManager";
import showToast from "../../services/toastService";
import CreateWorkCategory from "./CreateWorkCategory"; import CreateWorkCategory from "./CreateWorkCategory";
import EditWorkCategory from "./EditWorkCategory"; import EditWorkCategory from "./EditWorkCategory";
import CreateCategory from "./CreateContactCategory"; import CreateCategory from "./CreateContactCategory";
import CreateContactTag from "./CreateContactTag"; import CreateContactTag from "./CreateContactTag";
import EditContactCategory from "./EditContactCategory"; import EditContactCategory from "./EditContactCategory";
import EditContactTag from "./EditContactTag"; import EditContactTag from "./EditContactTag";
import { useDeleteMasterItem } from "../../hooks/masterHook/useMaster";
import ManageExpenseType from "./ManageExpenseType"; import ManageExpenseType from "./ManageExpenseType";
import ManagePaymentMode from "./ManagePaymentMode"; import ManagePaymentMode from "./ManagePaymentMode";
import ManageExpenseStatus from "./ManageExpenseStatus"; import ManageExpenseStatus from "./ManageExpenseStatus";
import ManageDocumentCategory from "./ManageDocumentCategory"; import ManageDocumentCategory from "./ManageDocumentCategory";
import ManageDocumentType from "./ManageDocumentType";
const MasterModal = ({ modaldata, closeModal }) => { const MasterModal = ({ modaldata, closeModal }) => {
const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false); if (!modaldata?.modalType || modaldata.modalType === "delete") {
const { mutate: deleteMasterItem, isPending } = useDeleteMasterItem();
const handleSelectedMasterDeleted = () => {
const { masterType, item, validateFn } = modaldata || {};
if (!masterType || !item?.id) {
showToast("Missing master type or item", "error");
return;
}
deleteMasterItem(
{ masterType, item, validateFn },
{ onSuccess: handleCloseDeleteModal }
);
};
const handleCloseDeleteModal = () => {
setIsDeleteModalOpen(false);
closeModal();
};
useEffect(() => {
if (modaldata?.modalType === "delete") {
setIsDeleteModalOpen(true);
}
}, [modaldata]);
if (!modaldata?.modalType) {
closeModal();
return null; return null;
} }
if (modaldata.modalType === "delete" && isDeleteModalOpen) { const { modalType, item, masterType } = modaldata;
return (
<div
className="modal fade show"
tabIndex="-1"
role="dialog"
style={{ display: "block", backgroundColor: "rgba(0,0,0,0.5)" }}
aria-hidden="false"
>
<ConfirmModal
type="delete"
header={`Delete ${modaldata.masterType}`}
message="Are you sure you want delete?"
onSubmit={handleSelectedMasterDeleted}
onClose={handleCloseDeleteModal}
/>
</div>
);
}
const renderModalContent = () => { const modalComponents = {
const { modalType, item, masterType } = modaldata; "Application Role": (
<CreateRole masmodalType={masterType} onClose={closeModal} />
const modalComponents = { ),
"Application Role": <CreateRole masmodalType={masterType} onClose={closeModal} />, "Edit-Application Role": (
"Edit-Application Role": <EditRole master={modaldata} onClose={closeModal} />, <EditRole master={modaldata} onClose={closeModal} />
"Job Role": <CreateJobRole onClose={closeModal} />, ),
"Edit-Job Role": <EditJobRole data={item} onClose={closeModal} />, "Job Role": <CreateJobRole onClose={closeModal} />,
"Activity": <CreateActivity onClose={closeModal} />, "Edit-Job Role": <EditJobRole data={item} onClose={closeModal} />,
"Edit-Activity": <EditActivity activityData={item} onClose={closeModal} />, "Activity": <CreateActivity onClose={closeModal} />,
"Work Category": <CreateWorkCategory onClose={closeModal} />, "Edit-Activity": <EditActivity activityData={item} onClose={closeModal} />,
"Edit-Work Category": <EditWorkCategory data={item} onClose={closeModal} />, "Work Category": <CreateWorkCategory onClose={closeModal} />,
"Contact Category": <CreateCategory data={item} onClose={closeModal} />, "Edit-Work Category": <EditWorkCategory data={item} onClose={closeModal} />,
"Edit-Contact Category": <EditContactCategory data={item} onClose={closeModal} />, "Contact Category": <CreateCategory data={item} onClose={closeModal} />,
"Contact Tag": <CreateContactTag data={item} onClose={closeModal} />, "Edit-Contact Category": (
"Edit-Contact Tag": <EditContactTag data={item} onClose={closeModal} />, <EditContactCategory data={item} onClose={closeModal} />
"Expense Type":<ManageExpenseType onClose={closeModal} />, ),
"Edit-Expense Type":<ManageExpenseType data={item} onClose={closeModal} />, "Contact Tag": <CreateContactTag data={item} onClose={closeModal} />,
"Payment Mode":<ManagePaymentMode onClose={closeModal}/>, "Edit-Contact Tag": <EditContactTag data={item} onClose={closeModal} />,
"Edit-Payment Mode":<ManagePaymentMode data={item} onClose={closeModal}/>, "Expense Type": <ManageExpenseType onClose={closeModal} />,
"Expense Status":<ManageExpenseStatus onClose={closeModal}/>, "Edit-Expense Type": <ManageExpenseType data={item} onClose={closeModal} />,
"Edit-Expense Status":<ManageExpenseStatus data={item} onClose={closeModal}/>, "Payment Mode": <ManagePaymentMode onClose={closeModal} />,
"Document Category":<ManageDocumentCategory onClose={closeModal}/>, "Edit-Payment Mode": <ManagePaymentMode data={item} onClose={closeModal} />,
"Edit-Document Category":<ManageDocumentCategory data={item} onClose={closeModal}/> "Expense Status": <ManageExpenseStatus onClose={closeModal} />,
}; "Edit-Expense Status": (
<ManageExpenseStatus data={item} onClose={closeModal} />
return modalComponents[modalType] || null; ),
"Document Category": <ManageDocumentCategory onClose={closeModal} />,
"Edit-Document Category": (
<ManageDocumentCategory data={item} onClose={closeModal} />
),
"Document Type": <ManageDocumentType onClose={closeModal} />,
"Edit-Document Type": (
<ManageDocumentType data={item} onClose={closeModal} />
),
}; };
const isLargeModal = ["Application Role", "Edit-Application Role"].includes( return modalComponents[modalType] || null;
modaldata.modalType
);
return (
<>
{renderModalContent()}
</>
);
}; };
export default MasterModal; export default MasterModal;

View File

@ -748,6 +748,7 @@ export const useCreateDocumentCatgory =(onSuccessCallback)=>{
onSuccess: ( data ) => onSuccess: ( data ) =>
{ {
queryClient.invalidateQueries( {queryKey:[ "masterData", "Document Category" ]} ) queryClient.invalidateQueries( {queryKey:[ "masterData", "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)
}, },
@ -770,6 +771,7 @@ export const useUpdateDocumentCategory =(onSuccessCallback)=>{
onSuccess: ( data ) => onSuccess: ( data ) =>
{ {
queryClient.invalidateQueries( {queryKey:[ "masterData", "Document Category" ]} ) queryClient.invalidateQueries( {queryKey:[ "masterData", "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)
}, },
@ -779,6 +781,51 @@ export const useUpdateDocumentCategory =(onSuccessCallback)=>{
} }
}) })
} }
// ------------------------------Document-Type-----------------------------------
export const useCreateDocumentType =(onSuccessCallback)=>{
const queryClient = useQueryClient();
return useMutation( {
mutationFn: async ( payload ) =>
{
const resp = await MasterRespository.createDocumentType(payload);
return resp.data;
},
onSuccess: ( data ) =>
{
queryClient.invalidateQueries( {queryKey:[ "masterData", "Document Type" ]} )
showToast( "Document Type added successfully", "success" );
if(onSuccessCallback) onSuccessCallback(data)
},
onError: ( error ) =>
{
showToast(error.message || "Something went wrong", "error");
}
})
}
export const useUpdateDocumentType =(onSuccessCallback)=>{
const queryClient = useQueryClient();
return useMutation( {
mutationFn: async ( {id,payload} ) =>
{
const resp = await MasterRespository.updateDocumentType(id,payload);
return resp.data;
},
onSuccess: ( data ) =>
{
queryClient.invalidateQueries( {queryKey:[ "masterData", "Document Type" ]} )
showToast( "Document Type Updated successfully", "success" );
if(onSuccessCallback) onSuccessCallback(data)
},
onError: ( error ) =>
{
showToast(error.message || "Something went wrong", "error");
}
})
}
// -Delete Master -------- // -Delete Master --------
export const useDeleteMasterItem = () => { export const useDeleteMasterItem = () => {
const queryClient = useQueryClient(); const queryClient = useQueryClient();

View File

@ -4,35 +4,45 @@ import MasterModal from "../../components/master/MasterModal";
import { mastersList } from "../../data/masters"; import { mastersList } from "../../data/masters";
import { useDispatch, useSelector } from "react-redux"; import { useDispatch, useSelector } from "react-redux";
import { changeMaster } from "../../slices/localVariablesSlice"; import { changeMaster } from "../../slices/localVariablesSlice";
import useMaster, { useMasterMenu } from "../../hooks/masterHook/useMaster" import useMaster, {
useDeleteMasterItem,
useMasterMenu,
} from "../../hooks/masterHook/useMaster";
import MasterTable from "./MasterTable"; import MasterTable from "./MasterTable";
import { getCachedData } from "../../slices/apiDataManager"; import { getCachedData } from "../../slices/apiDataManager";
import { useHasUserPermission } from "../../hooks/useHasUserPermission"; import { useHasUserPermission } from "../../hooks/useHasUserPermission";
import { MANAGE_MASTER } from "../../utils/constants"; import { MANAGE_MASTER } from "../../utils/constants";
import { useQueryClient } from "@tanstack/react-query"; import { useQueryClient } from "@tanstack/react-query";
import GlobalModel from "../../components/common/GlobalModel"; import GlobalModel from "../../components/common/GlobalModel";
import ConfirmModal from "../../components/common/ConfirmModal";
const MasterPage = () => { const MasterPage = () => {
const {data,isLoading,isError,error:menuError} = useMasterMenu() const { data, isLoading, isError, error: menuError } = useMasterMenu();
const [modalConfig, setModalConfig] = useState({ modalType: "", item: null, masterType: null }); const [modalConfig, setModalConfig] = useState(null);
const [searchTerm, setSearchTerm] = useState(''); const [searchTerm, setSearchTerm] = useState("");
const [filteredResults, setFilteredResults] = useState([]); const [filteredResults, setFilteredResults] = useState([]);
const [isCreateModalOpen, setIsCreateModalOpen] = useState(false); const [isCreateModalOpen, setIsCreateModalOpen] = useState(false);
const hasMasterPermission = useHasUserPermission(MANAGE_MASTER); const hasMasterPermission = useHasUserPermission(MANAGE_MASTER);
const dispatch = useDispatch(); const dispatch = useDispatch();
const selectedMaster = useSelector((store) => store.localVariables.selectedMaster); const selectedMaster = useSelector(
(store) => store.localVariables.selectedMaster
);
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const { data: masterData = [], loading, error, RecallApi,isError:isMasterError } = useMaster(); const {
data: masterData = [],
loading,
error,
RecallApi,
isError: isMasterError,
} = useMaster();
const { mutate: deleteMasterItem, isPending } = useDeleteMasterItem();
const openModal = () => setIsCreateModalOpen(true); const openModal = () => setIsCreateModalOpen(true);
const closeModal = () => { const closeModal = () => {
setIsCreateModalOpen(false); setIsCreateModalOpen(false);
setModalConfig(null); setModalConfig(null);
}; };
const handleModalData = (modalType, item, masterType = selectedMaster) => { const handleModalData = (modalType, item, masterType = selectedMaster) => {
@ -46,15 +56,17 @@ const MasterPage = () => {
if (!masterData?.length) return; if (!masterData?.length) return;
const results = masterData.filter((item) => const results = masterData.filter((item) =>
Object.values(item).some( Object.values(item).some((field) =>
(field) => field?.toString().toLowerCase().includes(value) field?.toString().toLowerCase().includes(value)
) )
); );
setFilteredResults(results); setFilteredResults(results);
}; };
const displayData = useMemo(() => { const displayData = useMemo(() => {
if (searchTerm) return filteredResults; if (searchTerm) return filteredResults;
return queryClient.getQueryData(["masterData", selectedMaster]) || masterData; return (
queryClient.getQueryData(["masterData", selectedMaster]) || masterData
);
}, [searchTerm, filteredResults, selectedMaster, masterData]); }, [searchTerm, filteredResults, selectedMaster, masterData]);
const columns = useMemo(() => { const columns = useMemo(() => {
@ -65,9 +77,12 @@ const MasterPage = () => {
})); }));
}, [displayData]); }, [displayData]);
useEffect(() => { useEffect(() => {
if (modalConfig) openModal(); if (modalConfig?.modalType && modalConfig?.modalType !== "delete") {
}, [modalConfig]); openModal();
}
}, [modalConfig]);
useEffect(() => { useEffect(() => {
return () => { return () => {
@ -76,14 +91,44 @@ const MasterPage = () => {
}; };
}, []); }, []);
if(isError || isMasterError) return <div className="d-flex flex-column align-items-center justify-content-center py-5"> if (isError || isMasterError)
<h4 className=" mb-3"><i className="fa-solid fa-triangle-exclamation fs-5" /> Oops, an error occurred</h4> return (
<p className="text-muted">{error?.message || menuError?.message}</p> <div className="d-flex flex-column align-items-center justify-content-center py-5">
</div> <h4 className=" mb-3">
<i className="fa-solid fa-triangle-exclamation fs-5" /> Oops, an error
occurred
</h4>
<p className="text-muted">{error?.message || menuError?.message}</p>
</div>
);
return ( return (
<> <>
{isCreateModalOpen && ( {modalConfig?.modalType === "delete" && (
<GlobalModel isOpen={isCreateModalOpen} closeModal={()=>setIsCreateModalOpen(false)} size={modalConfig.masterType === "Application Role" ? "lg":"md"}> <ConfirmModal
type="delete"
header={`Delete ${modalConfig.masterType}`}
message="Are you sure you want to delete?"
onSubmit={() => {
deleteMasterItem(
{
masterType: modalConfig.masterType,
item: modalConfig.item,
validateFn: modalConfig.validateFn,
},
{ onSuccess: closeModal }
);
}}
onClose={closeModal}
loading={isPending}
isOpen={true}
/>
)}
{isCreateModalOpen && modalConfig?.modalType !== "delete" && (
<GlobalModel
isOpen={isCreateModalOpen}
closeModal={closeModal}
size={modalConfig?.masterType === "Application Role" ? "lg" : "md"}
>
<MasterModal modaldata={modalConfig} closeModal={closeModal} /> <MasterModal modaldata={modalConfig} closeModal={closeModal} />
</GlobalModel> </GlobalModel>
)} )}
@ -112,17 +157,24 @@ const MasterPage = () => {
> >
<label> <label>
<select <select
onChange={(e) => dispatch(changeMaster(e.target.value))} onChange={(e) =>
dispatch(changeMaster(e.target.value))
}
name="DataTables_Table_0_length" name="DataTables_Table_0_length"
aria-controls="DataTables_Table_0" aria-controls="DataTables_Table_0"
className="form-select form-select-sm" className="form-select form-select-sm"
value={selectedMaster} value={selectedMaster}
> >
{isLoading && (<option value={null}>Loading...</option>)} {isLoading && (
{(!isLoading && data) && data?.map((item) => ( <option value={null}>Loading...</option>
)}
<option key={item.id} value={item.name}>{item.name}</option> {!isLoading &&
))} data &&
data?.map((item) => (
<option key={item.id} value={item.name}>
{item.name}
</option>
))}
</select> </select>
</label> </label>
</div> </div>
@ -145,10 +197,13 @@ const MasterPage = () => {
></input> ></input>
</label> </label>
</div> </div>
<div className={`dt-buttons btn-group flex-wrap ${!hasMasterPermission && 'd-none'}`}> <div
className={`dt-buttons btn-group flex-wrap ${
!hasMasterPermission && "d-none"
}`}
>
{" "} {" "}
<div className="input-group"> <div className="input-group">
<button <button
className={`btn btn-sm add-new btn-primary `} className={`btn btn-sm add-new btn-primary `}
tabIndex="0" tabIndex="0"
@ -157,13 +212,17 @@ const MasterPage = () => {
data-bs-toggle="modal" data-bs-toggle="modal"
data-bs-target="#master-modal" data-bs-target="#master-modal"
onClick={() => { onClick={() => {
handleModalData(selectedMaster, "null", selectedMaster) handleModalData(
selectedMaster,
null,
selectedMaster
);
}} }}
> >
<span> <span>
<i className="bx bx-plus-circle me-2"></i> <i className="bx bx-plus-circle me-2"></i>
<span className=" d-sm-inline-block"> <span className=" d-sm-inline-block">
Add {selectedMaster} Add {selectedMaster}
</span> </span>
</span> </span>
</button>{" "} </button>{" "}
@ -173,13 +232,17 @@ const MasterPage = () => {
</div> </div>
</div> </div>
<MasterTable data={displayData} columns={columns} loading={loading} handleModalData={handleModalData} /> <MasterTable
data={displayData}
columns={columns}
loading={loading}
handleModalData={handleModalData}
/>
<div style={{ width: "1%" }}></div> <div style={{ width: "1%" }}></div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</> </>
); );

View File

@ -157,19 +157,17 @@ const MasterTable = ({ data, columns, loading, handleModalData }) => {
data-bs-target="#master-modal" data-bs-target="#master-modal"
className="btn p-0 dropdown-toggle hide-arrow" className="btn p-0 dropdown-toggle hide-arrow"
onClick={() => onClick={() =>
handleModalData(`Edit-${selectedMaster}`, item) handleModalData(`Edit-${selectedMaster}`, item, selectedMaster)
} }
> >
<i className="bx bxs-edit me-2 text-primary"></i> <i className="bx bxs-edit me-2 text-primary"></i>
</button> </button>
<button <button
aria-label="Delete" aria-label="Delete"
type="button" type="button"
className="btn p-0 dropdown-toggle hide-arrow" className="btn p-0 dropdown-toggle hide-arrow"
data-bs-toggle="modal" onClick={() => handleModalData("delete", item, selectedMaster)}
data-bs-target="#master-modal"
onClick={() => handleModalData("delete", item)}
> >
<i className="bx bx-trash me-1 text-danger"></i> <i className="bx bx-trash me-1 text-danger"></i>
</button> </button>

View File

@ -48,6 +48,9 @@ export const MasterRespository = {
api.delete(`/api/Master/payment-mode/delete/${id}`, (isActive = false)), api.delete(`/api/Master/payment-mode/delete/${id}`, (isActive = false)),
"Expense Status": (id, isActive) => "Expense Status": (id, isActive) =>
api.delete(`/api/Master/expenses-status/delete/${id}`, (isActive = false)), api.delete(`/api/Master/expenses-status/delete/${id}`, (isActive = false)),
"Document Type": (id) => api.delete(`/api/Master/document-type/delete/${id}`),
"Document Category": (id) =>
api.delete(`/api/Master/document-category/delete/${id}`),
getWorkCategory: () => api.get(`/api/master/work-categories`), getWorkCategory: () => api.get(`/api/master/work-categories`),
createWorkCategory: (data) => api.post(`/api/master/work-category`, data), createWorkCategory: (data) => api.post(`/api/master/work-category`, data),