From 7349ae477c3b62a46bb3710ee5c6f03905e28006 Mon Sep 17 00:00:00 2001 From: Francisco Pessano <76450203+FranP-code@users.noreply.github.com> Date: Fri, 6 Jun 2025 21:16:33 -0300 Subject: [PATCH] Add authentication system with landing page --- src/components/AuthForm.tsx | 164 ++++++++++++++++++++++++++++++ src/components/Dashboard.tsx | 27 +++-- src/components/Navbar.tsx | 102 +++++++++++++++++++ src/components/ProtectedRoute.tsx | 52 ++++++++++ src/pages/dashboard.astro | 15 +++ src/pages/index.astro | 132 +++++++++++++++++++++++- src/pages/login.astro | 21 ++++ src/pages/signup.astro | 21 ++++ 8 files changed, 523 insertions(+), 11 deletions(-) create mode 100644 src/components/AuthForm.tsx create mode 100644 src/components/Navbar.tsx create mode 100644 src/components/ProtectedRoute.tsx create mode 100644 src/pages/dashboard.astro create mode 100644 src/pages/login.astro create mode 100644 src/pages/signup.astro diff --git a/src/components/AuthForm.tsx b/src/components/AuthForm.tsx new file mode 100644 index 0000000..2b8b305 --- /dev/null +++ b/src/components/AuthForm.tsx @@ -0,0 +1,164 @@ +import React, { useState } from 'react'; +import { supabase } from '../lib/supabase'; +import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'; +import { Button } from '@/components/ui/button'; +import { Input } from '@/components/ui/input'; +import { Label } from '@/components/ui/label'; +import { Alert, AlertDescription } from '@/components/ui/alert'; +import { Loader2, Mail, Lock, User } from 'lucide-react'; + +interface AuthFormProps { + mode: 'login' | 'signup'; +} + +export function AuthForm({ mode }: AuthFormProps) { + const [email, setEmail] = useState(''); + const [password, setPassword] = useState(''); + const [fullName, setFullName] = useState(''); + const [loading, setLoading] = useState(false); + const [message, setMessage] = useState(''); + const [error, setError] = useState(''); + + const handleSubmit = async (e: React.FormEvent) => { + e.preventDefault(); + setLoading(true); + setError(''); + setMessage(''); + + try { + if (mode === 'signup') { + const { error } = await supabase.auth.signUp({ + email, + password, + options: { + data: { + full_name: fullName, + } + } + }); + + if (error) throw error; + setMessage('Check your email for the confirmation link!'); + } else { + const { error } = await supabase.auth.signInWithPassword({ + email, + password, + }); + + if (error) throw error; + + // Redirect to dashboard on successful login + window.location.href = '/dashboard'; + } + } catch (error: any) { + setError(error.message); + } finally { + setLoading(false); + } + }; + + return ( + + + + {mode === 'login' ? 'Welcome back' : 'Create account'} + + + {mode === 'login' + ? 'Enter your credentials to access your dashboard' + : 'Enter your details to create your account' + } + + + +
+ {mode === 'signup' && ( +
+ +
+ + setFullName(e.target.value)} + className="pl-10" + required + /> +
+
+ )} + +
+ +
+ + setEmail(e.target.value)} + className="pl-10" + required + /> +
+
+ +
+ +
+ + setPassword(e.target.value)} + className="pl-10" + required + minLength={6} + /> +
+
+ + {error && ( + + {error} + + )} + + {message && ( + + {message} + + )} + + +
+ +
+ {mode === 'login' ? ( +

+ Don't have an account?{' '} + + Sign up + +

+ ) : ( +

+ Already have an account?{' '} + + Sign in + +

+ )} +
+
+
+ ); +} \ No newline at end of file diff --git a/src/components/Dashboard.tsx b/src/components/Dashboard.tsx index 04d5d34..947eca9 100644 --- a/src/components/Dashboard.tsx +++ b/src/components/Dashboard.tsx @@ -1,5 +1,6 @@ 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'; @@ -13,7 +14,8 @@ import { CheckCircle, AlertTriangle, RefreshCw, - BarChart3 + BarChart3, + LogOut } from 'lucide-react'; export function Dashboard() { @@ -96,6 +98,11 @@ export function Dashboard() { }); }; + const handleSignOut = async () => { + await supabase.auth.signOut(); + window.location.href = '/'; + }; + const formatCurrency = (amount: number) => { return new Intl.NumberFormat('en-US', { style: 'currency', @@ -125,14 +132,16 @@ export function Dashboard() {
{/* Header */} -
-

- - InboxNegotiator Dashboard -

-

- AI-powered debt resolution platform with real-time updates -

+
+
+

+ + InboxNegotiator Dashboard +

+

+ AI-powered debt resolution platform with real-time updates +

