267 lines
9.6 KiB
JavaScript
267 lines
9.6 KiB
JavaScript
import { zodResolver } from "@hookform/resolvers/zod";
|
|
import React, { useState } from "react";
|
|
import { FormProvider, useForm } from "react-hook-form";
|
|
import { defaultPayment, paymentSchema } from "./collectionSchema";
|
|
import Label from "../common/Label";
|
|
import DatePicker from "../common/DatePicker";
|
|
import { formatDate } from "date-fns";
|
|
import { useCollectionContext } from "../../pages/collections/CollectionPage";
|
|
import { useAddPayment, useCollection } from "../../hooks/useCollections";
|
|
import { formatFigure, localToUtc } from "../../utils/appUtils";
|
|
import { formatUTCToLocalTime } from "../../utils/dateUtils";
|
|
import Avatar from "../common/Avatar";
|
|
import { PaymentHistorySkeleton } from "./CollectionSkeleton";
|
|
import { usePaymentAjustmentHead } from "../../hooks/masterHook/useMaster";
|
|
import { AppFormController } from "../../hooks/appHooks/useAppForm";
|
|
import SelectField from "../common/Forms/SelectField";
|
|
|
|
const AddPayment = ({ onClose }) => {
|
|
const { addPayment } = useCollectionContext();
|
|
const { data, isLoading, isError, error } = useCollection(
|
|
addPayment?.invoiceId
|
|
);
|
|
const {
|
|
data: paymentTypes,
|
|
isLoading: isPaymentTypeLoading,
|
|
isError: isPaymentTypeError,
|
|
error: paymentError,
|
|
} = usePaymentAjustmentHead(true);
|
|
const methods = useForm({
|
|
resolver: zodResolver(paymentSchema),
|
|
defaultValues: defaultPayment,
|
|
});
|
|
const {
|
|
control,
|
|
register,
|
|
handleSubmit,
|
|
reset,
|
|
formState: { errors },
|
|
} = methods;
|
|
const { mutate: AddPayment, isPending } = useAddPayment(() => {
|
|
handleClose();
|
|
});
|
|
const onSubmit = (formData) => {
|
|
const payload = {
|
|
...formData,
|
|
paymentReceivedDate: localToUtc(formData.paymentReceivedDate),
|
|
invoiceId: addPayment.invoiceId,
|
|
};
|
|
AddPayment(payload);
|
|
};
|
|
const handleClose = (formData) => {
|
|
reset(defaultPayment);
|
|
};
|
|
|
|
return (
|
|
<div className="container pb-3">
|
|
<div className="text-black fs-5 mb-2">Add Payment</div>
|
|
<FormProvider {...methods}>
|
|
<form onSubmit={handleSubmit(onSubmit)} className="p-0 text-start">
|
|
<div className="row px-md-1 px-0">
|
|
<div className="col-12 col-md-6 mb-2">
|
|
<Label required>TransanctionId</Label>
|
|
<input
|
|
type="text"
|
|
className="form-control "
|
|
{...register("transactionId")}
|
|
/>
|
|
{errors.transactionId && (
|
|
<small className="danger-text">
|
|
{errors.transactionId.message}
|
|
</small>
|
|
)}
|
|
</div>
|
|
|
|
<div className="col-12 col-md-6 mb-2">
|
|
<Label required>Transaction Date </Label>
|
|
<DatePicker className="w-100"
|
|
name="paymentReceivedDate"
|
|
control={control}
|
|
minDate={
|
|
data?.clientSubmitedDate
|
|
? new Date(
|
|
new Date(data?.clientSubmitedDate).setDate(
|
|
new Date(data?.clientSubmitedDate).getDate() + 1
|
|
)
|
|
)
|
|
: null
|
|
}
|
|
maxDate={new Date()}
|
|
/>
|
|
{errors.paymentReceivedDate && (
|
|
<small className="danger-text">
|
|
{errors.paymentReceivedDate.message}
|
|
</small>
|
|
)}
|
|
</div>
|
|
|
|
<div className="col-12 col-md-6 mb-2">
|
|
<Label htmlFor="paymentAdjustmentHeadId" className="form-label" required>
|
|
Payment Adjustment Head
|
|
</Label>
|
|
|
|
<AppFormController
|
|
name="paymentAdjustmentHeadId"
|
|
control={control}
|
|
rules={{ required: "Payment Adjustment Head is required" }}
|
|
render={({ field }) => (
|
|
<SelectField
|
|
label="" // Label is already above
|
|
placeholder="Select Payment Head"
|
|
options={paymentTypes?.data
|
|
?.sort((a, b) => a.name.localeCompare(b.name)) ?? []}
|
|
value={field.value || ""}
|
|
onChange={field.onChange}
|
|
required
|
|
isLoading={isPaymentTypeLoading}
|
|
className="m-0 form-select-sm w-100"
|
|
/>
|
|
)}
|
|
/>
|
|
|
|
{errors.paymentAdjustmentHeadId && (
|
|
<small className="danger-text">
|
|
{errors.paymentAdjustmentHeadId.message}
|
|
</small>
|
|
)}
|
|
</div>
|
|
|
|
|
|
<div className="col-12 col-md-6 mb-2">
|
|
<Label htmlFor="amount" className="form-label" required>
|
|
Amount
|
|
</Label>
|
|
<input
|
|
type="number"
|
|
id="amount"
|
|
className="form-control "
|
|
min="1"
|
|
step="0.01"
|
|
inputMode="decimal"
|
|
{...register("amount", { valueAsNumber: true })}
|
|
/>
|
|
{errors.amount && (
|
|
<small className="danger-text">{errors.amount.message}</small>
|
|
)}
|
|
</div>
|
|
<div className="col-12 mb-2">
|
|
<Label htmlFor="comment" className="form-label" required>
|
|
Comment
|
|
</Label>
|
|
<textarea
|
|
id="comment"
|
|
className="form-control "
|
|
{...register("comment")}
|
|
/>
|
|
{errors.comment && (
|
|
<small className="danger-text">{errors.comment.message}</small>
|
|
)}
|
|
</div>
|
|
|
|
<div className="d-flex justify-content-end gap-3">
|
|
{" "}
|
|
<button
|
|
type="reset"
|
|
className="btn btn-label-secondary btn-sm mt-3"
|
|
onClick={() => {
|
|
handleClose();
|
|
onClose();
|
|
}}
|
|
disabled={isPending}
|
|
>
|
|
Cancel
|
|
</button>
|
|
<button
|
|
type="submit"
|
|
className="btn btn-primary btn-sm mt-3"
|
|
disabled={isPending}
|
|
>
|
|
{isPending ? "Please Wait..." : "Submit"}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
</FormProvider>
|
|
|
|
{isLoading ? (
|
|
<PaymentHistorySkeleton />
|
|
) : (
|
|
data?.receivedInvoicePayments?.length > 0 && (
|
|
<div className="mt-1 text-start">
|
|
<div className="mb-2 text-secondry fs-6">
|
|
<i className="bx bx-history bx-sm me-1"></i>History
|
|
</div>
|
|
|
|
<div className="row text-start mx-2">
|
|
{data.receivedInvoicePayments
|
|
.sort((a, b) => new Date(b.createdAt) - new Date(a.createdAt))
|
|
.map((payment, index) => (
|
|
<div className="col-12 mb-2" key={payment.id}>
|
|
<div className=" p-2 border-start border-warning">
|
|
<div className="row">
|
|
<div className="col-12 col-md-6 d-flex justify-content-between align-items-center ">
|
|
<div>
|
|
<small className="fw-semibold me-1">
|
|
Transaction Date:
|
|
</small>{" "}
|
|
{formatUTCToLocalTime(payment.paymentReceivedDate)}
|
|
</div>
|
|
<span className="fs-semibold d-block d-md-none">
|
|
{formatFigure(payment.amount, {
|
|
type: "currency",
|
|
currency: "INR",
|
|
})}
|
|
</span>
|
|
</div>
|
|
|
|
<div className="col-12 col-md-6 mb-0 d-flex align-items-center m-0">
|
|
<small className="fw-semibold me-2">
|
|
Updated By:
|
|
</small>{" "}
|
|
<Avatar
|
|
size="xs"
|
|
firstName={payment?.createdBy?.firstName}
|
|
lastName={payment?.createdBy?.lastName}
|
|
/>{" "}
|
|
{payment?.createdBy?.firstName}{" "}
|
|
{payment.createdBy?.lastName}
|
|
</div>
|
|
</div>
|
|
|
|
<div className="row">
|
|
<div className="col-12 col-md-6">
|
|
<p className="mb-1">
|
|
<small className="fw-semibold">
|
|
Transaction ID:
|
|
</small>{" "}
|
|
{payment.transactionId}
|
|
</p>
|
|
</div>
|
|
<div className="col-12 ">
|
|
<div className="d-flex justify-content-between">
|
|
<span>{payment?.paymentAdjustmentHead?.name}</span>
|
|
<span className="fs-semibold d-none d-md-block">
|
|
{formatFigure(payment.amount, {
|
|
type: "currency",
|
|
currency: "INR",
|
|
})}
|
|
</span>
|
|
</div>
|
|
<p className="text-tiny m-0 mt-1">
|
|
{payment?.comment}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
)
|
|
)}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default AddPayment;
|