Ledger section with sub-tabs: overview (money held/owed, payouts by status, and a reconciliation warning card), payouts + transactions lists, per-seller balances list, and a per-seller detail showing recorded vs derived balance + discrepancy, bank accounts and payout history. Enabled the Ledger nav item. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
113 lines
4.7 KiB
TypeScript
113 lines
4.7 KiB
TypeScript
import {
|
||
Loader2,
|
||
Wallet,
|
||
Landmark,
|
||
ArrowDownCircle,
|
||
ArrowUpCircle,
|
||
AlertTriangle,
|
||
Clock,
|
||
CheckCircle2,
|
||
} from "lucide-react";
|
||
import { useLedgerOverview } from "~/requestHandler/use-admin-hooks";
|
||
import { KpiCard } from "~/components/admin/KpiCard";
|
||
import { faToman, faNum } from "~/components/admin/DataTable";
|
||
|
||
export default function LedgerOverview() {
|
||
const { data, isLoading, isError } = useLedgerOverview();
|
||
|
||
if (isLoading)
|
||
return (
|
||
<div className="flex min-h-[40vh] items-center justify-center">
|
||
<Loader2 className="h-7 w-7 animate-spin text-GRAY" />
|
||
</div>
|
||
);
|
||
if (isError || !data)
|
||
return <p className="text-RED text-[14px]">خطا در بارگذاری دفتر مالی</p>;
|
||
|
||
const { payouts, reconciliation } = data;
|
||
const hasDiscrepancy = reconciliation.completedPayoutsNotDebited > 0;
|
||
|
||
return (
|
||
<div>
|
||
{/* Money held / owed */}
|
||
<div className="grid grid-cols-2 lg:grid-cols-4 gap-3">
|
||
<KpiCard label="موجودی کیف پول کاربران" value={faToman(data.walletHeld)} icon={Wallet} />
|
||
<KpiCard label="مانده قابل پرداخت فروشندگان" value={faToman(data.sellerPayable)} icon={Landmark} />
|
||
<KpiCard label="کل واریزها (شارژ کیف پول)" value={faToman(data.depositsTotal)} icon={ArrowDownCircle} accent="green" />
|
||
<KpiCard label="کل خریدها" value={faToman(data.purchasesTotal)} icon={ArrowUpCircle} />
|
||
</div>
|
||
|
||
{/* Payouts by status */}
|
||
<h2 className="text-[15px] font-extrabold mt-7 mb-3">برداشتها</h2>
|
||
<div className="grid grid-cols-3 gap-3">
|
||
<KpiCard
|
||
label="در انتظار"
|
||
value={faToman(payouts.pending.amount)}
|
||
sub={`${faNum(payouts.pending.count)} درخواست`}
|
||
icon={Clock}
|
||
accent={payouts.pending.count > 0 ? "red" : "default"}
|
||
/>
|
||
<KpiCard
|
||
label="پرداختشده"
|
||
value={faToman(payouts.completed.amount)}
|
||
sub={`${faNum(payouts.completed.count)} مورد`}
|
||
icon={CheckCircle2}
|
||
accent="green"
|
||
/>
|
||
<KpiCard
|
||
label="ردشده"
|
||
value={faToman(payouts.rejected.amount)}
|
||
sub={`${faNum(payouts.rejected.count)} مورد`}
|
||
/>
|
||
</div>
|
||
|
||
{/* Reconciliation warning */}
|
||
{hasDiscrepancy && (
|
||
<div className="mt-7 rounded-2xl border border-RED/30 bg-RED/5 p-4">
|
||
<div className="flex items-start gap-3">
|
||
<AlertTriangle className="h-5 w-5 text-RED shrink-0 mt-0.5" />
|
||
<div className="flex-1">
|
||
<h3 className="font-extrabold text-[15px] text-RED">
|
||
مغایرت حسابداری شناسایی شد
|
||
</h3>
|
||
<p className="text-[13px] text-BLACK2 mt-1 leading-6">
|
||
مبلغ{" "}
|
||
<b className="tabular-nums">
|
||
{faToman(reconciliation.completedPayoutsNotDebited)}
|
||
</b>{" "}
|
||
بهعنوان برداشت «پرداختشده» ثبت شده اما از مانده فروشندگان کسر
|
||
نشده است. به همین دلیل «مانده قابل پرداخت» فعلی احتمالاً بیش از
|
||
مقدار واقعی است.
|
||
</p>
|
||
<div className="grid grid-cols-2 lg:grid-cols-3 gap-3 mt-3">
|
||
<div className="rounded-xl bg-WHITE border border-WHITE3 p-3">
|
||
<p className="text-[12px] text-GRAY">مانده ثبتشده</p>
|
||
<p className="font-bold tabular-nums mt-1">
|
||
{faToman(reconciliation.sellerPayableRecorded)}
|
||
</p>
|
||
</div>
|
||
<div className="rounded-xl bg-WHITE border border-WHITE3 p-3">
|
||
<p className="text-[12px] text-GRAY">برآورد مانده واقعی</p>
|
||
<p className="font-bold tabular-nums mt-1 text-GREEN">
|
||
{faToman(reconciliation.sellerPayableEstimatedTrue)}
|
||
</p>
|
||
</div>
|
||
<div className="rounded-xl bg-WHITE border border-WHITE3 p-3">
|
||
<p className="text-[12px] text-GRAY">اختلاف</p>
|
||
<p className="font-bold tabular-nums mt-1 text-RED">
|
||
{faToman(reconciliation.completedPayoutsNotDebited)}
|
||
</p>
|
||
</div>
|
||
</div>
|
||
<p className="text-[12px] text-GRAY mt-3">
|
||
این مورد در فاز بعدی (دفتر روزنامهای و اصلاح جریان پول) رفع خواهد
|
||
شد.
|
||
</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
)}
|
||
</div>
|
||
);
|
||
}
|