Creating APi for Create Payemnt Request.
This commit is contained in:
parent
10c2e9dfee
commit
196069b39a
@ -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);
|
||||||
|
|||||||
@ -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>
|
||||||
|
|
||||||
|
|||||||
23
src/hooks/usePaymentRequest.js
Normal file
23
src/hooks/usePaymentRequest.js
Normal 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"
|
||||||
|
);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
@ -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: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
12
src/repositories/PaymentRequestRepository.jsx
Normal file
12
src/repositories/PaymentRequestRepository.jsx
Normal 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;
|
||||||
Loading…
x
Reference in New Issue
Block a user