Refactor_Expenses #321
							
								
								
									
										165
									
								
								src/components/master/ManageExpenseStatus.jsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										165
									
								
								src/components/master/ManageExpenseStatus.jsx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,165 @@ | |||||||
|  | import React, { useEffect } from "react"; | ||||||
|  | import { | ||||||
|  |   useForm, | ||||||
|  |   FormProvider, | ||||||
|  | } from "react-hook-form"; | ||||||
|  | import { z } from "zod"; | ||||||
|  | import { zodResolver } from "@hookform/resolvers/zod"; | ||||||
|  | import SelectMultiple from "../common/SelectMultiple"; | ||||||
|  | import { useFeatures } from "../../hooks/useMasterRole"; | ||||||
|  | import { EXPENSE_MANAGEMENT } from "../../utils/constants"; | ||||||
|  | import { useCreateExpenseStatus, useUpdateExpenseStatus } from "../../hooks/masterHook/useMaster"; | ||||||
|  | import { displayName } from "react-quill"; | ||||||
|  | import { AppColorconfig } from "../../utils/appUtils"; | ||||||
|  | 
 | ||||||
|  | const ExpenseStatusSchema = z.object({ | ||||||
|  |   name: z.string().min(1, { message: "Name is required" }), | ||||||
|  |   displayName: z.string().min(1, { message: "Display Name is required" }), | ||||||
|  |   description: z.string().min(1, { message: "Description is required" }), | ||||||
|  |   permissionIds: z.array(z.string()).min(1, { | ||||||
|  |     message: "At least one permission is required", | ||||||
|  |   }), | ||||||
|  |   color: z | ||||||
|  |     .string() | ||||||
|  |     .regex(/^#([0-9A-F]{3}){1,2}$/i, { message: "Invalid hex color" }), | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | const ManageExpenseStatus = ({data, onClose }) => { | ||||||
|  |   const methods = useForm({ | ||||||
|  |     resolver: zodResolver(ExpenseStatusSchema), | ||||||
|  |     defaultValues: { | ||||||
|  |       name: "", | ||||||
|  |       displayName: "", | ||||||
|  |       description: "", | ||||||
|  |       permissionIds: [], | ||||||
|  |       color: AppColorconfig.colors.primary, | ||||||
|  |     }, | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|  |   const { | ||||||
|  |     register, | ||||||
|  |     handleSubmit, | ||||||
|  |     reset, | ||||||
|  |     formState: { errors }, | ||||||
|  |   } = methods; | ||||||
|  | 
 | ||||||
|  |   const { masterFeatures, loading } = useFeatures(); | ||||||
|  | 
 | ||||||
|  |   const ExpenseFeature = masterFeatures?.find( | ||||||
|  |     (appfeature) => appfeature.id === EXPENSE_MANAGEMENT | ||||||
|  |   ); | ||||||
|  |   const {mutate:CreateExpenseStatus,isPending:isPending} = useCreateExpenseStatus(()=>onClose?.()) | ||||||
|  |   const {mutate:UpdateExpenseStatus,isPending:Updating} = useUpdateExpenseStatus(()=>onClose?.()); | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |   const onSubmit = (payload) => { | ||||||
|  |   if(data){ | ||||||
|  |         UpdateExpenseStatus({id:data.id,payload:{...payload,id:data.id}}) | ||||||
|  |   }else{ | ||||||
|  |      CreateExpenseStatus(payload) | ||||||
|  |   } | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |   useEffect(()=>{ | ||||||
|  |     if(data){ | ||||||
|  |      reset({ | ||||||
|  |         name:data.name ?? "", | ||||||
|  |         displayName:data.displayName ?? "", | ||||||
|  |         description:data.description ?? "", | ||||||
|  |         permissionIds:data.permissionIds ?? [], | ||||||
|  |         color:data.color ?? AppColorconfig.colors.primary | ||||||
|  |       }) | ||||||
|  |     } | ||||||
|  |   },[data]) | ||||||
|  |   return ( | ||||||
|  |     <FormProvider {...methods}> | ||||||
|  |       {loading ? ( | ||||||
|  |         <div>Loading...</div> | ||||||
|  |       ) : ( | ||||||
|  |         <form className="row g-2" onSubmit={handleSubmit(onSubmit)}> | ||||||
|  |           <div className="col-12"> | ||||||
|  |             <label className="form-label">Expense Status Name</label> | ||||||
|  |             <input | ||||||
|  |               type="text" | ||||||
|  |               {...register("name")} | ||||||
|  |               className={`form-control ${errors.name ? "is-invalid" : ""}`} | ||||||
|  |             /> | ||||||
|  |             {errors.name && <p className="text-danger">{errors.name.message}</p>} | ||||||
|  |           </div> | ||||||
|  | 
 | ||||||
|  |           <div className="col-12"> | ||||||
|  |             <label className="form-label">Status Display Name</label> | ||||||
|  |             <input | ||||||
|  |               type="text" | ||||||
|  |               {...register("displayName")} | ||||||
|  |               className={`form-control ${errors.displayName ? "is-invalid" : ""}`} | ||||||
|  |             /> | ||||||
|  |             {errors.displayName && ( | ||||||
|  |               <p className="text-danger">{errors.displayName.message}</p> | ||||||
|  |             )} | ||||||
|  |           </div> | ||||||
|  | 
 | ||||||
|  |           <div className="col-12"> | ||||||
|  |             <SelectMultiple | ||||||
|  |               name="permissionIds" | ||||||
|  |               label="Select Permissions" | ||||||
|  |               options={ExpenseFeature?.featurePermissions || []} | ||||||
|  |               labelKey="name" | ||||||
|  |               valueKey="id" | ||||||
|  |               IsLoading={loading} | ||||||
|  |             /> | ||||||
|  |             {errors.permissionIds && ( | ||||||
|  |               <p className="text-danger">{errors.permissionIds.message}</p> | ||||||
|  |             )} | ||||||
|  |           </div> | ||||||
|  | 
 | ||||||
|  |           <div className="col-12"> | ||||||
|  |             <label className="form-label">Select Color</label> | ||||||
|  |             <input | ||||||
|  |               type="color" | ||||||
|  |               className={`form-control form-control ${errors.color ? "is-invalid" : ""}`} | ||||||
|  |               {...register("color")} | ||||||
|  |             /> | ||||||
|  |             {errors.color && ( | ||||||
|  |               <p className="text-danger">{errors.color.message}</p> | ||||||
|  |             )} | ||||||
|  |           </div> | ||||||
|  | 
 | ||||||
|  |           <div className="col-12"> | ||||||
|  |             <label className="form-label">Description</label> | ||||||
|  |             <textarea | ||||||
|  |               rows="3" | ||||||
|  |               {...register("description")} | ||||||
|  |               className={`form-control ${errors.description ? "is-invalid" : ""}`} | ||||||
|  |             /> | ||||||
|  |             {errors.description && ( | ||||||
|  |               <p className="text-danger">{errors.description.message}</p> | ||||||
|  |             )} | ||||||
|  |           </div> | ||||||
|  | 
 | ||||||
|  |           <div className="col-12 text-center"> | ||||||
|  |             <button | ||||||
|  |               type="submit" | ||||||
|  |               className="btn btn-sm btn-primary me-3" | ||||||
|  |               disabled={isPending || Updating} | ||||||
|  |             > | ||||||
|  |               {isPending || Updating ? "Please Wait..." : Updating ? "Update" : "Submit"} | ||||||
|  |             </button> | ||||||
|  |             <button | ||||||
|  |               type="button" | ||||||
|  |               className="btn btn-sm btn-secondary" | ||||||
|  |               onClick={onClose} | ||||||
|  |               disabled={isPending || Updating} | ||||||
|  |             > | ||||||
|  |               Cancel | ||||||
|  |             </button> | ||||||
|  |           </div> | ||||||
|  |         </form> | ||||||
|  |       )} | ||||||
|  |     </FormProvider> | ||||||
|  |   ); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | export default ManageExpenseStatus; | ||||||
| @ -19,6 +19,7 @@ import EditContactTag from "./EditContactTag"; | |||||||
| import { useDeleteMasterItem } from "../../hooks/masterHook/useMaster"; | 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"; | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| const MasterModal = ({ modaldata, closeModal }) => { | const MasterModal = ({ modaldata, closeModal }) => { | ||||||
| @ -93,7 +94,9 @@ const MasterModal = ({ modaldata, closeModal }) => { | |||||||
|       "Expense Type":<ManageExpenseType  onClose={closeModal} />, |       "Expense Type":<ManageExpenseType  onClose={closeModal} />, | ||||||
|       "Edit-Expense Type":<ManageExpenseType data={item} onClose={closeModal} />, |       "Edit-Expense Type":<ManageExpenseType data={item} onClose={closeModal} />, | ||||||
|       "Payment Mode":<ManagePaymentMode onClose={closeModal}/>, |       "Payment Mode":<ManagePaymentMode onClose={closeModal}/>, | ||||||
|       "Edit-Payment Mode":<ManagePaymentMode data={item} onClose={closeModal}/> |       "Edit-Payment Mode":<ManagePaymentMode data={item} onClose={closeModal}/>, | ||||||
|  |       "Expense Status":<ManageExpenseStatus onClose={closeModal}/>, | ||||||
|  |       "Edit-Expense Status":<ManageExpenseStatus data={item} onClose={closeModal}/> | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     return modalComponents[modalType] || null; |     return modalComponents[modalType] || null; | ||||||
|  | |||||||
| @ -626,7 +626,49 @@ export const useUpdatePaymentMode = (onSuccessCallback)=>{ | |||||||
|     } |     } | ||||||
|   }) |   }) | ||||||
| } | } | ||||||
|  | // -------------------Expense Status----------------------------------
 | ||||||
