import React, { useState, useEffect } from 'react'; import axios from 'axios'; import { toast } from 'react-toastify'; import { Plus, Edit2, Trash2, Calendar, BookOpen, Loader2, Clock, ChevronDown, ChevronRight, Sparkles } from 'lucide-react'; import { format, isFuture, differenceInCalendarDays, formatDistanceToNow } from 'date-fns'; import { Exam, ApiResponse, User } from '../types'; import ExamModal from '../modals/ExamModal'; import ImportAIModal from '../modals/ImportAIModal'; type HomeProps = { user: User; }; function Home({ user }: HomeProps) { const [exams, setExams] = useState([]); const [loading, setLoading] = useState(true); const [showModal, setShowModal] = useState(false); const [showImportModal, setShowImportModal] = useState(false); const [showCompleted, setShowCompleted] = useState(false); const [editingExam, setEditingExam] = useState(null); const [formData, setFormData] = useState({ name: '', subject: '', date: '', description: '', result: '', duration: '' }); const fetchExams = async () => { try { const res = await axios.get>('/api/exams/list'); if (res.data.success) { setExams(res.data.exams); } } catch (err) { console.error(err); toast.error('Failed to load exams'); } finally { setLoading(false); } }; useEffect(() => { fetchExams(); }, []); const handleOpenModal = (exam: Exam | null = null) => { if (exam) { setEditingExam(exam); setFormData({ name: exam.name, subject: exam.subject, date: new Date(exam.date).toISOString().split('T')[0], description: exam.description || '', result: exam.result || '', duration: exam.duration?.toString() || '' }); } else { setEditingExam(null); setFormData({ name: '', subject: '', date: '', description: '', result: '', duration: '' }); } setShowModal(true); }; const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); // Convert "" values to undefined const cleanedFormData = Object.fromEntries( Object.entries(formData).map(([k, v]) => { if (k === 'duration') return [k, v === '' ? 0 : parseInt(v) || 0]; return [k, v === '' ? undefined : v]; }) ); try { if (editingExam) { await axios.post('/api/exams/update/', { id: editingExam.id, ...cleanedFormData }); } else { await axios.post('/api/exams/create', cleanedFormData); } setShowModal(false); fetchExams(); toast.success(editingExam ? 'Exam updated successfully' : 'Exam created successfully'); } catch (err) { toast.error('Error saving exam'); } }; const handleDelete = async (id: string) => { if (window.confirm('Are you sure you want to delete this exam?')) { try { await axios.delete(`/api/exams/delete/${id}`); fetchExams(); toast.success('Exam deleted successfully'); } catch (err) { toast.error('Error deleting exam'); } } }; const renderExamCard = (exam: Exam) => { const examDate = new Date(exam.date); const upcoming = isFuture(examDate); return (
{upcoming ? formatDistanceToNow(examDate, { addSuffix: true }) : 'Passed'}

{exam.name}

{exam.subject}
{format(examDate, 'MMMM d, yyyy')}
{exam.duration !== undefined && exam.duration > 0 && (
{exam.duration} min
)}
{exam.description && (

{exam.description}

)}
); }; // Compute upcoming exams and next exam const upcomingExams = exams.filter(e => isFuture(new Date(e.date))); const completedExams = exams.filter(e => !isFuture(new Date(e.date))).sort((a, b) => new Date(b.date).getTime() - new Date(a.date).getTime()); const sortedUpcoming = [...upcomingExams].sort((a, b) => new Date(a.date).getTime() - new Date(b.date).getTime()); const nextExam = sortedUpcoming[0]; const preferredName = user.displayName || user.username; let greetingText = ""; if (upcomingExams.length === 0) { greetingText = `Welcome back, ${preferredName}.\nYou currently have no upcoming exams scheduled.`; } else if (upcomingExams.length === 1) { const days = differenceInCalendarDays(new Date(nextExam.date), new Date()); greetingText = `Hello, ${preferredName}.\nYour next exam is scheduled for ${format(new Date(nextExam.date), 'PPP')} (${days} day${days !== 1 ? 's' : ''} remaining).`; } else { greetingText = `Hello, ${preferredName}.\nYour next evaluation is ${nextExam.name} (${nextExam.subject}), scheduled for ${format(new Date(nextExam.date), 'PPP')}.`; } if (loading) return (
); return (
{/* Greeting Section */}

{greetingText.split('\n')[0]}

{greetingText.split('\n')[1]}

Upcoming

You have {exams.filter(e => isFuture(new Date(e.date))).length} scheduled evaluations.

{sortedUpcoming.map(renderExamCard)}
{completedExams.length > 0 && (
{showCompleted && (
{completedExams.map(renderExamCard)}
)}
)} {exams.length === 0 && (

No exams yet

Looks like you're all caught up. Add a new exam to start tracking your progress.

)} {showModal && ( setShowModal(false)} onSubmit={handleSubmit} formData={formData} setFormData={setFormData} editingExam={editingExam} /> )} {showImportModal && ( setShowImportModal(false)} onSuccess={fetchExams} /> )}
); } export default Home;