Creating APi for Create Payemnt Request.

This commit is contained in:
Kartik Sharma 2025-11-01 16:00:00 +05:30
parent 10c2e9dfee
commit 196069b39a
5 changed files with 144 additions and 17 deletions

View File

@ -81,6 +81,7 @@ const ManageExpense = ({ closeModal, expenseToEdit = null }) => {
isLoading: EmpLoading, isLoading: EmpLoading,
isError: isEmployeeError, isError: isEmployeeError,
} = useEmployeesNameByProject(selectedproject); } = useEmployeesNameByProject(selectedproject);
const files = watch("billAttachments"); const files = watch("billAttachments");
const onFileChange = async (e) => { const onFileChange = async (e) => {
const newFiles = Array.from(e.target.files); const newFiles = Array.from(e.target.files);

View File

@ -1,21 +1,30 @@
import React from 'react' import React, { useEffect } from 'react'
import { useProjectName } from '../../hooks/useProjects'; import { useProjectName } from '../../hooks/useProjects';
import Label from '../common/Label'; import Label from '../common/Label';
import { useForm } from 'react-hook-form'; import { useForm } from 'react-hook-form';
import { useExpenseType } from '../../hooks/masterHook/useMaster'; import { useExpenseType } from '../../hooks/masterHook/useMaster';
import DatePicker from '../common/DatePicker'; import DatePicker from '../common/DatePicker';
import { useCreatePaymentRequest } from '../../hooks/usePaymentRequest';
import { defaultPaymentRequest, PaymentRequestSchema } from '../../pages/PaymentRequest/PaymentRequestSchema';
import { zodResolver } from '@hookform/resolvers/zod';
import { formatFileSize, localToUtc } from '../../utils/appUtils';
function ManagePaymentRequest({ closeModal, expenseToEdit = null }) { function ManagePaymentRequest({ closeModal, expenseToEdit = null }) {
const { projectNames, loading: projectLoading, error, isError: isProjectError, const { projectNames, loading: projectLoading, error, isError: isProjectError,
} = useProjectName(); } = useProjectName();
const { register, control, watch,reset, formState: { errors }, } = useForm();
const { const {
ExpenseTypes, ExpenseTypes,
loading: ExpenseLoading, loading: ExpenseLoading,
error: ExpenseError, error: ExpenseError,
} = useExpenseType(); } = useExpenseType();
const schema = PaymentRequestSchema(ExpenseTypes);
const { register, control, watch, handleSubmit, setValue, reset, formState: { errors }, } = useForm({
resolver: zodResolver(schema),
defaultValues: defaultPaymentRequest,
});
const files = watch("billAttachments"); const files = watch("billAttachments");
const onFileChange = async (e) => { const onFileChange = async (e) => {
@ -83,12 +92,60 @@ function ManagePaymentRequest({ closeModal, expenseToEdit = null }) {
closeModal(); closeModal();
}; };
const { mutate: CreatePaymentRequest, isPending: createPending } = useCreatePaymentRequest(
() => {
handleClose();
}
);
// useEffect(() => {
// if (expenseToEdit && data) {
// reset({
// title: data.title || "",
// description: data.description || "",
// payee: data.payee || "",
// currencyId: data.currencyId.id || "",
// amount: data.amount || "",
// dueDate: data.dueDate?.slice(0, 10) || "",
// projectId: data.project.id || "",
// expenseCategoryId: data.expenseCategoryId.id || "",
// isAdvancePayment: data.isAdvancePayment || "",
// billAttachments: data.documents
// ? data.documents.map((doc) => ({
// fileName: doc.fileName,
// base64Data: null,
// contentType: doc.contentType,
// documentId: doc.documentId,
// fileSize: 0,
// description: "",
// preSignedUrl: doc.preSignedUrl,
// isActive: doc.isActive ?? true,
// }))
// : [],
// });
// }
// }, [data, reset, employees]);
const onSubmit = (fromdata) => {
let payload = {
...fromdata,
transactionDate: localToUtc(fromdata.transactionDate),
};
if (expenseToEdit) {
const editPayload = { ...payload, id: data.id };
ExpenseUpdate({ id: data.id, payload: editPayload });
} else {
CreatePaymentRequest(payload);
}
};
return ( return (
<div className="container p-3"> <div className="container p-3">
<h5 className="m-0"> <h5 className="m-0">
{expenseToEdit ? "Update Expense " : "Create New Expense"} {expenseToEdit ? "Update Payment Request " : "Create Payment Request"}
</h5> </h5>
<form> <form id="expenseForm" onSubmit={handleSubmit(onSubmit)}>
<div className="row my-2 text-start"> <div className="row my-2 text-start">
<div className="col-md-6"> <div className="col-md-6">
<Label className="form-label" required> <Label className="form-label" required>
@ -216,6 +273,23 @@ function ManagePaymentRequest({ closeModal, expenseToEdit = null }) {
</div> </div>
</div> </div>
<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>
<div className="row my-2 text-start"> <div className="row my-2 text-start">
<div className="col-md-12"> <div className="col-md-12">
<Label htmlFor="description" className="form-label" required> <Label htmlFor="description" className="form-label" required>
@ -237,7 +311,7 @@ function ManagePaymentRequest({ closeModal, expenseToEdit = null }) {
<div className="row my-2 text-start"> <div className="row my-2 text-start">
<div className="col-md-12"> <div className="col-md-12">
<Label className="form-label" required> <Label className="form-label">
Upload Bill{" "} Upload Bill{" "}
</Label> </Label>
@ -322,19 +396,25 @@ function ManagePaymentRequest({ closeModal, expenseToEdit = null }) {
</div> </div>
</div> </div>
<div className="d-flex justify-content-end gap-3"> <div className="d-flex justify-content-end gap-3">
<button <button
type="reset" type="reset"
disabled={createPending}
onClick={handleClose} onClick={handleClose}
className="btn btn-label-secondary btn-sm mt-3" className="btn btn-label-secondary btn-sm mt-3"
> >
Cancel Cancel
</button> </button>
<button <button
type="submit" type="submit"
className="btn btn-primary btn-sm mt-3" className="btn btn-primary btn-sm mt-3"
disabled={createPending}
> >
Submit {createPending
? "Please Wait..."
: expenseToEdit
? "Update"
: "Submit"}
</button> </button>
</div> </div>

View File

@ -0,0 +1,23 @@
import { useMutation, useQueryClient } from "@tanstack/react-query";
import PaymentRequestRepository from "../repositories/PaymentRequestRepository";
import showToast from "../services/toastService";
export const useCreatePaymentRequest = (onSuccessCallBack) => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: async (payload) => {
await PaymentRequestRepository.CreatePaymentRequest(payload);
},
onSuccess: (_, variables) => {
queryClient.invalidateQueries({ queryKey: ["Expenses"] });
showToast("Expense Created Successfully", "success");
if (onSuccessCallBack) onSuccessCallBack();
},
onError: (error) => {
showToast(
error.message || "Something went wrong please try again !",
"error"
);
},
});
};

View File

@ -1,15 +1,23 @@
import { z } from "zod"; import { z } from "zod";
const MAX_FILE_SIZE = 5 * 1024 * 1024; // 5MB
const ALLOWED_TYPES = [
"application/pdf",
"image/png",
"image/jpg",
"image/jpeg",
];
export const PaymentRequestSchema = (expenseTypes) => { export const PaymentRequestSchema = (expenseTypes) => {
return z return z
.object({ .object({
title: z.string().min(1, { message: "Project is required" }),
projectId: z.string().min(1, { message: "Project is required" }), projectId: z.string().min(1, { message: "Project is required" }),
expensesTypeId: z expenseCategoryId: z
.string() .string()
.min(1, { message: "Expense type is required" }), .min(1, { message: "Expense Category is required" }),
transactionDate: z.string().min(1, { message: "Date is required" }), dueDate: z.string().min(1, { message: "Date is required" }),
description: z.string().min(1, { message: "Description is required" }), description: z.string().min(1, { message: "Description is required" }),
supplerName: z.string().min(1, { message: "Supplier name is required" }), payee: z.string().min(1, { message: "Supplier name is required" }),
isAdvancePayment: z.boolean(),
amount: z.coerce amount: z.coerce
.number({ .number({
invalid_type_error: "Amount is required and must be a number", invalid_type_error: "Amount is required and must be a number",
@ -67,12 +75,15 @@ export const PaymentRequestSchema = (expenseTypes) => {
}; };
export const defaultPaymentRequest = { export const defaultPaymentRequest = {
projectId: "", title:"",
expensesTypeId: "",
transactionDate: "",
description: "", description: "",
supplerName: "", payee: "",
currencyId: "",
amount: "", amount: "",
dueDate: "",
projectId: "",
expenseCategoryId: "",
isAdvancePayment:"",
billAttachments: [], billAttachments: [],
}; };

View File

@ -0,0 +1,12 @@
import { api } from "../utils/axiosClient";
const PaymentRequestRepository = {
CreatePaymentRequest:(data)=>api.post("/api/expense/payment-request/create",data),
}
export default PaymentRequestRepository;