Adding Radio Buttons at Manage Recurring Expense.

This commit is contained in:
Kartik Sharma 2025-11-05 16:19:44 +05:30
parent 92fa1c9a3d
commit ac9eaa1e67
4 changed files with 98 additions and 132 deletions

View File

@ -1,6 +1,6 @@
import React, { useEffect, useState } from 'react'
import Label from '../common/Label';
import { useForm } from 'react-hook-form';
import { Controller, useForm } from 'react-hook-form';
import { useExpenseCategory, useRecurringStatus } from '../../hooks/masterHook/useMaster';
import DatePicker from '../common/DatePicker';
import { zodResolver } from '@hookform/resolvers/zod';
@ -11,24 +11,16 @@ import { useCreateRecurringExpense, usePayee, useUpdateRecurringExpense } from '
import InputSuggestions from '../common/InputSuggestion';
function ManageRecurringExpense({ closeModal, requestToEdit = null }) {
const data = {}
const { projectNames, loading: projectLoading, error, isError: isProjectError,
} = useProjectName();
//APIs
const { projectNames, loading: projectLoading, error, isError: isProjectError, } = useProjectName();
const { data: currencyData, isLoading: currencyLoading, isError: currencyError } = useCurrencies();
const { data: statusData, isLoading: statusLoading, isError: statusError } = useRecurringStatus();
const { data: Payees, isLoading: isPayeeLoaing, isError: isPayeeError, error: payeeError } = usePayee()
const {
ExpenseCategories,
loading: ExpenseLoading,
error: ExpenseError,
} = useExpenseCategory();
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,
@ -82,7 +74,6 @@ function ManageRecurringExpense({ closeModal, requestToEdit = null }) {
}, [currencyData, requestToEdit, setValue]);
const onSubmit = (fromdata) => {
let payload = {
...fromdata,
strikeDate: fromdata.strikeDate ? new Date(fromdata.strikeDate).toISOString() : null,
@ -155,7 +146,6 @@ function ManageRecurringExpense({ closeModal, requestToEdit = null }) {
</small>
)}
</div>
</div>
{/* Title and Is Variable */}
@ -177,7 +167,7 @@ function ManageRecurringExpense({ closeModal, requestToEdit = null }) {
)}
</div>
<div className="col-md-6">
{/* <div className="col-md-6">
<Label htmlFor="isVariable" className="form-label" required>
Is Variable
</Label>
@ -194,10 +184,53 @@ function ManageRecurringExpense({ closeModal, requestToEdit = null }) {
{errors.isVariable && (
<small className="danger-text">{errors.isVariable.message}</small>
)}
</div> */}
<div className="col-md-6 mt-2">
<Label htmlFor="isVariable" className="form-label" required>
Payment Type
</Label>
<Controller
name="isVariable"
control={control}
defaultValue={defaultRecurringExpense.isVariable ?? false}
render={({ field }) => (
<div className="d-flex align-items-center gap-3">
<div className="form-check">
<input
type="radio"
id="isVariableTrue"
className="form-check-input"
checked={field.value === true}
onChange={() => field.onChange(true)}
/>
<Label htmlFor="isVariableTrue" className="form-check-label">
Is Variable
</Label>
</div>
<div className="form-check">
<input
type="radio"
id="isVariableFalse"
className="form-check-input"
checked={field.value === false}
onChange={() => field.onChange(false)}
/>
<Label htmlFor="isVariableFalse" className="form-check-label">
Fixed
</Label>
</div>
</div>
)}
/>
{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">
@ -210,7 +243,6 @@ function ManageRecurringExpense({ closeModal, requestToEdit = null }) {
minDate={new Date()}
className='w-100'
/>
{errors.strikeDate && (
<small className="danger-text">
{errors.strikeDate.message}
@ -239,24 +271,6 @@ function ManageRecurringExpense({ closeModal, requestToEdit = null }) {
{/* 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="payee" className="form-label" required>
Payee (Supplier Name/Transporter Name/Other)
@ -269,10 +283,8 @@ function ManageRecurringExpense({ closeModal, requestToEdit = null }) {
}
error={errors.payee?.message}
/>
</div>
<div className="col-md-6">
<Label htmlFor="currencyId" className="form-label" required>
Currency
@ -298,10 +310,9 @@ function ManageRecurringExpense({ closeModal, requestToEdit = null }) {
<small className="danger-text">{errors.currencyId.message}</small>
)}
</div>
</div>
{/* Notify To and Status Id */}
{/* Frequency To and Status Id */}
<div className="row my-2 text-start">
<div className="col-md-6">
<Label htmlFor="frequency" className="form-label" required>
@ -344,7 +355,6 @@ function ManageRecurringExpense({ closeModal, requestToEdit = null }) {
<small className="danger-text">{errors.statusId.message}</small>
)}
</div>
</div>
{/* Payment Buffer Days and Number of Iteration */}
@ -383,14 +393,11 @@ function ManageRecurringExpense({ closeModal, requestToEdit = null }) {
</div>
</div>
{/* Frequency */}
{/* Notify */}
<div className="row my-2 text-start">
<div className="col-md-6">
<Label htmlFor="notifyTo" className="form-label" required>
Notify (E-mail)
Notify Employees
</Label>
<input
type="text"
@ -427,28 +434,6 @@ function ManageRecurringExpense({ closeModal, requestToEdit = null }) {
</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"
@ -464,8 +449,6 @@ function ManageRecurringExpense({ closeModal, requestToEdit = null }) {
Submit
</button>
</div>
</form>
</div>
)

View File

@ -29,12 +29,12 @@ const RecurringExpenseList = ({ search, filterStatuses }) => {
);
const recurringExpenseColumns = [
{
key: "recurringPaymentUId",
label: "Recurring Payment ID",
align: "text-start ps-2",
getValue: (e) => e?.recurringPaymentUId || "N/A",
},
// {
// key: "recurringPaymentUId",
// label: "Recurring Payment ID",
// align: "text-start ps-2",
// getValue: (e) => e?.recurringPaymentUId || "N/A",
// },
{
key: "expenseCategory",
label: "Category",
@ -47,22 +47,13 @@ const RecurringExpenseList = ({ search, filterStatuses }) => {
align: "text-start",
getValue: (e) => e?.title || "N/A",
},
{
key: "strikeDate",
label: "Strike Date",
align: "text-center",
getValue: (e) =>
e?.strikeDate ? formatUTCToLocalTime(e.strikeDate) : "N/A",
},
{
key: "amount",
label: "Amount",
align: "text-end",
getValue: (e) =>
e?.amount
? `${e?.currency?.symbol || ""}${e.amount.toLocaleString()}`
: "N/A",
},
// {
// key: "strikeDate",
// label: "Strike Date",
// align: "text-center",
// getValue: (e) =>
// e?.strikeDate ? formatUTCToLocalTime(e.strikeDate) : "N/A",
// },
{
key: "payee",
label: "Payee",
@ -79,14 +70,25 @@ const RecurringExpenseList = ({ search, filterStatuses }) => {
: "N/A",
},
{
key: "latestPRGeneratedAt",
label: "Last Generation Date",
align: "text-center",
key: "amount",
label: "Amount",
align: "text-end",
getValue: (e) =>
e?.latestPRGeneratedAt
? formatUTCToLocalTime(e.latestPRGeneratedAt)
e?.amount
? `${e?.currency?.symbol || ""}${e.amount.toLocaleString()}`
: "N/A",
},
// {
// key: "latestPRGeneratedAt",
// label: "Last Generation Date",
// align: "text-center",
// getValue: (e) =>
// e?.latestPRGeneratedAt
// ? formatUTCToLocalTime(e.latestPRGeneratedAt)
// : "N/A",
// },
{
key: "createdAt",
label: "Next Generation Date",
@ -124,10 +126,15 @@ const RecurringExpenseList = ({ search, filterStatuses }) => {
}
const header = [
"Template Name",
"Recurring Payment ID",
"Category",
"Title",
"Strike Date",
"Amount",
"Payee",
"Frequency",
"Next Generation Date",
"Last Generation Date",
"Next Generation",
"Status",
"Action",
];
@ -197,7 +204,7 @@ const RecurringExpenseList = ({ search, filterStatuses }) => {
<tbody>
{filteredData.length > 0 ? (
filteredData.map((recurringExpense) => (
<tr key={recurringExpense.id} className="align-middle" style={{ height: "40px" }}>
<tr key={recurringExpense.id} className="align-middle" style={{ height: "50px" }}>
{recurringExpenseColumns.map((col) => (
<td
key={col.key}
@ -209,7 +216,7 @@ const RecurringExpenseList = ({ search, filterStatuses }) => {
</td>
))}
<td className="sticky-action-column bg-white">
<div className="d-flex justify-content-center gap-2">
<div className="d-flex justify-content-center gap-0">
<i
className="bx bx-show text-primary cursor-pointer"
// onClick={() =>
@ -234,7 +241,7 @@ const RecurringExpenseList = ({ search, filterStatuses }) => {
onClick={() =>
setManageRequest({
IsOpen: true,
RequestId: recurringExpense.id,
projectId: project.id,
})
}
>
@ -258,7 +265,6 @@ const RecurringExpenseList = ({ search, filterStatuses }) => {
</ul>
</div>
</div>
</td>
</tr>

View File

@ -64,7 +64,9 @@ export const PaymentRecurringExpense = (expenseTypes) => {
required_error: "Frequency is required",
invalid_type_error: "Frequency must be a number",
})
.min(1, { message: "Frequency must be greater than 0" }),
.refine((val) => [0, 1, 2, 3, 4, 5].includes(val), {
message: "Invalid frequency selected",
}),
isVariable: z.boolean().optional(),
});
@ -85,7 +87,7 @@ export const defaultRecurringExpense = {
expenseCategoryId: "",
statusId: "",
frequency: 1,
isVariable: false,
isVariable: true,
};
@ -106,15 +108,5 @@ export const SearchRecurringExpenseSchema = z.object({
isVariable: z.string().optional(),
});
// export const defaultPaymentRequestFilter = {
// projectIds: [],
// statusIds: [],
// createdByIds: [],
// currencyIds: [],
// expenseCategoryIds: [],
// payees: [],
// startDate: null,
// endDate: null,
// };

View File

@ -21,7 +21,6 @@ const RecurringExpensePage = () => {
RecurringId: null,
});
const [ViewRequest, setVieRequest] = useState({ view: false, requestId: null })
const { setOffcanvasContent, setShowTrigger } = useFab();
const [selectedStatuses, setSelectedStatuses] = useState(
PAYEE_RECURRING_EXPENSE.map((s) => s.id)
@ -34,20 +33,6 @@ const RecurringExpensePage = () => {
setVieRequest
};
useEffect(() => {
setShowTrigger(true);
setOffcanvasContent(
"Payment Request Filters",
// <PaymentRequestFilterPanel onApply={setFilters} />
);
return () => {
setShowTrigger(false);
setOffcanvasContent("", null);
};
}, []);
const handleStatusChange = (id) => {
setSelectedStatuses((prev) =>
prev.includes(id)
@ -73,7 +58,7 @@ const RecurringExpensePage = () => {
<div className="card-body py-2 px-1">
<div className="d-flex flex-wrap align-items-center justify-content-between">
{/* Left side: Search + Filter */}
<div className="d-flex align-items-center gap-2 flex-wrap">
<div className="d-flex align-items-center flex-wrap">
<input
type="search"
className="form-control form-control-sm w-auto"
@ -123,7 +108,7 @@ const RecurringExpensePage = () => {
>
<i className="bx bx-plus-circle me-2"></i>
<span className="d-none d-md-inline-block">
Add Payment Request
Add Recurring Expense
</span>
</button>
</div>