import { useEffect, useState } from "react"; import { account, databases, DATABASE_ID, COLLECTIONS, type Debt, type UserProfile } from "../lib/appwrite"; import { Query } from "appwrite"; import { Button } from "./ui/button"; import { DebtCard } from "./DebtCard"; // TODO: Migrate these components to Appwrite // import { ConversationTimeline } from "./ConversationTimeline"; // import { OnboardingDialog } from "./OnboardingDialog"; import { Card, CardContent, CardHeader, CardTitle } from "./ui/card"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "./ui/tabs"; import { Badge } from "./ui/badge"; import { Separator } from "./ui/separator"; import { DollarSign, TrendingUp, Mail, CheckCircle, AlertTriangle, RefreshCw, Settings, } from "lucide-react"; import { formatCurrency } from "../lib/utils"; import type { Models } from "appwrite"; export function Dashboard() { const [debts, setDebts] = useState([]); const [loading, setLoading] = useState(true); const [userProfile, setUserProfile] = useState(null); const [showOnboarding, setShowOnboarding] = useState(false); const [stats, setStats] = useState({ totalDebts: 0, totalAmount: 0, projectedSavings: 0, settledCount: 0, }); useEffect(() => { fetchUserProfile(); fetchDebts(); setupRealtimeSubscription(); }, []); useEffect(() => { calculateStats(); }, [debts]); const fetchUserProfile = async () => { try { const user = await account.get(); if (!user) return; const response = await databases.listDocuments( DATABASE_ID, COLLECTIONS.USER_PROFILES, [Query.equal('user_id', user.$id)] ); // Get profile for current user const profile = response.documents[0]; setUserProfile(profile as UserProfile); // Show onboarding if user hasn't completed it if (profile && !profile.onboarding_completed) { setShowOnboarding(true); } } catch (error) { console.error("Error fetching user profile:", error); } }; const fetchDebts = async () => { try { const user = await account.get(); if (!user) return; const response = await databases.listDocuments( DATABASE_ID, COLLECTIONS.DEBTS, [Query.equal('user_id', user.$id), Query.orderDesc('created_at')] ); // Debts are already filtered and sorted by the query setDebts(response.documents as Debt[]); } catch (error) { console.error("Error fetching debts:", error); } finally { setLoading(false); } }; const setupRealtimeSubscription = () => { // Appwrite real-time subscription for debts collection // Note: This is a simplified version. In production, you'd need to set up proper channels // and subscribe to document changes for the specific collection // For now, we'll implement a polling mechanism as a fallback // In a full migration, you'd set up Appwrite's real-time listeners const interval = setInterval(() => { fetchDebts(); }, 30000); // Poll every 30 seconds return () => { clearInterval(interval); }; // TODO: Implement proper Appwrite real-time subscription // client.subscribe('databases.${DATABASE_ID}.collections.${COLLECTIONS.DEBTS}.documents', response => { // // Handle real-time updates // }); }; const calculateStats = () => { const totalDebts = debts.length; const totalAmount = debts.reduce((sum, debt) => sum + debt.amount, 0); const projectedSavings = debts.reduce((sum, debt) => { // Use actual savings for accepted debts, projected for others if (debt.status === "accepted" && debt.metadata?.actualSavings?.amount) { return sum + debt.metadata.actualSavings.amount; } return sum + debt.projected_savings; }, 0); const settledCount = debts.filter( (debt) => debt.status === "settled" ).length; setStats({ totalDebts, totalAmount, projectedSavings, settledCount, }); }; const handleOnboardingComplete = () => { setShowOnboarding(false); // Refresh user profile to reflect onboarding completion fetchUserProfile(); }; const handleSignOut = async () => { await account.deleteSession('current'); window.location.href = "/"; }; const groupedDebts = { all: debts, active: debts.filter((debt) => [ "received", "negotiating", "approved", "awaiting_response", "counter_negotiating", "requires_manual_review", ].includes(debt.status) ), settled: debts.filter((debt) => ["settled", "accepted", "sent"].includes(debt.status) ), failed: debts.filter((debt) => ["failed", "rejected", "opted_out"].includes(debt.status) ), }; if (loading) { return (
Loading dashboard...
); } return (
{/* Header */}

Dashboard

AI-powered debt resolution platform with real-time updates

{/* Stats Cards */}
Total Debts
{stats.totalDebts}

Emails processed

Total Amount
{formatCurrency(stats.totalAmount)}

Across all debts

Projected Savings
{formatCurrency(stats.projectedSavings)}

From negotiations

Settled Cases
{stats.settledCount}

Successfully resolved

{/* Main Content */} All Debts {groupedDebts.all.length} Active {groupedDebts.active.length} Settled {groupedDebts.settled.length} Failed/Opted Out {groupedDebts.failed.length} {Object.entries(groupedDebts).map(([key, debtList]) => ( {debtList.length === 0 ? (

No debts found

{key === "all" ? "Forward your first debt email to get started with automated negotiations." : `No debts with ${key} status found.`}

) : (
{debtList.map((debt) => (
))}
)}
))}
{/* Footer */}

InboxNegotiator - FDCPA-compliant debt resolution platform

Real-time updates powered by Supabase

{/* Onboarding Dialog */} {/* TODO: Migrate OnboardingDialog to Appwrite */} {/* */}
); }