T.ME/BIBIL_0DAY
CasperSecurity


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/pages/lawyer/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Current File : /home/gositeme/domains/lavocat.ca/private_html/src/pages/lawyer/calendar.tsx
'use client';

import React, { useState, useEffect } from 'react';
import { useRouter } from 'next/router';
import { useSession } from 'next-auth/react';
import { 
  Calendar, 
  Clock, 
  Users, 
  Plus, 
  Edit, 
  Trash2, 
  Bell, 
  ExternalLink,
  Filter,
  Search,
  Download,
  Upload,
  Settings,
  User,
  MapPin,
  Phone,
  Mail,
  Video,
  FileText,
  AlertCircle,
  CheckCircle,
  XCircle,
  MoreVertical,
  ChevronLeft,
  ChevronRight
} from 'lucide-react';
import { format, startOfWeek, endOfWeek, eachDayOfInterval, isSameDay, parseISO, addDays, subDays, startOfMonth, endOfMonth, eachDayOfInterval as eachDay, addMonths, subMonths, isSameMonth, getDay } from 'date-fns';
import { fr, enUS } from 'date-fns/locale';
import { toast } from 'react-hot-toast';

interface CalendarEvent {
  id: string;
  title: string;
  description?: string;
  startTime: string;
  endTime: string;
  type: 'consultation' | 'court_hearing' | 'client_meeting' | 'team_meeting' | 'deadline' | 'reminder';
  status: 'scheduled' | 'confirmed' | 'completed' | 'cancelled';
  participants: string[];
  location?: string;
  meetingLink?: string;
  caseId?: string;
  clientId?: string;
  clientName?: string;
  clientEmail?: string;
  reminderSent: boolean;
  createdAt: string;
  updatedAt: string;
}

interface CalendarView {
  id: string;
  name: string;
  type: 'day' | 'week' | 'month' | 'agenda';
  color: string;
}

// Helper functions moved outside component for reuse
const getEventTypeColor = (type: string) => {
  const colors = {
    consultation: 'bg-blue-100 text-blue-800 border-blue-200',
    court_hearing: 'bg-red-100 text-red-800 border-red-200',
    client_meeting: 'bg-green-100 text-green-800 border-green-200',
    team_meeting: 'bg-purple-100 text-purple-800 border-purple-200',
    deadline: 'bg-orange-100 text-orange-800 border-orange-200',
    reminder: 'bg-gray-100 text-gray-800 border-gray-200'
  };
  return colors[type as keyof typeof colors] || colors.reminder;
};

const getStatusIcon = (status: string) => {
  switch (status) {
    case 'confirmed': return <CheckCircle className="w-4 h-4 text-green-500" />;
    case 'completed': return <CheckCircle className="w-4 h-4 text-blue-500" />;
    case 'cancelled': return <XCircle className="w-4 h-4 text-red-500" />;
    default: return <Clock className="w-4 h-4 text-yellow-500" />;
  }
};

