diff --git a/src/components/AdvancePayment/AdvancePaymentList.jsx b/src/components/AdvancePayment/AdvancePaymentList.jsx index 4bbe830a..0f975ab5 100644 --- a/src/components/AdvancePayment/AdvancePaymentList.jsx +++ b/src/components/AdvancePayment/AdvancePaymentList.jsx @@ -1,82 +1,68 @@ import React from "react"; import { useExpenseTransactions } from "../../hooks/useExpense"; +import Error from "../common/Error"; +import { formatUTCToLocalTime } from "../../utils/dateUtils"; +import Loader, { SpinnerLoader } from "../common/Loader"; const AdvancePaymentList = ({ employeeId }) => { - const {data,isError, isLoading,isFetching,error} = useExpenseTransactions(employeeId) - const record = { - openingBalance: 25000.0, - rows: [ - { id: 1, description: "Opening Balance", credit: 0.0, debit: 0.0 }, - { - id: 2, - description: "Sales Invoice #INV-001", - credit: 15000.0, - debit: 0.0, - }, - { - id: 3, - description: "Sales Invoice #INV-002", - credit: 12000.0, - debit: 0.0, - }, - { - id: 4, - description: "Purchase - Raw Materials", - credit: 0.0, - debit: 8000.0, - }, - { id: 5, description: "Office Rent - June", credit: 0.0, debit: 5000.0 }, - { - id: 6, - description: "Client Payment Received (Bank)", - credit: 10000.0, - debit: 0.0, - }, - { - id: 7, - description: "Supplier Payment - ABC Corp", - credit: 0.0, - debit: 6000.0, - }, - { id: 8, description: "Interest Income", credit: 750.0, debit: 0.0 }, - { id: 9, description: "Bank Charges", credit: 0.0, debit: 250.0 }, - { - id: 10, - description: "Utilities - Electricity", - credit: 0.0, - debit: 1800.0, - }, - { - id: 11, - description: "Service Income - Project Alpha", - credit: 5000.0, - debit: 0.0, - }, - { id: 12, description: "Misc Expense", credit: 0.0, debit: 450.0 }, - { - id: 13, - description: "Adjustment - Prior Year", - credit: 0.0, - debit: 500.0, - }, - { id: 14, description: "Commission Earned", credit: 1200.0, debit: 0.0 }, - { - id: 15, - description: "Employee Salary - June", - credit: 0.0, - debit: 9500.0, - }, - { id: 16, description: "GST Refund", credit: 2000.0, debit: 0.0 }, - { id: 17, description: "Insurance Premium", credit: 0.0, debit: 3000.0 }, - { id: 18, description: "Late Fee Collected", credit: 350.0, debit: 0.0 }, - { id: 19, description: "Maintenance Expense", credit: 0.0, debit: 600.0 }, - { id: 20, description: "Closing Balance", credit: 0.0, debit: 0.0 }, - ], - }; - let currentBalance = record.openingBalance; - const rowsWithBalance = record.rows.map((r) => { - currentBalance += r.credit - r.debit; - return { ...r, balance: currentBalance }; + const { data, isError, isLoading, error, isFetching } = + useExpenseTransactions(employeeId, { enabled: !!employeeId }); + + // Handle no employee selected + if (!employeeId) { + return ( +
+

Please select an employee

+
+ ); + } + + // Handle loading state + if (isLoading || isFetching) { + return ( +
+ +
+ ); + } + + // Handle error state + if (isError) { + return ( +
+ {error?.status === 404 ? ( + "No advance payment transactions found." + ) : ( + + )} +
+ ); + } + + const records = Array.isArray(data) ? data : []; + + let currentBalance = 0; + const rowsWithBalance = records.map((r) => { + const isCredit = r.amount > 0; + const credit = isCredit ? r.amount : 0; + const debit = !isCredit ? Math.abs(r.amount) : 0; + currentBalance += credit - debit; + + return { + id: r.id, + description: r.title || "-", + projectName: r.project?.name || "-", + createdAt: r.createdAt, + credit, + debit, + balance: currentBalance, + }; }); const columns = [ @@ -84,36 +70,45 @@ const AdvancePaymentList = ({ employeeId }) => { { key: "credit", label: ( - - Credit () - + <> + Credit + ), align: "text-end", }, { key: "debit", label: ( - - Debit () - + <> + Debit + ), align: "text-end", }, { key: "balance", label: ( - + <> Balance - + ), align: "text-end fw-bold", }, ]; + // Handle empty records + if (rowsWithBalance.length === 0) { + return ( +
+ No advance payment records found. +
+ ); + } + return ( -
- - +
+
+ {columns.map((col) => ( {columns.map((col) => ( - ))} ))} - + ) )}
@@ -126,25 +121,28 @@ const AdvancePaymentList = ({ employeeId }) => { {rowsWithBalance.map((row) => (
- {col.key === "balance" || - col.key === "credit" || - col.key === "debit" - ? row[col.key].toLocaleString("en-IN", { - style: "currency", - currency: "INR", - }) - : (
- {new Date().toISOString()} - Projec Name - {row[col.key]} -
)} +
+ {["balance", "credit", "debit"].includes(col.key) ? ( + + {row[col.key].toLocaleString("en-IN")} + + ) : ( +
+ + {formatUTCToLocalTime(row.createdAt)} + + + {row.projectName} + + {row.description} +
+ )}
Final Balance diff --git a/src/components/Expenses/ExpenseList.jsx b/src/components/Expenses/ExpenseList.jsx index 3b58316e..d7a0a1b4 100644 --- a/src/components/Expenses/ExpenseList.jsx +++ b/src/components/Expenses/ExpenseList.jsx @@ -123,9 +123,9 @@ const ExpenseList = ({ filters, groupBy = "transactionDate", searchText }) => { align: "text-start mx-2", }, { - key: "expensesType", + key: "expensesCategory", label: "Expense Category", - getValue: (e) => e.expensesType?.name || "N/A", + getValue: (e) => e.expenseCategory?.name || "N/A", align: "text-start", }, { @@ -253,7 +253,7 @@ const ExpenseList = ({ filters, groupBy = "transactionDate", searchText }) => { className={`sorting d-table-cell `} aria-sort="descending" > -
{col.label}
+
{col.label}
) )} @@ -288,16 +288,20 @@ const ExpenseList = ({ filters, groupBy = "transactionDate", searchText }) => { (col.isAlwaysVisible || groupBy !== col.key) && (
- {col.customRender +
{col.customRender ? col.customRender(expense) : col.getValue(expense)} +
-
+
diff --git a/src/components/Expenses/ExpenseSchema.js b/src/components/Expenses/ExpenseSchema.js index 46173f1a..ad22e67a 100644 --- a/src/components/Expenses/ExpenseSchema.js +++ b/src/components/Expenses/ExpenseSchema.js @@ -1,5 +1,6 @@ import { z } from "zod"; import { localToUtc } from "../../utils/appUtils"; +import { DEFAULT_CURRENCY } from "../../utils/constants"; const MAX_FILE_SIZE = 5 * 1024 * 1024; // 5MB const ALLOWED_TYPES = [ @@ -24,6 +25,10 @@ export const ExpenseSchema = (expenseTypes) => { location: z.string().min(1, { message: "Location is required" }), supplerName: z.string().min(1, { message: "Supplier name is required" }), gstNumber: z.string().optional(), + currencyId: z + .string() + .min(1, { message: "currency is required" }) + .default(DEFAULT_CURRENCY), amount: z.coerce .number({ invalid_type_error: "Amount is required and must be a number", @@ -94,6 +99,7 @@ export const defaultExpense = { amount: "", noOfPersons: "", gstNumber: "", + currencyId: DEFAULT_CURRENCY, billAttachments: [], }; @@ -108,6 +114,9 @@ export const ExpenseActionScheam = ( reimburseTransactionId: z.string().nullable().optional(), reimburseDate: z.string().nullable().optional(), reimburseById: z.string().nullable().optional(), + tdsPercentage: z.number().nullable().optional(), + baseAmount: z.string().nullable().optional(), + taxAmount: z.string().nullable().optional(), }) .superRefine((data, ctx) => { if (isReimbursement) { @@ -125,15 +134,7 @@ export const ExpenseActionScheam = ( message: "Reimburse Date is required", }); } - // let reimburse_Date = localToUtc(data.reimburseDate); - // if (transactionDate > reimburse_Date) { - // ctx.addIssue({ - // code: z.ZodIssueCode.custom, - // path: ["reimburseDate"], - // message: - // "Reimburse Date must be greater than or equal to Expense created Date", - // }); - // } + if (!data.reimburseById) { ctx.addIssue({ code: z.ZodIssueCode.custom, @@ -141,6 +142,20 @@ export const ExpenseActionScheam = ( message: "Reimburse By is required", }); } + if (!data.baseAmount) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + path: ["baseAmount"], + message: "Base Amount i required", + }); + } + if (!data.taxAmount) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + path: ["taxAmount"], + message: "Tax is required", + }); + } } }); }; @@ -152,6 +167,9 @@ export const defaultActionValues = { reimburseTransactionId: null, reimburseDate: null, reimburseById: null, + tdsPercentage: 0, + baseAmount:null, + taxAmount: 0, }; export const SearchSchema = z.object({ diff --git a/src/components/Expenses/ExpenseStatusLogs.jsx b/src/components/Expenses/ExpenseStatusLogs.jsx index 2baaa643..c7be711b 100644 --- a/src/components/Expenses/ExpenseStatusLogs.jsx +++ b/src/components/Expenses/ExpenseStatusLogs.jsx @@ -8,9 +8,9 @@ const ExpenseStatusLogs = ({ data }) => { const [visibleCount, setVisibleCount] = useState(4); const sortedLogs = useMemo(() => { - if (!data?.updateLogs) return []; - return [...data.updateLogs].sort( - (a, b) => new Date(b.updatedAt) - new Date(a.updatedAt) + if (!data?.expenseLogs) return []; + return [...data.expenseLogs].sort( + (a, b) => new Date(b.updateAt) - new Date(a.updateAt) ); }, [data?.updateLogs]); @@ -20,11 +20,12 @@ const ExpenseStatusLogs = ({ data }) => { ); const timelineData = useMemo(() => { + return logsToShow.map((log, index) => ({ id: index + 1, - title: log.nextStatus?.name || "Status Updated", - description: log.nextStatus?.description || "", - timeAgo: moment.utc(log?.updatedAt).local().fromNow(), + title: log.action || "Status Updated", + description: log.comment || "", + timeAgo: log.updateAt, color: getColorNameFromHex(log.nextStatus?.color) || "primary", users: log.updatedBy ? [ @@ -44,46 +45,8 @@ const ExpenseStatusLogs = ({ data }) => { }; return ( -
- {/*
- {logsToShow.map((log) => ( -
- - -
-
-
- {`${log.updatedBy.firstName} ${log.updatedBy.lastName}`} - - {log.action} - - - {formatUTCToLocalTime(log.updateAt, true)} - -
-
- {log.comment} -
-
-
-
- ))} -
- - {sortedLogs.length > visibleCount && ( -
- -
- )} */} +
+
diff --git a/src/components/Expenses/Filelist.jsx b/src/components/Expenses/Filelist.jsx index 2b1ce74e..15fe9fc3 100644 --- a/src/components/Expenses/Filelist.jsx +++ b/src/components/Expenses/Filelist.jsx @@ -12,19 +12,19 @@ const Filelist = ({ files, removeFile, expenseToEdit }) => { return true; }) .map((file, idx) => ( -
-
+
+
{/* File icon and info */} -
+
- + {file.fileName} @@ -33,16 +33,17 @@ const Filelist = ({ files, removeFile, expenseToEdit }) => {
-
+ {/* Delete icon */} + { e.preventDefault(); removeFile(expenseToEdit ? file.documentId : idx); }} > -
+
))} diff --git a/src/components/Expenses/ManageExpense.jsx b/src/components/Expenses/ManageExpense.jsx index f3872614..ce392463 100644 --- a/src/components/Expenses/ManageExpense.jsx +++ b/src/components/Expenses/ManageExpense.jsx @@ -3,7 +3,7 @@ import React, { useEffect, useState } from "react"; import { useForm } from "react-hook-form"; import { defaultExpense, ExpenseSchema } from "./ExpenseSchema"; import { formatFileSize, localToUtc } from "../../utils/appUtils"; -import { useProjectName } from "../../hooks/useProjects"; +import { useCurrencies, useProjectName } from "../../hooks/useProjects"; import { useDispatch, useSelector } from "react-redux"; import { changeMaster } from "../../slices/localVariablesSlice"; import useMaster, { @@ -30,6 +30,7 @@ import ErrorPage from "../../pages/ErrorPage"; import Label from "../common/Label"; import EmployeeSearchInput from "../common/EmployeeSearchInput"; import Filelist from "./Filelist"; +import { DEFAULT_CURRENCY } from "../../utils/constants"; const ManageExpense = ({ closeModal, expenseToEdit = null }) => { const { @@ -66,7 +67,11 @@ const ManageExpense = ({ closeModal, expenseToEdit = null }) => { error, isError: isProjectError, } = useProjectName(); - + const { + data: currencies, + isLoading: currencyLoading, + error: currencyError, + } = useCurrencies(); const { PaymentModes, loading: PaymentModeLoading, @@ -82,7 +87,7 @@ const ManageExpense = ({ closeModal, expenseToEdit = null }) => { isLoading: EmpLoading, isError: isEmployeeError, } = useEmployeesNameByProject(selectedproject); - + const files = watch("billAttachments"); const onFileChange = async (e) => { const newFiles = Array.from(e.target.files); @@ -129,6 +134,7 @@ const ManageExpense = ({ closeModal, expenseToEdit = null }) => { reader.onerror = (error) => reject(error); }); const removeFile = (index) => { + documentId; if (expenseToEdit) { const newFiles = files.map((file, i) => { if (file.documentId !== index) return file; @@ -159,6 +165,7 @@ const ManageExpense = ({ closeModal, expenseToEdit = null }) => { amount: data.amount || "", noOfPersons: data.noOfPersons || "", gstNumber: data.gstNumber || "", + currencyId: data.currencyId || DEFAULT_CURRENCY, billAttachments: data.documents ? data.documents.map((doc) => ({ fileName: doc.fileName, @@ -197,7 +204,9 @@ const ManageExpense = ({ closeModal, expenseToEdit = null }) => { const ExpenseTypeId = watch("expensesCategoryId"); useEffect(() => { - setExpenseType(ExpenseCategories?.find((type) => type.id === ExpenseTypeId)); + setExpenseType( + ExpenseCategories?.find((type) => type.id === ExpenseTypeId) + ); }, [ExpenseTypeId]); const handleClose = () => { @@ -297,37 +306,8 @@ const ManageExpense = ({ closeModal, expenseToEdit = null }) => { )}
- - {/*
- - - {errors.paidById && ( - {errors.paidById.message} - )} -
*/} -
- + {
)}
+
+ + + {errors.currencyId && ( + {errors.currencyId.message} + )} +
@@ -515,7 +521,13 @@ const ManageExpense = ({ closeModal, expenseToEdit = null }) => { {errors.billAttachments.message} )} - {files.length > 0 && } + {files.length > 0 && ( + + )} {Array.isArray(errors.billAttachments) && errors.billAttachments.map((fileError, index) => ( diff --git a/src/components/Expenses/ViewExpense.jsx b/src/components/Expenses/ViewExpense.jsx index ac5963cd..b6c5f311 100644 --- a/src/components/Expenses/ViewExpense.jsx +++ b/src/components/Expenses/ViewExpense.jsx @@ -9,7 +9,13 @@ import { useForm } from "react-hook-form"; import { zodResolver } from "@hookform/resolvers/zod"; import { defaultActionValues, ExpenseActionScheam } from "./ExpenseSchema"; import { useExpenseContext } from "../../pages/Expense/ExpensePage"; -import { getColorNameFromHex, getIconByFileType, localToUtc } from "../../utils/appUtils"; +import { + formatCurrency, + formatFigure, + getColorNameFromHex, + getIconByFileType, + localToUtc, +} from "../../utils/appUtils"; import { ExpenseDetailsSkeleton } from "./ExpenseSkeleton"; import { useHasUserPermission } from "../../hooks/useHasUserPermission"; import { @@ -103,365 +109,429 @@ const ViewExpense = ({ ExpenseId }) => { const handleImageLoad = (id) => { setImageLoaded((prev) => ({ ...prev, [id]: true })); }; - return (
-
-
-
Expense Details
-
-
-
{data?.expenseUId}
- {/* Row 1 */} -
-
- -
- {formatUTCToLocalTime(data?.transactionDate)} -
-
-
-
-
- -
{data?.expensesType?.name}
-
-
+
+
Expense Details
+
- {/* Row 2 */} -
-
- -
{data?.supplerName}
-
-
-
-
- -
₹ {data.amount}
-
-
- - {/* Row 3 */} -
-
- -
{data?.paymentMode?.name}
-
-
- {data?.gstNumber && ( -
-
-
-
+
diff --git a/src/components/PaymentRequest/PaymentRequestSchema.js b/src/components/PaymentRequest/PaymentRequestSchema.js index fb813b63..64757074 100644 --- a/src/components/PaymentRequest/PaymentRequestSchema.js +++ b/src/components/PaymentRequest/PaymentRequestSchema.js @@ -7,29 +7,27 @@ const ALLOWED_TYPES = [ "image/jpg", "image/jpeg", ]; -export const PaymentRequestSchema = (expenseTypes,isItself) => { - return z - .object({ - title: z.string().min(1, { message: "Project is required" }), - projectId: z.string().min(1, { message: "Project is required" }), - expenseCategoryId: z - .string() - .min(1, { message: "Expense Category is required" }), - currencyId: z - .string() - .min(1, { message: "Currency is required" }), - dueDate: z.string().min(1, { message: "Date is required" }), - description: z.string().min(1, { message: "Description is required" }), - payee: z.string().min(1, { message: "Supplier name is required" }), - isAdvancePayment: z.boolean().optional(), - 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", - }), +export const PaymentRequestSchema = (expenseTypes, isItself) => { + return z.object({ + title: z.string().min(1, { message: "Project is required" }), + projectId: z.string().min(1, { message: "Project is required" }), + expenseCategoryId: z + .string() + .min(1, { message: "Expense Category is required" }), + currencyId: z.string().min(1, { message: "Currency is required" }), + dueDate: z.string().min(1, { message: "Date is required" }), + description: z.string().min(1, { message: "Description is required" }), + payee: z.string().min(1, { message: "Supplier name is required" }), + isAdvancePayment: z.boolean().optional().default(false), + 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", + }), + billAttachments: z .array( z.object({ @@ -64,7 +62,7 @@ export const defaultPaymentRequest = { dueDate: "", projectId: "", expenseCategoryId: "", - isAdvancePayment:boolean, + isAdvancePayment: false, billAttachments: [], }; @@ -103,7 +101,9 @@ export const PaymentRequestActionScheam = ( paymentRequestId: z.string().nullable().optional(), paidAt: z.string().nullable().optional(), paidById: z.string().nullable().optional(), - + tdsPercentage: z.string().nullable().optional(), + baseAmount: z.string().nullable().optional(), + taxAmount: z.string().nullable().optional(), }) .superRefine((data, ctx) => { if (isTransaction) { @@ -121,15 +121,6 @@ export const PaymentRequestActionScheam = ( message: "Transacion Date is required", }); } - // let reimburse_Date = localToUtc(data.reimburseDate); - // if (transactionDate > reimburse_Date) { - // ctx.addIssue({ - // code: z.ZodIssueCode.custom, - // path: ["reimburseDate"], - // message: - // "Reimburse Date must be greater than or equal to Expense created Date", - // }); - // } if (!data.paidById) { ctx.addIssue({ code: z.ZodIssueCode.custom, @@ -137,6 +128,20 @@ export const PaymentRequestActionScheam = ( message: "Paid By is required", }); } + if (!data.baseAmount) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + path: ["baseAmount"], + message: "Base Amount i required", + }); + } + if (!data.taxAmount) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + path: ["taxAmount"], + message: "Tax is required", + }); + } } }); }; @@ -144,8 +149,41 @@ export const PaymentRequestActionScheam = ( export const defaultActionValues = { comment: "", statusId: "", - paidTransactionId: null, paidAt: null, paidById: null, -}; \ No newline at end of file + tdsPercentage:"0", + baseAmount: null, + taxAmount:null, +}; + +export const RequestedExpenseSchema = z.object({ + paymentModeId: z.string().min(1, { message: "Payment mode is required" }), + location: z.string().min(1, { message: "Location is required" }), + gstNumber: z.string().optional(), + billAttachments: z + .array( + z.object({ + fileName: z.string().min(1, { message: "Filename is required" }), + base64Data: z.string().nullable(), + contentType: z.string().refine((val) => ALLOWED_TYPES.includes(val), { + message: "Only PDF, PNG, JPG, or JPEG files are allowed", + }), + documentId: z.string().optional(), + fileSize: z.number().max(MAX_FILE_SIZE, { + message: "File size must be less than or equal to 5MB", + }), + description: z.string().optional(), + isActive: z.boolean().default(true), + }) + ) + .nonempty({ message: "At least one file attachment is required" }), +}); + +export const DefaultRequestedExpense = { + paymentModeId: "", + location: "", + gstNumber: "", + // amount:"", + billAttachments: [], +}; diff --git a/src/components/PaymentRequest/ViewPaymentRequest.jsx b/src/components/PaymentRequest/ViewPaymentRequest.jsx index 7be1b5e3..b6a9e2ad 100644 --- a/src/components/PaymentRequest/ViewPaymentRequest.jsx +++ b/src/components/PaymentRequest/ViewPaymentRequest.jsx @@ -42,7 +42,8 @@ const ViewPaymentRequest = ({ requestId }) => { const IsReview = useHasUserPermission(REVIEW_EXPENSE); const [imageLoaded, setImageLoaded] = useState({}); - const { setDocumentView } = usePaymentRequestContext(); + const { setDocumentView, setModalSize, setVieRequest, setIsExpenseGenerate } = + usePaymentRequestContext(); const ActionSchema = ExpenseActionScheam(IsPaymentProcess, data?.createdAt) ?? z.object({}); const navigate = useNavigate(); @@ -109,10 +110,16 @@ const ViewPaymentRequest = ({ requestId }) => { const handleImageLoad = (id) => { setImageLoaded((prev) => ({ ...prev, [id]: true })); }; - + const handleExpense = () => { + setIsExpenseGenerate({ IsOpen: true, requestId: requestId }); + setVieRequest({ IsOpen: true, requestId: requestId }); + }; return ( -
-
+ +
Payment Request Details

@@ -180,7 +187,10 @@ const ViewPaymentRequest = ({ requestId }) => { Amount :
- {formatCurrency(data?.amount, data?.currency?.currencyCode)} + {formatFigure(data?.amount, { + type: "currency", + currency: data?.currency?.currencyCode, + })}
@@ -331,42 +341,13 @@ const ViewPaymentRequest = ({ requestId }) => {
- {data?.documents?.length > 0 ? ( - data?.documents?.map((doc) => { - const isImage = doc?.contentType?.includes("image"); - - return ( -
{ - if (isImage) { - setDocumentView({ - IsOpen: true, - Image: doc.preSignedUrl, - }); - } - }} - > - - - {doc.fileName} - -
- ); - }) + {data?.attachments?.length > 0 ? ( + ) : ( -

No Attachment

+

No Attachment

)}
@@ -407,7 +388,7 @@ const ViewPaymentRequest = ({ requestId }) => { )} - {Array.isArray(data?.nextStatus) && data?.nextStatus.length > 0 && ( + {Array.isArray(data?.nextStatus) && data?.nextStatus.length > 0 ? ( <> {IsPaymentProcess && nextStatusWithPermission?.length > 0 && (
@@ -424,7 +405,7 @@ const ViewPaymentRequest = ({ requestId }) => { )}
-
+
{ projectId={null} />
+
+ + + {errors.tdsPercentage && ( + + {errors.tdsPercentage.message} + + )} +
+
+ + + {errors.baseAmount && ( + + {errors.baseAmount.message} + + )} +
+
+ + + {errors.taxAmount && ( + + {errors.taxAmount.message} + + )} +
)}
@@ -493,11 +517,26 @@ const ViewPaymentRequest = ({ requestId }) => { )}
+ ) : !data?.isExpenseCreated ? ( +
+ +
+ ) : ( + <> )} -
- +
+
+ {" "} +

TimeLine

+
+
diff --git a/src/components/common/Avatar.jsx b/src/components/common/Avatar.jsx index 5c3f25e6..34c14e50 100644 --- a/src/components/common/Avatar.jsx +++ b/src/components/common/Avatar.jsx @@ -52,7 +52,7 @@ const Avatar = ({ firstName, lastName, size = "sm", classAvatar }) => { return (
- + {generateAvatarText(firstName, lastName)}
diff --git a/src/components/common/EmployeeSearchInput.jsx b/src/components/common/EmployeeSearchInput.jsx index aa33c077..c4c68db2 100644 --- a/src/components/common/EmployeeSearchInput.jsx +++ b/src/components/common/EmployeeSearchInput.jsx @@ -112,7 +112,7 @@ const EmployeeSearchInput = ({ )} - {error && {error.message}} + {error && {error.message}}
); }; diff --git a/src/components/common/Loader.jsx b/src/components/common/Loader.jsx index 53c90486..7caaa324 100644 --- a/src/components/common/Loader.jsx +++ b/src/components/common/Loader.jsx @@ -26,7 +26,7 @@ export const SpinnerLoader = ()=>{
Loading...
-

Loading attendance data...

+

Loading data... Please wait

) } \ No newline at end of file diff --git a/src/hooks/useExpense.js b/src/hooks/useExpense.js index b9fa6f11..d7cf8ac4 100644 --- a/src/hooks/useExpense.js +++ b/src/hooks/useExpense.js @@ -358,8 +358,51 @@ export const useActionOnPaymentRequest = (onSuccessCallBack) => { }, }); }; -//#endregion +export const useDeletePaymentRequest = ()=>{ + const queryClient = useQueryClient(); + return useMutation({ + mutationFn: async (payload) => { + + return response.data; + }, + onSuccess: (updatedExpense, variables) => { + showToast("Request processed successfully.", "success"); + + queryClient.invalidateQueries({queryKey:["paymentRequestList"]}) + + if (onSuccessCallBack) onSuccessCallBack(); + }, + onError: (error) => { + showToast( + error.response.data.message || + "Something went wrong.Please try again later.", + "error" + ); + }, + }); +} +export const useCreatePaymentRequestExpense = (onSuccessCallBack) => { + const queryClient = useQueryClient(); + return useMutation({ + mutationFn: async (payload) => { + await ExpenseRepository.CreatePaymentRequestExpense(payload); + }, + + onSuccess: (_, variables) => { + queryClient.invalidateQueries({ queryKey: ["Expenses"] }); + queryClient.invalidateQueries({queryKey:["paymentRequest",variables.paymentRequestId]}) + showToast("Expense Created Successfully", "success"); + if (onSuccessCallBack) onSuccessCallBack(); + }, + onError: (error) => { + showToast( + error.message || "Something went wrong please try again !", + "error" + ); + }, + }); +}; export const usePaymentRequestFilter = () => { return useQuery({ queryKey: ["PaymentRequestFilter"], @@ -371,13 +414,15 @@ export const usePaymentRequestFilter = () => { }); }; +//#endregion + + //#region Advance Payment export const useExpenseTransactions = (employeeId)=>{ return useQuery({ queryKey:["transaction",employeeId], queryFn:async()=> { - debugger const resp = await ExpenseRepository.GetTranctionList(employeeId); return resp.data }, diff --git a/src/pages/AdvancePayment/AdvancePaymentPage.jsx b/src/pages/AdvancePayment/AdvancePaymentPage.jsx index 305df58e..d03ac49a 100644 --- a/src/pages/AdvancePayment/AdvancePaymentPage.jsx +++ b/src/pages/AdvancePayment/AdvancePaymentPage.jsx @@ -23,16 +23,16 @@ const AdvancePaymentPage = () => { { label: "Advance Payment" }, ]} /> -
+
-
-
- +
+
diff --git a/src/pages/PaymentRequest/PaymentRequestPage.jsx b/src/pages/PaymentRequest/PaymentRequestPage.jsx index be53bd31..f4c8bb55 100644 --- a/src/pages/PaymentRequest/PaymentRequestPage.jsx +++ b/src/pages/PaymentRequest/PaymentRequestPage.jsx @@ -8,6 +8,8 @@ import PaymentRequestList from "../../components/PaymentRequest/PaymentRequestLi import PaymentRequestFilterPanel from "../../components/PaymentRequest/PaymentRequestFilterPanel"; import { defaultPaymentRequestFilter,SearchPaymentRequestSchema } from "../../components/PaymentRequest/PaymentRequestSchema"; import ViewPaymentRequest from "../../components/PaymentRequest/ViewPaymentRequest"; +import PreviewDocument from "../../components/Expenses/PreviewDocument"; +import MakeExpense from "../../components/PaymentRequest/MakeExpense"; export const PaymentRequestContext = createContext(); export const usePaymentRequestContext = () => { @@ -25,12 +27,22 @@ const PaymentRequestPage = () => { const [ViewRequest,setVieRequest] = useState({view:false,requestId:null}) const { setOffcanvasContent, setShowTrigger } = useFab(); const [filters, setFilters] = useState(defaultPaymentRequestFilter); - + const [ViewDocument, setDocumentView] = useState({ + IsOpen: false, + Image: null, + }); + const [isExpenseGenerate,setIsExpenseGenerate] = useState({IsOpen: null, + RequestId: null,}) + const [modalSize,setModalSize] = useState("md") const [search, setSearch] = useState(""); const contextValue = { setManageRequest, - setVieRequest + setVieRequest, + setDocumentView, + setModalSize, + setIsExpenseGenerate, + isExpenseGenerate }; useEffect(() => { @@ -124,7 +136,27 @@ const PaymentRequestPage = () => { modalType="top" closeModal={() => setVieRequest({ requestId: null, view: false })} > - + + + )} + {isExpenseGenerate.IsOpen && ( + setIsExpenseGenerate({IsOpen:false, requestId: null})} + > + setIsExpenseGenerate({IsOpen:false, requestId: null})} /> + + )} + + {ViewDocument.IsOpen && ( + setDocumentView({ IsOpen: false, Image: null })} + > + )} diff --git a/src/repositories/ExpsenseRepository.jsx b/src/repositories/ExpsenseRepository.jsx index 09db8ac8..432edf07 100644 --- a/src/repositories/ExpsenseRepository.jsx +++ b/src/repositories/ExpsenseRepository.jsx @@ -21,11 +21,17 @@ const ExpenseRepository = { const payloadJsonString = JSON.stringify(filter); return api.get(`/api/Expense/get/payment-requests/list?isActive=${isActive}&pageSize=${pageSize}&pageNumber=${pageNumber}&filter=${payloadJsonString}&searchString=${searchString}`); }, - CreatePaymentRequest: (data) => api.post("/api/expense/payment-request/create", data), - UpdatePaymentRequest: (id, data) => api.put(`/api/Expense/payment-request/edit/${id}`, data), - GetPaymentRequest: (id) => api.get(`/api/Expense/get/payment-request/details/${id}`), - GetPaymentRequestFilter: () => api.get('/api/Expense/payment-request/filter'), - ActionOnPaymentRequest: (data) => api.post('/api/Expense/payment-request/action', data), + CreatePaymentRequest: (data) => + api.post("/api/expense/payment-request/create", data), + UpdatePaymentRequest: (id, data) => + api.put(`/api/Expense/payment-request/edit/${id}`, data), + GetPaymentRequest: (id) => + api.get(`/api/Expense/get/payment-request/details/${id}`), + GetPaymentRequestFilter: () => api.get("/api/Expense/payment-request/filter"), + ActionOnPaymentRequest: (data) => + api.post("/api/Expense/payment-request/action", data), + DeletePaymentRequest:()=>api.get("delete here come"), + CreatePaymentRequestExpense:(data)=>api.post('/api/Expense/payment-request/expense/create',data), //#endregion //#region Recurring Expense @@ -34,11 +40,11 @@ const ExpenseRepository = { UpdateRecurringExpense: (id, data) => api.put(`/api/Expense/recurring-payment/edit/${id}`, data), GetRecurringExpense: (id) => api.get(`/api/Expense/get/recurring-payment/details/${id}`), //#endregion - - + //#region Advance Payment - GetTranctionList: () => api.get(`/get/transactions/${employeeId}`) + GetTranctionList: (employeeId)=>api.get(`/api/Expense/get/transactions/${employeeId}`), //#endregion -} + +}; export default ExpenseRepository; diff --git a/src/utils/constants.jsx b/src/utils/constants.jsx index 67aa189e..433c906a 100644 --- a/src/utils/constants.jsx +++ b/src/utils/constants.jsx @@ -157,6 +157,7 @@ export const PROJECT_STATUS = [ }, ]; +export const DEFAULT_CURRENCY = "78e96e4a-7ce0-4164-ae3a-c833ad45ec2c"; export const EXPENSE_STATUS = { daft: "297e0d8f-f668-41b5-bfea-e03b354251c8",