Initial commit - PezkuwiChain Web Governance App

This commit is contained in:
2025-10-22 18:21:46 -07:00
commit 9aab34c101
135 changed files with 24254 additions and 0 deletions
+223
View File
@@ -0,0 +1,223 @@
import { useEffect, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
import { Button } from '@/components/ui/button';
import { Badge } from '@/components/ui/badge';
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
import { useAuth } from '@/contexts/AuthContext';
import { supabase } from '@/lib/supabase';
import { User, Mail, Phone, Globe, MapPin, Calendar, Shield, AlertCircle } from 'lucide-react';
import { useToast } from '@/hooks/use-toast';
export default function Dashboard() {
const { user } = useAuth();
const navigate = useNavigate();
const { toast } = useToast();
const [profile, setProfile] = useState<any>(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
fetchProfile();
}, [user]);
const fetchProfile = async () => {
if (!user) return;
try {
const { data, error } = await supabase
.from('profiles')
.select('*')
.eq('id', user.id)
.single();
if (error) throw error;
setProfile(data);
} catch (error) {
console.error('Error fetching profile:', error);
} finally {
setLoading(false);
}
};
const sendVerificationEmail = async () => {
try {
const { data, error } = await supabase.functions.invoke('email-verification', {
body: { action: 'send', email: user?.email }
});
if (error) throw error;
toast({
title: "Verification Email Sent",
description: "Please check your email for verification link",
});
} catch (error) {
toast({
title: "Error",
description: "Failed to send verification email",
variant: "destructive"
});
}
};
if (loading) {
return <div className="flex justify-center items-center h-screen">Loading...</div>;
}
return (
<div className="container mx-auto p-6 max-w-6xl">
<h1 className="text-3xl font-bold mb-6">User Dashboard</h1>
<div className="grid gap-6 md:grid-cols-3 mb-6">
<Card>
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
<CardTitle className="text-sm font-medium">Account Status</CardTitle>
<Shield className="h-4 w-4 text-muted-foreground" />
</CardHeader>
<CardContent>
<div className="text-2xl font-bold">
{profile?.email_verified ? (
<Badge className="bg-green-500">Verified</Badge>
) : (
<Badge variant="destructive">Unverified</Badge>
)}
</div>
<p className="text-xs text-muted-foreground">
Email verification status
</p>
</CardContent>
</Card>
<Card>
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
<CardTitle className="text-sm font-medium">Member Since</CardTitle>
<Calendar className="h-4 w-4 text-muted-foreground" />
</CardHeader>
<CardContent>
<div className="text-2xl font-bold">
{new Date(profile?.joined_at || user?.created_at).toLocaleDateString()}
</div>
<p className="text-xs text-muted-foreground">
Registration date
</p>
</CardContent>
</Card>
<Card>
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
<CardTitle className="text-sm font-medium">Role</CardTitle>
<User className="h-4 w-4 text-muted-foreground" />
</CardHeader>
<CardContent>
<div className="text-2xl font-bold">
{profile?.role || 'Member'}
</div>
<p className="text-xs text-muted-foreground">
Account type
</p>
</CardContent>
</Card>
</div>
<Tabs defaultValue="profile" className="space-y-4">
<TabsList>
<TabsTrigger value="profile">Profile</TabsTrigger>
<TabsTrigger value="security">Security</TabsTrigger>
<TabsTrigger value="activity">Activity</TabsTrigger>
</TabsList>
<TabsContent value="profile" className="space-y-4">
<Card>
<CardHeader>
<CardTitle>Profile Information</CardTitle>
<CardDescription>Your personal details and contact information</CardDescription>
</CardHeader>
<CardContent className="space-y-4">
<div className="grid gap-4">
<div className="flex items-center gap-2">
<User className="h-4 w-4 text-muted-foreground" />
<span className="font-medium">Full Name:</span>
<span>{profile?.full_name || 'Not set'}</span>
</div>
<div className="flex items-center gap-2">
<Mail className="h-4 w-4 text-muted-foreground" />
<span className="font-medium">Email:</span>
<span>{user?.email}</span>
{!profile?.email_verified && (
<Button size="sm" variant="outline" onClick={sendVerificationEmail}>
Verify Email
</Button>
)}
</div>
<div className="flex items-center gap-2">
<Mail className="h-4 w-4 text-muted-foreground" />
<span className="font-medium">Recovery Email:</span>
<span>{profile?.recovery_email || 'Not set'}</span>
{profile?.recovery_email_verified && (
<Badge className="bg-green-500">Verified</Badge>
)}
</div>
<div className="flex items-center gap-2">
<Phone className="h-4 w-4 text-muted-foreground" />
<span className="font-medium">Phone:</span>
<span>{profile?.phone_number || 'Not set'}</span>
</div>
<div className="flex items-center gap-2">
<Globe className="h-4 w-4 text-muted-foreground" />
<span className="font-medium">Website:</span>
<span>{profile?.website || 'Not set'}</span>
</div>
<div className="flex items-center gap-2">
<MapPin className="h-4 w-4 text-muted-foreground" />
<span className="font-medium">Location:</span>
<span>{profile?.location || 'Not set'}</span>
</div>
</div>
<Button onClick={() => navigate('/settings')}>Edit Profile</Button>
</CardContent>
</Card>
</TabsContent>
<TabsContent value="security" className="space-y-4">
<Card>
<CardHeader>
<CardTitle>Security Settings</CardTitle>
<CardDescription>Manage your account security</CardDescription>
</CardHeader>
<CardContent className="space-y-4">
<div className="space-y-2">
<h3 className="font-medium">Password</h3>
<p className="text-sm text-muted-foreground">Last changed: Never</p>
<Button onClick={() => navigate('/reset-password')}>Change Password</Button>
</div>
{!profile?.email_verified && (
<div className="border-l-4 border-yellow-500 bg-yellow-50 p-4">
<div className="flex items-center">
<AlertCircle className="h-5 w-5 text-yellow-600 mr-2" />
<div>
<h4 className="font-medium">Verify your email</h4>
<p className="text-sm">Please verify your email to access all features</p>
</div>
</div>
</div>
)}
</CardContent>
</Card>
</TabsContent>
<TabsContent value="activity" className="space-y-4">
<Card>
<CardHeader>
<CardTitle>Recent Activity</CardTitle>
<CardDescription>Your recent actions and transactions</CardDescription>
</CardHeader>
<CardContent>
<p className="text-muted-foreground">No recent activity</p>
</CardContent>
</Card>
</TabsContent>
</Tabs>
</div>
);
}