feat(layout): login, uygulama kabuğu, alt menü, hızlı ekle ve dashboard

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-11-05 01:35:10 +03:00
parent 4dbd2eb441
commit 1cf9fd9d8c
31 changed files with 1061 additions and 14 deletions
+67
View File
@@ -0,0 +1,67 @@
import type { Metadata } from "next";
import { Suspense } from "react";
import { PageHeader } from "@/components/page-header";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
import { MOCK_SESSION_USER } from "@/features/auth/mock";
import { SummaryCardsSkeleton } from "@/features/dashboard/components/summary-cards-skeleton";
import { tr } from "@/i18n/tr";
import { cn } from "@/lib/utils";
import { formatMoney } from "@/shared/format";
export const metadata: Metadata = { title: tr.dashboard.title };
type SummaryCard = {
key: keyof typeof tr.dashboard.cards;
tone?: string;
amountMinor: number | null;
};
/** FAZ 14: gerçek özet verisi (gelir, gider, bakiye, kart borcu, net varlık). */
async function getSummary(): Promise<SummaryCard[]> {
return [
{ key: "monthIncome", tone: "text-income", amountMinor: null },
{ key: "monthExpense", tone: "text-expense", amountMinor: null },
{ key: "monthRemaining", tone: "text-budget", amountMinor: null },
{ key: "totalBalance", amountMinor: null },
{ key: "cardDebt", tone: "text-expense", amountMinor: null },
{ key: "netWorth", amountMinor: null },
];
}
async function SummaryCards() {
const cards = await getSummary();
return (
<div className="grid grid-cols-2 gap-3 lg:grid-cols-3 xl:grid-cols-6">
{cards.map((c) => (
<Card key={c.key} size="sm">
<CardHeader>
<CardDescription>{tr.dashboard.cards[c.key]}</CardDescription>
<CardTitle className={cn("text-lg tabular-nums", c.tone)}>
{c.amountMinor === null ? "—" : formatMoney(c.amountMinor)}
</CardTitle>
</CardHeader>
{c.amountMinor === null ? (
<CardContent className="text-xs text-muted-foreground">
{tr.dashboard.noData}
</CardContent>
) : null}
</Card>
))}
</div>
);
}
export default function DashboardPage() {
const user = MOCK_SESSION_USER;
return (
<>
<PageHeader
title={tr.dashboard.welcome(user.name.split(" ")[0] ?? user.name)}
description={tr.dashboard.welcomeDescription}
/>
<Suspense fallback={<SummaryCardsSkeleton />}>
<SummaryCards />
</Suspense>
</>
);
}