import { useState, useEffect } from 'react'; import { Clock, LogOut, LogIn, Download, Calendar, User } from 'lucide-react'; export default function AttendanceApp() { const [user, setUser] = useState(null); const [users, setUsers] = useState(() => { const savedUsers = localStorage.getItem('users'); return savedUsers ? JSON.parse(savedUsers) : [ { username: 'admin', password: 'admin123', role: 'admin' }, { username: 'user1', password: 'user123', role: 'user' } ]; }); const [attendance, setAttendance] = useState(() => { const savedAttendance = localStorage.getItem('attendance'); return savedAttendance ? JSON.parse(savedAttendance) : []; }); const [view, setView] = useState('login'); const [dateRange, setDateRange] = useState({ start: '', end: '' }); useEffect(() => { localStorage.setItem('attendance', JSON.stringify(attendance)); }, [attendance]); useEffect(() => { localStorage.setItem('users', JSON.stringify(users)); }, [users]); // Geolocation check const checkLocation = async () => { try { const position = await new Promise((resolve, reject) => { navigator.geolocation.getCurrentPosition(resolve, reject); }); // Suva, Fiji coordinates (approximately) const SUVA_LAT = -18.1416; const SUVA_LNG = 178.4419; const distance = calculateDistance( position.coords.latitude, position.coords.longitude, SUVA_LAT, SUVA_LNG ); // Allow within 5km radius return distance <= 5; } catch (error) { console.error('Error getting location:', error); return false; } }; const calculateDistance = (lat1, lon1, lat2, lon2) => { const R = 6371; // Earth's radius in km const dLat = (lat2 - lat1) * Math.PI / 180; const dLon = (lon2 - lon1) * Math.PI / 180; const a = Math.sin(dLat/2) * Math.sin(dLat/2) + Math.cos(lat1 * Math.PI / 180) * Math.cos(lat2 * Math.PI / 180) * Math.sin(dLon/2) * Math.sin(dLon/2); const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); return R * c; }; const handleLogin = (e) => { e.preventDefault(); const username = e.target.username.value; const password = e.target.password.value; const foundUser = users.find(u => u.username === username && u.password === password); if (foundUser) { setUser(foundUser); setView('dashboard'); } else { alert('Invalid credentials'); } }; const handleSignInOut = async () => { const isInLocation = await checkLocation(); if (!isInLocation) { alert('You must be in Suva, Fiji to sign in/out'); return; } const lastRecord = attendance.find(a => a.username === user.username && a.date === new Date().toLocaleDateString() && !a.timeOut ); if (lastRecord) { // Sign out const updatedAttendance = attendance.map(a => a === lastRecord ? { ...a, timeOut: new Date().toLocaleTimeString() } : a ); setAttendance(updatedAttendance); } else { // Sign in setAttendance([ ...attendance, { username: user.username, date: new Date().toLocaleDateString(), timeIn: new Date().toLocaleTimeString(), timeOut: null } ]); } }; const downloadExcel = () => { const filteredData = attendance.filter(record => { const recordDate = new Date(record.date); return recordDate >= new Date(dateRange.start) && recordDate <= new Date(dateRange.end); }); const csv = [ ['Name', 'Date', 'Time In', 'Time Out'], ...filteredData.map(record => [ record.username, record.date, record.timeIn, record.timeOut || '' ]) ].map(row => row.join(',')).join('\n'); const blob = new Blob([csv], { type: 'text/csv' }); const url = window.URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = 'attendance.csv'; a.click(); }; const LoginView = () => (

Office Attendance

); const UserDashboard = () => { const currentMonth = new Date().getMonth(); const userRecords = attendance.filter( record => record.username === user.username && new Date(record.date).getMonth() === currentMonth ); return (

Welcome, {user.username}

This Month's Attendance

{userRecords.map((record, index) => ( ))}
Date Time In Time Out
{record.date} {record.timeIn} {record.timeOut || '-'}
); }; const AdminDashboard = () => (

Admin Dashboard

Export Attendance

setDateRange(prev => ({ ...prev, start: e.target.value }))} className="mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm" />
setDateRange(prev => ({ ...prev, end: e.target.value }))} className="mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm" />

All Attendance Records

{attendance.map((record, index) => ( ))}
Name Date Time In Time Out
{record.username} {record.date} {record.timeIn} {record.timeOut || '-'}
); return (
{view === 'login' && } {view === 'dashboard' && user?.role === 'user' && } {view === 'dashboard' && user?.role === 'admin' && }
); }