"use client"; import { ChevronLeft, ChevronRight, Download, Filter, Paperclip, Plus, X } from "lucide-react"; import Link from "next/link"; import { usePathname, useRouter } from "next/navigation"; import { useState } from "react"; import { useQuickAdd } from "@/components/layout/quick-add"; import { MoneyInput } from "@/components/money-input"; import { ResponsiveDialog } from "@/components/responsive-dialog"; import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { Card, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; import { Field, FieldGroup, FieldLabel } from "@/components/ui/field"; import { Input } from "@/components/ui/input"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; import { tr } from "@/i18n/tr"; import { cn } from "@/lib/utils"; import { formatMoney } from "@/shared/format"; import type { TransactionFilters } from "@/shared/schemas/transaction"; import { TRANSACTION_STATUSES, TRANSACTION_TYPES } from "@/shared/transactions"; import type { TransactionFormOptions, TransactionListItem, TransactionPage } from "../service"; import { Amount, dayLabel, RowIcon, rowSubtitle, rowTitle, signed, useTransactionDetail, } from "./transaction-parts"; const t = tr.transactions; const ALL = "__all__"; // --- Filtreler --- type Options = TransactionFormOptions & { members: { id: string; name: string }[] }; function countActive(f: TransactionFilters) { return ( [ "from", "to", "type", "hesap", "kategori", "kisi", "durum", "min", "max", "etiket", "q", ] as const ).filter((k) => f[k] !== undefined && f[k] !== "").length; } function FiltersDialog({ open, onOpenChange, filters, raw, options, }: { open: boolean; onOpenChange: (o: boolean) => void; filters: TransactionFilters; raw: Record; options: Options; }) { const router = useRouter(); const pathname = usePathname(); const [v, setV] = useState>(raw); const set = (k: string, value: string) => setV((prev) => ({ ...prev, [k]: value })); const f = t.filters; function apply(next: Record) { const params = new URLSearchParams(); for (const [k, value] of Object.entries(next)) if (value && k !== "sayfa") params.set(k, value); router.push(params.size ? `${pathname}?${params}` : pathname); onOpenChange(false); } const select = (key: string, label: string, items: { value: string; label: string }[]) => ( {label} ); return ( { if (o) setV(raw); onOpenChange(o); }} title={f.title} footer={ <> } >
{ e.preventDefault(); apply(v); }} > {f.search} set("q", e.target.value)} placeholder={f.searchPlaceholder} />
{f.from} set("from", e.target.value)} /> {f.to} set("to", e.target.value)} />
{select( "type", f.type, TRANSACTION_TYPES.map((x) => ({ value: x, label: t.types[x] })), )} {select( "durum", f.status, TRANSACTION_STATUSES.map((x) => ({ value: x, label: t.statuses[x] })), )}
{select( "hesap", f.account, options.accounts.map((a) => ({ value: a.id, label: a.name })), )} {select( "kategori", f.category, options.categories.map((c) => ({ value: c.id, label: `${c.kind === "income" ? "↑" : "↓"} ${c.path}`, })), )} {select( "kisi", f.person, options.members.map((m) => ({ value: m.id, label: m.name })), )}
{f.min} set("min", x)} /> {f.max} set("max", x)} />
{f.tag} set("etiket", e.target.value)} /> {active ? ( ) : null} {canWrite ? ( ) : null}
{( [ ["income", data.sums.incomeMinor, "text-income"], ["expense", data.sums.expenseMinor, "text-expense"], ["net", data.sums.incomeMinor - data.sums.expenseMinor, ""], ] as const ).map(([key, value, tone]) => ( {t.list.sums[key]} {formatMoney(value)} ))}
{data.items.length === 0 ? (

{active ? t.list.empty : t.list.emptyAll}

) : ( groups.map((g) => { const net = g.items.reduce( (a, i) => a + (i.status === "posted" ? signed(i.type, i.amountMinor) : 0), 0, ); return (

{dayLabel(g.date)}

0 && "text-income", net < 0 && "text-expense", )} title={t.list.dayTotal} > {net === 0 ? "" : `${net > 0 ? "+" : "−"}${formatMoney(Math.abs(net))}`}
    {g.items.map((item) => (
  • ))}
); }) )} {data.pageCount > 1 ? ( ) : data.total ? (

{t.list.total(data.total)}

) : null} {detailElement} ); }