Creating Form for Recurring Expense.
This commit is contained in:
parent
bede21aff2
commit
44a7749cd3
431
src/components/RecurringExpense/ManageRecurringExpense.jsx
Normal file
431
src/components/RecurringExpense/ManageRecurringExpense.jsx
Normal file
@ -0,0 +1,431 @@
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import Label from '../common/Label';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { useExpenseCategory } from '../../hooks/masterHook/useMaster';
|
||||
import DatePicker from '../common/DatePicker';
|
||||
// import { useCreatePaymentRequest, usePaymentRequestDetail, useUpdatePaymentRequest } from '../../hooks/useExpense';
|
||||
|
||||
import { zodResolver } from '@hookform/resolvers/zod';
|
||||
import { defaultRecurringExpense, PaymentRecurringExpense } from './RecurringExpenseSchema';
|
||||
import { INR_CURRENCY_CODE } from '../../utils/constants';
|
||||
import { useCurrencies, useProjectName } from '../../hooks/useProjects';
|
||||
|
||||
function ManageRecurringExpense({ closeModal, requestToEdit = null }) {
|
||||
|
||||
const data = {}
|
||||
const { projectNames, loading: projectLoading, error, isError: isProjectError,
|
||||
} = useProjectName();
|
||||
|
||||
const { data: currencyData, isLoading: currencyLoading, isError: currencyError } = useCurrencies();
|
||||
|
||||
|
||||
const {
|
||||
ExpenseCategories,
|
||||
loading: ExpenseLoading,
|
||||
error: ExpenseError,
|
||||
} = useExpenseCategory();
|
||||
|
||||
const schema = PaymentRecurringExpense();
|
||||
|
||||
const { register, control, watch, handleSubmit, setValue, reset, formState: { errors }, } = useForm({
|
||||
resolver: zodResolver(schema),
|
||||
defaultValues: defaultRecurringExpense,
|
||||
});
|
||||
const handleClose = () => {
|
||||
reset();
|
||||
closeModal();
|
||||
};
|
||||
|
||||
// const { mutate: CreatePaymentRequest, isPending: createPending } = useCreatePaymentRequest(
|
||||
// () => {
|
||||
// handleClose();
|
||||
// }
|
||||
// );
|
||||
// const { mutate: PaymentRequestUpdate, isPending } = useUpdatePaymentRequest(() =>
|
||||
// handleClose()
|
||||
// );
|
||||
|
||||
useEffect(() => {
|
||||
if (requestToEdit && data) {
|
||||
reset({
|
||||
title: data.title || "",
|
||||
description: data.description || "",
|
||||
payee: data.payee || "",
|
||||
notifyTo: data.notifyTo || "",
|
||||
currencyId: data.currency.id || "",
|
||||
amount: data.amount || "",
|
||||
strikeDate: data.strikeDate?.slice(0, 10) || "",
|
||||
projectId: data.project.id || "",
|
||||
paymentBufferDays: data.paymentBufferDays || "",
|
||||
numberOfIteration: data.numberOfIteration || "",
|
||||
expenseCategoryId: data.expenseCategory.id || "",
|
||||
statusId: data.statusId || "",
|
||||
frequency: data.frequency || "",
|
||||
isVariable: data.isVariable || false,
|
||||
|
||||
});
|
||||
}
|
||||
}, [data, reset]);
|
||||
|
||||
// console.log("Veer",data)
|
||||
|
||||
const onSubmit = (fromdata) => {
|
||||
|
||||
let payload = {
|
||||
...fromdata,
|
||||
// strikeDate: localToUtc(fromdata.strikeDate),
|
||||
strikeDate: fromdata.strikeDate ? new Date(fromdata.strikeDate).toISOString() : null,
|
||||
};
|
||||
// if (requestToEdit) {
|
||||
// const editPayload = { ...payload, id: data.id};
|
||||
// PaymentRequestUpdate({ id: data.id, payload: editPayload });
|
||||
// } else {
|
||||
// CreatePaymentRequest(payload);
|
||||
// }
|
||||
console.log("Kartik", payload)
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="container p-3">
|
||||
<h5 className="m-0">
|
||||
{requestToEdit ? "Update Payment Request " : "Create Payment Request"}
|
||||
</h5>
|
||||
<form id="expenseForm" onSubmit={handleSubmit(onSubmit)}>
|
||||
{/* Project and Category */}
|
||||
<div className="row my-2 text-start">
|
||||
<div className="col-md-6">
|
||||
<Label className="form-label" required>
|
||||
Select Project
|
||||
</Label>
|
||||
<select
|
||||
className="form-select form-select-sm"
|
||||
{...register("projectId")}
|
||||
>
|
||||
<option value="">Select Project</option>
|
||||
{projectLoading ? (
|
||||
<option>Loading...</option>
|
||||
) : (
|
||||
projectNames?.map((project) => (
|
||||
<option key={project.id} value={project.id}>
|
||||
{project.name}
|
||||
</option>
|
||||
))
|
||||
)}
|
||||
</select>
|
||||
{errors.projectId && (
|
||||
<small className="danger-text">{errors.projectId.message}</small>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="col-md-6">
|
||||
<Label htmlFor="expenseCategoryId" className="form-label" required>
|
||||
Expense Category
|
||||
</Label>
|
||||
<select
|
||||
className="form-select form-select-sm"
|
||||
id="expenseCategoryId"
|
||||
{...register("expenseCategoryId")}
|
||||
>
|
||||
<option value="" disabled>
|
||||
Select Category
|
||||
</option>
|
||||
{ExpenseLoading ? (
|
||||
<option disabled>Loading...</option>
|
||||
) : (
|
||||
ExpenseCategories?.map((expense) => (
|
||||
<option key={expense.id} value={expense.id}>
|
||||
{expense.name}
|
||||
</option>
|
||||
))
|
||||
)}
|
||||
</select>
|
||||
{errors.expenseCategoryId && (
|
||||
<small className="danger-text">
|
||||
{errors.expenseCategoryId.message}
|
||||
</small>
|
||||
)}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
{/* Title and Is Variable */}
|
||||
<div className="row my-2 text-start">
|
||||
<div className="col-md-6">
|
||||
<Label htmlFor="title" className="form-label" required>
|
||||
Title
|
||||
</Label>
|
||||
<input
|
||||
type="text"
|
||||
id="title"
|
||||
className="form-control form-control-sm"
|
||||
{...register("title")}
|
||||
/>
|
||||
{errors.title && (
|
||||
<small className="danger-text">
|
||||
{errors.title.message}
|
||||
</small>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="col-md-6">
|
||||
<Label htmlFor="isVariable" className="form-label" required>
|
||||
Is Variable
|
||||
</Label>
|
||||
<select
|
||||
id="isVariable"
|
||||
className="form-select form-select-sm"
|
||||
{...register("isVariable", {
|
||||
setValueAs: (v) => v === "true" ? true : v === "false" ? false : false,
|
||||
})}
|
||||
>
|
||||
<option value="false">False</option>
|
||||
<option value="true">True</option>
|
||||
</select>
|
||||
{errors.isVariable && (
|
||||
<small className="danger-text">{errors.isVariable.message}</small>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
{/* Date and Amount */}
|
||||
<div className="row my-2 text-start">
|
||||
<div className="col-md-6">
|
||||
<Label htmlFor="strikeDate" className="form-label" required>
|
||||
Strike Date
|
||||
</Label>
|
||||
<DatePicker
|
||||
name="strikeDate"
|
||||
control={control}
|
||||
minDate={new Date()}
|
||||
className='w-100'
|
||||
/>
|
||||
|
||||
{errors.strikeDate && (
|
||||
<small className="danger-text">
|
||||
{errors.strikeDate.message}
|
||||
</small>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="col-md-6">
|
||||
<Label htmlFor="amount" className="form-label" required>
|
||||
Amount
|
||||
</Label>
|
||||
<input
|
||||
type="number"
|
||||
id="amount"
|
||||
className="form-control form-control-sm"
|
||||
min="1"
|
||||
step="0.01"
|
||||
inputMode="decimal"
|
||||
{...register("amount", { valueAsNumber: true })}
|
||||
/>
|
||||
{errors.amount && (
|
||||
<small className="danger-text">{errors.amount.message}</small>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Payee and Currency */}
|
||||
<div className="row my-2 text-start">
|
||||
<div className="col-md-6">
|
||||
<Label htmlFor="payee" className="form-label" required>
|
||||
Payee (Supplier Name/Transporter Name/Other)
|
||||
</Label>
|
||||
<input
|
||||
type="text"
|
||||
id="payee"
|
||||
className="form-control form-control-sm"
|
||||
{...register("payee")}
|
||||
|
||||
/>
|
||||
{errors.payee && (
|
||||
<small className="danger-text">
|
||||
{errors.payee.message}
|
||||
</small>
|
||||
)}
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div className="col-md-6">
|
||||
<Label htmlFor="currencyId" className="form-label" required>
|
||||
Currency
|
||||
</Label>
|
||||
<select
|
||||
id="currencyId"
|
||||
className="form-select form-select-sm"
|
||||
{...register("currencyId")}
|
||||
>
|
||||
<option value="">Select Currency</option>
|
||||
|
||||
{currencyLoading && <option>Loading...</option>}
|
||||
|
||||
{!currencyLoading &&
|
||||
!currencyError &&
|
||||
currencyData?.map((currency) => (
|
||||
<option key={currency.id} value={currency.id}>
|
||||
{`${currency.currencyName} (${currency.symbol})`}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
{errors.currencyId && (
|
||||
<small className="danger-text">{errors.currencyId.message}</small>
|
||||
)}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
{/* Notify To and Status Id */}
|
||||
<div className="row my-2 text-start">
|
||||
<div className="col-md-6">
|
||||
<Label htmlFor="notifyTo" className="form-label" required>
|
||||
Notify (E-mail)
|
||||
</Label>
|
||||
<input
|
||||
type="text"
|
||||
id="notifyTo"
|
||||
className="form-control form-control-sm"
|
||||
{...register("notifyTo")}
|
||||
|
||||
/>
|
||||
{errors.notifyTo && (
|
||||
<small className="danger-text">
|
||||
{errors.notifyTo.message}
|
||||
</small>
|
||||
)}
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div className="col-md-6">
|
||||
<Label htmlFor="statusId" className="form-label" required>
|
||||
Status
|
||||
</Label>
|
||||
<select
|
||||
id="statusId"
|
||||
className="form-select form-select-sm"
|
||||
{...register("statusId")}
|
||||
>
|
||||
<option value="">Select Currency</option>
|
||||
|
||||
{currencyLoading && <option>Loading...</option>}
|
||||
|
||||
{!currencyLoading &&
|
||||
!currencyError &&
|
||||
currencyData?.map((currency) => (
|
||||
<option key={currency.id} value={currency.id}>
|
||||
{`${currency.currencyName} (${currency.symbol})`}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
{errors.statusId && (
|
||||
<small className="danger-text">{errors.statusId.message}</small>
|
||||
)}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
{/* Payment Buffer Days and Number of Iteration */}
|
||||
<div className="row my-2 text-start">
|
||||
|
||||
<div className="col-md-6">
|
||||
<Label htmlFor="paymentBufferDays" className="form-label" required>
|
||||
Payment Buffer Days
|
||||
</Label>
|
||||
<input
|
||||
type="number"
|
||||
id="paymentBufferDays"
|
||||
className="form-control form-control-sm"
|
||||
min="0"
|
||||
step="1"
|
||||
{...register("paymentBufferDays", { valueAsNumber: true })}
|
||||
/>
|
||||
{errors.paymentBufferDays && (
|
||||
<small className="danger-text">{errors.paymentBufferDays.message}</small>
|
||||
)}
|
||||
</div>
|
||||
<div className="col-md-6">
|
||||
<Label htmlFor="numberOfIteration" className="form-label" required>
|
||||
Number of Iteration
|
||||
</Label>
|
||||
<input
|
||||
type="number"
|
||||
id="numberOfIteration"
|
||||
className="form-control form-control-sm"
|
||||
min="1"
|
||||
step="1"
|
||||
{...register("numberOfIteration", { valueAsNumber: true })}
|
||||
/>
|
||||
{errors.numberOfIteration && (
|
||||
<small className="danger-text">{errors.numberOfIteration.message}</small>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Description */}
|
||||
<div className="row my-2 text-start">
|
||||
<div className="col-md-12">
|
||||
<Label htmlFor="description" className="form-label" required>
|
||||
Description
|
||||
</Label>
|
||||
<textarea
|
||||
id="description"
|
||||
className="form-control form-control-sm"
|
||||
{...register("description")}
|
||||
rows="2"
|
||||
></textarea>
|
||||
{errors.description && (
|
||||
<small className="danger-text">
|
||||
{errors.description.message}
|
||||
</small>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* <div className="d-flex justify-content-end gap-3">
|
||||
<button
|
||||
type="reset"
|
||||
// disabled={createPending}
|
||||
onClick={handleClose}
|
||||
className="btn btn-label-secondary btn-sm mt-3"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
<button
|
||||
type="submit"
|
||||
className="btn btn-primary btn-sm mt-3"
|
||||
// disabled={createPending}
|
||||
>
|
||||
{createPending
|
||||
? "Please Wait..."
|
||||
: requestToEdit
|
||||
? "Update"
|
||||
: "Submit"}
|
||||
</button>
|
||||
</div> */}
|
||||
|
||||
<div className="d-flex justify-content-end gap-3">
|
||||
<button
|
||||
type="reset"
|
||||
onClick={handleClose}
|
||||
className="btn btn-label-secondary btn-sm mt-3"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
<button
|
||||
type="submit"
|
||||
className="btn btn-primary btn-sm mt-3"
|
||||
>
|
||||
Submit
|
||||
</button>
|
||||
</div>
|
||||
|
||||
|
||||
</form>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default ManageRecurringExpense
|
||||
158
src/components/RecurringExpense/RecurringExpenseSchema.js
Normal file
158
src/components/RecurringExpense/RecurringExpenseSchema.js
Normal file
@ -0,0 +1,158 @@
|
||||
import { boolean, z } from "zod";
|
||||
import { INR_CURRENCY_CODE } from "../../utils/constants";
|
||||
|
||||
// export const PaymentRecurringExpense = (expenseTypes) => {
|
||||
// return z
|
||||
// .object({
|
||||
// title: z.string().min(1, { message: "Project is required" }),
|
||||
|
||||
// description: z.string().min(1, { message: "Description is required" }),
|
||||
|
||||
// payee: z.string().min(1, { message: "Supplier name is required" }),
|
||||
|
||||
// notifyTo: z.string().min(1, { message: "Notification is required" }),
|
||||
|
||||
// currencyId: z
|
||||
// .string()
|
||||
// .min(1, { message: "Currency is required" }),
|
||||
|
||||
// amount: z.coerce
|
||||
// .number({
|
||||
// invalid_type_error: "Amount is required and must be a number",
|
||||
// })
|
||||
// .min(1, "Amount must be Enter")
|
||||
// .refine((val) => /^\d+(\.\d{1,2})?$/.test(val.toString()), {
|
||||
// message: "Amount must have at most 2 decimal places",
|
||||
// }),
|
||||
|
||||
// strikeDate: z.string().min(1, { message: "Date is required" }),
|
||||
|
||||
// projectId: z.string().min(1, { message: "Project is required" }),
|
||||
|
||||
// paymentBufferDays: z.string().min(1, { message: "Buffer days is required" }),
|
||||
|
||||
// numberOfIteration: z.string().min(1, { message: "Iteration is required" }),
|
||||
|
||||
// expenseCategoryId: z
|
||||
// .string()
|
||||
// .min(1, { message: "Expense Category is required" }),
|
||||
|
||||
// statusId: z.string().min(1, { message: "Please select a status" }),
|
||||
|
||||
// frequency: z.string().min(1, { message: "Frequency is required" }),
|
||||
|
||||
// isVariable: z.boolean().optional(),
|
||||
|
||||
// })
|
||||
// };
|
||||
|
||||
|
||||
export const PaymentRecurringExpense = (expenseTypes) => {
|
||||
return z.object({
|
||||
title: z.string().min(1, { message: "Project is required" }),
|
||||
|
||||
description: z.string().min(1, { message: "Description is required" }),
|
||||
|
||||
payee: z.string().min(1, { message: "Supplier name is required" }),
|
||||
|
||||
notifyTo: z.string().min(1, { message: "Notification is required" }),
|
||||
|
||||
currencyId: z
|
||||
.string()
|
||||
.min(1, { message: "Currency is required" }),
|
||||
|
||||
amount: z
|
||||
.number({
|
||||
required_error: "Amount is required",
|
||||
invalid_type_error: "Amount must be a number",
|
||||
})
|
||||
.min(1, { message: "Amount must be greater than 0" })
|
||||
.refine((val) => /^\d+(\.\d{1,2})?$/.test(val.toString()), {
|
||||
message: "Amount must have at most 2 decimal places",
|
||||
}),
|
||||
|
||||
strikeDate: z
|
||||
.string()
|
||||
.min(1, { message: "Date is required" })
|
||||
.refine((val) => !isNaN(Date.parse(val)), {
|
||||
message: "Invalid date format",
|
||||
}),
|
||||
|
||||
projectId: z
|
||||
.string()
|
||||
.min(1, { message: "Project is required" }),
|
||||
|
||||
paymentBufferDays: z
|
||||
.number({
|
||||
required_error: "Buffer days is required",
|
||||
invalid_type_error: "Buffer days must be a number",
|
||||
})
|
||||
.min(0, { message: "Buffer days cannot be negative" }),
|
||||
|
||||
numberOfIteration: z
|
||||
.number({
|
||||
required_error: "Iteration is required",
|
||||
invalid_type_error: "Iteration must be a number",
|
||||
})
|
||||
.min(1, { message: "Iteration must be at least 1" }),
|
||||
|
||||
expenseCategoryId: z
|
||||
.string()
|
||||
.min(1, { message: "Expense Category is required" }),
|
||||
|
||||
statusId: z
|
||||
.string()
|
||||
.min(1, { message: "Please select a status" }),
|
||||
|
||||
frequency: z
|
||||
.number({
|
||||
required_error: "Frequency is required",
|
||||
invalid_type_error: "Frequency must be a number",
|
||||
})
|
||||
.min(1, { message: "Frequency must be greater than 0" }),
|
||||
|
||||
isVariable: z.boolean().optional(),
|
||||
});
|
||||
};
|
||||
|
||||
export const defaultRecurringExpense = {
|
||||
title: "",
|
||||
description: "",
|
||||
payee: "",
|
||||
notifyTo: "",
|
||||
currencyId: "",
|
||||
amount: 0,
|
||||
strikeDate: "", // or null if your DatePicker accepts null
|
||||
projectId: "",
|
||||
paymentBufferDays: 0,
|
||||
numberOfIteration: 1,
|
||||
expenseCategoryId: "",
|
||||
statusId: "",
|
||||
frequency: 1,
|
||||
isVariable: false,
|
||||
};
|
||||
|
||||
|
||||
// export const SearchPaymentRequestSchema = z.object({
|
||||
// projectIds: z.array(z.string()).optional(),
|
||||
// statusIds: z.array(z.string()).optional(),
|
||||
// createdByIds: z.array(z.string()).optional(),
|
||||
// currencyIds: z.array(z.string()).optional(),
|
||||
// expenseCategoryIds: z.array(z.string()).optional(),
|
||||
// payees: z.array(z.string()).optional(),
|
||||
// startDate: z.string().optional(),
|
||||
// endDate: z.string().optional(),
|
||||
// });
|
||||
|
||||
// export const defaultPaymentRequestFilter = {
|
||||
// projectIds: [],
|
||||
// statusIds: [],
|
||||
// createdByIds: [],
|
||||
// currencyIds: [],
|
||||
// expenseCategoryIds: [],
|
||||
// payees: [],
|
||||
// startDate: null,
|
||||
// endDate: null,
|
||||
// };
|
||||
|
||||
|
||||
132
src/pages/RecurringExpense/RecurringExpensePage.jsx
Normal file
132
src/pages/RecurringExpense/RecurringExpensePage.jsx
Normal file
@ -0,0 +1,132 @@
|
||||
import React, { createContext, useState, useEffect, useContext } from "react";
|
||||
import Breadcrumb from "../../components/common/Breadcrumb";
|
||||
import GlobalModel from "../../components/common/GlobalModel";
|
||||
import { useFab } from "../../Context/FabContext";
|
||||
// import { defaultPaymentRequestFilter,SearchPaymentRequestSchema } from "../../components/PaymentRequest/PaymentRequestSchema";
|
||||
import ManageRecurringExpense from "../../components/RecurringExpense/ManageRecurringExpense";
|
||||
|
||||
export const RecurringExpenseContext = createContext();
|
||||
export const useRecurringExpenseContext = () => {
|
||||
const context = useContext(RecurringExpenseContext);
|
||||
if (!context) {
|
||||
throw new Error("useRecurringExpenseContext must be used within an ExpenseProvider");
|
||||
}
|
||||
return context;
|
||||
};
|
||||
const RecurringExpensePage = () => {
|
||||
const [ManageRequest, setManageRequest] = useState({
|
||||
IsOpen: null,
|
||||
RequestId: null,
|
||||
});
|
||||
const [ViewRequest,setVieRequest] = useState({view:false,requestId:null})
|
||||
const { setOffcanvasContent, setShowTrigger } = useFab();
|
||||
// const [filters, setFilters] = useState(defaultPaymentRequestFilter);
|
||||
|
||||
const [search, setSearch] = useState("");
|
||||
|
||||
const contextValue = {
|
||||
setManageRequest,
|
||||
setVieRequest
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
setShowTrigger(true);
|
||||
setOffcanvasContent(
|
||||
"Payment Request Filters",
|
||||
// <PaymentRequestFilterPanel onApply={setFilters} />
|
||||
);
|
||||
|
||||
return () => {
|
||||
setShowTrigger(false);
|
||||
setOffcanvasContent("", null);
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<RecurringExpenseContext.Provider value={contextValue}>
|
||||
<div className="container-fluid">
|
||||
{/* Breadcrumb */}
|
||||
<Breadcrumb
|
||||
data={[
|
||||
{ label: "Home", link: "/" },
|
||||
{ label: "Finance", link: "/Payment Request" },
|
||||
{ label: "Payment Request" },
|
||||
]}
|
||||
/>
|
||||
|
||||
{/* 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 Payment Req.."
|
||||
value={search}
|
||||
// onChange={(e) => setSearch(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="col-6 text-end mt-2 mt-sm-0">
|
||||
<button
|
||||
className="btn btn-sm btn-primary"
|
||||
type="button"
|
||||
onClick={() =>
|
||||
setManageRequest({
|
||||
IsOpen: true,
|
||||
expenseId: null,
|
||||
})
|
||||
}
|
||||
>
|
||||
<i className="bx bx-plus-circle me-2"></i>
|
||||
<span className="d-none d-md-inline-block">
|
||||
Add Payment Request
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/* <PaymentRequestList
|
||||
search={search}
|
||||
filters={filters}
|
||||
/> */}
|
||||
|
||||
{/* Add/Edit Modal */}
|
||||
{ManageRequest.IsOpen && (
|
||||
<GlobalModel
|
||||
isOpen
|
||||
size="lg"
|
||||
closeModal={() =>
|
||||
setManageRequest({ IsOpen: null, expenseId: null })
|
||||
}
|
||||
>
|
||||
<ManageRecurringExpense
|
||||
key={ManageRequest.RequestId ?? "new"}
|
||||
requestToEdit={ManageRequest.RequestId}
|
||||
closeModal={() =>
|
||||
setManageRequest({ IsOpen: null, RequestId: null })
|
||||
}
|
||||
/>
|
||||
</GlobalModel>
|
||||
)}
|
||||
|
||||
{/* {ViewRequest.view && (
|
||||
<GlobalModel
|
||||
isOpen
|
||||
size="xl"
|
||||
modalType="top"
|
||||
closeModal={() => setVieRequest({ requestId: null, view: false })}
|
||||
>
|
||||
<ViewPaymentRequest requestId={ViewRequest?.requestId}/>
|
||||
</GlobalModel>
|
||||
)} */}
|
||||
|
||||
</div>
|
||||
</RecurringExpenseContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
export default RecurringExpensePage;
|
||||
@ -56,6 +56,7 @@ import { ComingSoonPage } from "../pages/Misc/ComingSoonPage";
|
||||
import CollectionPage from "../pages/collections/CollectionPage";
|
||||
import AdvancePaymentPage from "../pages/AdvancePayment/AdvancePaymentPage";
|
||||
import PaymentRequestPage from "../pages/PaymentRequest/PaymentRequestPage";
|
||||
import RecurringExpensePage from "../pages/RecurringExpense/RecurringExpensePage";
|
||||
const router = createBrowserRouter(
|
||||
[
|
||||
{
|
||||
@ -102,6 +103,7 @@ const router = createBrowserRouter(
|
||||
{ path: "/expenses", element: <ExpensePage /> },
|
||||
{ path: "/payment-request", element: <PaymentRequestPage /> },
|
||||
{ path: "/advance-payment", element: <AdvancePaymentPage /> },
|
||||
{ path: "/recurring-payment", element: <RecurringExpensePage /> },
|
||||
{ path: "/masters", element: <MasterPage /> },
|
||||
{ path: "/tenants", element: <TenantPage /> },
|
||||
{ path: "/tenants/new-tenant", element: <CreateTenant /> },
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user