mirror of
https://github.com/FranP-code/inbox-negotiator.git
synced 2025-10-13 00:42:26 +00:00
Added dark modes
This commit is contained in:
@@ -1,275 +1,295 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { supabase, type Debt } from '../lib/supabase';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { DebtCard } from './DebtCard';
|
||||
import { DebtTimeline } from './DebtTimeline';
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
|
||||
import { Badge } from '@/components/ui/badge';
|
||||
import { Separator } from '@/components/ui/separator';
|
||||
import {
|
||||
DollarSign,
|
||||
TrendingUp,
|
||||
Mail,
|
||||
CheckCircle,
|
||||
AlertTriangle,
|
||||
RefreshCw,
|
||||
BarChart3,
|
||||
LogOut
|
||||
} from 'lucide-react';
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { supabase, type Debt } from "../lib/supabase";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { DebtCard } from "./DebtCard";
|
||||
import { DebtTimeline } from "./DebtTimeline";
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
CardDescription,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from "@/components/ui/card";
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { Separator } from "@/components/ui/separator";
|
||||
import {
|
||||
DollarSign,
|
||||
TrendingUp,
|
||||
Mail,
|
||||
CheckCircle,
|
||||
AlertTriangle,
|
||||
RefreshCw,
|
||||
BarChart3,
|
||||
LogOut,
|
||||
} from "lucide-react";
|
||||
|
||||
export function Dashboard() {
|
||||
const [debts, setDebts] = useState<Debt[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [stats, setStats] = useState({
|
||||
totalDebts: 0,
|
||||
totalAmount: 0,
|
||||
projectedSavings: 0,
|
||||
settledCount: 0
|
||||
});
|
||||
const [debts, setDebts] = useState<Debt[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [stats, setStats] = useState({
|
||||
totalDebts: 0,
|
||||
totalAmount: 0,
|
||||
projectedSavings: 0,
|
||||
settledCount: 0,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
fetchDebts();
|
||||
setupRealtimeSubscription();
|
||||
}, []);
|
||||
useEffect(() => {
|
||||
fetchDebts();
|
||||
setupRealtimeSubscription();
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
calculateStats();
|
||||
}, [debts]);
|
||||
useEffect(() => {
|
||||
calculateStats();
|
||||
}, [debts]);
|
||||
|
||||
const fetchDebts = async () => {
|
||||
try {
|
||||
const { data, error } = await supabase
|
||||
.from('debts')
|
||||
.select('*')
|
||||
.order('created_at', { ascending: false });
|
||||
const fetchDebts = async () => {
|
||||
try {
|
||||
const { data, error } = await supabase
|
||||
.from("debts")
|
||||
.select("*")
|
||||
.order("created_at", { ascending: false });
|
||||
|
||||
if (error) throw error;
|
||||
setDebts(data || []);
|
||||
} catch (error) {
|
||||
console.error('Error fetching debts:', error);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
if (error) throw error;
|
||||
setDebts(data || []);
|
||||
} catch (error) {
|
||||
console.error("Error fetching debts:", error);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const setupRealtimeSubscription = () => {
|
||||
const subscription = supabase
|
||||
.channel('debts_changes')
|
||||
.on(
|
||||
'postgres_changes',
|
||||
{
|
||||
event: '*',
|
||||
schema: 'public',
|
||||
table: 'debts'
|
||||
},
|
||||
(payload) => {
|
||||
if (payload.eventType === 'INSERT') {
|
||||
setDebts(prev => [payload.new as Debt, ...prev]);
|
||||
} else if (payload.eventType === 'UPDATE') {
|
||||
setDebts(prev =>
|
||||
prev.map(debt =>
|
||||
debt.id === payload.new.id ? payload.new as Debt : debt
|
||||
)
|
||||
);
|
||||
} else if (payload.eventType === 'DELETE') {
|
||||
setDebts(prev => prev.filter(debt => debt.id !== payload.old.id));
|
||||
}
|
||||
}
|
||||
)
|
||||
.subscribe();
|
||||
const setupRealtimeSubscription = () => {
|
||||
const subscription = supabase
|
||||
.channel("debts_changes")
|
||||
.on(
|
||||
"postgres_changes",
|
||||
{
|
||||
event: "*",
|
||||
schema: "public",
|
||||
table: "debts",
|
||||
},
|
||||
(payload) => {
|
||||
if (payload.eventType === "INSERT") {
|
||||
setDebts((prev) => [payload.new as Debt, ...prev]);
|
||||
} else if (payload.eventType === "UPDATE") {
|
||||
setDebts((prev) =>
|
||||
prev.map((debt) =>
|
||||
debt.id === payload.new.id ? (payload.new as Debt) : debt
|
||||
)
|
||||
);
|
||||
} else if (payload.eventType === "DELETE") {
|
||||
setDebts((prev) =>
|
||||
prev.filter((debt) => debt.id !== payload.old.id)
|
||||
);
|
||||
}
|
||||
}
|
||||
)
|
||||
.subscribe();
|
||||
|
||||
return () => {
|
||||
subscription.unsubscribe();
|
||||
};
|
||||
};
|
||||
return () => {
|
||||
subscription.unsubscribe();
|
||||
};
|
||||
};
|
||||
|
||||
const calculateStats = () => {
|
||||
const totalDebts = debts.length;
|
||||
const totalAmount = debts.reduce((sum, debt) => sum + debt.amount, 0);
|
||||
const projectedSavings = debts.reduce((sum, debt) => sum + debt.projected_savings, 0);
|
||||
const settledCount = debts.filter(debt => debt.status === 'settled').length;
|
||||
const calculateStats = () => {
|
||||
const totalDebts = debts.length;
|
||||
const totalAmount = debts.reduce((sum, debt) => sum + debt.amount, 0);
|
||||
const projectedSavings = debts.reduce(
|
||||
(sum, debt) => sum + debt.projected_savings,
|
||||
0
|
||||
);
|
||||
const settledCount = debts.filter(
|
||||
(debt) => debt.status === "settled"
|
||||
).length;
|
||||
|
||||
setStats({
|
||||
totalDebts,
|
||||
totalAmount,
|
||||
projectedSavings,
|
||||
settledCount
|
||||
});
|
||||
};
|
||||
setStats({
|
||||
totalDebts,
|
||||
totalAmount,
|
||||
projectedSavings,
|
||||
settledCount,
|
||||
});
|
||||
};
|
||||
|
||||
const handleSignOut = async () => {
|
||||
await supabase.auth.signOut();
|
||||
window.location.href = '/';
|
||||
};
|
||||
const handleSignOut = async () => {
|
||||
await supabase.auth.signOut();
|
||||
window.location.href = "/";
|
||||
};
|
||||
|
||||
const formatCurrency = (amount: number) => {
|
||||
return new Intl.NumberFormat('en-US', {
|
||||
style: 'currency',
|
||||
currency: 'USD'
|
||||
}).format(amount);
|
||||
};
|
||||
const formatCurrency = (amount: number) => {
|
||||
return new Intl.NumberFormat("en-US", {
|
||||
style: "currency",
|
||||
currency: "USD",
|
||||
}).format(amount);
|
||||
};
|
||||
|
||||
const groupedDebts = {
|
||||
all: debts,
|
||||
active: debts.filter(debt => ['received', 'negotiating'].includes(debt.status)),
|
||||
settled: debts.filter(debt => debt.status === 'settled'),
|
||||
failed: debts.filter(debt => ['failed', 'opted_out'].includes(debt.status))
|
||||
};
|
||||
const groupedDebts = {
|
||||
all: debts,
|
||||
active: debts.filter((debt) =>
|
||||
["received", "negotiating"].includes(debt.status)
|
||||
),
|
||||
settled: debts.filter((debt) => debt.status === "settled"),
|
||||
failed: debts.filter((debt) =>
|
||||
["failed", "opted_out"].includes(debt.status)
|
||||
),
|
||||
};
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
<div className="flex items-center justify-center min-h-screen">
|
||||
<div className="flex items-center gap-2 text-lg">
|
||||
<RefreshCw className="h-5 w-5 animate-spin" />
|
||||
Loading dashboard...
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
if (loading) {
|
||||
return (
|
||||
<div className="flex items-center justify-center min-h-screen bg-gray-50 dark:bg-background">
|
||||
<div className="flex items-center gap-2 text-lg text-gray-900 dark:text-foreground">
|
||||
<RefreshCw className="h-5 w-5 animate-spin" />
|
||||
Loading dashboard...
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-gray-50">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
|
||||
{/* Header */}
|
||||
<div className="mb-8 flex justify-between items-start">
|
||||
<div>
|
||||
<h1 className="text-3xl font-bold text-gray-900 flex items-center gap-3">
|
||||
<BarChart3 className="h-8 w-8 text-primary" />
|
||||
InboxNegotiator Dashboard
|
||||
</h1>
|
||||
<p className="text-gray-600 mt-2">
|
||||
AI-powered debt resolution platform with real-time updates
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
return (
|
||||
<div className="min-h-screen bg-gray-50 dark:bg-background">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
|
||||
{/* Header */}
|
||||
<div className="mb-8 flex justify-between items-start">
|
||||
<div>
|
||||
<h1 className="text-3xl font-bold text-gray-900 dark:text-foreground flex items-center gap-3">
|
||||
<BarChart3 className="h-8 w-8 text-primary" />
|
||||
InboxNegotiator Dashboard
|
||||
</h1>
|
||||
<p className="text-gray-600 dark:text-gray-300 mt-2">
|
||||
AI-powered debt resolution platform with real-time updates
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Stats Cards */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-8">
|
||||
<Card>
|
||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
||||
<CardTitle className="text-sm font-medium">Total Debts</CardTitle>
|
||||
<Mail className="h-4 w-4 text-muted-foreground" />
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="text-2xl font-bold">{stats.totalDebts}</div>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
Emails processed
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
{/* Stats Cards */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-8">
|
||||
<Card>
|
||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
||||
<CardTitle className="text-sm font-medium">Total Debts</CardTitle>
|
||||
<Mail className="h-4 w-4 text-muted-foreground" />
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="text-2xl font-bold">{stats.totalDebts}</div>
|
||||
<p className="text-xs text-muted-foreground">Emails processed</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card>
|
||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
||||
<CardTitle className="text-sm font-medium">Total Amount</CardTitle>
|
||||
<DollarSign className="h-4 w-4 text-muted-foreground" />
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="text-2xl font-bold">{formatCurrency(stats.totalAmount)}</div>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
Across all debts
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
<Card>
|
||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
||||
<CardTitle className="text-sm font-medium">
|
||||
Total Amount
|
||||
</CardTitle>
|
||||
<DollarSign className="h-4 w-4 text-muted-foreground" />
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="text-2xl font-bold">
|
||||
{formatCurrency(stats.totalAmount)}
|
||||
</div>
|
||||
<p className="text-xs text-muted-foreground">Across all debts</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card>
|
||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
||||
<CardTitle className="text-sm font-medium">Projected Savings</CardTitle>
|
||||
<TrendingUp className="h-4 w-4 text-muted-foreground" />
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="text-2xl font-bold text-green-600">
|
||||
{formatCurrency(stats.projectedSavings)}
|
||||
</div>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
From negotiations
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
<Card>
|
||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
||||
<CardTitle className="text-sm font-medium">
|
||||
Projected Savings
|
||||
</CardTitle>
|
||||
<TrendingUp className="h-4 w-4 text-muted-foreground" />
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="text-2xl font-bold text-green-600 dark:text-green-400">
|
||||
{formatCurrency(stats.projectedSavings)}
|
||||
</div>
|
||||
<p className="text-xs text-muted-foreground">From negotiations</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card>
|
||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
||||
<CardTitle className="text-sm font-medium">Settled Cases</CardTitle>
|
||||
<CheckCircle className="h-4 w-4 text-muted-foreground" />
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="text-2xl font-bold">{stats.settledCount}</div>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
Successfully resolved
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
<Card>
|
||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
||||
<CardTitle className="text-sm font-medium">
|
||||
Settled Cases
|
||||
</CardTitle>
|
||||
<CheckCircle className="h-4 w-4 text-muted-foreground" />
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="text-2xl font-bold">{stats.settledCount}</div>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
Successfully resolved
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
{/* Main Content */}
|
||||
<Tabs defaultValue="all" className="space-y-6">
|
||||
<TabsList className="grid w-full grid-cols-4">
|
||||
<TabsTrigger value="all" className="flex items-center gap-2">
|
||||
All Debts
|
||||
<Badge variant="secondary" className="ml-1">
|
||||
{groupedDebts.all.length}
|
||||
</Badge>
|
||||
</TabsTrigger>
|
||||
<TabsTrigger value="active" className="flex items-center gap-2">
|
||||
Active
|
||||
<Badge variant="secondary" className="ml-1">
|
||||
{groupedDebts.active.length}
|
||||
</Badge>
|
||||
</TabsTrigger>
|
||||
<TabsTrigger value="settled" className="flex items-center gap-2">
|
||||
Settled
|
||||
<Badge variant="secondary" className="ml-1">
|
||||
{groupedDebts.settled.length}
|
||||
</Badge>
|
||||
</TabsTrigger>
|
||||
<TabsTrigger value="failed" className="flex items-center gap-2">
|
||||
Failed/Opted Out
|
||||
<Badge variant="secondary" className="ml-1">
|
||||
{groupedDebts.failed.length}
|
||||
</Badge>
|
||||
</TabsTrigger>
|
||||
</TabsList>
|
||||
{/* Main Content */}
|
||||
<Tabs defaultValue="all" className="space-y-6">
|
||||
<TabsList className="grid w-full grid-cols-4">
|
||||
<TabsTrigger value="all" className="flex items-center gap-2">
|
||||
All Debts
|
||||
<Badge variant="secondary" className="ml-1">
|
||||
{groupedDebts.all.length}
|
||||
</Badge>
|
||||
</TabsTrigger>
|
||||
<TabsTrigger value="active" className="flex items-center gap-2">
|
||||
Active
|
||||
<Badge variant="secondary" className="ml-1">
|
||||
{groupedDebts.active.length}
|
||||
</Badge>
|
||||
</TabsTrigger>
|
||||
<TabsTrigger value="settled" className="flex items-center gap-2">
|
||||
Settled
|
||||
<Badge variant="secondary" className="ml-1">
|
||||
{groupedDebts.settled.length}
|
||||
</Badge>
|
||||
</TabsTrigger>
|
||||
<TabsTrigger value="failed" className="flex items-center gap-2">
|
||||
Failed/Opted Out
|
||||
<Badge variant="secondary" className="ml-1">
|
||||
{groupedDebts.failed.length}
|
||||
</Badge>
|
||||
</TabsTrigger>
|
||||
</TabsList>
|
||||
|
||||
{Object.entries(groupedDebts).map(([key, debtList]) => (
|
||||
<TabsContent key={key} value={key} className="space-y-6">
|
||||
{debtList.length === 0 ? (
|
||||
<Card>
|
||||
<CardContent className="flex flex-col items-center justify-center py-12">
|
||||
<AlertTriangle className="h-12 w-12 text-gray-400 mb-4" />
|
||||
<h3 className="text-lg font-medium text-gray-900 mb-2">No debts found</h3>
|
||||
<p className="text-gray-600 text-center max-w-md">
|
||||
{key === 'all'
|
||||
? 'Forward your first debt email to get started with automated negotiations.'
|
||||
: `No debts with ${key} status found.`
|
||||
}
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
) : (
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 xl:grid-cols-3 gap-6">
|
||||
{debtList.map((debt) => (
|
||||
<div key={debt.id} className="space-y-4">
|
||||
<DebtCard debt={debt} />
|
||||
<Card className="bg-gray-50">
|
||||
<CardContent className="p-4">
|
||||
<DebtTimeline debt={debt} />
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</TabsContent>
|
||||
))}
|
||||
</Tabs>
|
||||
{Object.entries(groupedDebts).map(([key, debtList]) => (
|
||||
<TabsContent key={key} value={key} className="space-y-6">
|
||||
{debtList.length === 0 ? (
|
||||
<Card>
|
||||
<CardContent className="flex flex-col items-center justify-center py-12">
|
||||
<AlertTriangle className="h-12 w-12 text-gray-400 dark:text-gray-500 mb-4" />
|
||||
<h3 className="text-lg font-medium text-gray-900 dark:text-foreground mb-2">
|
||||
No debts found
|
||||
</h3>
|
||||
<p className="text-gray-600 dark:text-gray-300 text-center max-w-md">
|
||||
{key === "all"
|
||||
? "Forward your first debt email to get started with automated negotiations."
|
||||
: `No debts with ${key} status found.`}
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
) : (
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 xl:grid-cols-3 gap-6">
|
||||
{debtList.map((debt) => (
|
||||
<div key={debt.id} className="space-y-4">
|
||||
<DebtCard debt={debt} />
|
||||
<Card className="bg-gray-50 dark:bg-gray-800/50">
|
||||
<CardContent className="p-4">
|
||||
<DebtTimeline debt={debt} />
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</TabsContent>
|
||||
))}
|
||||
</Tabs>
|
||||
|
||||
{/* Footer */}
|
||||
<Separator className="my-8" />
|
||||
<div className="text-center text-sm text-gray-600">
|
||||
<p>InboxNegotiator - FDCPA-compliant debt resolution platform</p>
|
||||
<p className="mt-1">Real-time updates powered by Supabase</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
{/* Footer */}
|
||||
<Separator className="my-8" />
|
||||
<div className="text-center text-sm text-gray-600 dark:text-gray-300">
|
||||
<p>InboxNegotiator - FDCPA-compliant debt resolution platform</p>
|
||||
<p className="mt-1">Real-time updates powered by Supabase</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,136 +1,154 @@
|
||||
import React from 'react';
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
|
||||
import { Badge } from '@/components/ui/badge';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, DialogTrigger } from '@/components/ui/dialog';
|
||||
import { Calendar, DollarSign, Mail, FileText, TrendingUp } from 'lucide-react';
|
||||
import type { Debt } from '../lib/supabase';
|
||||
import React from "react";
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
CardDescription,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from "@/components/ui/card";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "@/components/ui/dialog";
|
||||
import { Calendar, DollarSign, Mail, FileText, TrendingUp } from "lucide-react";
|
||||
import type { Debt } from "../lib/supabase";
|
||||
|
||||
interface DebtCardProps {
|
||||
debt: Debt;
|
||||
debt: Debt;
|
||||
}
|
||||
|
||||
const statusColors = {
|
||||
received: 'bg-blue-100 text-blue-800 border-blue-200',
|
||||
negotiating: 'bg-yellow-100 text-yellow-800 border-yellow-200',
|
||||
settled: 'bg-green-100 text-green-800 border-green-200',
|
||||
failed: 'bg-red-100 text-red-800 border-red-200',
|
||||
opted_out: 'bg-gray-100 text-gray-800 border-gray-200'
|
||||
received:
|
||||
"bg-blue-100 text-blue-800 border-blue-200 dark:bg-blue-900/20 dark:text-blue-300 dark:border-blue-800",
|
||||
negotiating:
|
||||
"bg-yellow-100 text-yellow-800 border-yellow-200 dark:bg-yellow-900/20 dark:text-yellow-300 dark:border-yellow-800",
|
||||
settled:
|
||||
"bg-green-100 text-green-800 border-green-200 dark:bg-green-900/20 dark:text-green-300 dark:border-green-800",
|
||||
failed:
|
||||
"bg-red-100 text-red-800 border-red-200 dark:bg-red-900/20 dark:text-red-300 dark:border-red-800",
|
||||
opted_out:
|
||||
"bg-gray-100 text-gray-800 border-gray-200 dark:bg-gray-800/20 dark:text-gray-300 dark:border-gray-700",
|
||||
};
|
||||
|
||||
const statusLabels = {
|
||||
received: 'Received',
|
||||
negotiating: 'Negotiating',
|
||||
settled: 'Settled',
|
||||
failed: 'Failed',
|
||||
opted_out: 'Opted Out'
|
||||
received: "Received",
|
||||
negotiating: "Negotiating",
|
||||
settled: "Settled",
|
||||
failed: "Failed",
|
||||
opted_out: "Opted Out",
|
||||
};
|
||||
|
||||
export function DebtCard({ debt }: DebtCardProps) {
|
||||
const formatCurrency = (amount: number) => {
|
||||
return new Intl.NumberFormat('en-US', {
|
||||
style: 'currency',
|
||||
currency: 'USD'
|
||||
}).format(amount);
|
||||
};
|
||||
const formatCurrency = (amount: number) => {
|
||||
return new Intl.NumberFormat("en-US", {
|
||||
style: "currency",
|
||||
currency: "USD",
|
||||
}).format(amount);
|
||||
};
|
||||
|
||||
const formatDate = (dateString: string) => {
|
||||
return new Date(dateString).toLocaleDateString('en-US', {
|
||||
year: 'numeric',
|
||||
month: 'short',
|
||||
day: 'numeric',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit'
|
||||
});
|
||||
};
|
||||
const formatDate = (dateString: string) => {
|
||||
return new Date(dateString).toLocaleDateString("en-US", {
|
||||
year: "numeric",
|
||||
month: "short",
|
||||
day: "numeric",
|
||||
hour: "2-digit",
|
||||
minute: "2-digit",
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<Card className="w-full hover:shadow-lg transition-all duration-300 border-l-4 border-l-primary">
|
||||
<CardHeader className="pb-3">
|
||||
<div className="flex items-center justify-between">
|
||||
<CardTitle className="text-lg font-semibold text-gray-900">
|
||||
{debt.vendor}
|
||||
</CardTitle>
|
||||
<Badge
|
||||
variant="outline"
|
||||
className={`${statusColors[debt.status]} font-medium`}
|
||||
>
|
||||
{statusLabels[debt.status]}
|
||||
</Badge>
|
||||
</div>
|
||||
<CardDescription className="flex items-center gap-2 text-sm text-gray-600">
|
||||
<Calendar className="h-4 w-4" />
|
||||
{formatDate(debt.created_at)}
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
|
||||
<CardContent className="space-y-4">
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-center gap-2">
|
||||
<DollarSign className="h-5 w-5 text-gray-500" />
|
||||
<span className="text-2xl font-bold text-gray-900">
|
||||
{formatCurrency(debt.amount)}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{debt.projected_savings > 0 && (
|
||||
<div className="flex items-center gap-1 text-green-600">
|
||||
<TrendingUp className="h-4 w-4" />
|
||||
<span className="text-sm font-medium">
|
||||
Save {formatCurrency(debt.projected_savings)}
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
return (
|
||||
<Card className="w-full hover:shadow-lg transition-all duration-300 border-l-4 border-l-primary">
|
||||
<CardHeader className="pb-3">
|
||||
<div className="flex items-center justify-between">
|
||||
<CardTitle className="text-lg font-semibold text-gray-900 dark:text-foreground">
|
||||
{debt.vendor}
|
||||
</CardTitle>
|
||||
<Badge
|
||||
variant="outline"
|
||||
className={`${statusColors[debt.status]} font-medium`}
|
||||
>
|
||||
{statusLabels[debt.status]}
|
||||
</Badge>
|
||||
</div>
|
||||
<CardDescription className="flex items-center gap-2 text-sm text-gray-600 dark:text-gray-300">
|
||||
<Calendar className="h-4 w-4" />
|
||||
{formatDate(debt.created_at)}
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
|
||||
<div className="flex gap-2">
|
||||
<Dialog>
|
||||
<DialogTrigger asChild>
|
||||
<Button variant="outline" size="sm" className="flex-1">
|
||||
<Mail className="h-4 w-4 mr-2" />
|
||||
View Email
|
||||
</Button>
|
||||
</DialogTrigger>
|
||||
<DialogContent className="max-w-2xl max-h-[80vh] overflow-y-auto">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Original Email</DialogTitle>
|
||||
<DialogDescription>
|
||||
From: {debt.vendor} • {formatDate(debt.created_at)}
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<div className="mt-4">
|
||||
<pre className="whitespace-pre-wrap text-sm bg-gray-50 p-4 rounded-lg border">
|
||||
{debt.raw_email || 'No email content available'}
|
||||
</pre>
|
||||
</div>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
<CardContent className="space-y-4">
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-center gap-2">
|
||||
<DollarSign className="h-5 w-5 text-gray-500 dark:text-gray-400" />
|
||||
<span className="text-2xl font-bold text-gray-900 dark:text-foreground">
|
||||
{formatCurrency(debt.amount)}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{debt.negotiated_plan && (
|
||||
<Dialog>
|
||||
<DialogTrigger asChild>
|
||||
<Button variant="outline" size="sm" className="flex-1">
|
||||
<FileText className="h-4 w-4 mr-2" />
|
||||
View Response
|
||||
</Button>
|
||||
</DialogTrigger>
|
||||
<DialogContent className="max-w-2xl max-h-[80vh] overflow-y-auto">
|
||||
<DialogHeader>
|
||||
<DialogTitle>AI-Generated Negotiation Response</DialogTitle>
|
||||
<DialogDescription>
|
||||
FDCPA-compliant response ready to send
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<div className="mt-4">
|
||||
<pre className="whitespace-pre-wrap text-sm bg-gray-50 p-4 rounded-lg border">
|
||||
{debt.negotiated_plan}
|
||||
</pre>
|
||||
</div>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
)}
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
{debt.projected_savings > 0 && (
|
||||
<div className="flex items-center gap-1 text-green-600 dark:text-green-400">
|
||||
<TrendingUp className="h-4 w-4" />
|
||||
<span className="text-sm font-medium">
|
||||
Save {formatCurrency(debt.projected_savings)}
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="flex gap-2">
|
||||
<Dialog>
|
||||
<DialogTrigger asChild>
|
||||
<Button variant="outline" size="sm" className="flex-1">
|
||||
<Mail className="h-4 w-4 mr-2" />
|
||||
View Email
|
||||
</Button>
|
||||
</DialogTrigger>
|
||||
<DialogContent className="max-w-2xl max-h-[80vh] overflow-y-auto">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Original Email</DialogTitle>
|
||||
<DialogDescription>
|
||||
From: {debt.vendor} • {formatDate(debt.created_at)}
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<div className="mt-4">
|
||||
<pre className="whitespace-pre-wrap text-sm bg-gray-50 dark:bg-gray-800 p-4 rounded-lg border dark:border-gray-700">
|
||||
{debt.raw_email || "No email content available"}
|
||||
</pre>
|
||||
</div>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
|
||||
{debt.negotiated_plan && (
|
||||
<Dialog>
|
||||
<DialogTrigger asChild>
|
||||
<Button variant="outline" size="sm" className="flex-1">
|
||||
<FileText className="h-4 w-4 mr-2" />
|
||||
View Response
|
||||
</Button>
|
||||
</DialogTrigger>
|
||||
<DialogContent className="max-w-2xl max-h-[80vh] overflow-y-auto">
|
||||
<DialogHeader>
|
||||
<DialogTitle>AI-Generated Negotiation Response</DialogTitle>
|
||||
<DialogDescription>
|
||||
FDCPA-compliant response ready to send
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<div className="mt-4">
|
||||
<pre className="whitespace-pre-wrap text-sm bg-gray-50 dark:bg-gray-800 p-4 rounded-lg border dark:border-gray-700">
|
||||
{debt.negotiated_plan}
|
||||
</pre>
|
||||
</div>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
)}
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,113 +1,139 @@
|
||||
import React from 'react';
|
||||
import { CheckCircle, Clock, AlertCircle, XCircle, StopCircle } from 'lucide-react';
|
||||
import type { Debt } from '../lib/supabase';
|
||||
import React from "react";
|
||||
import {
|
||||
CheckCircle,
|
||||
Clock,
|
||||
AlertCircle,
|
||||
XCircle,
|
||||
StopCircle,
|
||||
} from "lucide-react";
|
||||
import type { Debt } from "../lib/supabase";
|
||||
|
||||
interface DebtTimelineProps {
|
||||
debt: Debt;
|
||||
debt: Debt;
|
||||
}
|
||||
|
||||
const timelineSteps = [
|
||||
{ key: 'received', label: 'Email Received', icon: CheckCircle },
|
||||
{ key: 'negotiating', label: 'Negotiating', icon: Clock },
|
||||
{ key: 'settled', label: 'Settled', icon: CheckCircle },
|
||||
{ key: "received", label: "Email Received", icon: CheckCircle },
|
||||
{ key: "negotiating", label: "Negotiating", icon: Clock },
|
||||
{ key: "settled", label: "Settled", icon: CheckCircle },
|
||||
];
|
||||
|
||||
const statusIcons = {
|
||||
received: CheckCircle,
|
||||
negotiating: Clock,
|
||||
settled: CheckCircle,
|
||||
failed: XCircle,
|
||||
opted_out: StopCircle
|
||||
received: CheckCircle,
|
||||
negotiating: Clock,
|
||||
settled: CheckCircle,
|
||||
failed: XCircle,
|
||||
opted_out: StopCircle,
|
||||
};
|
||||
|
||||
const statusColors = {
|
||||
received: 'text-blue-600',
|
||||
negotiating: 'text-yellow-600',
|
||||
settled: 'text-green-600',
|
||||
failed: 'text-red-600',
|
||||
opted_out: 'text-gray-600'
|
||||
received: "text-blue-600 dark:text-blue-400",
|
||||
negotiating: "text-yellow-600 dark:text-yellow-400",
|
||||
settled: "text-green-600 dark:text-green-400",
|
||||
failed: "text-red-600 dark:text-red-400",
|
||||
opted_out: "text-gray-600 dark:text-gray-400",
|
||||
};
|
||||
|
||||
export function DebtTimeline({ debt }: DebtTimelineProps) {
|
||||
const currentStepIndex = timelineSteps.findIndex(step => step.key === debt.status);
|
||||
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
<h3 className="text-lg font-semibold">Progress Timeline</h3>
|
||||
|
||||
<div className="space-y-4">
|
||||
{timelineSteps.map((step, index) => {
|
||||
const isCompleted = index <= currentStepIndex;
|
||||
const isActive = index === currentStepIndex;
|
||||
const Icon = step.icon;
|
||||
|
||||
return (
|
||||
<div key={step.key} className="flex items-center gap-3">
|
||||
<div className={`
|
||||
const currentStepIndex = timelineSteps.findIndex(
|
||||
(step) => step.key === debt.status
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
<h3 className="text-lg font-semibold">Progress Timeline</h3>
|
||||
|
||||
<div className="space-y-4">
|
||||
{timelineSteps.map((step, index) => {
|
||||
const isCompleted = index <= currentStepIndex;
|
||||
const isActive = index === currentStepIndex;
|
||||
const Icon = step.icon;
|
||||
|
||||
return (
|
||||
<div key={step.key} className="flex items-center gap-3">
|
||||
<div
|
||||
className={`
|
||||
flex items-center justify-center w-8 h-8 rounded-full border-2
|
||||
${isCompleted
|
||||
? 'bg-primary border-primary text-white'
|
||||
: 'border-gray-300 text-gray-300'
|
||||
}
|
||||
${isActive ? 'ring-2 ring-primary/20' : ''}
|
||||
`}>
|
||||
<Icon className="h-4 w-4" />
|
||||
</div>
|
||||
|
||||
<div className="flex-1">
|
||||
<div className={`
|
||||
${
|
||||
isCompleted
|
||||
? "bg-primary border-primary text-white"
|
||||
: "border-gray-300 dark:border-gray-600 text-gray-300 dark:text-gray-600"
|
||||
}
|
||||
${isActive ? "ring-2 ring-primary/20" : ""}
|
||||
`}
|
||||
>
|
||||
<Icon className="h-4 w-4" />
|
||||
</div>
|
||||
|
||||
<div className="flex-1">
|
||||
<div
|
||||
className={`
|
||||
font-medium
|
||||
${isCompleted ? 'text-gray-900' : 'text-gray-400'}
|
||||
`}>
|
||||
{step.label}
|
||||
</div>
|
||||
|
||||
{isActive && (
|
||||
<div className="text-sm text-gray-600 mt-1">
|
||||
{debt.status === 'received' && 'Processing email and generating response...'}
|
||||
{debt.status === 'negotiating' && 'Response generated, waiting for creditor reply'}
|
||||
{debt.status === 'settled' && 'Payment plan agreed upon'}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{isActive && (
|
||||
<div className="text-sm text-gray-500">
|
||||
{new Date(debt.updated_at).toLocaleDateString()}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
|
||||
{/* Special cases for failed and opted_out */}
|
||||
{(debt.status === 'failed' || debt.status === 'opted_out') && (
|
||||
<div className="flex items-center gap-3">
|
||||
<div className={`
|
||||
${
|
||||
isCompleted
|
||||
? "text-gray-900 dark:text-foreground"
|
||||
: "text-gray-400 dark:text-gray-500"
|
||||
}
|
||||
`}
|
||||
>
|
||||
{step.label}
|
||||
</div>
|
||||
|
||||
{isActive && (
|
||||
<div className="text-sm text-gray-600 dark:text-gray-300 mt-1">
|
||||
{debt.status === "received" &&
|
||||
"Processing email and generating response..."}
|
||||
{debt.status === "negotiating" &&
|
||||
"Response generated, waiting for creditor reply"}
|
||||
{debt.status === "settled" && "Payment plan agreed upon"}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{isActive && (
|
||||
<div className="text-sm text-gray-500 dark:text-gray-400">
|
||||
{new Date(debt.updated_at).toLocaleDateString()}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
|
||||
{/* Special cases for failed and opted_out */}
|
||||
{(debt.status === "failed" || debt.status === "opted_out") && (
|
||||
<div className="flex items-center gap-3">
|
||||
<div
|
||||
className={`
|
||||
flex items-center justify-center w-8 h-8 rounded-full border-2
|
||||
${debt.status === 'failed' ? 'border-red-500 text-red-500' : 'border-gray-500 text-gray-500'}
|
||||
`}>
|
||||
{React.createElement(statusIcons[debt.status], { className: 'h-4 w-4' })}
|
||||
</div>
|
||||
|
||||
<div className="flex-1">
|
||||
<div className={`font-medium ${statusColors[debt.status]}`}>
|
||||
{debt.status === 'failed' ? 'Negotiation Failed' : 'Opted Out'}
|
||||
</div>
|
||||
<div className="text-sm text-gray-600 mt-1">
|
||||
{debt.status === 'failed'
|
||||
? 'Creditor declined the negotiation proposal'
|
||||
: 'User requested to stop communication'
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="text-sm text-gray-500">
|
||||
{new Date(debt.updated_at).toLocaleDateString()}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
${
|
||||
debt.status === "failed"
|
||||
? "border-red-500 text-red-500 dark:border-red-400 dark:text-red-400"
|
||||
: "border-gray-500 text-gray-500 dark:border-gray-400 dark:text-gray-400"
|
||||
}
|
||||
`}
|
||||
>
|
||||
{React.createElement(statusIcons[debt.status], {
|
||||
className: "h-4 w-4",
|
||||
})}
|
||||
</div>
|
||||
|
||||
<div className="flex-1">
|
||||
<div className={`font-medium ${statusColors[debt.status]}`}>
|
||||
{debt.status === "failed" ? "Negotiation Failed" : "Opted Out"}
|
||||
</div>
|
||||
<div className="text-sm text-gray-600 dark:text-gray-300 mt-1">
|
||||
{debt.status === "failed"
|
||||
? "Creditor declined the negotiation proposal"
|
||||
: "User requested to stop communication"}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="text-sm text-gray-500 dark:text-gray-400">
|
||||
{new Date(debt.updated_at).toLocaleDateString()}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,137 +1,274 @@
|
||||
---
|
||||
import '@/styles/globals.css'
|
||||
import Layout from '../layouts/Layout.astro';
|
||||
import { Navbar } from '../components/Navbar';
|
||||
import "@/styles/globals.css";
|
||||
import Layout from "../layouts/Layout.astro";
|
||||
import { Navbar } from "../components/Navbar";
|
||||
---
|
||||
|
||||
<Layout title="InboxNegotiator - AI-Powered Debt Resolution">
|
||||
<Navbar client:load />
|
||||
|
||||
<main class="min-h-screen bg-gradient-to-br from-blue-50 via-white to-purple-50">
|
||||
<!-- Hero Section -->
|
||||
<section class="relative overflow-hidden">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 pt-20 pb-16">
|
||||
<div class="text-center">
|
||||
<h1 class="text-4xl md:text-6xl font-bold text-gray-900 mb-6">
|
||||
AI-Powered
|
||||
<span class="text-transparent bg-clip-text bg-gradient-to-r from-blue-600 to-purple-600">
|
||||
Debt Resolution
|
||||
</span>
|
||||
</h1>
|
||||
<p class="text-xl text-gray-600 mb-8 max-w-3xl mx-auto">
|
||||
Forward your debt emails and let our AI negotiate FDCPA-compliant payment plans automatically.
|
||||
Save time, reduce stress, and potentially save thousands on your debts.
|
||||
</p>
|
||||
<div class="flex flex-col sm:flex-row gap-4 justify-center">
|
||||
<a href="/signup" class="inline-flex items-center justify-center px-8 py-3 border border-transparent text-base font-medium rounded-md text-white bg-blue-600 hover:bg-blue-700 transition-colors">
|
||||
Get Started Free
|
||||
</a>
|
||||
<a href="#how-it-works" class="inline-flex items-center justify-center px-8 py-3 border border-gray-300 text-base font-medium rounded-md text-gray-700 bg-white hover:bg-gray-50 transition-colors">
|
||||
Learn More
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<Navbar client:load />
|
||||
|
||||
<!-- Features Section -->
|
||||
<section id="how-it-works" class="py-16 bg-white">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div class="text-center mb-16">
|
||||
<h2 class="text-3xl font-bold text-gray-900 mb-4">How It Works</h2>
|
||||
<p class="text-lg text-gray-600">Simple, automated, and compliant debt resolution</p>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-3 gap-8">
|
||||
<div class="text-center">
|
||||
<div class="w-16 h-16 bg-blue-100 rounded-full flex items-center justify-center mx-auto mb-4">
|
||||
<svg class="w-8 h-8 text-blue-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 8l7.89 4.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"></path>
|
||||
</svg>
|
||||
</div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2">Forward Emails</h3>
|
||||
<p class="text-gray-600">Simply forward your debt collection emails to our secure processing address.</p>
|
||||
</div>
|
||||
|
||||
<div class="text-center">
|
||||
<div class="w-16 h-16 bg-purple-100 rounded-full flex items-center justify-center mx-auto mb-4">
|
||||
<svg class="w-8 h-8 text-purple-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9.663 17h4.673M12 3v1m6.364 1.636l-.707.707M21 12h-1M4 12H3m3.343-5.657l-.707-.707m2.828 9.9a5 5 0 117.072 0l-.548.547A3.374 3.374 0 0014 18.469V19a2 2 0 11-4 0v-.531c0-.895-.356-1.754-.988-2.386l-.548-.547z"></path>
|
||||
</svg>
|
||||
</div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2">AI Analysis</h3>
|
||||
<p class="text-gray-600">Our AI analyzes the debt and generates FDCPA-compliant negotiation strategies.</p>
|
||||
</div>
|
||||
|
||||
<div class="text-center">
|
||||
<div class="w-16 h-16 bg-green-100 rounded-full flex items-center justify-center mx-auto mb-4">
|
||||
<svg class="w-8 h-8 text-green-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"></path>
|
||||
</svg>
|
||||
</div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2">Track Progress</h3>
|
||||
<p class="text-gray-600">Monitor negotiations in real-time and track your potential savings.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<main
|
||||
class="min-h-screen bg-gradient-to-br from-blue-50 via-white to-purple-50 dark:from-gray-900 dark:via-background dark:to-gray-800"
|
||||
>
|
||||
<!-- Hero Section -->
|
||||
<section class="relative overflow-hidden">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 pt-20 pb-16">
|
||||
<div class="text-center">
|
||||
<h1
|
||||
class="text-4xl md:text-6xl font-bold text-gray-900 dark:text-foreground mb-6"
|
||||
>
|
||||
AI-Powered
|
||||
<span
|
||||
class="text-transparent bg-clip-text bg-gradient-to-r from-blue-600 to-purple-600 dark:from-blue-400 dark:to-purple-400"
|
||||
>
|
||||
Debt Resolution
|
||||
</span>
|
||||
</h1>
|
||||
<p
|
||||
class="text-xl text-gray-600 dark:text-gray-300 mb-8 max-w-3xl mx-auto"
|
||||
>
|
||||
Forward your debt emails and let our AI negotiate FDCPA-compliant
|
||||
payment plans automatically. Save time, reduce stress, and
|
||||
potentially save thousands on your debts.
|
||||
</p>
|
||||
<div class="flex flex-col sm:flex-row gap-4 justify-center">
|
||||
<a
|
||||
href="/signup"
|
||||
class="inline-flex items-center justify-center px-8 py-3 border border-transparent text-base font-medium rounded-md text-white bg-blue-600 hover:bg-blue-700 dark:bg-blue-500 dark:hover:bg-blue-600 transition-colors"
|
||||
>
|
||||
Get Started Free
|
||||
</a>
|
||||
<a
|
||||
href="#how-it-works"
|
||||
class="inline-flex items-center justify-center px-8 py-3 border border-gray-300 dark:border-gray-600 text-base font-medium rounded-md text-gray-700 dark:text-gray-200 bg-white dark:bg-gray-800 hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors"
|
||||
>
|
||||
Learn More
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Benefits Section -->
|
||||
<section class="py-16 bg-gray-50">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div class="text-center mb-16">
|
||||
<h2 class="text-3xl font-bold text-gray-900 mb-4">Why Choose InboxNegotiator?</h2>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
|
||||
<div class="bg-white p-6 rounded-lg shadow-sm">
|
||||
<h3 class="text-lg font-semibold text-gray-900 mb-2">FDCPA Compliant</h3>
|
||||
<p class="text-gray-600">All responses follow Fair Debt Collection Practices Act guidelines.</p>
|
||||
</div>
|
||||
|
||||
<div class="bg-white p-6 rounded-lg shadow-sm">
|
||||
<h3 class="text-lg font-semibold text-gray-900 mb-2">Save Money</h3>
|
||||
<p class="text-gray-600">Potentially reduce your debt by up to 40% through strategic negotiations.</p>
|
||||
</div>
|
||||
|
||||
<div class="bg-white p-6 rounded-lg shadow-sm">
|
||||
<h3 class="text-lg font-semibold text-gray-900 mb-2">Real-time Updates</h3>
|
||||
<p class="text-gray-600">Track your negotiations with live dashboard updates.</p>
|
||||
</div>
|
||||
|
||||
<div class="bg-white p-6 rounded-lg shadow-sm">
|
||||
<h3 class="text-lg font-semibold text-gray-900 mb-2">Secure & Private</h3>
|
||||
<p class="text-gray-600">Your financial information is encrypted and protected.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<!-- Features Section -->
|
||||
<section id="how-it-works" class="py-16 bg-white dark:bg-background">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div class="text-center mb-16">
|
||||
<h2
|
||||
class="text-3xl font-bold text-gray-900 dark:text-foreground mb-4"
|
||||
>
|
||||
How It Works
|
||||
</h2>
|
||||
<p class="text-lg text-gray-600 dark:text-gray-300">
|
||||
Simple, automated, and compliant debt resolution
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- CTA Section -->
|
||||
<section class="py-16 bg-blue-600">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 text-center">
|
||||
<h2 class="text-3xl font-bold text-white mb-4">Ready to Take Control of Your Debt?</h2>
|
||||
<p class="text-xl text-blue-100 mb-8">Join thousands who have successfully negotiated their debts with AI assistance.</p>
|
||||
<a href="/signup" class="inline-flex items-center justify-center px-8 py-3 border border-transparent text-base font-medium rounded-md text-blue-600 bg-white hover:bg-gray-50 transition-colors">
|
||||
Start Your Free Account
|
||||
</a>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
<div class="grid grid-cols-1 md:grid-cols-3 gap-8">
|
||||
<div class="text-center">
|
||||
<div
|
||||
class="w-16 h-16 bg-blue-100 dark:bg-blue-900 rounded-full flex items-center justify-center mx-auto mb-4"
|
||||
>
|
||||
<svg
|
||||
class="w-8 h-8 text-blue-600 dark:text-blue-400"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M3 8l7.89 4.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"
|
||||
></path>
|
||||
</svg>
|
||||
</div>
|
||||
<h3
|
||||
class="text-xl font-semibold text-gray-900 dark:text-foreground mb-2"
|
||||
>
|
||||
Forward Emails
|
||||
</h3>
|
||||
<p class="text-gray-600 dark:text-gray-300">
|
||||
Simply forward your debt collection emails to our secure
|
||||
processing address.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Footer -->
|
||||
<footer class="bg-gray-900 text-white py-12">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div class="text-center">
|
||||
<div class="flex items-center justify-center gap-3 mb-4">
|
||||
<svg class="w-8 h-8" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z"></path>
|
||||
</svg>
|
||||
<span class="text-xl font-bold">InboxNegotiator</span>
|
||||
</div>
|
||||
<p class="text-gray-400 mb-4">AI-powered debt resolution platform</p>
|
||||
<p class="text-sm text-gray-500">© 2025 InboxNegotiator. All rights reserved.</p>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</Layout>
|
||||
<div class="text-center">
|
||||
<div
|
||||
class="w-16 h-16 bg-purple-100 dark:bg-purple-900 rounded-full flex items-center justify-center mx-auto mb-4"
|
||||
>
|
||||
<svg
|
||||
class="w-8 h-8 text-purple-600 dark:text-purple-400"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M9.663 17h4.673M12 3v1m6.364 1.636l-.707.707M21 12h-1M4 12H3m3.343-5.657l-.707-.707m2.828 9.9a5 5 0 117.072 0l-.548.547A3.374 3.374 0 0014 18.469V19a2 2 0 11-4 0v-.531c0-.895-.356-1.754-.988-2.386l-.548-.547z"
|
||||
></path>
|
||||
</svg>
|
||||
</div>
|
||||
<h3
|
||||
class="text-xl font-semibold text-gray-900 dark:text-foreground mb-2"
|
||||
>
|
||||
AI Analysis
|
||||
</h3>
|
||||
<p class="text-gray-600 dark:text-gray-300">
|
||||
Our AI analyzes the debt and generates FDCPA-compliant negotiation
|
||||
strategies.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="text-center">
|
||||
<div
|
||||
class="w-16 h-16 bg-green-100 dark:bg-green-900 rounded-full flex items-center justify-center mx-auto mb-4"
|
||||
>
|
||||
<svg
|
||||
class="w-8 h-8 text-green-600 dark:text-green-400"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"></path>
|
||||
</svg>
|
||||
</div>
|
||||
<h3
|
||||
class="text-xl font-semibold text-gray-900 dark:text-foreground mb-2"
|
||||
>
|
||||
Track Progress
|
||||
</h3>
|
||||
<p class="text-gray-600 dark:text-gray-300">
|
||||
Monitor negotiations in real-time and track your potential
|
||||
savings.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Benefits Section -->
|
||||
<section class="py-16 bg-gray-50 dark:bg-gray-900">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div class="text-center mb-16">
|
||||
<h2
|
||||
class="text-3xl font-bold text-gray-900 dark:text-foreground mb-4"
|
||||
>
|
||||
Why Choose InboxNegotiator?
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
|
||||
<div
|
||||
class="bg-white dark:bg-card p-6 rounded-lg shadow-sm border dark:border-border"
|
||||
>
|
||||
<h3
|
||||
class="text-lg font-semibold text-gray-900 dark:text-foreground mb-2"
|
||||
>
|
||||
FDCPA Compliant
|
||||
</h3>
|
||||
<p class="text-gray-600 dark:text-gray-300">
|
||||
All responses follow Fair Debt Collection Practices Act
|
||||
guidelines.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="bg-white dark:bg-card p-6 rounded-lg shadow-sm border dark:border-border"
|
||||
>
|
||||
<h3
|
||||
class="text-lg font-semibold text-gray-900 dark:text-foreground mb-2"
|
||||
>
|
||||
Save Money
|
||||
</h3>
|
||||
<p class="text-gray-600 dark:text-gray-300">
|
||||
Potentially reduce your debt by up to 40% through strategic
|
||||
negotiations.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="bg-white dark:bg-card p-6 rounded-lg shadow-sm border dark:border-border"
|
||||
>
|
||||
<h3
|
||||
class="text-lg font-semibold text-gray-900 dark:text-foreground mb-2"
|
||||
>
|
||||
Real-time Updates
|
||||
</h3>
|
||||
<p class="text-gray-600 dark:text-gray-300">
|
||||
Track your negotiations with live dashboard updates.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="bg-white dark:bg-card p-6 rounded-lg shadow-sm border dark:border-border"
|
||||
>
|
||||
<h3
|
||||
class="text-lg font-semibold text-gray-900 dark:text-foreground mb-2"
|
||||
>
|
||||
Secure & Private
|
||||
</h3>
|
||||
<p class="text-gray-600 dark:text-gray-300">
|
||||
Your financial information is encrypted and protected.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- CTA Section -->
|
||||
<section class="py-16 bg-blue-600 dark:bg-blue-700">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 text-center">
|
||||
<h2 class="text-3xl font-bold text-white mb-4">
|
||||
Ready to Take Control of Your Debt?
|
||||
</h2>
|
||||
<p class="text-xl text-blue-100 dark:text-blue-200 mb-8">
|
||||
Join thousands who have successfully negotiated their debts with AI
|
||||
assistance.
|
||||
</p>
|
||||
<a
|
||||
href="/signup"
|
||||
class="inline-flex items-center justify-center px-8 py-3 border border-transparent text-base font-medium rounded-md text-blue-600 bg-white hover:bg-gray-50 dark:text-blue-700 dark:bg-gray-100 dark:hover:bg-gray-200 transition-colors"
|
||||
>
|
||||
Start Your Free Account
|
||||
</a>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
<!-- Footer -->
|
||||
<footer class="bg-gray-900 dark:bg-gray-950 text-white py-12">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div class="text-center">
|
||||
<div class="flex items-center justify-center gap-3 mb-4">
|
||||
<svg
|
||||
class="w-8 h-8"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z"
|
||||
></path>
|
||||
</svg>
|
||||
<span class="text-xl font-bold">InboxNegotiator</span>
|
||||
</div>
|
||||
<p class="text-gray-400 dark:text-gray-500 mb-4">
|
||||
AI-powered debt resolution platform
|
||||
</p>
|
||||
<p class="text-sm text-gray-500 dark:text-gray-600">
|
||||
© 2025 InboxNegotiator. All rights reserved.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</Layout>
|
||||
|
||||
@@ -1,24 +1,32 @@
|
||||
---
|
||||
import '@/styles/globals.css'
|
||||
import Layout from '../layouts/Layout.astro';
|
||||
import { AuthForm } from '../components/AuthForm';
|
||||
import { Navbar } from '../components/Navbar';
|
||||
import { AuthGuard } from '../components/AuthGuard';
|
||||
import "@/styles/globals.css";
|
||||
import Layout from "../layouts/Layout.astro";
|
||||
import { AuthForm } from "../components/AuthForm";
|
||||
import { Navbar } from "../components/Navbar";
|
||||
import { AuthGuard } from "../components/AuthGuard";
|
||||
---
|
||||
|
||||
<Layout title="Sign In - InboxNegotiator">
|
||||
<Navbar client:load />
|
||||
|
||||
<AuthGuard requireAuth={false} client:load>
|
||||
<main class="min-h-screen bg-gray-50 flex items-center justify-center py-12 px-4 sm:px-6 lg:px-8">
|
||||
<div class="w-full max-w-md">
|
||||
<div class="text-center mb-8">
|
||||
<h1 class="text-3xl font-bold text-gray-900 mb-2">Sign In</h1>
|
||||
<p class="text-gray-600">Access your debt resolution dashboard</p>
|
||||
</div>
|
||||
|
||||
<AuthForm mode="login" client:load />
|
||||
</div>
|
||||
</main>
|
||||
</AuthGuard>
|
||||
</Layout>
|
||||
<Navbar client:load />
|
||||
|
||||
<AuthGuard requireAuth={false} client:load>
|
||||
<main
|
||||
class="min-h-screen bg-gray-50 dark:bg-background flex items-center justify-center py-12 px-4 sm:px-6 lg:px-8"
|
||||
>
|
||||
<div class="w-full max-w-md">
|
||||
<div class="text-center mb-8">
|
||||
<h1
|
||||
class="text-3xl font-bold text-gray-900 dark:text-foreground mb-2"
|
||||
>
|
||||
Sign In
|
||||
</h1>
|
||||
<p class="text-gray-600 dark:text-gray-300">
|
||||
Access your debt resolution dashboard
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<AuthForm mode="login" client:load />
|
||||
</div>
|
||||
</main>
|
||||
</AuthGuard>
|
||||
</Layout>
|
||||
|
||||
@@ -1,24 +1,32 @@
|
||||
---
|
||||
import '@/styles/globals.css'
|
||||
import Layout from '../layouts/Layout.astro';
|
||||
import { AuthForm } from '../components/AuthForm';
|
||||
import { Navbar } from '../components/Navbar';
|
||||
import { AuthGuard } from '../components/AuthGuard';
|
||||
import "@/styles/globals.css";
|
||||
import Layout from "../layouts/Layout.astro";
|
||||
import { AuthForm } from "../components/AuthForm";
|
||||
import { Navbar } from "../components/Navbar";
|
||||
import { AuthGuard } from "../components/AuthGuard";
|
||||
---
|
||||
|
||||
<Layout title="Sign Up - InboxNegotiator">
|
||||
<Navbar client:load />
|
||||
|
||||
<AuthGuard requireAuth={false} client:load>
|
||||
<main class="min-h-screen bg-gray-50 flex items-center justify-center py-12 px-4 sm:px-6 lg:px-8">
|
||||
<div class="w-full max-w-md">
|
||||
<div class="text-center mb-8">
|
||||
<h1 class="text-3xl font-bold text-gray-900 mb-2">Create Account</h1>
|
||||
<p class="text-gray-600">Start resolving your debts with AI assistance</p>
|
||||
</div>
|
||||
|
||||
<AuthForm mode="signup" client:load />
|
||||
</div>
|
||||
</main>
|
||||
</AuthGuard>
|
||||
</Layout>
|
||||
<Navbar client:load />
|
||||
|
||||
<AuthGuard requireAuth={false} client:load>
|
||||
<main
|
||||
class="min-h-screen bg-gray-50 dark:bg-background flex items-center justify-center py-12 px-4 sm:px-6 lg:px-8"
|
||||
>
|
||||
<div class="w-full max-w-md">
|
||||
<div class="text-center mb-8">
|
||||
<h1
|
||||
class="text-3xl font-bold text-gray-900 dark:text-foreground mb-2"
|
||||
>
|
||||
Create Account
|
||||
</h1>
|
||||
<p class="text-gray-600 dark:text-gray-300">
|
||||
Start resolving your debts with AI assistance
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<AuthForm mode="signup" client:load />
|
||||
</div>
|
||||
</main>
|
||||
</AuthGuard>
|
||||
</Layout>
|
||||
|
||||
Reference in New Issue
Block a user