Files
IB/src/app/(main)/accounts/account_statement/accountStatement.tsx
tomosa.sarkar 10a3da8949 fix: Homepage design
wip :Integrate quick pay for own bank
wip: Design account page as discussed
2025-07-20 11:23:07 +05:30

222 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") > 90) {
notifications.show({
withBorder: true,
color: "red",
title: "Invalid Date range",
message: "End date must be within 90 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,
})} <span style={{fontSize:'10px'}}>{txn.type==="DR"?"Dr.":"Cr."}</span>
</td>
</tr>
))}
</tbody>
</Table>
</>
)}
</ScrollArea>
</Paper>
</Grid.Col >
</Grid >
);
}