allow to delete document category and type and edit type
This commit is contained in:
parent
e007c0e8da
commit
a52cf0bc39
@ -1,70 +1,71 @@
|
||||
import React, { useState } from 'react';
|
||||
import React from "react";
|
||||
|
||||
const ConfirmModal = ({ type, onSubmit, onClose, message, loading ,header, paramData}) => {
|
||||
|
||||
const TypeofIcon = (type) => {
|
||||
switch (type) {
|
||||
case "delete":
|
||||
return <i className='bx bx-x-circle text-danger ' style={{fontSize:"60px"}} ></i>;
|
||||
default:
|
||||
return null;
|
||||
const ConfirmModal = ({
|
||||
type,
|
||||
onSubmit,
|
||||
onClose,
|
||||
message,
|
||||
loading,
|
||||
header,
|
||||
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) => {
|
||||
switch (type) {
|
||||
case "delete":
|
||||
return "sm";
|
||||
case "other":
|
||||
return "md";
|
||||
default:
|
||||
return "sm";
|
||||
}
|
||||
};
|
||||
const modalSize = type === "delete" ? "sm" : "md";
|
||||
|
||||
return (
|
||||
<div className={`modal-dialog modal-${TypeofModal(type)} modal-simple modal-confirm`}>
|
||||
<div className='modal-dialog modal-dialog-centered'>
|
||||
<div
|
||||
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-body py-1 px-2">
|
||||
<div className="row">
|
||||
|
||||
<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>}
|
||||
<div className="d-flex justify-content-between mb-4">
|
||||
{header && <strong className="mb-0">{header}</strong>}
|
||||
<button
|
||||
type="button"
|
||||
className="btn-close"
|
||||
aria-label="Close"
|
||||
onClick={onClose}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className='row'>
|
||||
<div className='col-4 col-sm-2'> {TypeofIcon(type)}</div>
|
||||
<div className='col-8 col-sm-10 py-sm-2 py-1 text-sm-start'>
|
||||
<span className='fs-6 text'>{message}</span>
|
||||
<div className='d-flex justify-content-end mt-4'>
|
||||
</div>
|
||||
|
||||
<div className="row">
|
||||
<div className="col-4 col-sm-2">{TypeofIcon()}</div>
|
||||
<div className="col-8 col-sm-10 py-sm-2 py-1 text-sm-start">
|
||||
<span className="fs-6">{message}</span>
|
||||
<div className="d-flex justify-content-end mt-4">
|
||||
<button
|
||||
className='btn btn-primary btn-sm'
|
||||
onClick={()=>onSubmit(paramData)}
|
||||
disabled={loading}
|
||||
className="btn btn-primary btn-sm"
|
||||
onClick={() => onSubmit(paramData)}
|
||||
disabled={loading}
|
||||
>
|
||||
{loading ? "Please Wait..." : "Yes"}
|
||||
</button>
|
||||
<button
|
||||
className='btn btn-secondary ms-4 btn-sm'
|
||||
className="btn btn-secondary ms-4 btn-sm"
|
||||
onClick={onClose}
|
||||
disabled={loading}
|
||||
disabled={loading}
|
||||
>
|
||||
No
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
223
src/components/master/ManageDocumentType.jsx
Normal file
223
src/components/master/ManageDocumentType.jsx
Normal 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;
|
@ -1,119 +1,68 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import React from "react";
|
||||
import CreateRole from "./CreateRole";
|
||||
import DeleteMaster from "./DeleteMaster";
|
||||
import EditRole from "./EditRole";
|
||||
import CreateJobRole from "./CreateJobRole";
|
||||
import EditJobRole from "./EditJobRole";
|
||||
import CreateActivity from "./CreateActivity";
|
||||
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 EditWorkCategory from "./EditWorkCategory";
|
||||
import CreateCategory from "./CreateContactCategory";
|
||||
import CreateContactTag from "./CreateContactTag";
|
||||
import EditContactCategory from "./EditContactCategory";
|
||||
import EditContactTag from "./EditContactTag";
|
||||
import { useDeleteMasterItem } from "../../hooks/masterHook/useMaster";
|
||||
import ManageExpenseType from "./ManageExpenseType";
|
||||
import ManagePaymentMode from "./ManagePaymentMode";
|
||||
import ManageExpenseStatus from "./ManageExpenseStatus";
|
||||
import ManageDocumentCategory from "./ManageDocumentCategory";
|
||||
|
||||
import ManageDocumentType from "./ManageDocumentType";
|
||||
|
||||
const MasterModal = ({ modaldata, closeModal }) => {
|
||||
const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false);
|
||||
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();
|
||||
if (!modaldata?.modalType || modaldata.modalType === "delete") {
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
if (modaldata.modalType === "delete" && isDeleteModalOpen) {
|
||||
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 { modalType, item, masterType } = modaldata;
|
||||
|
||||
const renderModalContent = () => {
|
||||
const { modalType, item, masterType } = modaldata;
|
||||
|
||||
const modalComponents = {
|
||||
"Application Role": <CreateRole masmodalType={masterType} onClose={closeModal} />,
|
||||
"Edit-Application Role": <EditRole master={modaldata} onClose={closeModal} />,
|
||||
"Job Role": <CreateJobRole onClose={closeModal} />,
|
||||
"Edit-Job Role": <EditJobRole data={item} onClose={closeModal} />,
|
||||
"Activity": <CreateActivity onClose={closeModal} />,
|
||||
"Edit-Activity": <EditActivity activityData={item} onClose={closeModal} />,
|
||||
"Work Category": <CreateWorkCategory onClose={closeModal} />,
|
||||
"Edit-Work Category": <EditWorkCategory data={item} onClose={closeModal} />,
|
||||
"Contact Category": <CreateCategory data={item} onClose={closeModal} />,
|
||||
"Edit-Contact Category": <EditContactCategory data={item} onClose={closeModal} />,
|
||||
"Contact Tag": <CreateContactTag data={item} onClose={closeModal} />,
|
||||
"Edit-Contact Tag": <EditContactTag data={item} onClose={closeModal} />,
|
||||
"Expense Type":<ManageExpenseType onClose={closeModal} />,
|
||||
"Edit-Expense Type":<ManageExpenseType data={item} onClose={closeModal} />,
|
||||
"Payment Mode":<ManagePaymentMode onClose={closeModal}/>,
|
||||
"Edit-Payment Mode":<ManagePaymentMode data={item} onClose={closeModal}/>,
|
||||
"Expense Status":<ManageExpenseStatus onClose={closeModal}/>,
|
||||
"Edit-Expense Status":<ManageExpenseStatus data={item} onClose={closeModal}/>,
|
||||
"Document Category":<ManageDocumentCategory onClose={closeModal}/>,
|
||||
"Edit-Document Category":<ManageDocumentCategory data={item} onClose={closeModal}/>
|
||||
};
|
||||
|
||||
return modalComponents[modalType] || null;
|
||||
const modalComponents = {
|
||||
"Application Role": (
|
||||
<CreateRole masmodalType={masterType} onClose={closeModal} />
|
||||
),
|
||||
"Edit-Application Role": (
|
||||
<EditRole master={modaldata} onClose={closeModal} />
|
||||
),
|
||||
"Job Role": <CreateJobRole onClose={closeModal} />,
|
||||
"Edit-Job Role": <EditJobRole data={item} onClose={closeModal} />,
|
||||
"Activity": <CreateActivity onClose={closeModal} />,
|
||||
"Edit-Activity": <EditActivity activityData={item} onClose={closeModal} />,
|
||||
"Work Category": <CreateWorkCategory onClose={closeModal} />,
|
||||
"Edit-Work Category": <EditWorkCategory data={item} onClose={closeModal} />,
|
||||
"Contact Category": <CreateCategory data={item} onClose={closeModal} />,
|
||||
"Edit-Contact Category": (
|
||||
<EditContactCategory data={item} onClose={closeModal} />
|
||||
),
|
||||
"Contact Tag": <CreateContactTag data={item} onClose={closeModal} />,
|
||||
"Edit-Contact Tag": <EditContactTag data={item} onClose={closeModal} />,
|
||||
"Expense Type": <ManageExpenseType onClose={closeModal} />,
|
||||
"Edit-Expense Type": <ManageExpenseType data={item} onClose={closeModal} />,
|
||||
"Payment Mode": <ManagePaymentMode onClose={closeModal} />,
|
||||
"Edit-Payment Mode": <ManagePaymentMode data={item} onClose={closeModal} />,
|
||||
"Expense Status": <ManageExpenseStatus onClose={closeModal} />,
|
||||
"Edit-Expense Status": (
|
||||
<ManageExpenseStatus data={item} onClose={closeModal} />
|
||||
),
|
||||
"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(
|
||||
modaldata.modalType
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
{renderModalContent()}
|
||||
</>
|
||||
);
|
||||
return modalComponents[modalType] || null;
|
||||
};
|
||||
|
||||
export default MasterModal;
|
||||
|
@ -748,6 +748,7 @@ export const useCreateDocumentCatgory =(onSuccessCallback)=>{
|
||||
onSuccess: ( data ) =>
|
||||
{
|
||||
queryClient.invalidateQueries( {queryKey:[ "masterData", "Document Category" ]} )
|
||||
queryClient.invalidateQueries( {queryKey:[ "Document Category" ]} )
|
||||
showToast( "Document Category added successfully", "success" );
|
||||
if(onSuccessCallback) onSuccessCallback(data)
|
||||
},
|
||||
@ -770,6 +771,7 @@ export const useUpdateDocumentCategory =(onSuccessCallback)=>{
|
||||
onSuccess: ( data ) =>
|
||||
{
|
||||
queryClient.invalidateQueries( {queryKey:[ "masterData", "Document Category" ]} )
|
||||
queryClient.invalidateQueries( {queryKey:[ "Document Category" ]} )
|
||||
showToast( "Document Category Updated successfully", "success" );
|
||||
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 --------
|
||||
export const useDeleteMasterItem = () => {
|
||||
const queryClient = useQueryClient();
|
||||
|
@ -4,35 +4,45 @@ import MasterModal from "../../components/master/MasterModal";
|
||||
import { mastersList } from "../../data/masters";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
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 { getCachedData } from "../../slices/apiDataManager";
|
||||
import { useHasUserPermission } from "../../hooks/useHasUserPermission";
|
||||
import { MANAGE_MASTER } from "../../utils/constants";
|
||||
import { useQueryClient } from "@tanstack/react-query";
|
||||
import GlobalModel from "../../components/common/GlobalModel";
|
||||
|
||||
import ConfirmModal from "../../components/common/ConfirmModal";
|
||||
|
||||
const MasterPage = () => {
|
||||
const {data,isLoading,isError,error:menuError} = useMasterMenu()
|
||||
const [modalConfig, setModalConfig] = useState({ modalType: "", item: null, masterType: null });
|
||||
const [searchTerm, setSearchTerm] = useState('');
|
||||
const { data, isLoading, isError, error: menuError } = useMasterMenu();
|
||||
const [modalConfig, setModalConfig] = useState(null);
|
||||
const [searchTerm, setSearchTerm] = useState("");
|
||||
const [filteredResults, setFilteredResults] = useState([]);
|
||||
const [isCreateModalOpen, setIsCreateModalOpen] = useState(false);
|
||||
|
||||
const hasMasterPermission = useHasUserPermission(MANAGE_MASTER);
|
||||
const dispatch = useDispatch();
|
||||
const selectedMaster = useSelector((store) => store.localVariables.selectedMaster);
|
||||
const selectedMaster = useSelector(
|
||||
(store) => store.localVariables.selectedMaster
|
||||
);
|
||||
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 closeModal = () => {
|
||||
setIsCreateModalOpen(false);
|
||||
setModalConfig(null);
|
||||
|
||||
};
|
||||
|
||||
const handleModalData = (modalType, item, masterType = selectedMaster) => {
|
||||
@ -46,15 +56,17 @@ const MasterPage = () => {
|
||||
if (!masterData?.length) return;
|
||||
|
||||
const results = masterData.filter((item) =>
|
||||
Object.values(item).some(
|
||||
(field) => field?.toString().toLowerCase().includes(value)
|
||||
Object.values(item).some((field) =>
|
||||
field?.toString().toLowerCase().includes(value)
|
||||
)
|
||||
);
|
||||
setFilteredResults(results);
|
||||
};
|
||||
const displayData = useMemo(() => {
|
||||
if (searchTerm) return filteredResults;
|
||||
return queryClient.getQueryData(["masterData", selectedMaster]) || masterData;
|
||||
return (
|
||||
queryClient.getQueryData(["masterData", selectedMaster]) || masterData
|
||||
);
|
||||
}, [searchTerm, filteredResults, selectedMaster, masterData]);
|
||||
|
||||
const columns = useMemo(() => {
|
||||
@ -65,9 +77,12 @@ const MasterPage = () => {
|
||||
}));
|
||||
}, [displayData]);
|
||||
|
||||
useEffect(() => {
|
||||
if (modalConfig) openModal();
|
||||
}, [modalConfig]);
|
||||
useEffect(() => {
|
||||
if (modalConfig?.modalType && modalConfig?.modalType !== "delete") {
|
||||
openModal();
|
||||
}
|
||||
}, [modalConfig]);
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
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">
|
||||
<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>
|
||||
if (isError || isMasterError)
|
||||
return (
|
||||
<div className="d-flex flex-column align-items-center justify-content-center py-5">
|
||||
<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 (
|
||||
<>
|
||||
{isCreateModalOpen && (
|
||||
<GlobalModel isOpen={isCreateModalOpen} closeModal={()=>setIsCreateModalOpen(false)} size={modalConfig.masterType === "Application Role" ? "lg":"md"}>
|
||||
{modalConfig?.modalType === "delete" && (
|
||||
<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} />
|
||||
</GlobalModel>
|
||||
)}
|
||||
@ -112,17 +157,24 @@ const MasterPage = () => {
|
||||
>
|
||||
<label>
|
||||
<select
|
||||
onChange={(e) => dispatch(changeMaster(e.target.value))}
|
||||
onChange={(e) =>
|
||||
dispatch(changeMaster(e.target.value))
|
||||
}
|
||||
name="DataTables_Table_0_length"
|
||||
aria-controls="DataTables_Table_0"
|
||||
className="form-select form-select-sm"
|
||||
value={selectedMaster}
|
||||
>
|
||||
{isLoading && (<option value={null}>Loading...</option>)}
|
||||
{(!isLoading && data) && data?.map((item) => (
|
||||
|
||||
<option key={item.id} value={item.name}>{item.name}</option>
|
||||
))}
|
||||
{isLoading && (
|
||||
<option value={null}>Loading...</option>
|
||||
)}
|
||||
{!isLoading &&
|
||||
data &&
|
||||
data?.map((item) => (
|
||||
<option key={item.id} value={item.name}>
|
||||
{item.name}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</label>
|
||||
</div>
|
||||
@ -145,10 +197,13 @@ const MasterPage = () => {
|
||||
></input>
|
||||
</label>
|
||||
</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">
|
||||
|
||||
<button
|
||||
className={`btn btn-sm add-new btn-primary `}
|
||||
tabIndex="0"
|
||||
@ -157,13 +212,17 @@ const MasterPage = () => {
|
||||
data-bs-toggle="modal"
|
||||
data-bs-target="#master-modal"
|
||||
onClick={() => {
|
||||
handleModalData(selectedMaster, "null", selectedMaster)
|
||||
handleModalData(
|
||||
selectedMaster,
|
||||
null,
|
||||
selectedMaster
|
||||
);
|
||||
}}
|
||||
>
|
||||
<span>
|
||||
<i className="bx bx-plus-circle me-2"></i>
|
||||
<span className=" d-sm-inline-block">
|
||||
Add {selectedMaster}
|
||||
Add {selectedMaster}
|
||||
</span>
|
||||
</span>
|
||||
</button>{" "}
|
||||
@ -173,13 +232,17 @@ const MasterPage = () => {
|
||||
</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>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
@ -157,19 +157,17 @@ const MasterTable = ({ data, columns, loading, handleModalData }) => {
|
||||
data-bs-target="#master-modal"
|
||||
className="btn p-0 dropdown-toggle hide-arrow"
|
||||
onClick={() =>
|
||||
handleModalData(`Edit-${selectedMaster}`, item)
|
||||
handleModalData(`Edit-${selectedMaster}`, item, selectedMaster)
|
||||
}
|
||||
>
|
||||
<i className="bx bxs-edit me-2 text-primary"></i>
|
||||
</button>
|
||||
|
||||
<button
|
||||
aria-label="Delete"
|
||||
type="button"
|
||||
className="btn p-0 dropdown-toggle hide-arrow"
|
||||
data-bs-toggle="modal"
|
||||
data-bs-target="#master-modal"
|
||||
onClick={() => handleModalData("delete", item)}
|
||||
aria-label="Delete"
|
||||
type="button"
|
||||
className="btn p-0 dropdown-toggle hide-arrow"
|
||||
onClick={() => handleModalData("delete", item, selectedMaster)}
|
||||
>
|
||||
<i className="bx bx-trash me-1 text-danger"></i>
|
||||
</button>
|
||||
|
@ -48,6 +48,9 @@ export const MasterRespository = {
|
||||
api.delete(`/api/Master/payment-mode/delete/${id}`, (isActive = false)),
|
||||
"Expense Status": (id, isActive) =>
|
||||
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`),
|
||||
createWorkCategory: (data) => api.post(`/api/master/work-category`, data),
|
||||
|
Loading…
x
Reference in New Issue
Block a user