Compare commits
4 Commits
main
...
Kartik_Enh
| Author | SHA1 | Date | |
|---|---|---|---|
| b4b7173726 | |||
| aff9a14af1 | |||
| 76abfb5fd3 | |||
| 20b8d9ae01 |
73
src/components/InventoryManagement/AddProductModal.jsx
Normal file
73
src/components/InventoryManagement/AddProductModal.jsx
Normal file
@ -0,0 +1,73 @@
|
||||
import React, { useState } from "react";
|
||||
import GlobalModel from "../../components/common/GlobalModel";
|
||||
import Stepper from "./Stepper";
|
||||
import SupplierInfoStep from "./SupplierInfoStep";
|
||||
import BankStep from "./BankStep";
|
||||
import AddressStep from "./AddressStep";
|
||||
|
||||
const AddProductModal = ({ isOpen, onClose }) => {
|
||||
const steps = [
|
||||
{ key: "supplierInfo", label: "Supplier Info" },
|
||||
{ key: "bank", label: "Bank" },
|
||||
{ key: "address", label: "Address" },
|
||||
];
|
||||
|
||||
const [activeStepIndex, setActiveStepIndex] = useState(0);
|
||||
const activeStepKey = steps[activeStepIndex].key;
|
||||
|
||||
if (!isOpen) return null;
|
||||
|
||||
const handleNext = () => {
|
||||
if (activeStepIndex < steps.length - 1) setActiveStepIndex(activeStepIndex + 1);
|
||||
else handleSubmit();
|
||||
};
|
||||
|
||||
const handleBack = () => {
|
||||
if (activeStepIndex > 0) setActiveStepIndex(activeStepIndex - 1);
|
||||
};
|
||||
|
||||
const handleSubmit = () => {
|
||||
console.log("Form submitted");
|
||||
onClose();
|
||||
};
|
||||
|
||||
return (
|
||||
<GlobalModel isOpen size="xl" closeModal={onClose}>
|
||||
<div className="p-4">
|
||||
<h5 className="mb-4">Add New Supplier</h5>
|
||||
|
||||
<Stepper steps={steps} activeStep={activeStepIndex} />
|
||||
|
||||
<form onSubmit={(e) => e.preventDefault()}>
|
||||
{activeStepKey === "supplierInfo" && <SupplierInfoStep />}
|
||||
{activeStepKey === "bank" && <BankStep />}
|
||||
{activeStepKey === "address" && <AddressStep />}
|
||||
|
||||
<div className="d-flex justify-content-between mt-5 border-top pt-3">
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-label-secondary btn-sm"
|
||||
onClick={activeStepIndex > 0 ? handleBack : onClose}
|
||||
>
|
||||
{activeStepIndex > 0 ? "← Back" : "Cancel"}
|
||||
</button>
|
||||
|
||||
<div>
|
||||
{activeStepIndex < steps.length - 1 ? (
|
||||
<button type="button" className="btn btn-primary btn-sm" onClick={handleNext}>
|
||||
Next →
|
||||
</button>
|
||||
) : (
|
||||
<button type="button" className="btn btn-primary btn-sm" onClick={handleSubmit}>
|
||||
Submit
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</GlobalModel>
|
||||
);
|
||||
};
|
||||
|
||||
export default AddProductModal;
|
||||
71
src/components/InventoryManagement/AddressStep.jsx
Normal file
71
src/components/InventoryManagement/AddressStep.jsx
Normal file
@ -0,0 +1,71 @@
|
||||
import React from "react";
|
||||
import Label from "../common/Label";
|
||||
|
||||
const AddressStep = () => {
|
||||
return (
|
||||
<div className="text-start">
|
||||
<h6 className="fw-bold text-primary mb-3">Address Details</h6>
|
||||
<div className="row g-3">
|
||||
<div className="col-md-6">
|
||||
<Label required>Address Type</Label>
|
||||
<select className="form-select form-select-sm">
|
||||
<option value="">Select Type</option>
|
||||
<option>Billing</option>
|
||||
<option>Shipping</option>
|
||||
</select>
|
||||
</div>
|
||||
<div className="col-md-6">
|
||||
<Label required>Street</Label>
|
||||
<input type="text" className="form-control form-select-sm" placeholder="Enter street" />
|
||||
</div>
|
||||
<div className="col-md-6">
|
||||
<Label required>City</Label>
|
||||
<input type="text" className="form-control form-select-sm" placeholder="Enter city" />
|
||||
</div>
|
||||
<div className="col-md-6">
|
||||
<Label required>Postal Code</Label>
|
||||
<input type="text" className="form-control form-select-sm" placeholder="Enter postal code" />
|
||||
</div>
|
||||
<div className="col-md-6">
|
||||
<Label required>Country</Label>
|
||||
<input type="text" className="form-control form-select-sm" placeholder="Enter country" />
|
||||
</div>
|
||||
<div className="col-md-6">
|
||||
<Label required>Contact</Label>
|
||||
<input type="text" className="form-control form-select-sm" placeholder="Enter contact name" />
|
||||
</div>
|
||||
{/* <div className="col-md-6">
|
||||
<Label>Contact Email</Label>
|
||||
<input type="email" className="form-control form-select-sm" placeholder="Enter email" />
|
||||
</div>
|
||||
<div className="col-md-6">
|
||||
<Label>Contact Phone</Label>
|
||||
<input type="text" className="form-control form-select-sm" placeholder="Enter phone" />
|
||||
</div>
|
||||
<div className="col-md-6">
|
||||
<Label>Office Phone</Label>
|
||||
<input type="text" className="form-control form-select-sm" placeholder="Enter office phone" />
|
||||
</div> */}
|
||||
<div className="col-md-6">
|
||||
<Label required>GSTIN</Label>
|
||||
<input type="text" className="form-control form-select-sm" placeholder="Enter Tax ID or EIN" />
|
||||
</div>
|
||||
<div className="col-md-6">
|
||||
<Label>PAN Number</Label>
|
||||
<input type="text" className="form-control form-select-sm" placeholder="Enter PAN" />
|
||||
</div>
|
||||
<div className="col-md-6">
|
||||
<Label required>Status</Label>
|
||||
<select className="form-select form-select-sm">
|
||||
<option value="">Select Status</option>
|
||||
<option>Active</option>
|
||||
<option>In-active</option>
|
||||
<option>Blocked</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default AddressStep;
|
||||
34
src/components/InventoryManagement/BankStep.jsx
Normal file
34
src/components/InventoryManagement/BankStep.jsx
Normal file
@ -0,0 +1,34 @@
|
||||
import React from "react";
|
||||
import Label from "../common/Label";
|
||||
|
||||
const BankStep = () => {
|
||||
return (
|
||||
<div className="text-start">
|
||||
<h6 className="fw-bold text-primary mb-3">Bank Details</h6>
|
||||
<div className="row g-3">
|
||||
<div className="col-md-6">
|
||||
<Label required>Bank Name</Label>
|
||||
<input type="text" className="form-control form-select-sm" placeholder="Enter bank name" />
|
||||
</div>
|
||||
<div className="col-md-6">
|
||||
<Label required>Bank Account</Label>
|
||||
<input type="text" className="form-control form-select-sm" placeholder="Enter account number" />
|
||||
</div>
|
||||
<div className="col-md-6">
|
||||
<Label>IBAN / IFSC</Label>
|
||||
<input type="text" className="form-control form-select-sm" placeholder="Enter IBAN or IFSC" />
|
||||
</div>
|
||||
<div className="col-md-6">
|
||||
<Label>SWIFT / BIC Code</Label>
|
||||
<input type="text" className="form-control form-select-sm" placeholder="Enter SWIFT or BIC" />
|
||||
</div>
|
||||
<div className="col-md-6">
|
||||
<Label>Payment Terms</Label>
|
||||
<input type="text" className="form-control form-select-sm" placeholder="Enter payment terms" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default BankStep;
|
||||
35
src/components/InventoryManagement/Stepper.jsx
Normal file
35
src/components/InventoryManagement/Stepper.jsx
Normal file
@ -0,0 +1,35 @@
|
||||
import React from "react";
|
||||
|
||||
const Stepper = ({ steps, activeStep }) => (
|
||||
<div className="d-flex justify-content-between align-items-center mb-5">
|
||||
{steps.map((step, index) => (
|
||||
<React.Fragment key={step.key}>
|
||||
<div className={`text-center ${index <= activeStep ? 'text-primary' : 'text-muted'}`}>
|
||||
<div
|
||||
className={`rounded-circle d-inline-flex align-items-center justify-content-center border p-2 mb-2 ${
|
||||
index === activeStep
|
||||
? 'bg-primary text-white border-primary'
|
||||
: index < activeStep
|
||||
? 'bg-success text-white border-success'
|
||||
: 'bg-light text-muted border-secondary'
|
||||
}`}
|
||||
style={{ width: '30px', height: '30px', fontSize: '14px' }}
|
||||
>
|
||||
{index < activeStep ? '✓' : index + 1}
|
||||
</div>
|
||||
<small className="d-block fw-bold">{step.label}</small>
|
||||
</div>
|
||||
{index < steps.length - 1 && (
|
||||
<div
|
||||
className={`flex-grow-1 mx-2 border-top ${
|
||||
index < activeStep ? 'border-primary' : 'border-secondary'
|
||||
}`}
|
||||
style={{ height: '0', marginTop: '-20px' }}
|
||||
></div>
|
||||
)}
|
||||
</React.Fragment>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
|
||||
export default Stepper;
|
||||
48
src/components/InventoryManagement/SupplierInfoStep.jsx
Normal file
48
src/components/InventoryManagement/SupplierInfoStep.jsx
Normal file
@ -0,0 +1,48 @@
|
||||
import React from "react";
|
||||
import Label from "../common/Label";
|
||||
|
||||
const SupplierInfoStep = () => {
|
||||
return (
|
||||
<div className="text-start">
|
||||
<h6 className="fw-bold text-primary mb-3">Supplier Information</h6>
|
||||
<div className="row g-3">
|
||||
<div className="col-md-6">
|
||||
<Label required>Supplier Name</Label>
|
||||
<input type="text" className="form-control form-select-sm" placeholder="Enter supplier name" />
|
||||
</div>
|
||||
<div className="col-md-6">
|
||||
<Label required>Supplier Status</Label>
|
||||
<select className="form-select form-select-sm">
|
||||
<option value="">Select Status</option>
|
||||
<option>Active</option>
|
||||
<option>In-active</option>
|
||||
<option>Pending Approval</option>
|
||||
</select>
|
||||
</div>
|
||||
<div className="col-md-6">
|
||||
<Label>Supplier Email</Label>
|
||||
<input type="email" className="form-control form-select-sm" placeholder="Enter email" />
|
||||
</div>
|
||||
<div className="col-md-6">
|
||||
<Label required>Supplier Group</Label>
|
||||
<select className="form-select form-select-sm">
|
||||
<option value="">Select Group</option>
|
||||
<option>Domestic</option>
|
||||
<option>International</option>
|
||||
<option>Inter-Company</option>
|
||||
</select>
|
||||
</div>
|
||||
<div className="col-md-6">
|
||||
<Label required>Supplier Category</Label>
|
||||
<input type="text" className="form-control form-select-sm" placeholder="Enter category" />
|
||||
</div>
|
||||
<div className="col-md-6">
|
||||
<Label>Website URL</Label>
|
||||
<input type="url" className="form-control form-select-sm" placeholder="Enter website URL" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default SupplierInfoStep;
|
||||
76
src/components/InventoryManagement/SupplierListView.jsx
Normal file
76
src/components/InventoryManagement/SupplierListView.jsx
Normal file
@ -0,0 +1,76 @@
|
||||
import React from "react";
|
||||
|
||||
const SupplierListView = () => {
|
||||
const supplierColumns = [
|
||||
{ key: "supplierName", label: "Supplier Name", align: "text-start" },
|
||||
{ key: "contactPerson", label: "Contact Person", align: "text-start" },
|
||||
{ key: "email", label: "Email", align: "text-start" },
|
||||
{ key: "phone", label: "Phone", align: "text-start" },
|
||||
{ key: "address", label: "Address", align: "text-start" },
|
||||
{ key: "gstNumber", label: "GST No.", align: "text-start" },
|
||||
];
|
||||
|
||||
// Temporary static data (can be replaced with API data later)
|
||||
const supplierData = [
|
||||
{
|
||||
supplierName: "Techno Supplies Pvt. Ltd.",
|
||||
contactPerson: "Rohit Sharma",
|
||||
email: "rohit@techno.com",
|
||||
phone: "9876543210",
|
||||
address: "Sector 15, Noida, UP",
|
||||
gstNumber: "29ABCDE1234F1Z5",
|
||||
},
|
||||
{
|
||||
supplierName: "FireSafe Traders",
|
||||
contactPerson: "Aman Verma",
|
||||
email: "aman@firesafe.com",
|
||||
phone: "9911223344",
|
||||
address: "MG Road, Gurgaon, HR",
|
||||
gstNumber: "07XYZAB7890P2Q6",
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<div className="card px-0 px-sm-4">
|
||||
<div className="card-datatable table-responsive">
|
||||
<table className="table border-top text-nowrap">
|
||||
<thead>
|
||||
<tr>
|
||||
{supplierColumns.map((col) => (
|
||||
<th key={col.key} className={col.align}>
|
||||
{col.label}
|
||||
</th>
|
||||
))}
|
||||
<th className="sticky-action-column bg-white text-center">Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{supplierData.length > 0 ? (
|
||||
supplierData.map((row, index) => (
|
||||
<tr key={index}>
|
||||
{supplierColumns.map((col) => (
|
||||
<td key={col.key} className={col.align}>
|
||||
{row[col.key]}
|
||||
</td>
|
||||
))}
|
||||
<td className="text-center">
|
||||
<i className="bx bx-edit text-secondary cursor-pointer"></i>
|
||||
<i className="bx bx-trash text-danger cursor-pointer"></i>
|
||||
</td>
|
||||
</tr>
|
||||
))
|
||||
) : (
|
||||
<tr>
|
||||
<td colSpan={supplierColumns.length + 1} className="text-center py-4 text-muted">
|
||||
No supplier data available.
|
||||
</td>
|
||||
</tr>
|
||||
)}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default SupplierListView;
|
||||
@ -0,0 +1,97 @@
|
||||
import React, { useEffect } from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { z } from "zod";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import Label from "../../common/Label";
|
||||
import { useCreatePurhaseOrderStatus, useUpdatePurchaseOrderStatus } from "../../../hooks/masterHook/useMaster";
|
||||
|
||||
const PurchaseOrderStatusSchema = z.object({
|
||||
name: z.string().min(1, { message: "Name is required" }),
|
||||
description: z.string().min(1, { message: "Description is required" }),
|
||||
});
|
||||
|
||||
const PurchaseOrderStatus = ({ data = null, onClose }) => {
|
||||
const {
|
||||
register,
|
||||
handleSubmit,
|
||||
reset,
|
||||
formState: { errors },
|
||||
} = useForm({
|
||||
resolver: zodResolver(PurchaseOrderStatusSchema),
|
||||
defaultValues: { name: "", description: "" },
|
||||
});
|
||||
|
||||
const { mutate: CreatePurchaseOrderStatus, isPending } = useCreatePurhaseOrderStatus(() =>
|
||||
onClose?.()
|
||||
);
|
||||
const { mutate: UpdatePurchaseOrderStatus, isPending: Updating } = useUpdatePurchaseOrderStatus(() => onClose?.())
|
||||
|
||||
const onSubmit = (payload) => {
|
||||
if (data) {
|
||||
UpdatePurchaseOrderStatus({ id: data.id, payload: { ...payload, id: data.id } })
|
||||
} else (
|
||||
CreatePurchaseOrderStatus(payload)
|
||||
)
|
||||
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (data) {
|
||||
reset({
|
||||
name: data.name ?? "",
|
||||
description: data.description ?? ""
|
||||
})
|
||||
}
|
||||
}, [data])
|
||||
|
||||
|
||||
return (
|
||||
<form className="row g-2" onSubmit={handleSubmit(onSubmit)}>
|
||||
<div className="col-12 col-md-12 text-start">
|
||||
<Label className="form-label" required>Name</Label>
|
||||
<input
|
||||
type="text"
|
||||
{...register("name")}
|
||||
className={`form-control ${errors.name ? "is-invalids" : ""}`}
|
||||
/>
|
||||
{errors.name && <p className="danger-text">{errors.name.message}</p>}
|
||||
</div>
|
||||
<div className="col-12 col-md-12 text-start">
|
||||
<Label className="form-label" htmlFor="description" required>
|
||||
Description
|
||||
</Label>
|
||||
<textarea
|
||||
rows="3"
|
||||
{...register("description")}
|
||||
className={`form-control ${errors.description ? "is-invalids" : ""}`}
|
||||
></textarea>
|
||||
|
||||
{errors.description && (
|
||||
<p className="danger-text">{errors.description.message}</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="col-12 text-end">
|
||||
<button
|
||||
type="reset"
|
||||
className="btn btn-sm btn-label-secondary me-3"
|
||||
data-bs-dismiss="modal"
|
||||
aria-label="Close"
|
||||
disabled={isPending || Updating}
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
<button
|
||||
type="submit"
|
||||
className="btn btn-sm btn-primary"
|
||||
disabled={isPending || Updating}
|
||||
>
|
||||
{isPending || Updating ? "Please Wait..." : Updating ? "Update" : "Submit"}
|
||||
</button>
|
||||
|
||||
</div>
|
||||
</form>
|
||||
);
|
||||
};
|
||||
|
||||
export default PurchaseOrderStatus;
|
||||
@ -0,0 +1,99 @@
|
||||
import React, { useEffect } from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { z } from "zod";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
// import { useCreatePaymentMode, useUpdatePaymentMode } from "../../hooks/masterHook/useMaster";
|
||||
// import Label from "../common/Label";
|
||||
import Label from "../../common/Label";
|
||||
import { useCreateRequisitionStatus, useUpdateRequisitionStatus } from "../../../hooks/masterHook/useMaster";
|
||||
|
||||
const RequisitionStatusSchema = z.object({
|
||||
name: z.string().min(1, { message: "Name is required" }),
|
||||
description: z.string().min(1, { message: "Description is required" }),
|
||||
});
|
||||
|
||||
const RequisitionStatus = ({ data = null, onClose }) => {
|
||||
const {
|
||||
register,
|
||||
handleSubmit,
|
||||
reset,
|
||||
formState: { errors },
|
||||
} = useForm({
|
||||
resolver: zodResolver(RequisitionStatusSchema),
|
||||
defaultValues: { name: "", description: "" },
|
||||
});
|
||||
|
||||
const { mutate: CreateRequisitionStatus, isPending } = useCreateRequisitionStatus(() =>
|
||||
onClose?.()
|
||||
);
|
||||
const { mutate: UpdateRequisitionStatus, isPending: Updating } = useUpdateRequisitionStatus(() => onClose?.())
|
||||
|
||||
const onSubmit = (payload) => {
|
||||
if (data) {
|
||||
UpdateRequisitionStatus({ id: data.id, payload: { ...payload, id: data.id } })
|
||||
} else (
|
||||
CreateRequisitionStatus(payload)
|
||||
)
|
||||
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (data) {
|
||||
reset({
|
||||
name: data.name ?? "",
|
||||
description: data.description ?? ""
|
||||
})
|
||||
}
|
||||
}, [data])
|
||||
|
||||
|
||||
return (
|
||||
<form className="row g-2" onSubmit={handleSubmit(onSubmit)}>
|
||||
<div className="col-12 col-md-12 text-start">
|
||||
<Label className="form-label" required>Name</Label>
|
||||
<input
|
||||
type="text"
|
||||
{...register("name")}
|
||||
className={`form-control ${errors.name ? "is-invalids" : ""}`}
|
||||
/>
|
||||
{errors.name && <p className="danger-text">{errors.name.message}</p>}
|
||||
</div>
|
||||
<div className="col-12 col-md-12 text-start">
|
||||
<Label className="form-label" htmlFor="description" required>
|
||||
Description
|
||||
</Label>
|
||||
<textarea
|
||||
rows="3"
|
||||
{...register("description")}
|
||||
className={`form-control ${errors.description ? "is-invalids" : ""}`}
|
||||
></textarea>
|
||||
|
||||
{errors.description && (
|
||||
<p className="danger-text">{errors.description.message}</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="col-12 text-end">
|
||||
<button
|
||||
type="reset"
|
||||
className="btn btn-sm btn-label-secondary me-3"
|
||||
data-bs-dismiss="modal"
|
||||
aria-label="Close"
|
||||
disabled={isPending || Updating}
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
<button
|
||||
type="submit"
|
||||
className="btn btn-sm btn-primary"
|
||||
disabled={isPending || Updating}
|
||||
>
|
||||
{isPending || Updating ? "Please Wait..." : Updating ? "Update" : "Submit"}
|
||||
</button>
|
||||
|
||||
</div>
|
||||
</form>
|
||||
);
|
||||
};
|
||||
|
||||
export default RequisitionStatus;
|
||||
@ -17,6 +17,8 @@ import ManageDocumentType from "./ManageDocumentType";
|
||||
import ManageServices from "./Services/ManageServices";
|
||||
import ServiceGroups from "./Services/ServicesGroups";
|
||||
import ManagePaymentHead from "./paymentAdjustmentHead/ManagePaymentHead";
|
||||
import RequisitionStatus from "./InventoryManagement/RequisitionStatus";
|
||||
import PurchaseOrderStatus from "./InventoryManagement/PurchaseOrderStatus";
|
||||
|
||||
const MasterModal = ({ modaldata, closeModal }) => {
|
||||
if (!modaldata?.modalType || modaldata.modalType === "delete") {
|
||||
@ -62,7 +64,16 @@ const MasterModal = ({ modaldata, closeModal }) => {
|
||||
"Edit-Services": <ManageServices data={item} onClose={closeModal} />,
|
||||
"Manage-Services": <ServiceGroups service={item} onClose={closeModal} />,
|
||||
"Payment Adjustment Head": <ManagePaymentHead onClose={closeModal} />,
|
||||
"Edit-Payment Adjustment Head": <ManagePaymentHead data={item} onClose={closeModal} />
|
||||
"Edit-Payment Adjustment Head": <ManagePaymentHead data={item} onClose={closeModal} />,
|
||||
|
||||
"Requisition Status": <RequisitionStatus onClose={closeModal} />,
|
||||
"Edit-Requisition Status": (
|
||||
<RequisitionStatus data={item} onClose={closeModal} />
|
||||
),
|
||||
"Purchase Order Status": <PurchaseOrderStatus onClose={closeModal} />,
|
||||
"Edit-Purchase Order Status": (
|
||||
<PurchaseOrderStatus data={item} onClose={closeModal} />
|
||||
),
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
@ -277,7 +277,7 @@ export const useOrganizationType = () => {
|
||||
};
|
||||
// ===Application Masters Query=================================================
|
||||
|
||||
const fetchMasterData = async (masterType) => {
|
||||
const fetchMasterData = async (masterType,isActiveMaster) => {
|
||||
switch (masterType) {
|
||||
case "Application Role":
|
||||
return (await MasterRespository.getRoles()).data;
|
||||
@ -305,6 +305,10 @@ const fetchMasterData = async (masterType) => {
|
||||
return (await MasterRespository.getDocumentCategories()).data;
|
||||
case "Payment Adjustment Head":
|
||||
return (await MasterRespository.getPaymentAdjustmentHead(true)).data;
|
||||
case "Requisition Status":
|
||||
return (await MasterRespository.getRequisitionStatus(isActiveMaster)).data;
|
||||
case "Purchase Order Status":
|
||||
return (await MasterRespository.getPurchaseOrderStatus(isActiveMaster)).data;
|
||||
case "Status":
|
||||
return [
|
||||
{
|
||||
@ -331,20 +335,20 @@ const fetchMasterData = async (masterType) => {
|
||||
}
|
||||
};
|
||||
|
||||
const useMaster = () => {
|
||||
const useMaster = (isActiveMaster) => {
|
||||
const selectedMaster = useSelector(
|
||||
(store) => store.localVariables.selectedMaster
|
||||
);
|
||||
const queryFn = useCallback(
|
||||
() => fetchMasterData(selectedMaster),
|
||||
[selectedMaster]
|
||||
const queryFn = useCallback(
|
||||
() => fetchMasterData(selectedMaster, isActiveMaster),
|
||||
[selectedMaster, isActiveMaster]
|
||||
);
|
||||
const {
|
||||
data = [],
|
||||
isLoading,
|
||||
error,
|
||||
} = useQuery({
|
||||
queryKey: ["masterData", selectedMaster],
|
||||
queryKey: ["masterData", selectedMaster,isActiveMaster],
|
||||
queryFn,
|
||||
enabled: !!selectedMaster,
|
||||
staleTime: 1000 * 60 * 10,
|
||||
@ -361,7 +365,6 @@ const useMaster = () => {
|
||||
|
||||
return { data, loading: isLoading, error };
|
||||
};
|
||||
|
||||
export default useMaster;
|
||||
|
||||
// ================================Mutation====================================
|
||||
@ -1043,8 +1046,96 @@ export const useUpdatePaymentAjustmentHead = (onSuccessCallback) => {
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
// ============================== Requisition-Status =============================
|
||||
|
||||
export const useCreateRequisitionStatus = (onSuccessCallback) => {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
return useMutation({
|
||||
mutationFn: async (payload) => {
|
||||
const resp = await MasterRespository.createRequisitionStatus(payload);
|
||||
return resp.data;
|
||||
},
|
||||
onSuccess: (data) => {
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: ["masterData", "Requisition Status"],
|
||||
});
|
||||
showToast("Requisition Status successfully", "success");
|
||||
if (onSuccessCallback) onSuccessCallback(data);
|
||||
},
|
||||
onError: (error) => {
|
||||
showToast(error.message || "Something went wrong", "error");
|
||||
},
|
||||
});
|
||||
};
|
||||
export const useUpdateRequisitionStatus = (onSuccessCallback) => {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
return useMutation({
|
||||
mutationFn: async ({ id, payload }) => {
|
||||
const resp = await MasterRespository.updateRequisitionStatus(id, payload);
|
||||
return resp.data;
|
||||
},
|
||||
onSuccess: (data) => {
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: ["masterData", "Requisition Status"],
|
||||
});
|
||||
showToast("Requisition Status Updated successfully", "success");
|
||||
if (onSuccessCallback) onSuccessCallback(data);
|
||||
},
|
||||
onError: (error) => {
|
||||
showToast(error.message || "Something went wrong", "error");
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
// ============================== Purchase Order Status =============================
|
||||
|
||||
export const useCreatePurhaseOrderStatus = (onSuccessCallback) => {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
return useMutation({
|
||||
mutationFn: async (payload) => {
|
||||
const resp = await MasterRespository.createPurchaseOrderStatus(payload);
|
||||
return resp.data;
|
||||
},
|
||||
onSuccess: (data) => {
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: ["masterData", "Purchase Order Status"],
|
||||
});
|
||||
showToast("Purchase Order Status successfully", "success");
|
||||
if (onSuccessCallback) onSuccessCallback(data);
|
||||
},
|
||||
onError: (error) => {
|
||||
showToast(error.message || "Something went wrong", "error");
|
||||
},
|
||||
});
|
||||
};
|
||||
export const useUpdatePurchaseOrderStatus = (onSuccessCallback) => {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
return useMutation({
|
||||
mutationFn: async ({ id, payload }) => {
|
||||
const resp = await MasterRespository.updatePurchaseOrderStatus(id, payload);
|
||||
return resp.data;
|
||||
},
|
||||
onSuccess: (data) => {
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: ["masterData", "Purchase Order Status"],
|
||||
});
|
||||
showToast("Purchase Order Status Updated successfully", "success");
|
||||
if (onSuccessCallback) onSuccessCallback(data);
|
||||
},
|
||||
onError: (error) => {
|
||||
showToast(error.message || "Something went wrong", "error");
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
// ====================x=x====================x=x==================================
|
||||
|
||||
|
||||
// --------Delete Master --------
|
||||
export const useDeleteMasterItem = () => {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
53
src/pages/InventoryManagement/ProductPage.jsx
Normal file
53
src/pages/InventoryManagement/ProductPage.jsx
Normal file
@ -0,0 +1,53 @@
|
||||
|
||||
import React, { useState } from "react";
|
||||
import Breadcrumb from "../../components/common/Breadcrumb";
|
||||
import AddProductModal from "../../components/InventoryManagement/AddProductModal";
|
||||
import SupplierListView from "../../components/InventoryManagement/SupplierListView";
|
||||
|
||||
const ProductPage = () => {
|
||||
const [isAddInventoryOpen, setIsAddInventoryOpen] = useState(false);
|
||||
const [viewInventory, setViewInventory] = useState(false);
|
||||
|
||||
return (
|
||||
<div className="container-fluid">
|
||||
{/* Breadcrumb */}
|
||||
<Breadcrumb data={[{ label: "Home", link: "/" }, { label: "Inventory" }]} />
|
||||
|
||||
{/* Top Bar */}
|
||||
<div className="card my-3 px-sm-4 px-0">
|
||||
<div className="card-body py-2 px-3">
|
||||
<div className="row align-items-center">
|
||||
<div className="col-6">
|
||||
<input
|
||||
type="search"
|
||||
className="form-control form-control-sm w-auto"
|
||||
placeholder="Search Inventory"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="col-6 text-end mt-2 mt-sm-0">
|
||||
<button
|
||||
className="btn btn-sm btn-primary"
|
||||
type="button"
|
||||
onClick={() => setIsAddInventoryOpen(true)}
|
||||
>
|
||||
<i className="bx bx-plus-circle me-2"></i>
|
||||
<span className="d-none d-md-inline-block">Add New Inventory</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<SupplierListView/>
|
||||
|
||||
{/* Add Inventory Modal */}
|
||||
<AddProductModal
|
||||
isOpen={isAddInventoryOpen}
|
||||
onClose={() => setIsAddInventoryOpen(false)}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ProductPage;
|
||||
@ -33,6 +33,7 @@ const MasterPage = () => {
|
||||
(store) => store.localVariables.selectedMaster
|
||||
);
|
||||
const hasMasterPermission = useHasUserPermission(MANAGE_MASTER);
|
||||
const [isActiveMaster, setIsActiveMaster] = useState(true);
|
||||
|
||||
const {
|
||||
data: menuData,
|
||||
@ -44,11 +45,11 @@ const MasterPage = () => {
|
||||
data: masterData = [],
|
||||
loading,
|
||||
isError: isMasterError,
|
||||
} = useMaster();
|
||||
} = useMaster(isActiveMaster);
|
||||
const { mutate: DeleteMaster, isPending: isDeleting } = useDeleteMasterItem();
|
||||
const [isDeleletingServiceItem,setDeleletingServiceItem] = useState({isOpen:false,ItemId:null,whichItem:null})
|
||||
const {mutate:DeleteSericeGroup,isPending:deletingGroup} =useDeleteServiceGroup()
|
||||
const {mutate:DeleteAcivity,isPending:deletingActivity} = useDeleteActivity()
|
||||
const [isDeleletingServiceItem, setDeleletingServiceItem] = useState({ isOpen: false, ItemId: null, whichItem: null })
|
||||
const { mutate: DeleteSericeGroup, isPending: deletingGroup } = useDeleteServiceGroup()
|
||||
const { mutate: DeleteAcivity, isPending: deletingActivity } = useDeleteActivity()
|
||||
|
||||
const [modalConfig, setModalConfig] = useState(null);
|
||||
const [deleteData, setDeleteData] = useState(null);
|
||||
@ -89,15 +90,15 @@ const MasterPage = () => {
|
||||
};
|
||||
|
||||
|
||||
const handleDeleteServiceItem =()=>{
|
||||
if(!isDeleletingServiceItem.ItemId) return
|
||||
const handleDeleteServiceItem = () => {
|
||||
if (!isDeleletingServiceItem.ItemId) return
|
||||
debugger
|
||||
if(isDeleletingServiceItem.whichItem === "activity"){
|
||||
DeleteAcivity(isDeleletingServiceItem.ItemId,{onSuccess:()=>setDeleletingServiceItem({isOpen:false,ItemId:null,whichItem:null})})
|
||||
}else{
|
||||
DeleteSericeGroup(isDeleletingServiceItem.ItemId,{onSuccess:()=>setDeleletingServiceItem({isOpen:false,ItemId:null,whichItem:null})})
|
||||
if (isDeleletingServiceItem.whichItem === "activity") {
|
||||
DeleteAcivity(isDeleletingServiceItem.ItemId, { onSuccess: () => setDeleletingServiceItem({ isOpen: false, ItemId: null, whichItem: null }) })
|
||||
} else {
|
||||
DeleteSericeGroup(isDeleletingServiceItem.ItemId, { onSuccess: () => setDeleletingServiceItem({ isOpen: false, ItemId: null, whichItem: null }) })
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -115,7 +116,7 @@ const MasterPage = () => {
|
||||
);
|
||||
|
||||
return (
|
||||
<MasterContext.Provider value={{setDeleletingServiceItem}}>
|
||||
<MasterContext.Provider value={{ setDeleletingServiceItem }}>
|
||||
{modalConfig && (
|
||||
<GlobalModel
|
||||
size={
|
||||
@ -134,7 +135,7 @@ const MasterPage = () => {
|
||||
/>
|
||||
</GlobalModel>
|
||||
)}
|
||||
|
||||
|
||||
|
||||
<ConfirmModal
|
||||
type="delete"
|
||||
@ -145,15 +146,15 @@ const MasterPage = () => {
|
||||
onSubmit={handleDeleteSubmit}
|
||||
onClose={() => setDeleteData(null)}
|
||||
/>
|
||||
|
||||
|
||||
<ConfirmModal
|
||||
type="delete"
|
||||
header={`Delete ${isDeleletingServiceItem?.whichItem}`}
|
||||
message={`Are you sure you want to delete this ${isDeleletingServiceItem?.whichItem}?`}
|
||||
isOpen={!!isDeleletingServiceItem?.isOpen}
|
||||
loading={deletingActivity}
|
||||
onSubmit={handleDeleteServiceItem}
|
||||
onClose={() => setDeleletingServiceItem({isOpen:false,ItemId:null,whichItem:null})}
|
||||
onSubmit={handleDeleteServiceItem}
|
||||
onClose={() => setDeleletingServiceItem({ isOpen: false, ItemId: null, whichItem: null })}
|
||||
/>
|
||||
|
||||
<div className="container-fluid">
|
||||
@ -171,7 +172,7 @@ const MasterPage = () => {
|
||||
<div className="col-12 col-md-3">
|
||||
<select
|
||||
className="form-select py-1 px-2"
|
||||
|
||||
|
||||
value={selectedMaster}
|
||||
onChange={(e) => dispatch(changeMaster(e.target.value))}
|
||||
>
|
||||
@ -196,6 +197,27 @@ const MasterPage = () => {
|
||||
onChange={(e) => setSearchTerm(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{(selectedMaster === "Purchase Order Status" ||
|
||||
selectedMaster === "Requisition Status") && (
|
||||
<div className="form-check form-switch d-flex align-items-center">
|
||||
<input
|
||||
className="form-check-input"
|
||||
type="checkbox"
|
||||
role="switch"
|
||||
id="flexSwitchCheckActive"
|
||||
checked={isActiveMaster}
|
||||
onChange={() => setIsActiveMaster((prev) => !prev)}
|
||||
/>
|
||||
<label
|
||||
className="form-check-label ms-2"
|
||||
htmlFor="flexSwitchCheckActive"
|
||||
>
|
||||
{isActiveMaster ? "Active" : "In-active"}
|
||||
</label>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{hasMasterPermission && (
|
||||
<button
|
||||
className="btn btn-sm btn-primary"
|
||||
@ -204,7 +226,7 @@ const MasterPage = () => {
|
||||
}
|
||||
>
|
||||
<i className="bx bx-plus-circle me-2"></i> <span className="d-none d-md-inline-block">Add{" "}
|
||||
{selectedMaster}</span>
|
||||
{selectedMaster}</span>
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
@ -215,12 +237,13 @@ const MasterPage = () => {
|
||||
columns={columns}
|
||||
loading={loading}
|
||||
handleModalData={handleModalData}
|
||||
isActiveMaster={isActiveMaster}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</MasterContext.Provider>
|
||||
</MasterContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@ -4,7 +4,7 @@ import { useHasUserPermission } from "../../hooks/useHasUserPermission";
|
||||
import { ITEMS_PER_PAGE, MANAGE_MASTER } from "../../utils/constants";
|
||||
import showToast from "../../services/toastService";
|
||||
|
||||
const MasterTable = ({ data, columns, loading, handleModalData }) => {
|
||||
const MasterTable = ({ data, columns, loading, handleModalData,isActiveMaster }) => {
|
||||
const hasMasterPermission = useHasUserPermission(MANAGE_MASTER);
|
||||
const selectedMaster = useSelector(
|
||||
(store) => store.localVariables.selectedMaster
|
||||
@ -92,14 +92,14 @@ const MasterTable = ({ data, columns, loading, handleModalData }) => {
|
||||
{" "}
|
||||
{selectedMaster === "Activity" ? "Activity" : "Name"}
|
||||
</th>
|
||||
<th className="text-start d-none d-md-table-cell">
|
||||
<th className="text-start d-none d-md-table-cell">
|
||||
|
||||
{" "}
|
||||
{selectedMaster === "Activity"
|
||||
? "Unit"
|
||||
: selectedMaster === "Document Type"
|
||||
? "Content Type"
|
||||
: "Description"}
|
||||
? "Content Type"
|
||||
: "Description"}
|
||||
</th>
|
||||
<th className={` ${!hasMasterPermission && "d-none"}`}>
|
||||
Actions
|
||||
@ -117,7 +117,7 @@ const MasterTable = ({ data, columns, loading, handleModalData }) => {
|
||||
<td className={`text-start mx-2 py-3 ${col.key === "description" && "d-none d-md-table-cell"}`} key={col.key} >
|
||||
{col.key === "description" ? (
|
||||
item[col.key] !== undefined &&
|
||||
item[col.key] !== null ? (
|
||||
item[col.key] !== null ? (
|
||||
item[col.key].length > 80 ? (
|
||||
<>{item[col.key].slice(0, 80)}...</>
|
||||
) : (
|
||||
@ -137,7 +137,7 @@ const MasterTable = ({ data, columns, loading, handleModalData }) => {
|
||||
<td className={!hasMasterPermission ? "d-none" : "py-3"}>
|
||||
{(selectedMaster === "Application Role" ||
|
||||
selectedMaster === "Work Category") &&
|
||||
item?.isSystem ? (
|
||||
item?.isSystem ? (
|
||||
<>
|
||||
<button
|
||||
aria-label="Modify"
|
||||
@ -230,9 +230,8 @@ const MasterTable = ({ data, columns, loading, handleModalData }) => {
|
||||
{[...Array(totalPages)].map((_, index) => (
|
||||
<li
|
||||
key={index}
|
||||
className={`page-item ${
|
||||
currentPage === index + 1 ? "active" : ""
|
||||
}`}
|
||||
className={`page-item ${currentPage === index + 1 ? "active" : ""
|
||||
}`}
|
||||
>
|
||||
<button
|
||||
className="page-link"
|
||||
@ -243,9 +242,8 @@ const MasterTable = ({ data, columns, loading, handleModalData }) => {
|
||||
</li>
|
||||
))}
|
||||
<li
|
||||
className={`page-item ${
|
||||
currentPage === totalPages ? "disabled" : ""
|
||||
}`}
|
||||
className={`page-item ${currentPage === totalPages ? "disabled" : ""
|
||||
}`}
|
||||
>
|
||||
<button
|
||||
className="page-link"
|
||||
|
||||
@ -58,7 +58,13 @@ export const MasterRespository = {
|
||||
"Document Type": (id) => api.delete(`/api/Master/document-type/delete/${id}`),
|
||||
"Document Category": (id) =>
|
||||
api.delete(`/api/Master/document-category/delete/${id}`),
|
||||
"Payment Adjustment Head":(id,isActive)=>api.delete(`/api/Master/payment-adjustment-head/delete/${id}`,(isActive=false)),
|
||||
"Payment Adjustment Head": (id, isActive) => api.delete(`/api/Master/payment-adjustment-head/delete/${id}`, (isActive = false)),
|
||||
|
||||
"Requisition Status": (id, isActive = false) =>
|
||||
api.delete(`/api/master/requisition-status/delete/${id}?isActive=${isActive}`),
|
||||
"Purchase Order Status": (id, isActive = false) =>
|
||||
api.delete(`/api/master/purchase-order-status/delete/${id}?isActive=${isActive}`),
|
||||
|
||||
|
||||
getWorkCategory: () => api.get(`/api/master/work-categories`),
|
||||
createWorkCategory: (data) => api.post(`/api/master/work-category`, data),
|
||||
@ -95,8 +101,7 @@ export const MasterRespository = {
|
||||
|
||||
getDocumentCategories: (entityType) =>
|
||||
api.get(
|
||||
`/api/Master/document-category/list${
|
||||
entityType ? `?entityTypeId=${entityType}` : ""
|
||||
`/api/Master/document-category/list${entityType ? `?entityTypeId=${entityType}` : ""
|
||||
}`
|
||||
),
|
||||
createDocumenyCategory: (data) =>
|
||||
@ -106,8 +111,7 @@ export const MasterRespository = {
|
||||
|
||||
getDocumentTypes: (category) =>
|
||||
api.get(
|
||||
`/api/Master/document-type/list${
|
||||
category ? `?documentCategoryId=${category}` : ""
|
||||
`/api/Master/document-type/list${category ? `?documentCategoryId=${category}` : ""
|
||||
}`
|
||||
),
|
||||
|
||||
@ -134,6 +138,21 @@ export const MasterRespository = {
|
||||
|
||||
getPaymentAdjustmentHead: (isActive) =>
|
||||
api.get(`/api/Master/payment-adjustment-head/list?isActive=${isActive}`),
|
||||
createPaymentAjustmentHead:(data)=>api.post(`/api/Master/payment-adjustment-head`, data),
|
||||
updatePaymentAjustmentHead:(id,data)=>api.put(`/api/Master/payment-adjustment-head/edit/${id}`, data)
|
||||
createPaymentAjustmentHead: (data) => api.post(`/api/Master/payment-adjustment-head`, data),
|
||||
updatePaymentAjustmentHead: (id, data) => api.put(`/api/Master/payment-adjustment-head/edit/${id}`, data),
|
||||
|
||||
getRequisitionStatus: (isActive = true) =>
|
||||
api.get(`/api/master/requisition-status/list?isActive=${isActive}`),
|
||||
createRequisitionStatus: (data) => api.post(`/api/master/requisition-status/create`, data),
|
||||
updateRequisitionStatus: (id, data) => api.put(`/api/master/requisition-status/edit/${id}`, data),
|
||||
|
||||
|
||||
getPurchaseOrderStatus: (isActive = true) =>
|
||||
api.get(`/api/master/purchase-order-status/list?isActive=${isActive}`),
|
||||
createPurchaseOrderStatus: (data) => api.post(`/api/master/purchase-order-status/create`, data),
|
||||
updatePurchaseOrderStatus: (id, data) => api.put(`/api/master/purchase-order-status/edit/${id}`, data),
|
||||
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
@ -54,6 +54,7 @@ import ProjectPage from "../pages/project/ProjectPage";
|
||||
import { ComingSoonPage } from "../pages/Misc/ComingSoonPage";
|
||||
import ImageGalleryPage from "../pages/Gallary/ImageGallaryPage";
|
||||
import CollectionPage from "../pages/collections/CollectionPage";
|
||||
import ProductPage from "../pages/InventoryManagement/ProductPage";
|
||||
const router = createBrowserRouter(
|
||||
[
|
||||
{
|
||||
@ -89,7 +90,7 @@ const router = createBrowserRouter(
|
||||
// { path: "/employee/manage", element: <ManageEmp /> },
|
||||
// {path: "/employee/manage/:employeeId", element: <ManageEmp />},
|
||||
{ path: "/directory", element: <DirectoryPage /> },
|
||||
{ path: "/inventory", element: <Inventory /> },
|
||||
{ path: "/supplier", element: <ProductPage /> },
|
||||
{ path: "/activities/attendance", element: <AttendancePage /> },
|
||||
{ path: "/activities/records/:projectId?", element: <DailyProgrssReport /> },
|
||||
{ path: "/activities/task", element: <TaskPlannng /> },
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user