Compare commits
3 Commits
d4582c101a
...
b8df8a2bde
| Author | SHA1 | Date | |
|---|---|---|---|
| b8df8a2bde | |||
| 5d773b0680 | |||
| f13005a031 |
@ -1,7 +1,7 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en" lang="en" class="light-style layout-navbar-fixed layout-menu-fixed layout-compact" dir="ltr"
|
<html lang="en" lang="en" class="light-style layout-navbar-fixed layout-menu-fixed layout-compact layout-menu-collapsed " dir="ltr"
|
||||||
data-theme="theme-default" data-assets-path="/assets/" data-template="vertical-menu-template" data-style="light">
|
data-theme="theme-default" data-assets-path="/assets/" data-template="vertical-menu-template" data-style="light">
|
||||||
|
<!-- layout-menu-collapsed layout-menu-hover -->
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
|||||||
@ -31,7 +31,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.app-brand-text {
|
.app-brand-text {
|
||||||
font-size: 1.75rem;
|
font-size: 1rem;
|
||||||
letter-spacing: -0.5px;
|
letter-spacing: -0.5px;
|
||||||
/* text-transform: lowercase; */
|
/* text-transform: lowercase; */
|
||||||
}
|
}
|
||||||
|
|||||||
@ -149,4 +149,40 @@ function Main () {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
document.addEventListener("DOMContentLoaded", function () {
|
||||||
|
const html = document.documentElement;
|
||||||
|
|
||||||
|
/******************************
|
||||||
|
* SIDEBAR HOVER BEHAVIOR
|
||||||
|
******************************/
|
||||||
|
document.addEventListener("mouseover", function (e) {
|
||||||
|
const isInsideSidebar = e.target.closest("#layout-menu");
|
||||||
|
|
||||||
|
if (isInsideSidebar && html.classList.contains("layout-menu-collapsed")) {
|
||||||
|
html.classList.add("layout-menu-hover");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
document.addEventListener("mouseout", function (e) {
|
||||||
|
const leftSidebar = !e.relatedTarget || !e.relatedTarget.closest("#layout-menu");
|
||||||
|
|
||||||
|
if (leftSidebar) {
|
||||||
|
html.classList.remove("layout-menu-hover");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/******************************
|
||||||
|
* TOGGLE MENU BUTTON OVERRIDE
|
||||||
|
******************************/
|
||||||
|
document.body.addEventListener("click", function (e) {
|
||||||
|
const btn = e.target.closest(".layout-menu-toggle");
|
||||||
|
if (!btn) return;
|
||||||
|
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
html.classList.toggle("layout-menu-collapsed");
|
||||||
|
html.classList.remove("layout-menu-hover");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
@ -25,20 +25,28 @@ const Sidebar = () => {
|
|||||||
/>
|
/>
|
||||||
</span> */}
|
</span> */}
|
||||||
|
|
||||||
<small
|
<a
|
||||||
className="app-brand-link fw-bold navbar-brand text-green fs-6"
|
href="/"
|
||||||
|
className="app-brand-link d-flex align-items-center gap-1 fw-bold navbar-brand "
|
||||||
>
|
>
|
||||||
<span className="app-brand-logo demo">
|
<span className="app-brand-logo demo d-flex align-items-center">
|
||||||
<img src="/img/brand/marco.png" width="50" />
|
<img
|
||||||
|
src="/img/brand/marco.png"
|
||||||
|
width="40"
|
||||||
|
height="40"
|
||||||
|
alt="OnFieldWork logo"
|
||||||
|
/>
|
||||||
</span>
|
</span>
|
||||||
<span className="text-blue">OnField</span>
|
|
||||||
<span>Work</span>
|
<span className="app-brand-text">
|
||||||
|
<span className="text-primary ">OnField</span>
|
||||||
|
<span className="mx-1">Work</span>
|
||||||
<span className="text-dark">.com</span>
|
<span className="text-dark">.com</span>
|
||||||
</small>
|
</span>
|
||||||
|
</a>
|
||||||
</Link>
|
</Link>
|
||||||
|
|
||||||
<small className="layout-menu-toggle menu-link text-large ms-auto">
|
<small className="layout-menu-toggle menu-link text-large ms-auto cursor-pointer">
|
||||||
|
|
||||||
<i className="bx bx-chevron-left bx-sm d-flex align-items-center justify-content-center"></i>
|
<i className="bx bx-chevron-left bx-sm d-flex align-items-center justify-content-center"></i>
|
||||||
</small>
|
</small>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
117
src/components/purchase/ManagePurchase.jsx
Normal file
117
src/components/purchase/ManagePurchase.jsx
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
import React, { useState } from "react";
|
||||||
|
import { AppFormProvider, useAppForm } from "../../hooks/appHooks/useAppForm";
|
||||||
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
|
import {
|
||||||
|
defaultPurchaseValue,
|
||||||
|
PurchaseSchema,
|
||||||
|
getStepFields,
|
||||||
|
} from "./PurchaseSchema";
|
||||||
|
import { defaultJobValue } from "../ServiceProject/ServiceProjectSchema";
|
||||||
|
import PurchasePartyDetails from "./PurchasePartyDetails";
|
||||||
|
|
||||||
|
const ManagePurchase = () => {
|
||||||
|
const [activeTab, setActiveTab] = useState(0);
|
||||||
|
const [completedTabs, setCompletedTabs] = useState([]);
|
||||||
|
|
||||||
|
const newTenantConfig = [
|
||||||
|
{
|
||||||
|
name: "Contact Info",
|
||||||
|
icon: "bx bx-user bx-md",
|
||||||
|
subtitle: "Provide Contact Details",
|
||||||
|
component: <PurchasePartyDetails />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Organization",
|
||||||
|
icon: "bx bx-buildings bx-md",
|
||||||
|
subtitle: "Organization Details",
|
||||||
|
component: <div>Invoice & Transport Details</div>,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "SubScription",
|
||||||
|
icon: "bx bx-star bx-md",
|
||||||
|
component: <div>Payment & Financials</div>,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
const purchaseOrder = useAppForm({
|
||||||
|
resolver: zodResolver(PurchaseSchema),
|
||||||
|
defaultJobValue: defaultPurchaseValue,
|
||||||
|
});
|
||||||
|
const getCurrentTrigger = () =>
|
||||||
|
activeTab === 2 ? subscriptionForm.trigger : tenantForm.trigger;
|
||||||
|
|
||||||
|
const handleNext = async () => {
|
||||||
|
const currentStepFields = getStepFields(activeTab);
|
||||||
|
const trigger = getCurrentTrigger();
|
||||||
|
const valid = await trigger(currentStepFields);
|
||||||
|
|
||||||
|
if (valid) {
|
||||||
|
setCompletedTabs((prev) => [...new Set([...prev, activeTab])]);
|
||||||
|
setActiveTab((prev) => Math.min(prev + 1, newTenantConfig.length - 1));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handlePrev = () => {
|
||||||
|
setActiveTab((prev) => Math.max(prev - 1, 0));
|
||||||
|
};
|
||||||
|
|
||||||
|
const onsubmit = (formData) => {};
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
id="wizard-property-listing"
|
||||||
|
className="bs-stepper horizontically mt-2 b-secondry px-1 shadow-none border-0"
|
||||||
|
>
|
||||||
|
{/* <span className="fs-5">New Parchase</span> */}
|
||||||
|
<div className="bs-stepper-header text-start px-0">
|
||||||
|
{newTenantConfig
|
||||||
|
.filter((step) => step.name.toLowerCase() !== "congratulation")
|
||||||
|
.map((step, index) => {
|
||||||
|
const isActive = activeTab === index;
|
||||||
|
const isCompleted = completedTabs.includes(index);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<React.Fragment key={step.name}>
|
||||||
|
<div
|
||||||
|
className={`step ${isActive ? "active" : ""} ${
|
||||||
|
isCompleted ? "crossed" : ""
|
||||||
|
}`}
|
||||||
|
data-target={`#step-${index}`}
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className={`step-trigger ${isActive ? "active" : ""}`}
|
||||||
|
// onClick={() => setActiveTab(index)} // optional
|
||||||
|
>
|
||||||
|
<span className="bs-stepper-circle">
|
||||||
|
{isCompleted ? (
|
||||||
|
<i className="bx bx-check"></i>
|
||||||
|
) : (
|
||||||
|
<i className={step.icon}></i>
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
|
<span className="bs-stepper-label">
|
||||||
|
<span className="bs-stepper-title">{step.name}</span>
|
||||||
|
<span className="bs-stepper-subtitle">
|
||||||
|
{step.subtitle}
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
{index < newTenantConfig.length - 1 && (
|
||||||
|
<div className="line text-primary"></div>
|
||||||
|
)}
|
||||||
|
</React.Fragment>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
<div className="bs-stepper-content py-2">
|
||||||
|
<AppFormProvider>
|
||||||
|
<form onSubmit={purchaseOrder.handleSubmit(onsubmit)}>
|
||||||
|
{newTenantConfig[activeTab].component}
|
||||||
|
</form>
|
||||||
|
</AppFormProvider>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ManagePurchase;
|
||||||
31
src/components/purchase/PurchasePartyDetails.jsx
Normal file
31
src/components/purchase/PurchasePartyDetails.jsx
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { useAppFormContext } from "../../hooks/appHooks/useAppForm";
|
||||||
|
|
||||||
|
const PurchasePartyDetails = ({ onNext }) => {
|
||||||
|
const {
|
||||||
|
register,
|
||||||
|
control,
|
||||||
|
trigger,
|
||||||
|
formState: { errors },
|
||||||
|
} = useAppFormContext();
|
||||||
|
|
||||||
|
const handleNext = async () => {
|
||||||
|
const valid = await trigger([
|
||||||
|
"title",
|
||||||
|
"projectId",
|
||||||
|
"organizationId",
|
||||||
|
"supplier",
|
||||||
|
"billingAddress",
|
||||||
|
"shippingAddress",
|
||||||
|
"purchaseOrderNumber",
|
||||||
|
"purchaseOrderDate",
|
||||||
|
"porformaInvoiceNo",
|
||||||
|
]);
|
||||||
|
if (valid) {
|
||||||
|
onNext();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return <div className="row"></div>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default PurchasePartyDetails;
|
||||||
11
src/components/purchase/PurchasePaymentDetails.jsx
Normal file
11
src/components/purchase/PurchasePaymentDetails.jsx
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import React from 'react'
|
||||||
|
|
||||||
|
const PurchasePaymentDetails = () => {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PurchasePaymentDetails
|
||||||
127
src/components/purchase/PurchaseSchema.jsx
Normal file
127
src/components/purchase/PurchaseSchema.jsx
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
import { z } from "zod";
|
||||||
|
|
||||||
|
export const AttachmentSchema = (allowedContentType, maxSizeAllowedInMB) => {
|
||||||
|
const allowedTypes = normalizeAllowedContentTypes(allowedContentType);
|
||||||
|
|
||||||
|
return z.object({
|
||||||
|
fileName: z.string().min(1, { message: "File name is required" }),
|
||||||
|
base64Data: z.string().min(1, { message: "File data is required" }),
|
||||||
|
contentType: z
|
||||||
|
.string()
|
||||||
|
.min(1, { message: "MIME type is required" })
|
||||||
|
.refine(
|
||||||
|
(val) => (allowedTypes.length ? allowedTypes.includes(val) : true),
|
||||||
|
{
|
||||||
|
message: `File type must be one of: ${allowedTypes.join(", ")}`,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
fileSize: z
|
||||||
|
.number()
|
||||||
|
.int()
|
||||||
|
.nonnegative("fileSize must be ≥ 0")
|
||||||
|
.max(
|
||||||
|
(maxSizeAllowedInMB ?? 25) * 1024 * 1024,
|
||||||
|
`fileSize must be ≤ ${maxSizeAllowedInMB ?? 25}MB`
|
||||||
|
),
|
||||||
|
description: z.string().optional().default(""),
|
||||||
|
isActive: z.boolean(),
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const PurchaseSchema = z.object({
|
||||||
|
title: z.string().min(1, { message: "Title is required" }),
|
||||||
|
projectId: z.string().min(1, { message: "Project is required" }),
|
||||||
|
organizationId: z.string().min(1, { message: "Organization is required" }),
|
||||||
|
billingAddress: z.string().min(1, { message: "Address is required" }),
|
||||||
|
shippingAddress: z.string().min(1, { message: "Address is required" }),
|
||||||
|
purchaseOrderNumber: z.string().nullable(),
|
||||||
|
purchaseOrderDate: z.string().nullable(),
|
||||||
|
supplier: z.string().min(1, { message: "Supplier is required" }),
|
||||||
|
porformaInvoiceNo: z.string().nullable(),
|
||||||
|
// Supplier Details
|
||||||
|
|
||||||
|
invoiceNo: z.string().min(1, { message: "Invoice No is required" }),
|
||||||
|
invoiceDate: z.string().min(1, { message: "Date is required" }),
|
||||||
|
ewayBillNo: z.string().min(1, { message: "E-Way Bill No is required" }),
|
||||||
|
ewayBillDate: z.string().min(1, { message: "E-Way Bill Date is required" }),
|
||||||
|
irnNo: z.string().min(1, { message: "IRN is required" }),
|
||||||
|
ackDate: z.string().min(1, { message: "Date is required" }),
|
||||||
|
ackNo: z.string().min(1, { message: "acknowledgement No is required" }),
|
||||||
|
|
||||||
|
// Payment Detail
|
||||||
|
baseAmount: z.string().min(1, { message: "Base amount is required" }),
|
||||||
|
taxAmount: z.string().min(1, { message: "Tax amount is required" }),
|
||||||
|
totalAmount: z.string().min(1, { message: "Total amount is required" }),
|
||||||
|
paymentDueDate: z.string().nullable(),
|
||||||
|
TransportCharges: z.string().nullable(),
|
||||||
|
description: z.string().min(1, { message: "description is required" }),
|
||||||
|
});
|
||||||
|
|
||||||
|
// deliveryChallanNo: z
|
||||||
|
// .string()
|
||||||
|
// .min(1, { message: "Delivery Challan No is required" }),
|
||||||
|
// deliveryDate: z.string().min(1, { message: "Delevery Date is required" }),
|
||||||
|
// shippingAddress: z.string().min(1, { message: "Delevery Date is required" }),
|
||||||
|
|
||||||
|
export const defaultPurchaseValue = {
|
||||||
|
title: null,
|
||||||
|
projectId: null,
|
||||||
|
organizationId: null,
|
||||||
|
billingAddress: null,
|
||||||
|
shippingAddress: null,
|
||||||
|
purchaseOrderNumber: null,
|
||||||
|
purchaseOrderDate: null,
|
||||||
|
supplier: null,
|
||||||
|
porformaInvoiceNo: null,
|
||||||
|
|
||||||
|
invoiceNo: null,
|
||||||
|
invoiceDate: null,
|
||||||
|
ewayBillNo: null,
|
||||||
|
ewayBillDate: null,
|
||||||
|
irnNo: null,
|
||||||
|
ackDate: null,
|
||||||
|
ackNo: null,
|
||||||
|
|
||||||
|
baseAmount: null,
|
||||||
|
taxAmount: null,
|
||||||
|
totalAmount: null,
|
||||||
|
paymentDueDate: null,
|
||||||
|
TransportCharges: null,
|
||||||
|
description: null,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getStepFields = (stepIndex) => {
|
||||||
|
const stepFieldMap = {
|
||||||
|
0: [
|
||||||
|
"title",
|
||||||
|
"projectId",
|
||||||
|
"organizationId",
|
||||||
|
"supplier",
|
||||||
|
"billingAddress",
|
||||||
|
"shippingAddress",
|
||||||
|
"purchaseOrderNumber",
|
||||||
|
"purchaseOrderDate",
|
||||||
|
"porformaInvoiceNo",
|
||||||
|
],
|
||||||
|
1: [
|
||||||
|
"invoiceNo",
|
||||||
|
"invoiceDate",
|
||||||
|
"ewayBillNo",
|
||||||
|
"ewayBillDate",
|
||||||
|
"irnNo",
|
||||||
|
"ackNo",
|
||||||
|
"taxId",
|
||||||
|
"ackDate",
|
||||||
|
],
|
||||||
|
2: [
|
||||||
|
"baseAmount",
|
||||||
|
"taxAmount",
|
||||||
|
"totalAmount",
|
||||||
|
"TransportCharges",
|
||||||
|
"paymentDueDate",
|
||||||
|
"description",
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
return stepFieldMap[stepIndex] || [];
|
||||||
|
};
|
||||||
11
src/components/purchase/PurchaseTansportDetails.jsx
Normal file
11
src/components/purchase/PurchaseTansportDetails.jsx
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import React from 'react'
|
||||||
|
|
||||||
|
const PurchaseTansportDetails = () => {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PurchaseTansportDetails
|
||||||
@ -1,6 +1,6 @@
|
|||||||
import { useForm, Controller,FormProvider } from "react-hook-form";
|
import { useForm, Controller, FormProvider, useFormContext } from "react-hook-form";
|
||||||
|
|
||||||
export const useAppForm = (config) => useForm(config);
|
export const useAppForm = (config) => useForm(config);
|
||||||
export const AppFormProvider = FormProvider;
|
export const AppFormProvider = FormProvider;
|
||||||
export const AppFormController = Controller;
|
export const AppFormController = Controller;
|
||||||
|
export const useAppFormContext = useFormContext;
|
||||||
|
|||||||
57
src/pages/purchase/PurchasePage.jsx
Normal file
57
src/pages/purchase/PurchasePage.jsx
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
import React, { createContext, useContext, useState } from "react";
|
||||||
|
import Breadcrumb from "../../components/common/Breadcrumb";
|
||||||
|
import showToast from "../../services/toastService";
|
||||||
|
import GlobalModel from "../../components/common/GlobalModel";
|
||||||
|
import ManagePurchase from "../../components/purchase/ManagePurchase";
|
||||||
|
|
||||||
|
export const PurchaseContext = createContext();
|
||||||
|
export const usePurchaseContext = () => {
|
||||||
|
let context = useContext(PurchaseContext);
|
||||||
|
|
||||||
|
if (!context) {
|
||||||
|
showToast("Please use Innne cntext", "warning");
|
||||||
|
window.location = "/dashboard";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const PurchasePage = () => {
|
||||||
|
const [addePurchase, setAddedPurchase] = useState(false);
|
||||||
|
|
||||||
|
const contextValue = {};
|
||||||
|
return (
|
||||||
|
<PurchaseContext.Provider value={contextValue}>
|
||||||
|
<div className="container-fluid">
|
||||||
|
<Breadcrumb
|
||||||
|
data={[
|
||||||
|
{ label: "Home", link: "/dashboard" },
|
||||||
|
{ label: "Procurement & Inventory", link: "/purchase-invoice" },
|
||||||
|
{ label: "Purchase" },
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
<div className="card">
|
||||||
|
<div className="row p-2">
|
||||||
|
<di className="col-12 text-end">
|
||||||
|
<button
|
||||||
|
className="btn btn-sm btn-primary"
|
||||||
|
onClick={() => setAddedPurchase(true)}
|
||||||
|
>
|
||||||
|
<i className="bx bx-plus-circle me-2"></i>Add
|
||||||
|
</button>
|
||||||
|
</di>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* MOdals */}
|
||||||
|
|
||||||
|
<GlobalModel
|
||||||
|
isOpen={addePurchase}
|
||||||
|
size="lg"
|
||||||
|
closeModal={() => setAddedPurchase(false)}
|
||||||
|
>
|
||||||
|
<ManagePurchase onClose={() => () => setAddedPurchase(false)} />
|
||||||
|
</GlobalModel>
|
||||||
|
</div>
|
||||||
|
</PurchaseContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default PurchasePage;
|
||||||
@ -62,6 +62,7 @@ import AdvancePaymentPage from "../pages/AdvancePayment/AdvancePaymentPage";
|
|||||||
import ServiceProjectDetail from "../pages/ServiceProject/ServiceProjectDetail";
|
import ServiceProjectDetail from "../pages/ServiceProject/ServiceProjectDetail";
|
||||||
import ManageJob from "../components/ServiceProject/ServiceProjectJob/ManageJob";
|
import ManageJob from "../components/ServiceProject/ServiceProjectJob/ManageJob";
|
||||||
import AdvancePaymentPage1 from "../pages/AdvancePayment/AdvancePaymentPage1";
|
import AdvancePaymentPage1 from "../pages/AdvancePayment/AdvancePaymentPage1";
|
||||||
|
import PurchasePage from "../pages/purchase/PurchasePage";
|
||||||
const router = createBrowserRouter(
|
const router = createBrowserRouter(
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
@ -113,6 +114,8 @@ const router = createBrowserRouter(
|
|||||||
{ path: "/activities/task", element: <TaskPlannng /> },
|
{ path: "/activities/task", element: <TaskPlannng /> },
|
||||||
{ path: "/activities/reports", element: <Reports /> },
|
{ path: "/activities/reports", element: <Reports /> },
|
||||||
{ path: "/gallary", element: <ImageGalleryPage /> },
|
{ path: "/gallary", element: <ImageGalleryPage /> },
|
||||||
|
|
||||||
|
// Finance
|
||||||
{ path: "/expenses/:status?/:project?", element: <ExpensePage /> },
|
{ path: "/expenses/:status?/:project?", element: <ExpensePage /> },
|
||||||
{ path: "/expenses", element: <ExpensePage /> },
|
{ path: "/expenses", element: <ExpensePage /> },
|
||||||
{ path: "/payment-request", element: <PaymentRequestPage /> },
|
{ path: "/payment-request", element: <PaymentRequestPage /> },
|
||||||
@ -120,6 +123,10 @@ const router = createBrowserRouter(
|
|||||||
{ path: "/advance-payment", element: <AdvancePaymentPage1 /> },
|
{ path: "/advance-payment", element: <AdvancePaymentPage1 /> },
|
||||||
{ path: "/advance-payment/:employeeId", element: <AdvancePaymentPage /> },
|
{ path: "/advance-payment/:employeeId", element: <AdvancePaymentPage /> },
|
||||||
{ path: "/collection", element: <CollectionPage /> },
|
{ path: "/collection", element: <CollectionPage /> },
|
||||||
|
|
||||||
|
// Purchases and Inventory
|
||||||
|
{ path: "/purchase-invoice", element: <PurchasePage /> },
|
||||||
|
// Administration
|
||||||
{ path: "/masters", element: <MasterPage /> },
|
{ path: "/masters", element: <MasterPage /> },
|
||||||
{ path: "/tenants", element: <TenantPage /> },
|
{ path: "/tenants", element: <TenantPage /> },
|
||||||
{ path: "/tenants/new-tenant", element: <CreateTenant /> },
|
{ path: "/tenants/new-tenant", element: <CreateTenant /> },
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user