"use client"; import { useState } from "react"; import { AppShell } from "../../components/app-shell"; type ApiResponse = { data: T; meta: { timestamp: string; version: "v1" }; error: null | { message: string; code?: string }; }; type ExportData = { status: string; csv?: string; rowCount?: number }; export default function ExportsPage() { const [status, setStatus] = useState(""); const [datePreset, setDatePreset] = useState("custom"); const [filters, setFilters] = useState({ startDate: "", endDate: "", minAmount: "", maxAmount: "", category: "", source: "", includeHidden: false }); const applyPreset = (preset: string) => { setDatePreset(preset); if (preset === "custom") { return; } const now = new Date(); const end = new Date(now.getFullYear(), now.getMonth(), now.getDate()); let start = new Date(end); if (preset === "this_month") { start = new Date(end.getFullYear(), end.getMonth(), 1); } else if (preset === "last_month") { start = new Date(end.getFullYear(), end.getMonth() - 1, 1); end.setDate(0); } else if (preset === "last_6_months") { start = new Date(end.getFullYear(), end.getMonth() - 5, 1); } else if (preset === "last_year") { start = new Date(end.getFullYear() - 1, 0, 1); end.setMonth(11, 31); } const format = (value: Date) => value.toISOString().slice(0, 10); setFilters((prev) => ({ ...prev, startDate: format(start), endDate: format(end) })); }; const onExport = async () => { setStatus("Generating export..."); const userId = localStorage.getItem("ledgerone_user_id"); const params = new URLSearchParams(); if (userId) { params.set("user_id", userId); } if (filters.startDate) { params.set("start_date", filters.startDate); } if (filters.endDate) { params.set("end_date", filters.endDate); } if (filters.minAmount) { params.set("min_amount", filters.minAmount); } if (filters.maxAmount) { params.set("max_amount", filters.maxAmount); } if (filters.category) { params.set("category", filters.category); } if (filters.source) { params.set("source", filters.source); } if (filters.includeHidden) { params.set("include_hidden", "true"); } const query = params.toString() ? `?${params.toString()}` : ""; try { const res = await fetch(`/api/exports/csv${query}`); const payload = (await res.json()) as ApiResponse; if (!res.ok || payload.error) { setStatus(payload.error?.message ?? "Export failed."); return; } if (payload.data.csv) { const blob = new Blob([payload.data.csv], { type: "text/csv" }); const url = URL.createObjectURL(blob); window.open(url, "_blank", "noopener,noreferrer"); setStatus(`Export ready (${payload.data.rowCount ?? 0} rows).`); } else { setStatus("Export ready."); } } catch { setStatus("Export failed."); } }; return (
setFilters((prev) => ({ ...prev, startDate: event.target.value })) } className="mt-2 w-full rounded-xl border border-border bg-background/50 px-4 py-2 text-sm text-foreground focus:border-primary focus:ring-primary" disabled={datePreset !== "custom"} />
setFilters((prev) => ({ ...prev, endDate: event.target.value })) } className="mt-2 w-full rounded-xl border border-border bg-background/50 px-4 py-2 text-sm text-foreground focus:border-primary focus:ring-primary" disabled={datePreset !== "custom"} />
setFilters((prev) => ({ ...prev, category: event.target.value })) } placeholder="Dining, Payroll, Utilities" className="mt-2 w-full rounded-xl border border-border bg-background/50 px-4 py-2 text-sm text-foreground focus:border-primary focus:ring-primary" />
setFilters((prev) => ({ ...prev, minAmount: event.target.value })) } placeholder="0.00" className="mt-2 w-full rounded-xl border border-border bg-background/50 px-4 py-2 text-sm text-foreground focus:border-primary focus:ring-primary" />
setFilters((prev) => ({ ...prev, maxAmount: event.target.value })) } placeholder="10000.00" className="mt-2 w-full rounded-xl border border-border bg-background/50 px-4 py-2 text-sm text-foreground focus:border-primary focus:ring-primary" />
setFilters((prev) => ({ ...prev, source: event.target.value })) } placeholder="plaid" className="mt-2 w-full rounded-xl border border-border bg-background/50 px-4 py-2 text-sm text-foreground focus:border-primary focus:ring-primary" />
{status ?

{status}

: null}
); }