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