+
{/* Stats Cards */} diff --git a/src/components/Navbar.tsx b/src/components/Navbar.tsx new file mode 100644 index 0000000..9bb704d --- /dev/null +++ b/src/components/Navbar.tsx @@ -0,0 +1,102 @@ +import React, { useEffect, useState } from 'react'; +import { supabase } from '../lib/supabase'; +import type { User } from '@supabase/supabase-js'; +import { Button } from '@/components/ui/button'; +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuSeparator, + DropdownMenuTrigger +} from '@/components/ui/dropdown-menu'; +import { Avatar, AvatarFallback } from '@/components/ui/avatar'; +import { BarChart3, LogOut, User as UserIcon } from 'lucide-react'; + +export function Navbar() { + const [user, setUser] = useState(null); + + useEffect(() => { + supabase.auth.getSession().then(({ data: { session } }) => { + setUser(session?.user ?? null); + }); + + const { data: { subscription } } = supabase.auth.onAuthStateChange( + (event, session) => { + setUser(session?.user ?? null); + } + ); + + return () => subscription.unsubscribe(); + }, []); + + const handleSignOut = async () => { + await supabase.auth.signOut(); + window.location.href = '/'; + }; + + const getInitials = (email: string) => { + return email.substring(0, 2).toUpperCase(); + }; + + return ( + + ); +} \ No newline at end of file diff --git a/src/components/ProtectedRoute.tsx b/src/components/ProtectedRoute.tsx new file mode 100644 index 0000000..53f3aeb --- /dev/null +++ b/src/components/ProtectedRoute.tsx @@ -0,0 +1,52 @@ +import React, { useEffect, useState } from 'react'; +import { supabase } from '../lib/supabase'; +import type { User } from '@supabase/supabase-js'; +import { Loader2 } from 'lucide-react'; + +interface ProtectedRouteProps { + children: React.ReactNode; +} + +export function ProtectedRoute({ children }: ProtectedRouteProps) { + const [user, setUser] = useState(null); + const [loading, setLoading] = useState(true); + + useEffect(() => { + // Get initial session + supabase.auth.getSession().then(({ data: { session } }) => { + setUser(session?.user ?? null); + setLoading(false); + }); + + // Listen for auth changes + const { data: { subscription } } = supabase.auth.onAuthStateChange( + (event, session) => { + setUser(session?.user ?? null); + setLoading(false); + } + ); + + return () => subscription.unsubscribe(); + }, []); + + if (loading) { + return ( +
+
+ + Loading... +
+
+ ); + } + + if (!user) { + // Redirect to login if not authenticated + if (typeof window !== 'undefined') { + window.location.href = '/login'; + } + return null; + } + + return <>{children}; +} \ No newline at end of file diff --git a/src/pages/dashboard.astro b/src/pages/dashboard.astro new file mode 100644 index 0000000..1445b35 --- /dev/null +++ b/src/pages/dashboard.astro @@ -0,0 +1,15 @@ +--- +import '@/styles/globals.css' +import Layout from '../layouts/Layout.astro'; +import { Dashboard } from '../components/Dashboard'; +import { ProtectedRoute } from '../components/ProtectedRoute'; +import { Navbar } from '../components/Navbar'; +--- + + + + + + + + \ No newline at end of file diff --git a/src/pages/index.astro b/src/pages/index.astro index e5366a8..911e415 100644 --- a/src/pages/index.astro +++ b/src/pages/index.astro @@ -1,9 +1,137 @@ --- import '@/styles/globals.css' import Layout from '../layouts/Layout.astro'; -import { Dashboard } from '../components/Dashboard'; +import { Navbar } from '../components/Navbar'; --- - + + +
+ +
+
+
+

+ AI-Powered + + Debt Resolution + +

+

+ 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. +

+ +
+
+
+ + +
+
+
+

How It Works

+

Simple, automated, and compliant debt resolution

+
+ +
+
+
+ + + +
+

Forward Emails

+

Simply forward your debt collection emails to our secure processing address.

+
+ +
+
+ + + +
+

AI Analysis

+

Our AI analyzes the debt and generates FDCPA-compliant negotiation strategies.

+
+ +
+
+ + + +
+

Track Progress

+

Monitor negotiations in real-time and track your potential savings.

+
+
+
+
+ + +
+
+
+

Why Choose InboxNegotiator?

+
+ +
+
+

FDCPA Compliant

+

All responses follow Fair Debt Collection Practices Act guidelines.

+
+ +
+

Save Money

+

Potentially reduce your debt by up to 40% through strategic negotiations.

+
+ +
+

Real-time Updates

+

Track your negotiations with live dashboard updates.

+
+ +
+

Secure & Private

+

Your financial information is encrypted and protected.

+
+
+
+
+ + +
+
+

Ready to Take Control of Your Debt?

+

Join thousands who have successfully negotiated their debts with AI assistance.

+ + Start Your Free Account + +
+
+
+ + +
+
+
+
+ + + + InboxNegotiator +
+

AI-powered debt resolution platform

+

© 2025 InboxNegotiator. All rights reserved.

+
+
+
\ No newline at end of file diff --git a/src/pages/login.astro b/src/pages/login.astro new file mode 100644 index 0000000..593e6d8 --- /dev/null +++ b/src/pages/login.astro @@ -0,0 +1,21 @@ +--- +import '@/styles/globals.css' +import Layout from '../layouts/Layout.astro'; +import { AuthForm } from '../components/AuthForm'; +import { Navbar } from '../components/Navbar'; +--- + + + + +
+
+
+

Sign In

+

Access your debt resolution dashboard

+
+ + +
+
+
\ No newline at end of file diff --git a/src/pages/signup.astro b/src/pages/signup.astro new file mode 100644 index 0000000..70306a2 --- /dev/null +++ b/src/pages/signup.astro @@ -0,0 +1,21 @@ +--- +import '@/styles/globals.css' +import Layout from '../layouts/Layout.astro'; +import { AuthForm } from '../components/AuthForm'; +import { Navbar } from '../components/Navbar'; +--- + + + + +
+
+
+

Create Account

+

Start resolving your debts with AI assistance

+
+ + +
+
+
\ No newline at end of file