|  | export const useCreateExpenseStatus =(onSuccessCallback)=>{ | ||||||
|  |       const queryClient = useQueryClient(); | ||||||
| 
 | 
 | ||||||
|  |   return useMutation( { | ||||||
|  |     mutationFn: async ( payload ) => | ||||||
|  |     { | ||||||
|  |       const resp = await MasterRespository.createExpenseStatus(payload); | ||||||
|  |       return resp.data; | ||||||
|  |     }, | ||||||
|  |     onSuccess: ( data ) => | ||||||
|  |     { | ||||||
|  |       queryClient.invalidateQueries( {queryKey:[ "masterData", "Expense Status" ]} ) | ||||||
|  |       showToast( "Expense Status added successfully", "success" ); | ||||||
|  |       if(onSuccessCallback) onSuccessCallback(data) | ||||||
|  |     }, | ||||||
|  |     onError: ( error ) => | ||||||
|  |     { | ||||||
|  |      showToast(error.message || "Something went wrong", "error"); | ||||||
|  |     } | ||||||
|  |   }) | ||||||
|  | } | ||||||
|  | export const useUpdateExpenseStatus = (onSuccessCallback)=>{ | ||||||
|  |     const queryClient = useQueryClient(); | ||||||
|  | 
 | ||||||
|  |   return useMutation( { | ||||||
|  |     mutationFn: async ( {id,payload} ) => | ||||||
|  |     { | ||||||
|  |       const resp = await MasterRespository.updateExepnseStatus(id,payload); | ||||||
|  |       return resp.data; | ||||||
|  |     }, | ||||||
|  |     onSuccess: ( data ) => | ||||||
|  |     { | ||||||
|  |       queryClient.invalidateQueries( {queryKey:[ "masterData", "Expense Status" ]} ) | ||||||
|  |       showToast( "Expense Status 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(); | ||||||
|  | |||||||
| @ -19,7 +19,8 @@ const MasterTable = ({ data, columns, loading, handleModalData }) => { | |||||||
|     "isActive", |     "isActive", | ||||||
|     "noOfPersonsRequired", |     "noOfPersonsRequired", | ||||||
|     "color", |     "color", | ||||||
|     "displayName" |     "displayName", | ||||||
|  |     "permissionIds" | ||||||
|   ]; |   ]; | ||||||
| 
 | 
 | ||||||
|   const safeData = Array.isArray(data) ? data : []; |   const safeData = Array.isArray(data) ? data : []; | ||||||
|  | |||||||
| @ -42,8 +42,10 @@ export const MasterRespository = { | |||||||
|   "Contact Tag": (id) => api.delete(`/api/master/contact-tag/${id}`), |   "Contact Tag": (id) => api.delete(`/api/master/contact-tag/${id}`), | ||||||
|   "Expense Type": (id, isActive) => |   "Expense Type": (id, isActive) => | ||||||
|     api.delete(`/api/Master/expenses-type/delete/${id}`, (isActive = false)), |     api.delete(`/api/Master/expenses-type/delete/${id}`, (isActive = false)), | ||||||
|   "Payment Mode": (id,isActive) => |   "Payment Mode": (id, isActive) => | ||||||
|     api.delete(`/api/Master/payment-mode/delete/${id}`, (isActive = false)), |     api.delete(`/api/Master/payment-mode/delete/${id}`, (isActive = false)), | ||||||
|  |   "Expense Status": (id, isActive) => | ||||||
|  |     api.delete(`/api/Master/expenses-status/delete/${id}`, (isActive = false)), | ||||||
| 
 | 
 | ||||||
|   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), | ||||||
| @ -74,4 +76,7 @@ export const MasterRespository = { | |||||||
|     api.put(`/api/Master/payment-mode/edit/${id}`, data), |     api.put(`/api/Master/payment-mode/edit/${id}`, data), | ||||||
| 
 | 
 | ||||||
|   getExpenseStatus: () => api.get("/api/Master/expenses-status"), |   getExpenseStatus: () => api.get("/api/Master/expenses-status"), | ||||||
|  |   createExpenseStatus: (data) => api.post("/api/Master/expenses-status", data), | ||||||
|  |   updateExepnseStatus: (id, data) => | ||||||
|  |     api.put(`/api/Master/expenses-status/edit/${id}`, data), | ||||||
| }; | }; | ||||||
|  | |||||||
| @ -56,5 +56,11 @@ export const PROCESS_EXPENSE = "ea5a1529-4ee8-4828-80ea-0e23c9d4dd11" | |||||||
| 
 | 
 | ||||||
| export const EXPENSE_MANAGE = "ea5a1529-4ee8-4828-80ea-0e23c9d4dd11" | export const EXPENSE_MANAGE = "ea5a1529-4ee8-4828-80ea-0e23c9d4dd11" | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
|  | // -------------------Application Role------------------------------ | ||||||
|  | 
 | ||||||
|  | // 1 - Expense Manage  | ||||||
|  | export const EXPENSE_MANAGEMENT = "a4e25142-449b-4334-a6e5-22f70e4732d7" | ||||||
|  | 
 | ||||||
| export const BASE_URL = process.env.VITE_BASE_URL; | export const BASE_URL = process.env.VITE_BASE_URL; | ||||||
| // export const BASE_URL = "https://api.marcoaiot.com"; | // export const BASE_URL = "https://api.marcoaiot.com"; | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user