const CalendarPage: React.FC = () => {
  const { data: session, status } = useSession();
  const router = useRouter();
  const { locale } = router;
  const t = locale === 'fr' ? require('../../dictionaries/fr.json') : require('../../dictionaries/en.json');

  const [events, setEvents] = useState<CalendarEvent[]>([]);
  const [loading, setLoading] = useState(true);
  const [currentDate, setCurrentDate] = useState(new Date());
  const [selectedView, setSelectedView] = useState<'day' | 'week' | 'month' | 'agenda'>('month'); // Default to month view
  const [showEventModal, setShowEventModal] = useState(false);
  const [selectedEvent, setSelectedEvent] = useState<CalendarEvent | null>(null);
  const [selectedDate, setSelectedDate] = useState<Date | null>(null);
  const [showDayModal, setShowDayModal] = useState(false);
  const [filters, setFilters] = useState({
    type: 'all',
    status: 'all',
    participant: 'all'
  });
  const [searchTerm, setSearchTerm] = useState('');

  // Calendar views
  const calendarViews: CalendarView[] = [
    { id: 'month', name: t.calendar.month, type: 'month', color: '#F59E0B' },
    { id: 'week', name: t.calendar.week, type: 'week', color: '#10B981' },
    { id: 'day', name: t.calendar.day, type: 'day', color: '#3B82F6' },
    { id: 'agenda', name: t.calendar.agenda, type: 'agenda', color: '#EF4444' }
  ];

  useEffect(() => {
    if (status === 'loading') return;
    
    if (!session?.user) {
      router.push('/auth/login');
      return;
    }

    fetchEvents();
  }, [session, status, currentDate, selectedView, filters]);

  const fetchEvents = async () => {
    try {
      setLoading(true);
      // Enhanced API call with better error handling and real data integration
      const params = new URLSearchParams({
        date: currentDate.toISOString(),
        view: selectedView,
        filters: JSON.stringify(filters),
        lawyerId: session?.user?.id || ''
      });
      
      const response = await fetch(`/api/lawyer/calendar?${params}`);
      
      if (response.ok) {
        const data = await response.json();
        setEvents(data.events || []);
      } else {
        const errorData = await response.json();
        console.error('Failed to fetch calendar events:', errorData.error);
        // Show user-friendly error message
        toast.error('Failed to load calendar events. Please try again.');
      }
    } catch (error) {
      console.error('Error fetching calendar events:', error);
      toast.error('Network error. Please check your connection.');
    } finally {
      setLoading(false);
    }
  };

  const handleCreateEvent = () => {
    setSelectedEvent(null);
    setShowEventModal(true);
  };

  const handleEditEvent = (event: CalendarEvent) => {
    setSelectedEvent(event);
    setShowEventModal(true);
  };

  const handleDeleteEvent = async (eventId: string) => {
    if (!confirm(t.calendar.confirmDelete)) return;

    try {
      const response = await fetch(`/api/lawyer/calendar/${eventId}`, {
        method: 'DELETE'
      });

      if (response.ok) {
        setEvents(events.filter(e => e.id !== eventId));
        toast.success('Event deleted successfully');
      } else {
        console.error('Failed to delete event');
        toast.error('Failed to delete event');
      }
    } catch (error) {
      console.error('Error deleting event:', error);
      toast.error('Failed to delete event');
    }
  };

  const handleSaveEvent = async (eventData: Partial<CalendarEvent>) => {
    try {
      const url = selectedEvent 
        ? `/api/lawyer/calendar/${selectedEvent.id}`
        : '/api/lawyer/calendar';
      
      const method = selectedEvent ? 'PUT' : 'POST';
      
      const response = await fetch(url, {
        method,
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(eventData)
      });

      if (response.ok) {
        setShowEventModal(false);
        fetchEvents();
        toast.success(selectedEvent ? 'Event updated successfully' : 'Event created successfully');
      } else {
        console.error('Failed to save event');
        toast.error('Failed to save event');
      }
    } catch (error) {
      console.error('Error saving event:', error);
      toast.error('Failed to save event');
    }
  };



  // Quick actions for calendar
  const quickActions = [
    { label: 'Today', action: () => setCurrentDate(new Date()) },
    { label: 'Previous Week', action: () => setCurrentDate(subDays(currentDate, 7)) },
    { label: 'Next Week', action: () => setCurrentDate(addDays(currentDate, 7)) },
    { label: 'Refresh', action: fetchEvents }
  ];

  // MONTH VIEW - This is what lawyers actually need!
  const renderMonthView = () => {
    const start = startOfMonth(currentDate);
    const end = endOfMonth(currentDate);
    const startDate = startOfWeek(start, { weekStartsOn: 1 });
    const endDate = endOfWeek(end, { weekStartsOn: 1 });
    const days = eachDay({ start: startDate, end: endDate });

    const weekDays = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'];

    return (
      <div className="bg-white rounded-lg shadow-sm border border-gray-200 overflow-hidden">
        {/* Month header */}
        <div className="bg-gray-50 px-6 py-4 border-b border-gray-200">
          <div className="flex items-center justify-between">
            <h2 className="text-xl font-semibold text-gray-900">
              {format(currentDate, 'MMMM yyyy', { locale: locale === 'fr' ? fr : enUS })}
            </h2>
            <div className="flex items-center gap-2">
              <button
                onClick={() => setCurrentDate(subMonths(currentDate, 1))}
                className="p-2 text-gray-600 hover:bg-gray-100 rounded-full"
              >
                <ChevronLeft className="w-5 h-5" />
              </button>
              <button
                onClick={() => setCurrentDate(new Date())}
                className="px-3 py-1 text-sm bg-blue-600 text-white rounded-md hover:bg-blue-700"
              >
                Today
              </button>
              <button
                onClick={() => setCurrentDate(addMonths(currentDate, 1))}
                className="p-2 text-gray-600 hover:bg-gray-100 rounded-full"
              >
                <ChevronRight className="w-5 h-5" />
              </button>
            </div>
          </div>
        </div>

        {/* Week days header */}
        <div className="grid grid-cols-7 bg-gray-50 border-b border-gray-200">
          {weekDays.map(day => (
            <div key={day} className="px-3 py-3 text-center text-sm font-medium text-gray-700">
              {day}
            </div>
          ))}
        </div>

        {/* Calendar grid */}
        <div className="grid grid-cols-7">
          {days.map((day, index) => {
            const dayEvents = events.filter(event => 
              isSameDay(parseISO(event.startTime), day)
            );
            const isCurrentMonth = isSameMonth(day, currentDate);
            const isToday = isSameDay(day, new Date());

            return (
              <div
                key={index}
                className={`min-h-[120px] border-r border-b border-gray-200 p-2 cursor-pointer hover:bg-gray-50 transition-colors ${
                  !isCurrentMonth ? 'bg-gray-50' : ''
                }`}
                onClick={() => {
                  setSelectedDate(day);
                  setShowDayModal(true);
                }}
              >
                <div className={`text-sm font-medium mb-1 ${
                  isToday 
                    ? 'bg-blue-600 text-white rounded-full w-6 h-6 flex items-center justify-center' 
                    : isCurrentMonth 
                      ? 'text-gray-900' 
                      : 'text-gray-400'
                }`}>
                  {format(day, 'd')}
                </div>
                
                {/* Events for this day */}
                <div className="space-y-1">
                  {dayEvents.slice(0, 3).map(event => (
                    <div
                      key={event.id}
                      className={`text-xs p-1 rounded truncate cursor-pointer ${getEventTypeColor(event.type)}`}
                      onClick={(e) => {
                        e.stopPropagation();
                        handleEditEvent(event);
                      }}
                    >
                      {event.title}
                    </div>
                  ))}
                  {dayEvents.length > 3 && (
                    <div className="text-xs text-gray-500 text-center">
                      +{dayEvents.length - 3} more
                    </div>
                  )}
                </div>
              </div>
            );
          })}
        </div>
      </div>
    );
  };

  const renderWeekView = () => {
    const start = startOfWeek(currentDate, { weekStartsOn: 1 });
    const end = endOfWeek(currentDate, { weekStartsOn: 1 });
    const days = eachDayOfInterval({ start, end });

    return (
      <div className="grid grid-cols-8 gap-1">
        {/* Time column */}
        <div className="col-span-1">
          <div className="h-12"></div>
          {Array.from({ length: 24 }, (_, i) => (
            <div key={i} className="h-16 border-r border-gray-200 text-xs text-gray-500 pr-2 text-right">
              {i === 0 ? '00:00' : `${i.toString().padStart(2, '0')}:00`}
            </div>
          ))}
        </div>

        {/* Days columns */}
        {days.map((day, dayIndex) => (
          <div key={dayIndex} className="col-span-1">
            <div className="h-12 border-b border-gray-200 text-center text-sm font-medium">
              <div>{format(day, 'EEE', { locale: locale === 'fr' ? fr : enUS })}</div>
              <div className={`text-lg ${isSameDay(day, new Date()) ? 'bg-blue-500 text-white rounded-full w-8 h-8 mx-auto flex items-center justify-center' : ''}`}>
                {format(day, 'd')}
              </div>
            </div>
            
            {Array.from({ length: 24 }, (_, hour) => (
              <div key={hour} className="h-16 border-b border-gray-100 relative">
                {events
                  .filter(event => {
                    const eventDate = parseISO(event.startTime);
                    return isSameDay(eventDate, day) && eventDate.getHours() === hour;
                  })
                  .map(event => (
                    <div
                      key={event.id}
                      className={`absolute left-0 right-0 mx-1 p-1 text-xs rounded cursor-pointer ${getEventTypeColor(event.type)}`}
                      onClick={() => handleEditEvent(event)}
                    >
                      <div className="font-medium truncate">{event.title}</div>
                      <div className="text-xs opacity-75">
                        {format(parseISO(event.startTime), 'HH:mm')} - {format(parseISO(event.endTime), 'HH:mm')}
                      </div>
                    </div>
                  ))}
              </div>
            ))}
          </div>
        ))}
      </div>
    );
  };

  const renderAgendaView = () => {
    const sortedEvents = events.sort((a, b) => 
      new Date(a.startTime).getTime() - new Date(b.startTime).getTime()
    );

    return (
      <div className="space-y-4">
        {sortedEvents.map(event => (
          <div key={event.id} className="bg-white rounded-lg border border-gray-200 p-4 hover:shadow-md transition-shadow">
            <div className="flex items-start justify-between">
              <div className="flex-1">
                <div className="flex items-center gap-2 mb-2">
                  <span className={`px-2 py-1 rounded-full text-xs font-medium ${getEventTypeColor(event.type)}`}>
                    {t.calendar.eventTypes[event.type]}
                  </span>
                  {getStatusIcon(event.status)}
                </div>
                
                <h3 className="font-semibold text-lg mb-1">{event.title}</h3>
                
                {event.description && (
                  <p className="text-gray-600 text-sm mb-2">{event.description}</p>
                )}
                
                <div className="flex items-center gap-4 text-sm text-gray-500">
                  <div className="flex items-center gap-1">
                    <Clock className="w-4 h-4" />
                    {format(parseISO(event.startTime), 'PPp', { locale: locale === 'fr' ? fr : enUS })}
                  </div>
                  
                  {event.location && (
                    <div className="flex items-center gap-1">
                      <MapPin className="w-4 h-4" />
                      {event.location}
                    </div>
                  )}
                  
                  {event.participants.length > 0 && (
                    <div className="flex items-center gap-1">
                      <Users className="w-4 h-4" />
                      {event.participants.length} {t.calendar.participants}
                    </div>
                  )}
                </div>
              </div>
              
              <div className="flex items-center gap-2">
                {event.meetingLink && (
                  <a
                    href={event.meetingLink}
                    target="_blank"
                    rel="noopener noreferrer"
                    className="p-2 text-blue-600 hover:bg-blue-50 rounded-full"
                  >
                    <Video className="w-4 h-4" />
                  </a>
                )}
                
                <button
                  onClick={() => handleEditEvent(event)}
                  className="p-2 text-gray-600 hover:bg-gray-50 rounded-full"
                >
                  <Edit className="w-4 h-4" />
                </button>
                
                <button
                  onClick={() => handleDeleteEvent(event.id)}
                  className="p-2 text-red-600 hover:bg-red-50 rounded-full"
                >
                  <Trash2 className="w-4 h-4" />
                </button>
              </div>
            </div>
          </div>
        ))}
      </div>
    );
  };

  if (status === 'loading' || loading) {
    return (
      <div className="min-h-screen bg-gray-50 flex items-center justify-center">
        <div className="animate-spin rounded-full h-32 w-32 border-b-2 border-blue-600"></div>
      </div>
    );
  }

  return (
    <div className="min-h-screen bg-gray-50">
      <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
        {/* Header */}
        <div className="mb-8">
          <div className="flex items-center justify-between">
            <div>
              <h1 className="text-3xl font-bold text-gray-900">{t.calendar.title}</h1>
              <p className="text-gray-600 mt-2">{t.calendar.description}</p>
            </div>
            
            <div className="flex items-center gap-4">
              <button
                onClick={handleCreateEvent}
                className="inline-flex items-center px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors"
              >
                <Plus className="w-4 h-4 mr-2" />
                New Event
              </button>
            </div>
          </div>
        </div>

        {/* Controls */}
        <div className="bg-white rounded-lg shadow-sm border border-gray-200 p-6 mb-6">
          <div className="flex items-center justify-between mb-6">
            <div className="flex items-center gap-4">
              {/* View Selector */}
              <div className="flex bg-gray-100 rounded-lg p-1">
                {calendarViews.map(view => (
                  <button
                    key={view.id}
                    onClick={() => setSelectedView(view.type)}
                    className={`px-4 py-2 rounded-md text-sm font-medium transition-colors ${
                      selectedView === view.type
                        ? 'bg-white text-gray-900 shadow-sm'
                        : 'text-gray-600 hover:text-gray-900'
                    }`}
                  >
                    {view.name}
                  </button>
                ))}
              </div>
            </div>

            {/* Search and Filters */}
            <div className="flex items-center gap-4">
              <div className="relative">
                <Search className="absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400 w-4 h-4" />
                <input
                  type="text"
                  placeholder={t.calendar.searchEvents}
                  value={searchTerm}
                  onChange={(e) => setSearchTerm(e.target.value)}
                  className="pl-10 pr-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
                />
              </div>
              
              <button className="p-2 text-gray-600 hover:bg-gray-100 rounded-lg">
                <Filter className="w-4 h-4" />
              </button>
            </div>
          </div>
        </div>

        {/* Calendar Content */}
        <div className="mb-6">
          {selectedView === 'month' && renderMonthView()}
          {selectedView === 'week' && renderWeekView()}
          {selectedView === 'agenda' && renderAgendaView()}
        </div>

        {/* Event Modal */}
        {showEventModal && (
          <EventModal
            event={selectedEvent}
            onSave={handleSaveEvent}
            onClose={() => setShowEventModal(false)}
            t={t}
            locale={locale || 'en'}
          />
        )}

        {/* Day Modal - Shows all events for a selected day */}
        {showDayModal && selectedDate && (
          <DayModal
            date={selectedDate}
            events={events.filter(event => isSameDay(parseISO(event.startTime), selectedDate))}
            onClose={() => setShowDayModal(false)}
            onEditEvent={handleEditEvent}
            onDeleteEvent={handleDeleteEvent}
            onCreateEvent={() => {
              setShowDayModal(false);
              setSelectedEvent(null);
              setShowEventModal(true);
            }}
            t={t}
            locale={locale || 'en'}
          />
        )}
      </div>
    </div>
  );
};

