"use client"; import { useState, useEffect, useRef } from "react"; import { Upload, FileText, CheckCircle, XCircle, Download, Trash2 } from "lucide-react"; import { Button } from "@/components/ui/button"; import { Badge } from "@/components/ui/badge"; import { Card, CardContent } from "@/components/ui/card"; import { importBankTransactions, fetchBankTransactions, reconcileTransaction, type BankTransaction, } from "@/lib/supabase/bank-feeds-actions"; import PageSkeleton from "./PageSkeleton"; export default function BankFeedsPage() { const [transactions, setTransactions] = useState([]); const [loading, setLoading] = useState(true); const [importing, setImporting] = useState(false); const [error, setError] = useState(null); const [successMsg, setSuccessMsg] = useState(null); const [accountName, setAccountName] = useState("Primary Account"); const [showImport, setShowImport] = useState(false); const [csvContent, setCsvContent] = useState(""); const fileInputRef = useRef(null); useEffect(() => { let cancelled = false; fetchBankTransactions() .then((t) => { if (!cancelled) setTransactions(t); }) .catch(() => {}) .finally(() => { if (!cancelled) setLoading(false); }); return () => { cancelled = true; }; }, []); const handleFileUpload = async (e: React.ChangeEvent) => { const file = e.target.files?.[0]; if (!file) return; setImporting(true); setError(null); setSuccessMsg(null); const text = await file.text(); try { const result = await importBankTransactions(text, accountName); if (!result.success) { setError(result.error || "Import failed"); return; } setSuccessMsg(`Imported ${result.count} transactions`); const updated = await fetchBankTransactions(); setTransactions(updated); setShowImport(false); setCsvContent(""); } catch (err: any) { setError(err.message || "An unexpected error occurred"); } finally { setImporting(false); } }; const handleReconcile = async (id: string) => { const result = await reconcileTransaction(id); if (result.success) setTransactions((prev) => prev.map((t) => t.id === id ? { ...t, reconciled: true } : t)); }; if (loading) return ; const totalCredits = transactions.filter((t) => t.type === "credit").reduce((s, t) => s + Math.abs(t.amount), 0); const totalDebits = transactions.filter((t) => t.type === "debit").reduce((s, t) => s + Math.abs(t.amount), 0); const unreconciled = transactions.filter((t) => !t.reconciled).length; return (

Bank Feeds

Import and reconcile bank transactions

{error &&
{error}
} {successMsg &&
{successMsg}
} {/* Summary */}

Total Credits

${totalCredits.toFixed(2)}

Total Debits

${totalDebits.toFixed(2)}

Net

= 0 ? "text-emerald-600" : "text-red-600"}`}> ${(totalCredits - totalDebits).toFixed(2)}

Unreconciled

{unreconciled}

{/* Import form */} {showImport && (

Import Bank Transactions

setAccountName(e.target.value)} className="mt-1 w-full border border-gray-200 rounded-lg px-3 py-2.5 text-sm focus:outline-none focus:ring-2 focus:ring-[#1D9E75]/20 focus:border-[#1D9E75]" />
fileInputRef.current?.click()}>

Click to upload CSV

Columns: date, description, amount

Expected CSV format:

date,description,amount{"\n"}2025-04-01,Client payment,1500.00{"\n"}2025-04-02,Office supplies,-45.50
)} {/* Transactions list */} {transactions.length === 0 ? (

No transactions imported

Upload a CSV bank statement to get started

) : (
{transactions.map((t) => ( ))}
Date Description Account Amount Status
{new Date(t.date + "T00:00:00").toLocaleDateString("en-AU", { day: "numeric", month: "short" })}

{t.description}

{t.account_name} {t.type === "credit" ? "+" : "-"}${Math.abs(t.amount).toFixed(2)} {t.reconciled ? ( Reconciled ) : ( Unreconciled )} {!t.reconciled && ( )}
)}
); }