"use client"; import { useState, useTransition } from "react"; import { Archive, ArchiveRestore, Check, CreditCard as CreditCardIcon, Loader2, MoreHorizontal, Pencil, Plus, Trash2, } from "lucide-react"; import { toast } from "sonner"; import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { Card, CardContent } from "@/components/ui/card"; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from "@/components/ui/dialog"; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu"; import { Input } from "@/components/ui/input"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from "@/components/ui/table"; import { archiveCreditCardAction, deleteCreditCardAction, deleteStatementAction, payStatementAction, } from "@/lib/appwrite/credit-card-actions"; import { formatDate, formatTRY } from "@/lib/format"; import { cn } from "@/lib/utils"; import { CardFormSheet } from "./card-form-sheet"; import { StatementFormSheet } from "./statement-form-sheet"; import { type BankAccountOption, type CreditCardRow, STATEMENT_STATUS_COLOR, STATEMENT_STATUS_LABEL, type StatementRow, } from "./types"; type Props = { cards: CreditCardRow[]; statements: StatementRow[]; bankAccounts: BankAccountOption[]; }; export function CardsClient({ cards, statements, bankAccounts }: Props) { const [cardFormOpen, setCardFormOpen] = useState(false); const [editingCard, setEditingCard] = useState(null); const [deletingCard, setDeletingCard] = useState(null); const [stmtFormOpen, setStmtFormOpen] = useState(false); const [stmtCard, setStmtCard] = useState(null); const [payDialog, setPayDialog] = useState(null); const [payAmount, setPayAmount] = useState(""); const [deletingStmt, setDeletingStmt] = useState(null); const [busy, startTransition] = useTransition(); const active = cards.filter((c) => !c.archived); const archived = cards.filter((c) => c.archived); const stmtsByCard = new Map(); for (const s of statements) { const arr = stmtsByCard.get(s.cardId) ?? []; arr.push(s); stmtsByCard.set(s.cardId, arr); } const totalOutstanding = statements .filter((s) => s.status !== "paid") .reduce((sum, s) => sum + (s.totalDebt - s.paidAmount), 0); const overdueCount = statements.filter((s) => s.status === "overdue").length; const toggleArchive = (c: CreditCardRow) => { startTransition(async () => { const fd = new FormData(); fd.set("id", c.id); const r = await archiveCreditCardAction(fd); if (r.ok) toast.success(c.archived ? "Kart geri açıldı." : "Kart arşivlendi."); else toast.error(r.error ?? "İşlem başarısız."); }); }; const handleDeleteCard = () => { if (!deletingCard) return; startTransition(async () => { const fd = new FormData(); fd.set("id", deletingCard.id); const r = await deleteCreditCardAction(fd); if (r.ok) { toast.success("Kart silindi."); setDeletingCard(null); } else { toast.error(r.error ?? "Silme başarısız."); } }); }; const handlePay = () => { if (!payDialog) return; startTransition(async () => { const fd = new FormData(); fd.set("id", payDialog.id); if (payAmount.trim()) fd.set("amount", payAmount); const r = await payStatementAction(fd); if (r.ok) { toast.success("Ödeme kaydedildi."); setPayDialog(null); setPayAmount(""); } else { toast.error(r.error ?? "Ödeme başarısız."); } }); }; const handleDeleteStmt = () => { if (!deletingStmt) return; startTransition(async () => { const fd = new FormData(); fd.set("id", deletingStmt.id); const r = await deleteStatementAction(fd); if (r.ok) { toast.success("Ekstre silindi."); setDeletingStmt(null); } else { toast.error(r.error ?? "Silme başarısız."); } }); }; return (

Aktif kart

{active.length}

Bekleyen toplam borç

{formatTRY(totalOutstanding)}

Vadesi geçmiş ekstre

0 && "text-red-600 dark:text-red-400", )} > {overdueCount}

{cards.length === 0 ? (

Henüz kredi kartı eklenmemiş.

) : (
{active.map((c) => { const items = stmtsByCard.get(c.id) ?? []; const totalDebt = items .filter((s) => s.status !== "paid") .reduce((sum, s) => sum + (s.totalDebt - s.paidAmount), 0); return (

{c.bankName}

· {c.cardName} {c.last4 && ( **{c.last4} )}
Limit {formatTRY(c.creditLimit)} Kesim: ayın {c.statementDay}'i Vade: ayın {c.dueDay}'i Aylık faiz: %{c.interestRate}
{c.bankAccountLabel && (

Hesap: {c.bankAccountLabel}

)}

Bekleyen

{formatTRY(totalDebt)}

{ setStmtCard(c); setStmtFormOpen(true); }} > Ekstre ekle { setEditingCard(c); setCardFormOpen(true); }} > Düzenle toggleArchive(c)}> Arşivle setDeletingCard(c)} > Sil
{items.length > 0 && (
Dönem Son ödeme Toplam Asgari Ödenen Durum İşlem {items.map((s) => { const remaining = s.totalDebt - s.paidAmount; return ( {s.period} {formatDate(s.dueDate)} {formatTRY(s.totalDebt)} {formatTRY(s.minimumPayment)} {formatTRY(s.paidAmount)} {STATEMENT_STATUS_LABEL[s.status]}
{remaining > 0 && ( )}
); })}
)}
); })} {archived.length > 0 && (
Arşivlenmiş kartlar ({archived.length})
{archived.map((c) => (

{c.bankName} — {c.cardName}{" "} {c.last4 && ( **{c.last4} )}

Arşivli

))}
)}
)} { setCardFormOpen(v); if (!v) setEditingCard(null); }} card={editingCard} bankAccounts={bankAccounts} /> { setStmtFormOpen(v); if (!v) setStmtCard(null); }} card={stmtCard} cards={cards} /> !v && setDeletingCard(null)}> Kartı sil {deletingCard?.bankName} — {deletingCard?.cardName} {" "} ve tüm ekstreleri silinecek. { if (!v) { setPayDialog(null); setPayAmount(""); } }} > Ekstre ödemesi {payDialog && ( <> {payDialog.period} dönemi — kalan{" "} {formatTRY(payDialog.totalDebt - payDialog.paidAmount)}.
Tutarı boş bırakırsanız tamamı ödenir. )}
setPayAmount(e.target.value)} />
!v && setDeletingStmt(null)}> Ekstreyi sil {deletingStmt?.period} ekstresi silinecek. Bağlı gider kaydı varsa o da silinir.
); }