Files
erpnext/banking/src/pages/BankReconciliation.tsx
Nikhil Kothari ebe5decb96 fix(banking): UI cleanup and better statement parsing (#58817)
* fix(banking): reset scroll on searching accounts

* fix(banking): show only past dates in date filter

* fix(banking): clean up line heights and remove beta badge

* fix(banking): show accurate count of import progress
fix(banking): show latest 20 imports instead of 10

* fix(banking): layout sizing needs to be preserved on page change

* fix(banking): cleaner bank balance UI

* fix(banking): correctly parse Cr/Dr values in statement importer

* Update banking/src/components/features/BankReconciliation/BankBalance.tsx

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

---------

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
2026-09-07 13:10:02 +00:00

144 lines
7.6 KiB
TypeScript

import BankAccountBalancePanel from "@/components/features/BankReconciliation/BankBalance"
import BankPicker from "@/components/features/BankReconciliation/BankPicker"
import BankRecDateFilter from "@/components/features/BankReconciliation/BankRecDateFilter"
import BankTransactionUnreconcileModal from "@/components/features/BankReconciliation/BankTransactionUnreconcileModal"
import CompanySelector from "@/components/features/BankReconciliation/CompanySelector"
import MatchAndReconcile from "@/components/features/BankReconciliation/MatchAndReconcile"
import Settings from "@/components/features/Settings/Settings"
import ActionLog from "@/components/features/ActionLog/ActionLog"
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"
import { TooltipProvider } from "@/components/ui/tooltip"
import _ from "@/lib/translate"
import { lazy, Suspense } from "react"
import { AlertTriangleIcon, CheckCircleIcon, HomeIcon, LandmarkIcon, ListIcon, Loader2Icon, ScrollTextIcon, ShuffleIcon } from "lucide-react"
import { Breadcrumb, BreadcrumbItem, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator } from "@/components/ui/breadcrumb"
import { Empty, EmptyContent, EmptyDescription, EmptyHeader, EmptyMedia, EmptyTitle } from "@/components/ui/empty"
import { Button } from "@/components/ui/button"
import { useAtomValue } from "jotai"
import { selectedBankAccountAtom } from "@/components/features/BankReconciliation/bankRecAtoms"
const BankReconciliationStatement = lazy(() => import('@/components/features/BankReconciliation/BankReconciliationStatement'))
const BankTransactions = lazy(() => import('@/components/features/BankReconciliation/BankTransactionList'))
const BankClearanceSummary = lazy(() => import('@/components/features/BankReconciliation/BankClearanceSummary'))
const IncorrectlyClearedEntries = lazy(() => import('@/components/features/BankReconciliation/IncorrectlyClearedEntries'))
const BankReconciliation = () => {
return (
<div>
{/* The page owns the viewport height and the tabs/lists below fill what's left, so
the virtualizers size themselves from layout instead of a measured pixel value. */}
<div className="px-2 pt-1 flex-col gap-4 md:flex hidden h-dvh">
<div className="flex flex-col gap-4 shrink-0">
<div className="flex justify-between shrink-0">
<div className="flex items-center gap-6">
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem>
<a href="/desk" className="text-ink-gray-7">
<HomeIcon size={16} />
</a>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbPage>
<div className="flex gap-1 items-center">
{_("Banking")}
</div>
</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>
<CompanySelector />
</div>
<div className="flex items-center gap-2">
<TooltipProvider>
<Settings />
<ActionLog />
</TooltipProvider>
<BankRecDateFilter />
</div>
</div>
</div>
<BankRecWorkspace />
<BankTransactionUnreconcileModal />
</div>
<div className="md:hidden flex h-screen items-center justify-between">
<Empty>
<EmptyMedia>
<LandmarkIcon />
</EmptyMedia>
<EmptyHeader>
<EmptyTitle>
{_("Banking")}
</EmptyTitle>
<EmptyDescription>
{_("This screen is not supported on mobile devices.")}
</EmptyDescription>
</EmptyHeader>
<EmptyContent>
<Button asChild>
<a href="/desk">
{_("Go to Desktop")}
</a>
</Button>
</EmptyContent>
</Empty>
</div>
</div>
)
}
const BankRecWorkspace = () => {
const selectedBankAccount = useAtomValue(selectedBankAccountAtom)
return <Tabs defaultValue="Match and Reconcile" className="min-h-0 flex-1 gap-4">
{/* Picker + tab strip stack on the left, balance panel beside them - the tab strip
fills height the panel needs anyway, so it costs no row of its own. The picker
scrolls horizontally (`min-w-0` lets it shrink so its overflow-x engages) while
the panel stays put, so the figures never scroll away. */}
{/* No gap here: the panel's own `border-s ps-4` supplies the separation, and a gap
would leave dead space the picker's edge fade can't reach. */}
<div className="flex shrink-0 items-stretch">
<div className="flex min-w-0 flex-1 flex-col justify-between gap-3">
<BankPicker />
{selectedBankAccount && <TabsList>
<TabsTrigger value="Match and Reconcile"><ShuffleIcon /> {_("Match and Reconcile")}</TabsTrigger>
<TabsTrigger value="Bank Reconciliation Statement"><ScrollTextIcon /> {_("Reconciliation Statement")}</TabsTrigger>
<TabsTrigger value="Bank Transactions"><ListIcon />{_("Transactions")}</TabsTrigger>
<TabsTrigger value="Bank Clearance Summary"><CheckCircleIcon />{_("Clearance Summary")}</TabsTrigger>
<TabsTrigger value="Incorrectly Cleared Entries"><AlertTriangleIcon /> {_("Incorrectly Cleared")}</TabsTrigger>
</TabsList>}
</div>
{selectedBankAccount && <BankAccountBalancePanel />}
</div>
{selectedBankAccount && <>
<TabsContent value="Match and Reconcile" className="flex min-h-0 flex-col">
<MatchAndReconcile />
</TabsContent>
<Suspense fallback={
<div className="flex items-center justify-center p-16">
<Loader2Icon className="size-6 animate-spin text-muted-foreground" />
</div>
}>
<TabsContent value="Bank Reconciliation Statement" className="flex min-h-0 flex-col">
<BankReconciliationStatement />
</TabsContent>
<TabsContent value="Bank Transactions" className="flex min-h-0 flex-col">
<BankTransactions />
</TabsContent>
<TabsContent value="Bank Clearance Summary" className="flex min-h-0 flex-col">
<BankClearanceSummary />
</TabsContent>
<TabsContent value="Incorrectly Cleared Entries" className="flex min-h-0 flex-col">
<IncorrectlyClearedEntries />
</TabsContent>
</Suspense>
</>}
</Tabs>
}
export default BankReconciliation