Files
IB/src/app/(main)/accounts/account_statement/accountStatement.tsx
tomosa.sarkar 26e6dea82b feat: api integration for account tab
fix: layout design
feat : add screen for account tab
2025-07-13 19:21:53 +05:30

223 lines
9.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use client";
import { Paper, Select, Title, Button, Text, Grid, ScrollArea, Table, Divider } from "@mantine/core";
import { DateInput } from '@mantine/dates';
import { useEffect, useState } from "react";
import { useSearchParams } from "next/navigation";
import { notifications } from "@mantine/notifications";
import dayjs from 'dayjs';
import isSameOrAfter from 'dayjs/plugin/isSameOrAfter';
import isSameOrBefore from 'dayjs/plugin/isSameOrBefore';
import customParseFormat from 'dayjs/plugin/customParseFormat';
dayjs.extend(isSameOrAfter);
dayjs.extend(isSameOrBefore);
dayjs.extend(customParseFormat);
export default function AccountStatementPage() {
const [accountOptions, setAccountOptions] = useState<{ value: string; label: string }[]>([]);
const [selectedAccNo, setSelectedAccNo] = useState<string | null>(null);
const [startDate, setStartDate] = useState<Date | null>(null);
const [endDate, setEndDate] = useState<Date | null>(null);
const [transactions, setTransactions] = useState<any[]>([]);
const searchParams = useSearchParams();
const passedAccNo = searchParams.get("accNo");
useEffect(() => {
const saved = sessionStorage.getItem("accountData");
if (saved) {
const parsed = JSON.parse(saved);
const options = parsed.map((acc: any) => ({
label: `${acc.stAccountNo} - ${acc.stAccountType}`,
value: acc.stAccountNo,
}));
setAccountOptions(options);
if (passedAccNo) {
setSelectedAccNo(passedAccNo);
//Automatically fetch last 5 transactions if accNo is passed
const token = localStorage.getItem("access_token");
fetch(`/api/transactions/account/${passedAccNo}`, {
method: "GET",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${token}`,
},
})
.then(res => res.json())
.then(data => {
if (Array.isArray(data)) {
const last5 = data.slice(-5).reverse();
setTransactions(last5);
}
})
.catch(() => {
notifications.show({
withBorder: true,
color: "red",
title: "Fetch Failed",
message: "Could not load recent transactions.",
autoClose: 5000,
});
});
}
}
}, [passedAccNo]);
const handleAccountTransaction = async () => {
if (!selectedAccNo || !startDate || !endDate) {
notifications.show({
withBorder: true,
color: "red",
title: "Missing field",
message: "Please select Account number,Start date and End date",
autoClose: 5000,
});
return;
}
const start = dayjs(startDate);
const end = dayjs(endDate);
const today = dayjs().startOf('day');
if (end.isAfter(today)) {
notifications.show({
withBorder: true,
color: "red",
title: "Invalid End Date",
message: "End date can not be the future date.",
autoClose: 4000,
});
return;
}
if (start.isAfter(end)) {
notifications.show({
withBorder: true,
color: "red",
title: "Invalid Start Date",
message: "Start date can not be less than end date",
autoClose: 4000,
});
return;
}
if (end.diff(start, "day") > 60) {
notifications.show({
withBorder: true,
color: "red",
title: "Invalid Date range",
message: "End date must be within 60 days from start date",
autoClose: 4000,
});
return;
}
try {
const token = localStorage.getItem("access_token");
const response = await fetch(`/api/transactions/account/${selectedAccNo}`, {
method: "GET",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${token}`,
},
});
const data = await response.json();
if (response.ok && Array.isArray(data)) {
const filterData = data.filter((txn: any) => {
const txnDate = dayjs(txn.date, 'DD/MM/YYYY');
return txnDate.isSameOrAfter(start) && txnDate.isSameOrBefore(end);
});
setTransactions(filterData);
}
} catch {
notifications.show({
withBorder: true,
color: "red",
title: "Please try again later",
message: "Unable to Fetch Account Transaction, Please try again later",
autoClose: 5000,
});
}
};
const cellStyle = {
border: "1px solid #ccc",
padding: "8px",
};
return (
<Grid gutter="md">
{/* Left side form */}
<Grid.Col span={{ base: 12, md: 4 }}>
<Paper shadow="sm" radius="md" p="md" withBorder h={400}>
<Title order={4} mb="sm">Account Statement</Title>
<Select
label="Select Account Number"
placeholder="Choose account number"
data={accountOptions}
value={selectedAccNo}
onChange={setSelectedAccNo}
searchable
/>
<DateInput
label="Start Date"
value={startDate}
onChange={setStartDate}
placeholder="Enter start date"
/>
<DateInput
label="End Date"
value={endDate}
onChange={setEndDate}
placeholder="Enter end date"
/>
<Button fullWidth mt="md" onClick={handleAccountTransaction}>
Proceed
</Button>
</Paper>
</Grid.Col>
{/* Right side transaction list */}
<Grid.Col span={{ base: 12, md: 8 }}>
<Paper shadow="sm" radius="md" p="md" withBorder h={400} style={{ display: 'flex', flexDirection: 'column' }}>
<Title order={5} mb="xs">Account Transaction Statement</Title>
<Text fw={500} fs="italic" >Account No : {selectedAccNo}</Text>
<Divider size="xs" />
<ScrollArea style={{ flex: 1 }}>
{transactions.length === 0 ? (
<p>No transactions found.</p>
) : (
<>
<Text fs="italic" c='#228be6' ta='center'>
{!startDate && !endDate ? 'Last 5 Transactions'
: startDate && endDate ? `Transactions from ${dayjs(startDate).format("DD/MM/YYYY")} to ${dayjs(endDate).format("DD/MM/YYYY")}`
: ""}
</Text>
<Table style={{ borderCollapse: "collapse", width: '100%' }}>
<thead style={{ backgroundColor: "#3385ff" }}>
{/* <tr>
<th style={{ ...cellStyle, position: 'sticky', textAlign: "left" }}>Name</th>
<th style={{ ...cellStyle, position: 'sticky', textAlign: "left" }}>Date</th>
<th style={{ ...cellStyle, position: 'sticky', textAlign: "left" }}>Type</th>
<th style={{ ...cellStyle, position: 'sticky', textAlign: "left" }}>Amount(₹)</th>
</tr> */}
</thead>
<tbody style={{ maxHeight: '250px', overflowY: 'auto', width: '100%' }}>
{transactions.map((txn, i) => (
<tr key={i}>
<td style={{ ...cellStyle, textAlign: "left" }}> {txn.name || "—"}</td>
<td style={{ ...cellStyle, textAlign: "left" }}>{txn.date || "—"}</td>
{/* <td style={{ ...cellStyle, textAlign: "left" }}>{txn.type}</td> */}
<td style={{ ...cellStyle, textAlign: "left", color: txn.type === "DR" ? "#e03131" : "#2f9e44" }}>
{parseFloat(txn.amount).toLocaleString("en-IN", {
minimumFractionDigits: 2,
})}
</td>
</tr>
))}
</tbody>
</Table>
</>
)}
</ScrollArea>
</Paper>
</Grid.Col >
</Grid >
);
}