![]() 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/private_html/src/components/ |
import React, { useState, useEffect } from 'react';
import { Calendar, Clock, Users, FileText, Scale, Brain, Zap, AlertTriangle, Bell, MapPin, Video, Phone, MessageSquare, BookOpen, Database, Shield, TrendingUp } from 'lucide-react';
interface CalendarEvent {
id: string;
title: string;
type: 'court_hearing' | 'client_meeting' | 'deadline' | 'consultation' | 'deposition' | 'mediation' | 'filing_deadline' | 'discovery_deadline';
date: string;
time: string;
duration: number;
priority: 'low' | 'medium' | 'high' | 'critical';
caseId: string;
caseName: string;
clientName: string;
lawyerId: string;
lawyerName: string;
location?: string;
isVirtual: boolean;
courtJurisdiction?: string;
documentsRequired: string[];
notes: string;
reminders: {
type: 'email' | 'sms' | 'push';
timing: string;
sent: boolean;
}[];
billingRate?: number;
estimatedHours?: number;
status: 'scheduled' | 'confirmed' | 'completed' | 'cancelled' | 'rescheduled';
linkedEvents: string[];
aiSuggestions: string[];
}
interface CourtRule {
jurisdiction: string;
ruleNumber: string;
description: string;
timeLimit: number;
triggers: string[];
exceptions: string[];
}
interface AIInsight {
type: 'scheduling_conflict' | 'optimal_timing' | 'preparation_reminder' | 'billing_opportunity' | 'case_milestone';
message: string;
priority: 'low' | 'medium' | 'high' | 'critical';
action?: string;
}
const AdvancedLegalCalendar: React.FC = () => {
const [currentView, setCurrentView] = useState<'month' | 'week' | 'day' | 'agenda'>('month');
const [selectedDate, setSelectedDate] = useState(new Date());
const [events, setEvents] = useState<CalendarEvent[]>([]);
const [aiInsights, setAiInsights] = useState<AIInsight[]>([]);
const [courtRules, setCourtRules] = useState<CourtRule[]>([]);
const [showAIPanel, setShowAIPanel] = useState(true);
const [activeFilters, setActiveFilters] = useState<string[]>([]);
// Simulated data loading
useEffect(() => {
loadCalendarData();
loadAIInsights();
loadCourtRules();
}, []);
const loadCalendarData = () => {
// Simulated comprehensive calendar events
const sampleEvents: CalendarEvent[] = [
{
id: 'evt_001',
title: 'Bordeaux Detention Center - Pre-Trial Motion Hearing',
type: 'court_hearing',
date: '2025-03-05',
time: '09:00',
duration: 120,
priority: 'critical',
caseId: 'case_bordeaux_2024',
caseName: 'Bordeaux Detention Center Class Action',
clientName: 'Multiple Detainees',
lawyerId: 'lawyer_justin',
lawyerName: 'Justin Wee',
location: 'Palais de Justice de Montréal, Room 2.09',
isVirtual: false,
courtJurisdiction: 'Quebec Superior Court',
documentsRequired: ['Motion Brief', 'Evidence Package A-1', 'Witness Statements'],
notes: 'Critical hearing for preliminary injunction. Media attention expected.',
reminders: [
{ type: 'email', timing: '48h', sent: true },
{ type: 'sms', timing: '2h', sent: false }
],
billingRate: 650,
estimatedHours: 4,
status: 'confirmed',
linkedEvents: ['prep_001', 'follow_001'],
aiSuggestions: [
'Schedule prep meeting 2 days prior',
'Coordinate with co-counsel',
'Prepare media statement'
]
},
{
id: 'evt_002',
title: 'Client Consultation - Family Detention Conditions',
type: 'client_meeting',
date: '2025-03-04',
time: '14:00',
duration: 60,
priority: 'high',
caseId: 'case_family_001',
caseName: 'Family Detention Conditions Review',
clientName: 'Marie Dubois',
lawyerId: 'lawyer_audrey',
lawyerName: 'Audrey Labrecque',
location: 'Office - Conference Room A',
isVirtual: false,
documentsRequired: ['Intake Form', 'Detention Records', 'Medical Reports'],
notes: 'New case intake. Client reports health concerns during detention.',
reminders: [
{ type: 'email', timing: '24h', sent: true },
{ type: 'sms', timing: '1h', sent: false }
],
billingRate: 450,
estimatedHours: 1.5,
status: 'scheduled',
linkedEvents: [],
aiSuggestions: [
'Prepare compassionate interview questions',
'Have medical evaluation forms ready',
'Schedule follow-up within 48h'
]
}
];
setEvents(sampleEvents);
};
const loadAIInsights = () => {
const insights: AIInsight[] = [
{
type: 'scheduling_conflict',
message: 'Potential conflict: Court hearing overlaps with scheduled deposition in Quebec City',
priority: 'high',
action: 'Reschedule deposition or arrange remote attendance'
},
{
type: 'optimal_timing',
message: 'Best time for client meetings this week: Tuesday 2-4 PM based on client availability patterns',
priority: 'medium'
},
{
type: 'billing_opportunity',
message: '14.5 unbilled hours identified from last month. Potential revenue: $9,425',
priority: 'high',
action: 'Generate invoices for completed work'
},
{
type: 'case_milestone',
message: 'Bordeaux case approaching discovery deadline in 15 days',
priority: 'critical',
action: 'Schedule discovery completion review'
}
];
setAiInsights(insights);
};
const loadCourtRules = () => {
const rules: CourtRule[] = [
{
jurisdiction: 'Quebec Superior Court',
ruleNumber: 'Rule 165',
description: 'Motion for preliminary injunction must be filed 10 days before hearing',
timeLimit: 10,
triggers: ['preliminary_injunction', 'emergency_motion'],
exceptions: ['urgent_circumstances', 'constitutional_challenge']
},
{
jurisdiction: 'Federal Court of Canada',
ruleNumber: 'Rule 302',
description: 'Discovery must be completed 30 days before trial',
timeLimit: 30,
triggers: ['trial_scheduling', 'discovery_phase'],
exceptions: ['court_ordered_extension']
}
];
setCourtRules(rules);
};
const priorityColors = {
low: 'bg-green-100 text-green-800',
medium: 'bg-yellow-100 text-yellow-800',
high: 'bg-orange-100 text-orange-800',
critical: 'bg-red-100 text-red-800'
};
const typeIcons = {
court_hearing: Scale,
client_meeting: Users,
deadline: Clock,
consultation: MessageSquare,
deposition: FileText,
mediation: Users,
filing_deadline: FileText,
discovery_deadline: BookOpen
};
return (
<div className="min-h-screen bg-gradient-to-br from-blue-50 via-purple-50 to-indigo-50 p-6">
{/* Header with AI-Powered Title */}
<div className="mb-8">
<div className="flex items-center justify-between">
<div className="flex items-center space-x-4">
<div className="p-3 bg-gradient-to-r from-purple-600 to-blue-600 rounded-xl">
<Calendar className="h-8 w-8 text-white" />
</div>
<div>
<h1 className="text-3xl font-bold bg-gradient-to-r from-purple-600 to-blue-600 bg-clip-text text-transparent">
⚖️ LegalMaster Calendar Pro
</h1>
<p className="text-gray-600 flex items-center space-x-2">
<Brain className="h-4 w-4" />
<span>AI-Powered Legal Calendar with Court Rules Automation</span>
</p>
</div>
</div>
<div className="flex items-center space-x-4">
{/* View Switcher */}
<div className="flex bg-white rounded-lg p-1 shadow-md">
{['month', 'week', 'day', 'agenda'].map((view) => (
<button
key={view}
onClick={() => setCurrentView(view as any)}
className={`px-4 py-2 rounded-md text-sm font-medium transition-all ${
currentView === view
? 'bg-purple-600 text-white shadow-md'
: 'text-gray-600 hover:text-purple-600'
}`}
>
{view.charAt(0).toUpperCase() + view.slice(1)}
</button>
))}
</div>
{/* AI Toggle */}
<button
onClick={() => setShowAIPanel(!showAIPanel)}
className={`flex items-center space-x-2 px-4 py-2 rounded-lg font-medium transition-all ${
showAIPanel
? 'bg-gradient-to-r from-purple-600 to-blue-600 text-white shadow-lg'
: 'bg-white text-gray-600 shadow-md hover:shadow-lg'
}`}
>
<Brain className="h-4 w-4" />
<span>AI Assistant</span>
</button>
</div>
</div>
</div>
<div className="grid grid-cols-12 gap-6">
{/* Main Calendar Area */}
<div className={`${showAIPanel ? 'col-span-8' : 'col-span-12'} space-y-6`}>
{/* Quick Stats Dashboard */}
<div className="grid grid-cols-4 gap-4">
<div className="bg-white rounded-xl p-6 shadow-lg border border-gray-100">
<div className="flex items-center justify-between">
<div>
<p className="text-sm font-medium text-gray-600">Today's Events</p>
<p className="text-3xl font-bold text-purple-600">8</p>
</div>
<div className="p-3 bg-purple-100 rounded-lg">
<Calendar className="h-6 w-6 text-purple-600" />
</div>
</div>
<div className="mt-4 flex items-center text-sm">
<TrendingUp className="h-4 w-4 text-green-500 mr-1" />
<span className="text-green-600">+15% from last week</span>
</div>
</div>
<div className="bg-white rounded-xl p-6 shadow-lg border border-gray-100">
<div className="flex items-center justify-between">
<div>
<p className="text-sm font-medium text-gray-600">Court Hearings</p>
<p className="text-3xl font-bold text-blue-600">3</p>
</div>
<div className="p-3 bg-blue-100 rounded-lg">
<Scale className="h-6 w-6 text-blue-600" />
</div>
</div>
<div className="mt-4 flex items-center text-sm">
<AlertTriangle className="h-4 w-4 text-orange-500 mr-1" />
<span className="text-orange-600">2 critical this week</span>
</div>
</div>
<div className="bg-white rounded-xl p-6 shadow-lg border border-gray-100">
<div className="flex items-center justify-between">
<div>
<p className="text-sm font-medium text-gray-600">Billable Hours</p>
<p className="text-3xl font-bold text-green-600">24.5</p>
</div>
<div className="p-3 bg-green-100 rounded-lg">
<Clock className="h-6 w-6 text-green-600" />
</div>
</div>
<div className="mt-4 flex items-center text-sm">
<TrendingUp className="h-4 w-4 text-green-500 mr-1" />
<span className="text-green-600">$15,925 revenue</span>
</div>
</div>
<div className="bg-white rounded-xl p-6 shadow-lg border border-gray-100">
<div className="flex items-center justify-between">
<div>
<p className="text-sm font-medium text-gray-600">Deadlines</p>
<p className="text-3xl font-bold text-red-600">5</p>
</div>
<div className="p-3 bg-red-100 rounded-lg">
<AlertTriangle className="h-6 w-6 text-red-600" />
</div>
</div>
<div className="mt-4 flex items-center text-sm">
<Clock className="h-4 w-4 text-red-500 mr-1" />
<span className="text-red-600">2 due this week</span>
</div>
</div>
</div>
{/* Enhanced Calendar View */}
<div className="bg-white rounded-xl shadow-lg border border-gray-100 p-6">
<div className="flex items-center justify-between mb-6">
<h2 className="text-xl font-bold text-gray-900">March 2025</h2>
<div className="flex items-center space-x-4">
{/* Filters */}
<div className="flex items-center space-x-2">
<span className="text-sm font-medium text-gray-600">Filter:</span>
{['Court', 'Clients', 'Deadlines'].map((filter) => (
<button
key={filter}
onClick={() => {
if (activeFilters.includes(filter)) {
setActiveFilters(activeFilters.filter(f => f !== filter));
} else {
setActiveFilters([...activeFilters, filter]);
}
}}
className={`px-3 py-1 rounded-full text-xs font-medium transition-all ${
activeFilters.includes(filter)
? 'bg-purple-600 text-white'
: 'bg-gray-100 text-gray-600 hover:bg-gray-200'
}`}
>
{filter}
</button>
))}
</div>
<button className="flex items-center space-x-2 px-4 py-2 bg-gradient-to-r from-purple-600 to-blue-600 text-white rounded-lg font-medium hover:shadow-lg transition-all">
<Zap className="h-4 w-4" />
<span>AI Schedule</span>
</button>
</div>
</div>
{/* Simplified Calendar Grid for Demo */}
<div className="grid grid-cols-7 gap-2 mb-4">
{['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'].map((day) => (
<div key={day} className="p-3 text-center font-medium text-gray-600 bg-gray-50 rounded-lg">
{day}
</div>
))}
</div>
{/* Events for Today */}
<div className="space-y-3">
<h3 className="font-semibold text-gray-900 flex items-center">
<Clock className="h-4 w-4 mr-2" />
Today's Schedule
</h3>
{events.slice(0, 3).map((event) => {
const IconComponent = typeIcons[event.type];
return (
<div
key={event.id}
className="flex items-center justify-between p-4 bg-gradient-to-r from-gray-50 to-white rounded-lg border border-gray-100 hover:shadow-md transition-all cursor-pointer"
>
<div className="flex items-center space-x-4">
<div className={`p-2 rounded-lg ${event.priority === 'critical' ? 'bg-red-100' : 'bg-purple-100'}`}>
<IconComponent className={`h-4 w-4 ${event.priority === 'critical' ? 'text-red-600' : 'text-purple-600'}`} />
</div>
<div>
<h4 className="font-medium text-gray-900">{event.title}</h4>
<div className="flex items-center space-x-4 text-sm text-gray-600">
<span className="flex items-center">
<Clock className="h-3 w-3 mr-1" />
{event.time} ({event.duration}min)
</span>
<span className="flex items-center">
<Users className="h-3 w-3 mr-1" />
{event.clientName}
</span>
{event.location && (
<span className="flex items-center">
<MapPin className="h-3 w-3 mr-1" />
{event.location}
</span>
)}
</div>
</div>
</div>
<div className="flex items-center space-x-3">
<span className={`px-2 py-1 rounded-full text-xs font-medium ${priorityColors[event.priority]}`}>
{event.priority.toUpperCase()}
</span>
<div className="flex items-center space-x-1">
{event.isVirtual ? (
<Video className="h-4 w-4 text-blue-600" />
) : (
<MapPin className="h-4 w-4 text-gray-600" />
)}
<button className="p-2 hover:bg-gray-100 rounded-lg transition-colors">
<MessageSquare className="h-4 w-4 text-gray-600" />
</button>
</div>
</div>
</div>
);
})}
</div>
</div>
</div>
{/* AI Assistant Panel */}
{showAIPanel && (
<div className="col-span-4 space-y-6">
{/* AI Insights */}
<div className="bg-white rounded-xl shadow-lg border border-gray-100 p-6">
<div className="flex items-center justify-between mb-4">
<h3 className="font-bold text-gray-900 flex items-center">
<Brain className="h-5 w-5 mr-2 text-purple-600" />
AI Legal Assistant
</h3>
<div className="flex items-center space-x-2">
<div className="w-2 h-2 bg-green-500 rounded-full animate-pulse"></div>
<span className="text-xs text-green-600 font-medium">ACTIVE</span>
</div>
</div>
<div className="space-y-3">
{aiInsights.map((insight, index) => (
<div
key={index}
className={`p-3 rounded-lg border-l-4 ${
insight.priority === 'critical'
? 'bg-red-50 border-red-500'
: insight.priority === 'high'
? 'bg-orange-50 border-orange-500'
: 'bg-blue-50 border-blue-500'
}`}
>
<p className="text-sm font-medium text-gray-900">{insight.message}</p>
{insight.action && (
<button className="mt-2 text-xs bg-purple-600 text-white px-3 py-1 rounded-full hover:bg-purple-700 transition-colors">
{insight.action}
</button>
)}
</div>
))}
</div>
<div className="mt-6 pt-4 border-t border-gray-100">
<button className="w-full flex items-center justify-center space-x-2 py-3 bg-gradient-to-r from-purple-600 to-blue-600 text-white rounded-lg font-medium hover:shadow-lg transition-all">
<Zap className="h-4 w-4" />
<span>Get More AI Insights</span>
</button>
</div>
</div>
{/* Court Rules Engine */}
<div className="bg-white rounded-xl shadow-lg border border-gray-100 p-6">
<h3 className="font-bold text-gray-900 flex items-center mb-4">
<Database className="h-5 w-5 mr-2 text-blue-600" />
Court Rules Engine
</h3>
<div className="space-y-3">
{courtRules.slice(0, 2).map((rule, index) => (
<div key={index} className="p-3 bg-blue-50 rounded-lg border border-blue-200">
<div className="flex items-center justify-between mb-2">
<span className="text-sm font-medium text-blue-900">{rule.jurisdiction}</span>
<span className="text-xs bg-blue-600 text-white px-2 py-1 rounded-full">{rule.ruleNumber}</span>
</div>
<p className="text-sm text-gray-700">{rule.description}</p>
<div className="mt-2 flex items-center space-x-2">
<Clock className="h-3 w-3 text-blue-600" />
<span className="text-xs text-blue-600">{rule.timeLimit} days required</span>
</div>
</div>
))}
</div>
<div className="mt-4">
<button className="w-full py-2 text-sm bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors">
View All Court Rules (2,847 jurisdictions)
</button>
</div>
</div>
{/* Quick Actions */}
<div className="bg-white rounded-xl shadow-lg border border-gray-100 p-6">
<h3 className="font-bold text-gray-900 mb-4">Quick Actions</h3>
<div className="grid grid-cols-2 gap-3">
<button className="p-3 bg-green-50 text-green-700 rounded-lg text-sm font-medium hover:bg-green-100 transition-colors flex items-center justify-center space-x-2">
<Users className="h-4 w-4" />
<span>New Meeting</span>
</button>
<button className="p-3 bg-purple-50 text-purple-700 rounded-lg text-sm font-medium hover:bg-purple-100 transition-colors flex items-center justify-center space-x-2">
<Scale className="h-4 w-4" />
<span>Court Filing</span>
</button>
<button className="p-3 bg-orange-50 text-orange-700 rounded-lg text-sm font-medium hover:bg-orange-100 transition-colors flex items-center justify-center space-x-2">
<Clock className="h-4 w-4" />
<span>Set Deadline</span>
</button>
<button className="p-3 bg-blue-50 text-blue-700 rounded-lg text-sm font-medium hover:bg-blue-100 transition-colors flex items-center justify-center space-x-2">
<Bell className="h-4 w-4" />
<span>Add Reminder</span>
</button>
</div>
</div>
</div>
)}
</div>
</div>
);
};
export default AdvancedLegalCalendar;