c063186e80
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
108 lines
3.9 KiB
TypeScript
108 lines
3.9 KiB
TypeScript
import { lazy, Suspense, useState } from 'react'
|
||
import { CreditCard, Landmark } from 'lucide-react'
|
||
import { Link } from 'react-router'
|
||
import { paths } from '@/components/layout/nav-items'
|
||
import { PageError, PageHeader, PageLoading } from '@/components/page'
|
||
import { Skeleton } from '@/components/skeleton'
|
||
import { Button } from '@/components/ui/button'
|
||
import { Section } from '@/features/planning/plan-read'
|
||
import { useDebt } from '@/lib/debt'
|
||
import { t } from '@/lib/strings'
|
||
import type { DebtSnapshot } from '@/types/DebtSnapshot'
|
||
import { DebtCard } from './debt-card'
|
||
import { History } from './history'
|
||
import { ImportSection } from './import-section'
|
||
import { SnapshotForm } from './snapshot-form'
|
||
import { TargetsEditor } from './targets-editor'
|
||
|
||
const DebtChart = lazy(() => import('./debt-chart'))
|
||
const s = t.debt
|
||
|
||
/** /borc: toplam borç, gerçek + hedef grafiği, ölçümler, yeni ölçüm, yol haritası, içe aktarma */
|
||
export function DebtPage() {
|
||
const debt = useDebt()
|
||
const [editing, setEditing] = useState<DebtSnapshot | null>(null)
|
||
const d = debt.data
|
||
|
||
return (
|
||
<>
|
||
<PageHeader
|
||
title={s.title}
|
||
description={s.description}
|
||
actions={
|
||
<Button asChild variant="outline">
|
||
<Link to={paths.installments}>
|
||
<CreditCard aria-hidden />
|
||
{s.toInstallments}
|
||
</Link>
|
||
</Button>
|
||
}
|
||
/>
|
||
{debt.isError ? (
|
||
<PageError message={debt.error.message} onRetry={debt.refetch} />
|
||
) : !d ? (
|
||
<PageLoading />
|
||
) : (
|
||
<div className="space-y-4">
|
||
{d.latest ? (
|
||
<DebtCard debt={d} />
|
||
) : (
|
||
<section className="flex flex-col items-center gap-3 rounded-2xl border bg-card p-8 text-center">
|
||
<div className="grid size-14 place-items-center rounded-full bg-primary/10 text-primary">
|
||
<Landmark className="size-7" aria-hidden />
|
||
</div>
|
||
<h2 className="text-lg font-semibold">{s.emptyTitle}</h2>
|
||
<p className="max-w-md text-muted-foreground">{s.emptyText}</p>
|
||
</section>
|
||
)}
|
||
{d.snapshots.length > 0 && (
|
||
<Section title={s.chartTitle}>
|
||
<Suspense fallback={<Skeleton className="h-72" />}>
|
||
<DebtChart debt={d} />
|
||
</Suspense>
|
||
</Section>
|
||
)}
|
||
{d.snapshots.length > 0 && (
|
||
<Section title={s.historyTitle}>
|
||
<History
|
||
snapshots={d.snapshots}
|
||
onEdit={(sn) => {
|
||
setEditing(sn)
|
||
document
|
||
.getElementById('debt-form')
|
||
?.scrollIntoView({ behavior: 'smooth', block: 'start' })
|
||
}}
|
||
/>
|
||
</Section>
|
||
)}
|
||
<div className="grid items-start gap-4 lg:grid-cols-2">
|
||
<div id="debt-form" className="scroll-mt-4">
|
||
<Section title={editing ? s.formEditTitle : s.formTitle}>
|
||
<SnapshotForm
|
||
// Taksit planları değişince (ör. içe aktarma) kalan taksit önerisi yeniden dolsun
|
||
key={
|
||
editing?.id ?? `new-${d.installments.map((p) => `${p.id}:${p.version}`).join()}`
|
||
}
|
||
plans={d.installments}
|
||
editing={editing ?? undefined}
|
||
onDone={() => setEditing(null)}
|
||
/>
|
||
</Section>
|
||
</div>
|
||
<Section title={s.targetsTitle}>
|
||
<TargetsEditor
|
||
key={d.targets.map((x) => `${x.month}:${x.closing_target}`).join()}
|
||
targets={d.targets}
|
||
thisMonth={d.this_month}
|
||
/>
|
||
</Section>
|
||
<Section title={s.importTitle}>
|
||
<ImportSection />
|
||
</Section>
|
||
</div>
|
||
</div>
|
||
)}
|
||
</>
|
||
)
|
||
}
|