import React, { useState, useMemo, useEffect, useRef } from 'react'; import { useMockStore } from '../data/mockStore'; import { useTheme } from '../context/ThemeContext'; import { Calendar, User, Clock, MapPin, MoreHorizontal, Filter, X, ChevronDown } from 'lucide-react'; import { SpotlightCard } from '../components/SpotlightCard'; const AdminSchedule = () => { const { meetings } = useMockStore(); const { theme } = useTheme(); // Refs for click-outside detection const dateDropdownRef = useRef(null); const statusDropdownRef = useRef(null); // Filter states const [dateFilter, setDateFilter] = useState('all'); // all, today, week, month, quarter, custom const [customDateRange, setCustomDateRange] = useState({ start: '', end: '' }); const [statusFilter, setStatusFilter] = useState([]); const [showDateDropdown, setShowDateDropdown] = useState(false); const [showStatusDropdown, setShowStatusDropdown] = useState(false); const [openDropdownId, setOpenDropdownId] = useState(null); // Click-outside detection for filter dropdowns useEffect(() => { const handleClickOutside = (event) => { if (dateDropdownRef.current && !dateDropdownRef.current.contains(event.target)) { setShowDateDropdown(false); } if (statusDropdownRef.current && !statusDropdownRef.current.contains(event.target)) { setShowStatusDropdown(false); } }; document.addEventListener('mousedown', handleClickOutside); return () => document.removeEventListener('mousedown', handleClickOutside); }, []); // Click-outside detection for action dropdowns useEffect(() => { const handleClickOutside = (event) => { if (openDropdownId && !event.target.closest('.action-dropdown-container')) { setOpenDropdownId(null); } }; document.addEventListener('mousedown', handleClickOutside); return () => document.removeEventListener('mousedown', handleClickOutside); }, [openDropdownId]); // Get unique statuses from meetings const availableStatuses = useMemo(() => { return [...new Set(meetings.map(m => m.status))]; }, [meetings]); // Filter meetings based on selected filters const filteredMeetings = useMemo(() => { let filtered = [...meetings]; // Date filtering if (dateFilter !== 'all') { const now = new Date(); const today = new Date(now.getFullYear(), now.getMonth(), now.getDate()); filtered = filtered.filter(meeting => { const meetingDate = new Date(meeting.date); switch (dateFilter) { case 'today': return meetingDate.toDateString() === today.toDateString(); case 'week': const weekStart = new Date(today); weekStart.setDate(today.getDate() - today.getDay()); const weekEnd = new Date(weekStart); weekEnd.setDate(weekStart.getDate() + 6); return meetingDate >= weekStart && meetingDate <= weekEnd; case 'month': return meetingDate.getMonth() === now.getMonth() && meetingDate.getFullYear() === now.getFullYear(); case 'quarter': const quarter = Math.floor(now.getMonth() / 3); const meetingQuarter = Math.floor(meetingDate.getMonth() / 3); return meetingQuarter === quarter && meetingDate.getFullYear() === now.getFullYear(); case 'custom': if (customDateRange.start && customDateRange.end) { const start = new Date(customDateRange.start); const end = new Date(customDateRange.end); return meetingDate >= start && meetingDate <= end; } return true; default: return true; } }); } // Status filtering if (statusFilter.length > 0) { filtered = filtered.filter(meeting => statusFilter.includes(meeting.status)); } return filtered; }, [meetings, dateFilter, customDateRange, statusFilter]); const toggleStatusFilter = (status) => { setStatusFilter(prev => prev.includes(status) ? prev.filter(s => s !== status) : [...prev, status] ); }; const clearFilters = () => { setDateFilter('all'); setCustomDateRange({ start: '', end: '' }); setStatusFilter([]); }; const handleActionClick = (meetingId, action) => { console.log(`Action ${action} for meeting ${meetingId}`); // TODO: Implement actual actions setOpenDropdownId(null); }; const [viewMode, setViewMode] = useState('list'); // 'list' or 'calendar' // Mock color mapping for agents const agentColors = { 'a1': 'bg-blue-100 text-blue-700 border-blue-200 dark:bg-blue-900/30 dark:text-blue-300 dark:border-blue-800', 'a2': 'bg-emerald-100 text-emerald-700 border-emerald-200 dark:bg-emerald-900/30 dark:text-emerald-300 dark:border-emerald-800', 'a3': 'bg-purple-100 text-purple-700 border-purple-200 dark:bg-purple-900/30 dark:text-purple-300 dark:border-purple-800', 'a4': 'bg-amber-100 text-amber-700 border-amber-200 dark:bg-amber-900/30 dark:text-amber-300 dark:border-amber-800', 'a5': 'bg-pink-100 text-pink-700 border-pink-200 dark:bg-pink-900/30 dark:text-pink-300 dark:border-pink-800', }; const getAgentColor = (agentId) => { // Simple hash or lookup const id = agentId?.toLowerCase() || 'a1'; return agentColors[id] || agentColors['a1']; }; return (
Manage field agent appointments
Custom Range
setCustomDateRange(prev => ({ ...prev, start: e.target.value }))} className="w-full px-2 py-1 text-xs bg-white dark:bg-zinc-900 border border-zinc-200 dark:border-zinc-700 rounded mb-2 text-zinc-900 dark:text-white" placeholder="Start date" /> setCustomDateRange(prev => ({ ...prev, end: e.target.value }))} className="w-full px-2 py-1 text-xs bg-white dark:bg-zinc-900 border border-zinc-200 dark:border-zinc-700 rounded mb-2 text-zinc-900 dark:text-white" placeholder="End date" />| Agent | Customer | Property | Date & Time | Status | Actions |
|---|---|---|---|---|---|
| No appointments found matching the selected filters. | |||||
|
{meeting.agentId}
Agent {meeting.agentId}
|
{meeting.customerName} | {meeting.propertyId} |
{meeting.date}
{meeting.time}
|
{meeting.status} |
{openDropdownId === meeting.id && (
|