![]() Server : Apache/2 System : Linux server-15-235-50-60 5.15.0-164-generic #174-Ubuntu SMP Fri Nov 14 20:25:16 UTC 2025 x86_64 User : gositeme ( 1004) PHP Version : 8.2.29 Disable Function : exec,system,passthru,shell_exec,proc_close,proc_open,dl,popen,show_source,posix_kill,posix_mkfifo,posix_getpwuid,posix_setpgid,posix_setsid,posix_setuid,posix_setgid,posix_seteuid,posix_setegid,posix_uname Directory : /home/gositeme/domains/lavocat.ca/public_html/src/pages/ |
import React, { useState, useEffect } from 'react';
import { useSession } from 'next-auth/react';
import { useRouter } from 'next/router';
import LayoutWithSidebar from '@/components/LayoutWithSidebar';
import { motion } from 'framer-motion';
import Link from 'next/link';
import Head from 'next/head';
import {
Scale,
Users,
Building2,
FileText,
MapPin,
TrendingUp,
Shield,
Crown,
Search,
Filter,
Calendar,
BarChart3,
Settings,
Plus,
Eye,
Edit,
Trash2,
Download,
Upload,
Bell,
Star,
Award,
Globe,
Phone,
Mail,
Clock,
CheckCircle,
AlertTriangle,
XCircle
} from 'lucide-react';
interface QuebecStats {
totalLawyers: number;
totalFirms: number;
totalCases: number;
activeCases: number;
completedCases: number;
totalRegions: number;
averageWinRate: number;
totalSocietyMembers: number;
}
interface QuebecRegion {
id: string;
name: string;
code: string;
lawyerCount: number;
firmCount: number;
caseCount: number;
population: number;
}
const QuebecDashboard: React.FC = () => {
const { data: session } = useSession();
const router = useRouter();
const [activeTab, setActiveTab] = useState<'overview' | 'cases' | 'lawyers' | 'firms' | 'regions' | 'management'>('overview');
const [stats, setStats] = useState<QuebecStats>({
totalLawyers: 0,
totalFirms: 0,
totalCases: 0,
activeCases: 0,
completedCases: 0,
totalRegions: 0,
averageWinRate: 0,
totalSocietyMembers: 0
});
const [regions, setRegions] = useState<QuebecRegion[]>([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
fetchQuebecData();
}, []);
const fetchQuebecData = async () => {
try {
setLoading(true);
// Fetch Quebec statistics
const statsResponse = await fetch('/api/quebec/stats');
if (statsResponse.ok) {
const statsData = await statsResponse.json();
setStats(statsData);
}
// Fetch regional data
const regionsResponse = await fetch('/api/quebec/regions');
if (regionsResponse.ok) {
const regionsData = await regionsResponse.json();
setRegions(regionsData);
}
} catch (error) {
console.error('Error fetching Quebec data:', error);
} finally {
setLoading(false);
}
};
const getRegionIcon = (regionCode: string) => {
switch (regionCode) {
case 'MONTREAL': return <Building2 className="w-5 h-5" />;
case 'QUEBEC': return <Crown className="w-5 h-5" />;
case 'SHERBROOKE': return <Scale className="w-5 h-5" />;
case 'GATINEAU': return <Globe className="w-5 h-5" />;
default: return <MapPin className="w-5 h-5" />;
}
};
const getRegionColor = (regionCode: string) => {
switch (regionCode) {
case 'MONTREAL': return 'from-blue-500 to-blue-600';
case 'QUEBEC': return 'from-purple-500 to-purple-600';
case 'SHERBROOKE': return 'from-green-500 to-green-600';
case 'GATINEAU': return 'from-orange-500 to-orange-600';
default: return 'from-gray-500 to-gray-600';
}
};
if (loading) {
return (
<LayoutWithSidebar>
<div className="flex items-center justify-center min-h-screen">
<div className="animate-spin rounded-full h-12 w-12 border-b-2 border-blue-600"></div>
</div>
</LayoutWithSidebar>
);
}
return (
<LayoutWithSidebar>
<Head>
<title>🏛️ Quebec Judicial Ecosystem - Dashboard</title>
<meta name="description" content="Comprehensive Quebec judicial ecosystem dashboard for legal professionals, cases, and regional management." />
</Head>
<div className="max-w-7xl mx-auto px-4 py-8">
{/* Header */}
<div className="mb-8">
<h1 className="text-4xl font-bold text-gray-900 dark:text-white mb-4">
🏛️ Quebec Judicial Ecosystem
</h1>
<p className="text-xl text-gray-600 dark:text-gray-400">
Comprehensive platform for Quebec's legal professionals, cases, and regional management
</p>
</div>
{/* Navigation Tabs */}
<div className="flex flex-wrap gap-2 mb-8">
{[
{ id: 'overview', label: '📊 Overview', icon: BarChart3 },
{ id: 'cases', label: '⚖️ Cases', icon: FileText },
{ id: 'lawyers', label: '👥 Lawyers', icon: Users },
{ id: 'firms', label: '🏢 Firms', icon: Building2 },
{ id: 'regions', label: '📍 Regions', icon: MapPin },
{ id: 'management', label: '⚙️ Management', icon: Settings }
].map((tab) => {
const Icon = tab.icon;
return (
<button
key={tab.id}
onClick={() => setActiveTab(tab.id as any)}
className={`flex items-center space-x-2 px-4 py-2 rounded-lg font-medium transition-all ${
activeTab === tab.id
? 'bg-blue-600 text-white shadow-lg'
: 'bg-gray-100 dark:bg-gray-800 text-gray-700 dark:text-gray-300 hover:bg-gray-200 dark:hover:bg-gray-700'
}`}
>
<Icon className="w-4 h-4" />
<span>{tab.label}</span>
</button>
);
})}
</div>
{/* Overview Tab */}
{activeTab === 'overview' && (
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
className="space-y-8"
>
{/* Quebec Statistics */}
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
className="bg-gradient-to-r from-blue-500 to-blue-600 rounded-lg p-6 text-white"
>
<div className="flex items-center justify-between">
<div>
<p className="text-sm opacity-90">Total Lawyers</p>
<p className="text-3xl font-bold">{stats.totalLawyers.toLocaleString()}</p>
</div>
<Users className="w-8 h-8 opacity-80" />
</div>
</motion.div>
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: 0.1 }}
className="bg-gradient-to-r from-green-500 to-green-600 rounded-lg p-6 text-white"
>
<div className="flex items-center justify-between">
<div>
<p className="text-sm opacity-90">Law Firms</p>
<p className="text-3xl font-bold">{stats.totalFirms.toLocaleString()}</p>
</div>
<Building2 className="w-8 h-8 opacity-80" />
</div>
</motion.div>
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: 0.2 }}
className="bg-gradient-to-r from-purple-500 to-purple-600 rounded-lg p-6 text-white"
>
<div className="flex items-center justify-between">
<div>
<p className="text-sm opacity-90">Active Cases</p>
<p className="text-3xl font-bold">{stats.activeCases.toLocaleString()}</p>
</div>
<FileText className="w-8 h-8 opacity-80" />
</div>
</motion.div>
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: 0.3 }}
className="bg-gradient-to-r from-yellow-500 to-yellow-600 rounded-lg p-6 text-white"
>
<div className="flex items-center justify-between">
<div>
<p className="text-sm opacity-90">Win Rate</p>
<p className="text-3xl font-bold">{stats.averageWinRate.toFixed(1)}%</p>
</div>
<TrendingUp className="w-8 h-8 opacity-80" />
</div>
</motion.div>
</div>
{/* Regional Overview */}
<div className="bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 p-6">
<h2 className="text-2xl font-bold text-gray-900 dark:text-white mb-6">
📍 Regional Overview
</h2>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
{regions.map((region, index) => (
<motion.div
key={region.id}
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: index * 0.1 }}
className={`bg-gradient-to-r ${getRegionColor(region.code)} rounded-lg p-4 text-white cursor-pointer hover:scale-105 transition-transform`}
onClick={() => router.push(`/quebec/regions/${region.code.toLowerCase()}`)}
>
<div className="flex items-center justify-between mb-3">
<div className="flex items-center space-x-2">
{getRegionIcon(region.code)}
<h3 className="font-semibold">{region.name}</h3>
</div>
</div>
<div className="grid grid-cols-2 gap-4 text-sm">
<div>
<p className="opacity-80">Lawyers</p>
<p className="font-bold">{region.lawyerCount}</p>
</div>
<div>
<p className="opacity-80">Firms</p>
<p className="font-bold">{region.firmCount}</p>
</div>
<div>
<p className="opacity-80">Cases</p>
<p className="font-bold">{region.caseCount}</p>
</div>
<div>
<p className="opacity-80">Population</p>
<p className="font-bold">{(region.population / 1000).toFixed(0)}K</p>
</div>
</div>
</motion.div>
))}
</div>
</div>
{/* Quick Actions */}
<div className="bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 p-6">
<h2 className="text-2xl font-bold text-gray-900 dark:text-white mb-6">
⚡ Quick Actions
</h2>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
<Link
href="/quebec/cases/new"
className="flex items-center space-x-3 p-4 bg-blue-50 dark:bg-blue-900/20 rounded-lg hover:bg-blue-100 dark:hover:bg-blue-900/30 transition-colors"
>
<Plus className="w-6 h-6 text-blue-600" />
<div>
<div className="font-medium text-gray-900 dark:text-white">New Case</div>
<div className="text-sm text-gray-500 dark:text-gray-400">Create case</div>
</div>
</Link>
<Link
href="/quebec/lawyers/add"
className="flex items-center space-x-3 p-4 bg-green-50 dark:bg-green-900/20 rounded-lg hover:bg-green-100 dark:hover:bg-green-900/30 transition-colors"
>
<Users className="w-6 h-6 text-green-600" />
<div>
<div className="font-medium text-gray-900 dark:text-white">Add Lawyer</div>
<div className="text-sm text-gray-500 dark:text-gray-400">Register lawyer</div>
</div>
</Link>
<Link
href="/quebec/firms/add"
className="flex items-center space-x-3 p-4 bg-purple-50 dark:bg-purple-900/20 rounded-lg hover:bg-purple-100 dark:hover:bg-purple-900/30 transition-colors"
>
<Building2 className="w-6 h-6 text-purple-600" />
<div>
<div className="font-medium text-gray-900 dark:text-white">Add Firm</div>
<div className="text-sm text-gray-500 dark:text-gray-400">Register firm</div>
</div>
</Link>
<Link
href="/quebec/reports"
className="flex items-center space-x-3 p-4 bg-yellow-50 dark:bg-yellow-900/20 rounded-lg hover:bg-yellow-100 dark:hover:bg-yellow-900/30 transition-colors"
>
<BarChart3 className="w-6 h-6 text-yellow-600" />
<div>
<div className="font-medium text-gray-900 dark:text-white">Reports</div>
<div className="text-sm text-gray-500 dark:text-gray-400">View analytics</div>
</div>
</Link>
</div>
</div>
</motion.div>
)}
{/* Cases Tab */}
{activeTab === 'cases' && (
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
className="space-y-6"
>
<div className="flex justify-between items-center">
<h2 className="text-2xl font-bold text-gray-900 dark:text-white">
⚖️ Quebec Cases
</h2>
<Link
href="/quebec/cases/new"
className="bg-blue-600 text-white px-4 py-2 rounded-lg hover:bg-blue-700 transition-colors flex items-center space-x-2"
>
<Plus className="w-4 h-4" />
<span>New Case</span>
</Link>
</div>
<div className="bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 p-6">
<p className="text-gray-600 dark:text-gray-400">
Case management system coming soon. This will include:
</p>
<ul className="mt-4 space-y-2 text-gray-600 dark:text-gray-400">
<li>• Public case directory</li>
<li>• Case tracking and management</li>
<li>• Regional case distribution</li>
<li>• Case outcomes and statistics</li>
</ul>
</div>
</motion.div>
)}
{/* Lawyers Tab */}
{activeTab === 'lawyers' && (
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
className="space-y-6"
>
<div className="flex justify-between items-center">
<h2 className="text-2xl font-bold text-gray-900 dark:text-white">
👥 Quebec Lawyers
</h2>
<Link
href="/quebec/lawyers/add"
className="bg-green-600 text-white px-4 py-2 rounded-lg hover:bg-green-700 transition-colors flex items-center space-x-2"
>
<Plus className="w-4 h-4" />
<span>Add Lawyer</span>
</Link>
</div>
<div className="bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 p-6">
<p className="text-gray-600 dark:text-gray-400">
Lawyer directory system coming soon. This will include:
</p>
<ul className="mt-4 space-y-2 text-gray-600 dark:text-gray-400">
<li>• Complete Quebec lawyer registry</li>
<li>• Regional lawyer search</li>
<li>• Specialization filtering</li>
<li>• Performance metrics</li>
</ul>
</div>
</motion.div>
)}
{/* Firms Tab */}
{activeTab === 'firms' && (
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
className="space-y-6"
>
<div className="flex justify-between items-center">
<h2 className="text-2xl font-bold text-gray-900 dark:text-white">
🏢 Quebec Law Firms
</h2>
<Link
href="/quebec/firms/add"
className="bg-purple-600 text-white px-4 py-2 rounded-lg hover:bg-purple-700 transition-colors flex items-center space-x-2"
>
<Plus className="w-4 h-4" />
<span>Add Firm</span>
</Link>
</div>
<div className="bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 p-6">
<p className="text-gray-600 dark:text-gray-400">
Law firm directory system coming soon. This will include:
</p>
<ul className="mt-4 space-y-2 text-gray-600 dark:text-gray-400">
<li>• Complete Quebec firm registry</li>
<li>• Firm size and structure</li>
<li>• Regional firm distribution</li>
<li>• Firm performance metrics</li>
</ul>
</div>
</motion.div>
)}
{/* Regions Tab */}
{activeTab === 'regions' && (
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
className="space-y-6"
>
<h2 className="text-2xl font-bold text-gray-900 dark:text-white">
📍 Quebec Regions
</h2>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
{regions.map((region, index) => (
<motion.div
key={region.id}
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: index * 0.1 }}
className={`bg-gradient-to-r ${getRegionColor(region.code)} rounded-lg p-6 text-white cursor-pointer hover:scale-105 transition-transform`}
onClick={() => router.push(`/quebec/regions/${region.code.toLowerCase()}`)}
>
<div className="flex items-center justify-between mb-4">
<div className="flex items-center space-x-3">
{getRegionIcon(region.code)}
<h3 className="text-xl font-bold">{region.name}</h3>
</div>
</div>
<div className="space-y-3">
<div className="flex justify-between">
<span className="opacity-80">Lawyers:</span>
<span className="font-bold">{region.lawyerCount}</span>
</div>
<div className="flex justify-between">
<span className="opacity-80">Firms:</span>
<span className="font-bold">{region.firmCount}</span>
</div>
<div className="flex justify-between">
<span className="opacity-80">Cases:</span>
<span className="font-bold">{region.caseCount}</span>
</div>
<div className="flex justify-between">
<span className="opacity-80">Population:</span>
<span className="font-bold">{(region.population / 1000).toFixed(0)}K</span>
</div>
</div>
<div className="mt-4 pt-4 border-t border-white/20">
<button className="w-full bg-white/20 hover:bg-white/30 transition-colors rounded-lg py-2 text-sm font-medium">
View Details
</button>
</div>
</motion.div>
))}
</div>
</motion.div>
)}
{/* Management Tab */}
{activeTab === 'management' && (
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
className="space-y-6"
>
<h2 className="text-2xl font-bold text-gray-900 dark:text-white">
⚙️ System Management
</h2>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
<Link
href="/admin/dashboard"
className="bg-blue-50 dark:bg-blue-900/20 rounded-lg p-6 hover:bg-blue-100 dark:hover:bg-blue-900/30 transition-colors"
>
<Shield className="w-8 h-8 text-blue-600 mb-4" />
<h3 className="text-lg font-semibold text-gray-900 dark:text-white mb-2">
Admin Dashboard
</h3>
<p className="text-gray-600 dark:text-gray-400">
System administration and user management
</p>
</Link>
<Link
href="/quebec/import"
className="bg-green-50 dark:bg-green-900/20 rounded-lg p-6 hover:bg-green-100 dark:hover:bg-green-900/30 transition-colors"
>
<Upload className="w-8 h-8 text-green-600 mb-4" />
<h3 className="text-lg font-semibold text-gray-900 dark:text-white mb-2">
Data Import
</h3>
<p className="text-gray-600 dark:text-gray-400">
Import Quebec Bar Association data
</p>
</Link>
<Link
href="/quebec/reports"
className="bg-purple-50 dark:bg-purple-900/20 rounded-lg p-6 hover:bg-purple-100 dark:hover:bg-purple-900/30 transition-colors"
>
<BarChart3 className="w-8 h-8 text-purple-600 mb-4" />
<h3 className="text-lg font-semibold text-gray-900 dark:text-white mb-2">
Analytics
</h3>
<p className="text-gray-600 dark:text-gray-400">
System analytics and reporting
</p>
</Link>
<Link
href="/quebec/settings"
className="bg-yellow-50 dark:bg-yellow-900/20 rounded-lg p-6 hover:bg-yellow-100 dark:hover:bg-yellow-900/30 transition-colors"
>
<Settings className="w-8 h-8 text-yellow-600 mb-4" />
<h3 className="text-lg font-semibold text-gray-900 dark:text-white mb-2">
System Settings
</h3>
<p className="text-gray-600 dark:text-gray-400">
Configure system parameters
</p>
</Link>
<Link
href="/quebec/backup"
className="bg-red-50 dark:bg-red-900/20 rounded-lg p-6 hover:bg-red-100 dark:hover:bg-red-900/30 transition-colors"
>
<Download className="w-8 h-8 text-red-600 mb-4" />
<h3 className="text-lg font-semibold text-gray-900 dark:text-white mb-2">
Backup & Export
</h3>
<p className="text-gray-600 dark:text-gray-400">
System backup and data export
</p>
</Link>
<Link
href="/quebec/monitoring"
className="bg-indigo-50 dark:bg-indigo-900/20 rounded-lg p-6 hover:bg-indigo-100 dark:hover:bg-indigo-900/30 transition-colors"
>
<Bell className="w-8 h-8 text-indigo-600 mb-4" />
<h3 className="text-lg font-semibold text-gray-900 dark:text-white mb-2">
System Monitoring
</h3>
<p className="text-gray-600 dark:text-gray-400">
Monitor system health and performance
</p>
</Link>
</div>
</motion.div>
)}
</div>
</LayoutWithSidebar>
);
};
export default QuebecDashboard;