// Event Modal Component
interface EventModalProps {
  event: CalendarEvent | null;
  onSave: (eventData: Partial<CalendarEvent>) => void;
  onClose: () => void;
  t: any;
  locale: string;
}

const EventModal: React.FC<EventModalProps> = ({ event, onSave, onClose, t, locale }) => {
  const [formData, setFormData] = useState({
    title: event?.title || '',
    description: event?.description || '',
    startTime: event?.startTime ? format(parseISO(event.startTime), "yyyy-MM-dd'T'HH:mm") : '',
    endTime: event?.endTime ? format(parseISO(event.endTime), "yyyy-MM-dd'T'HH:mm") : '',
    type: event?.type || 'consultation',
    status: event?.status || 'scheduled',
    location: event?.location || '',
    meetingLink: event?.meetingLink || '',
    participants: event?.participants || []
  });

  const handleSubmit = (e: React.FormEvent) => {
    e.preventDefault();
    onSave(formData);
  };

  return (
    <div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
      <div className="bg-white rounded-lg shadow-xl max-w-2xl w-full mx-4 max-h-[90vh] overflow-y-auto">
        <div className="p-6">
          <div className="flex items-center justify-between mb-6">
            <h2 className="text-2xl font-bold text-gray-900">
              {event ? t.calendar.editEvent : t.calendar.createEvent}
            </h2>
            <button
              onClick={onClose}
              className="p-2 text-gray-400 hover:text-gray-600 rounded-full"
            >
              ×
            </button>
          </div>

          <form onSubmit={handleSubmit} className="space-y-6">
            <div className="grid grid-cols-2 gap-4">
              <div>
                <label className="block text-sm font-medium text-gray-700 mb-2">
                  {t.calendar.title}
                </label>
                <input
                  type="text"
                  value={formData.title}
                  onChange={(e) => setFormData({ ...formData, title: e.target.value })}
                  className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
                  required
                />
              </div>

              <div>
                <label className="block text-sm font-medium text-gray-700 mb-2">
                  {t.calendar.type}
                </label>
                <select
                  value={formData.type}
                  onChange={(e) => setFormData({ ...formData, type: e.target.value as any })}
                  className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
                >
                  <option value="consultation">{t.calendar.eventTypes.consultation}</option>
                  <option value="court_hearing">{t.calendar.eventTypes.court_hearing}</option>
                  <option value="client_meeting">{t.calendar.eventTypes.client_meeting}</option>
                  <option value="team_meeting">{t.calendar.eventTypes.team_meeting}</option>
                  <option value="deadline">{t.calendar.eventTypes.deadline}</option>
                  <option value="reminder">{t.calendar.eventTypes.reminder}</option>
                </select>
              </div>
            </div>

            <div>
              <label className="block text-sm font-medium text-gray-700 mb-2">
                {t.calendar.description}
              </label>
              <textarea
                value={formData.description}
                onChange={(e) => setFormData({ ...formData, description: e.target.value })}
                rows={3}
                className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
              />
            </div>

            <div className="grid grid-cols-2 gap-4">
              <div>
                <label className="block text-sm font-medium text-gray-700 mb-2">
                  {t.calendar.startTime}
                </label>
                <input
                  type="datetime-local"
                  value={formData.startTime}
                  onChange={(e) => setFormData({ ...formData, startTime: e.target.value })}
                  className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
                  required
                />
              </div>

              <div>
                <label className="block text-sm font-medium text-gray-700 mb-2">
                  {t.calendar.endTime}
                </label>
                <input
                  type="datetime-local"
                  value={formData.endTime}
                  onChange={(e) => setFormData({ ...formData, endTime: e.target.value })}
                  className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
                  required
                />
              </div>
            </div>

            <div className="grid grid-cols-2 gap-4">
              <div>
                <label className="block text-sm font-medium text-gray-700 mb-2">
                  {t.calendar.location}
                </label>
                <input
                  type="text"
                  value={formData.location}
                  onChange={(e) => setFormData({ ...formData, location: e.target.value })}
                  className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
                />
              </div>

              <div>
                <label className="block text-sm font-medium text-gray-700 mb-2">
                  {t.calendar.meetingLink}
                </label>
                <input
                  type="url"
                  value={formData.meetingLink}
                  onChange={(e) => setFormData({ ...formData, meetingLink: e.target.value })}
                  className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
                  placeholder="https://meet.google.com/..."
                />
              </div>
            </div>

            <div>
              <label className="block text-sm font-medium text-gray-700 mb-2">
                {t.calendar.status}
              </label>
              <select
                value={formData.status}
                onChange={(e) => setFormData({ ...formData, status: e.target.value as any })}
                className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
              >
                <option value="scheduled">{t.calendar.statuses.scheduled}</option>
                <option value="confirmed">{t.calendar.statuses.confirmed}</option>
                <option value="completed">{t.calendar.statuses.completed}</option>
                <option value="cancelled">{t.calendar.statuses.cancelled}</option>
              </select>
            </div>

            <div className="flex items-center justify-end gap-4 pt-6 border-t border-gray-200">
              <button
                type="button"
                onClick={onClose}
                className="px-4 py-2 text-gray-600 hover:text-gray-800"
              >
                {t.common.cancel}
              </button>
              <button
                type="submit"
                className="px-6 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700"
              >
                {event ? t.common.update : t.common.create}
              </button>
            </div>
          </form>
        </div>
      </div>
    </div>
  );
};

