import React, { useState, useEffect } from 'react'; import { Calendar, Clock, Users, MessageSquare, Plus, Edit, Check, X, Bell, User, Settings, LogOut, BarChart3, TrendingUp, Download, RefreshCw, Smartphone, Wifi, WifiOff } from 'lucide-react'; const SchedulingApp = () => { const [currentUser, setCurrentUser] = useState({ id: 1, name: 'Sarah Manager', role: 'manager' }); const [activeTab, setActiveTab] = useState('schedule'); const [isOnline, setIsOnline] = useState(true); // PWA State const [deferredPrompt, setDeferredPrompt] = useState(null); const [showInstallPrompt, setShowInstallPrompt] = useState(false); // PWA Install Handler useEffect(() => { const handleBeforeInstallPrompt = (e) => { e.preventDefault(); setDeferredPrompt(e); setShowInstallPrompt(true); }; const handleOnline = () => setIsOnline(true); const handleOffline = () => setIsOnline(false); window.addEventListener('beforeinstallprompt', handleBeforeInstallPrompt); window.addEventListener('online', handleOnline); window.addEventListener('offline', handleOffline); return () => { window.removeEventListener('beforeinstallprompt', handleBeforeInstallPrompt); window.removeEventListener('online', handleOnline); window.removeEventListener('offline', handleOffline); }; }, []); const handleInstallApp = async () => { if (deferredPrompt) { deferredPrompt.prompt(); const { outcome } = await deferredPrompt.userChoice; if (outcome === 'accepted') { setShowInstallPrompt(false); } setDeferredPrompt(null); } }; // Sample data const [employees] = useState([ { id: 1, name: 'Sarah Manager', role: 'manager', email: 'sarah@company.com' }, { id: 2, name: 'John Smith', role: 'employee', email: 'john@company.com' }, { id: 3, name: 'Emma Davis', role: 'employee', email: 'emma@company.com' }, { id: 4, name: 'Mike Johnson', role: 'employee', email: 'mike@company.com' }, { id: 5, name: 'Lisa Chen', role: 'employee', email: 'lisa@company.com' } ]); const [schedule, setSchedule] = useState([ { id: 1, employeeId: 2, date: '2025-08-13', startTime: '09:00', endTime: '17:00', position: 'Sales Floor' }, { id: 2, employeeId: 3, date: '2025-08-13', startTime: '13:00', endTime: '21:00', position: 'Customer Service' }, { id: 3, employeeId: 4, date: '2025-08-14', startTime: '08:00', endTime: '16:00', position: 'Stock Room' }, { id: 4, employeeId: 5, date: '2025-08-14', startTime: '12:00', endTime: '20:00', position: 'Sales Floor' } ]); const [timeOffRequests, setTimeOffRequests] = useState([ { id: 1, employeeId: 2, startDate: '2025-08-16', endDate: '2025-08-17', reason: 'Family vacation', status: 'pending' }, { id: 2, employeeId: 3, startDate: '2025-08-20', endDate: '2025-08-20', reason: 'Doctor appointment', status: 'approved' } ]); const [shiftSwapRequests, setShiftSwapRequests] = useState([ { id: 1, requesterId: 2, targetId: 3, shiftId: 1, reason: 'Family emergency', status: 'pending', requesterShift: { date: '2025-08-13', startTime: '09:00', endTime: '17:00', position: 'Sales Floor' }, targetShift: { date: '2025-08-14', startTime: '13:00', endTime: '21:00', position: 'Customer Service' } }, { id: 2, requesterId: 4, targetId: 2, shiftId: 3, reason: 'Concert tickets', status: 'approved', requesterShift: { date: '2025-08-15', startTime: '08:00', endTime: '16:00', position: 'Stock Room' }, targetShift: { date: '2025-08-16', startTime: '12:00', endTime: '20:00', position: 'Sales Floor' } } ]); const [announcements, setAnnouncements] = useState([ { id: 1, title: 'Store Hours Update', message: 'Starting next week, we will extend our hours until 10 PM on weekends.', date: '2025-08-10', priority: 'high' }, { id: 2, title: 'Team Meeting', message: 'Monthly team meeting scheduled for Friday at 2 PM in the break room.', date: '2025-08-09', priority: 'medium' } ]); const [newShift, setNewShift] = useState({ employeeId: '', date: '', startTime: '', endTime: '', position: '' }); const [newTimeOff, setNewTimeOff] = useState({ startDate: '', endDate: '', reason: '' }); const [newShiftSwap, setNewShiftSwap] = useState({ targetEmployeeId: '', myShiftId: '', theirShiftId: '', reason: '' }); const [newAnnouncement, setNewAnnouncement] = useState({ title: '', message: '', priority: 'medium' }); const [reportData, setReportData] = useState({ totalHours: 156, totalShifts: 24, pendingRequests: 3, approvalRate: 87, topPerformers: [ { name: 'John Smith', hours: 40, shifts: 5 }, { name: 'Emma Davis', hours: 38, shifts: 5 }, { name: 'Mike Johnson', hours: 35, shifts: 4 } ], weeklyStats: [ { week: 'Week 1', hours: 38, shifts: 6 }, { week: 'Week 2', hours: 42, shifts: 7 }, { week: 'Week 3', hours: 40, shifts: 6 }, { week: 'Week 4', hours: 36, shifts: 5 } ] }); const getEmployeeName = (id) => { const employee = employees.find(emp => emp.id === id); return employee ? employee.name : 'Unknown'; }; const formatDate = (dateString) => { return new Date(dateString).toLocaleDateString('en-US', { weekday: 'short', month: 'short', day: 'numeric' }); }; const handleAddShift = () => { if (newShift.employeeId && newShift.date && newShift.startTime && newShift.endTime && newShift.position) { const shift = { id: Date.now(), employeeId: parseInt(newShift.employeeId), date: newShift.date, startTime: newShift.startTime, endTime: newShift.endTime, position: newShift.position }; setSchedule([...schedule, shift]); setNewShift({ employeeId: '', date: '', startTime: '', endTime: '', position: '' }); } }; const handleTimeOffRequest = () => { if (newTimeOff.startDate && newTimeOff.endDate && newTimeOff.reason) { const request = { id: Date.now(), employeeId: currentUser.id, startDate: newTimeOff.startDate, endDate: newTimeOff.endDate, reason: newTimeOff.reason, status: 'pending' }; setTimeOffRequests([...timeOffRequests, request]); setNewTimeOff({ startDate: '', endDate: '', reason: '' }); } }; const handleShiftSwapRequest = () => { if (newShiftSwap.targetEmployeeId && newShiftSwap.myShiftId && newShiftSwap.theirShiftId && newShiftSwap.reason) { const myShift = schedule.find(s => s.id === parseInt(newShiftSwap.myShiftId)); const theirShift = schedule.find(s => s.id === parseInt(newShiftSwap.theirShiftId)); const request = { id: Date.now(), requesterId: currentUser.id, targetId: parseInt(newShiftSwap.targetEmployeeId), shiftId: parseInt(newShiftSwap.myShiftId), reason: newShiftSwap.reason, status: 'pending', requesterShift: { date: myShift?.date, startTime: myShift?.startTime, endTime: myShift?.endTime, position: myShift?.position }, targetShift: { date: theirShift?.date, startTime: theirShift?.startTime, endTime: theirShift?.endTime, position: theirShift?.position } }; setShiftSwapRequests([...shiftSwapRequests, request]); setNewShiftSwap({ targetEmployeeId: '', myShiftId: '', theirShiftId: '', reason: '' }); } }; const handleTimeOffResponse = (requestId, status) => { setTimeOffRequests(requests => requests.map(req => req.id === requestId ? { ...req, status } : req ) ); }; const handleShiftSwapResponse = (requestId, status) => { setShiftSwapRequests(requests => requests.map(req => req.id === requestId ? { ...req, status } : req ) ); }; const handleAddAnnouncement = () => { if (newAnnouncement.title && newAnnouncement.message) { const announcement = { id: Date.now(), title: newAnnouncement.title, message: newAnnouncement.message, date: new Date().toISOString().split('T')[0], priority: newAnnouncement.priority }; setAnnouncements([announcement, ...announcements]); setNewAnnouncement({ title: '', message: '', priority: 'medium' }); } }; const exportReport = (format) => { const data = { generatedAt: new Date().toISOString(), summary: reportData, schedules: schedule, timeOffRequests, shiftSwapRequests }; const blob = new Blob([JSON.stringify(data, null, 2)], { type: 'application/json' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = `schedule-report-${new Date().toISOString().split('T')[0]}.${format}`; document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(url); }; const roleSwitch = () => { const newRole = currentUser.role === 'manager' ? 'employee' : 'manager'; const newUser = newRole === 'manager' ? { id: 1, name: 'Sarah Manager', role: 'manager' } : { id: 2, name: 'John Smith', role: 'employee' }; setCurrentUser(newUser); }; return (
{/* Header */}

WorkScheduler

{!isOnline && (
Offline
)}
{showInstallPrompt && ( )}
{currentUser.name} {currentUser.role}
{/* Navigation */}
{/* Main Content */}
{activeTab === 'schedule' && (

Schedule Management

{currentUser.role === 'manager' && (
Manage shifts for all employees
)}
{/* Add New Shift (Manager Only) */} {currentUser.role === 'manager' && (

Add New Shift

setNewShift({...newShift, date: 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" />
setNewShift({...newShift, 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" />
setNewShift({...newShift, 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" />
)} {/* Schedule View */}

Current Schedule

{schedule .filter(shift => currentUser.role === 'manager' || shift.employeeId === currentUser.id) .map(shift => ( ))}
Employee Date Time Position Actions
{getEmployeeName(shift.employeeId)} {formatDate(shift.date)} {shift.startTime} - {shift.endTime} {shift.position} {currentUser.role === 'employee' && shift.employeeId === currentUser.id && ( )} {currentUser.role === 'manager' && ( <> )}
)} {activeTab === 'requests' && (

Time Off & Shift Swaps

{/* Shift Swap Request Form (Employee) */} {currentUser.role === 'employee' && (

Request Shift Swap

setNewShiftSwap({...newShiftSwap, reason: 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" />
)} {/* Time Off Request Form (Employee) */} {currentUser.role === 'employee' && (

Request Time Off

// ... (code you provided)
setNewTimeOff({...newTimeOff, startDate: 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" />
{/* Other form fields would go here */}
{/* A submit button would likely go here */}
)} {/* Other request sections would go here */}
)}
); }; export default SchedulingApp; // Don't forget to export the component