// Day Modal Component - Shows all events for a specific day
interface DayModalProps {
  date: Date;
  events: CalendarEvent[];
  onClose: () => void;
  onEditEvent: (event: CalendarEvent) => void;
  onDeleteEvent: (eventId: string) => void;
  onCreateEvent: () => void;
  t: any;
  locale: string;
}

const DayModal: React.FC<DayModalProps> = ({ 
  date, 
  events, 
  onClose, 
  onEditEvent, 
  onDeleteEvent, 
  onCreateEvent,
  t,
  locale 
}) => {
  const [loading, setLoading] = React.useState(false);
  React.useEffect(() => {
    const handleEsc = (e: KeyboardEvent) => {
      if (e.key === 'Escape') onClose();
    };
    window.addEventListener('keydown', handleEsc);
    return () => window.removeEventListener('keydown', handleEsc);
  }, [onClose]);
  return (
    <div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50" onClick={onClose}>
      <div className="bg-white rounded-lg shadow-xl max-w-2xl w-full mx-4 max-h-[80vh] overflow-hidden" onClick={e => e.stopPropagation()}>
        <div className="px-6 py-4 border-b border-gray-200 flex items-center justify-between">
          <h2 className="text-xl font-semibold text-gray-900">
            {format(date, 'EEEE, MMMM d, yyyy', { locale: locale === 'fr' ? fr : enUS })}
          </h2>
          <button
            onClick={onClose}
            className="text-gray-400 hover:text-gray-600"
            title="Close (ESC)"
          >
            <XCircle className="w-6 h-6" />
          </button>
        </div>
        <div className="p-6 overflow-y-auto max-h-[60vh]">
          {loading ? (
            <div className="flex items-center justify-center py-8">
              <div className="animate-spin rounded-full h-10 w-10 border-b-2 border-blue-600"></div>
            </div>
          ) : events.length === 0 ? (
            <div className="text-center py-8">
              <Calendar className="w-12 h-12 text-gray-400 mx-auto mb-4" />
              <h3 className="text-lg font-medium text-gray-900 mb-2">No events scheduled</h3>
              <p className="text-gray-500 mb-4">This day is free of scheduled events.</p>
              <button
                onClick={onCreateEvent}
                className="inline-flex items-center px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700"
              >
                <Plus className="w-4 h-4 mr-2" />
                Schedule Event
              </button>
            </div>
          ) : (
            <div className="space-y-4">
              {events.map(event => (
                <div key={event.id} className="border border-gray-200 rounded-lg p-4 hover:shadow-md transition-shadow">
                  <div className="flex items-start justify-between mb-3">
                    <div className="flex-1">
                      <div className="flex items-center gap-2 mb-2">
                        <span className={`px-2 py-1 rounded-full text-xs font-medium ${getEventTypeColor(event.type)}`}>
                          {t.calendar.eventTypes?.[event.type] || event.type}
                        </span>
                        {getStatusIcon(event.status)}
                      </div>
                      <h3 className="font-semibold text-lg mb-1">{event.title}</h3>
                      {event.description && (
                        <p className="text-gray-600 text-sm mb-2">{event.description}</p>
                      )}
                      <div className="flex items-center gap-4 text-sm text-gray-500 mb-3">
                        <div className="flex items-center gap-1">
                          <Clock className="w-4 h-4" />
                          {format(parseISO(event.startTime), 'HH:mm')} - {format(parseISO(event.endTime), 'HH:mm')}
                        </div>
                        {event.location && (
                          <div className="flex items-center gap-1">
                            <MapPin className="w-4 h-4" />
                            {event.location}
                          </div>
                        )}
                      </div>
                      {/* Client Information - Clickable to profile */}
                      {event.clientId && event.clientName && (
                        <div className="mb-3 p-3 bg-blue-50 rounded-lg">
                          <div className="flex items-center justify-between">
                            <div>
                              <p className="text-sm font-medium text-gray-900">Client</p>
                              <button
                                onClick={() => window.open(`/lawyer/clients/${event.clientId}`, '_blank')}
                                className="text-blue-700 underline hover:text-blue-900 text-sm font-semibold"
                                title="View client profile"
                              >
                                {event.clientName}
                              </button>
                              {event.clientEmail && (
                                <p className="text-xs text-gray-500">{event.clientEmail}</p>
                              )}
                            </div>
                          </div>
                        </div>
                      )}
                    </div>
                    <div className="flex items-center gap-2">
                      {event.meetingLink && (
                        <a
                          href={event.meetingLink}
                          target="_blank"
                          rel="noopener noreferrer"
                          className="p-2 text-blue-600 hover:bg-blue-50 rounded-full"
                          title="Join meeting"
                        >
                          <Video className="w-4 h-4" />
                        </a>
                      )}
                      <button
                        onClick={() => onEditEvent(event)}
                        className="p-2 text-gray-600 hover:bg-gray-50 rounded-full"
                        title="Edit event"
                      >
                        <Edit className="w-4 h-4" />
                      </button>
                      <button
                        onClick={() => onDeleteEvent(event.id)}
                        className="p-2 text-red-600 hover:bg-red-50 rounded-full"
                        title="Delete event"
                      >
                        <Trash2 className="w-4 h-4" />
                      </button>
                    </div>
                  </div>
                </div>
              ))}
              <div className="pt-4 border-t border-gray-200">
                <button
                  onClick={onCreateEvent}
                  className="w-full inline-flex items-center justify-center px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700"
                >
                  <Plus className="w-4 h-4 mr-2" />
                  Add Event to This Day
                </button>
              </div>
            </div>
          )}
        </div>
      </div>
    </div>
  );
};

export default CalendarPage; 

CasperSecurity Mini