import React, { useEffect, useState, useCallback } from 'react'; import { Box, Typography, CircularProgress, Alert, Chip, IconButton, Tooltip, } from '@mui/material'; import { ChevronLeft, ChevronRight, Today } from '@mui/icons-material'; import { useAuth } from '../../contexts/AuthContext'; const API_BASE = import.meta.env.VITE_API_BASE || import.meta.env.VITE_API_URL || '/api'; // ─── Types ──────────────────────────────────────────────────────────────────── interface Lesson { id: string; date: string; period_code: string; period_name: string; start_time: string | null; end_time: string | null; class_name: string | null; subject: string | null; year_group: string | null; week_cycle: string; day_of_week: string; status: string; teacher_name: string | null; } interface DayEntry { date: string; day_of_week: string; is_today: boolean; lessons: Lesson[]; } // ─── Helpers ────────────────────────────────────────────────────────────────── function toMonday(d: Date): string { const day = d.getDay(); const diff = day === 0 ? -6 : 1 - day; const m = new Date(d); m.setDate(d.getDate() + diff); return m.toISOString().slice(0, 10); } function addWeeks(iso: string, n: number): string { const d = new Date(iso + 'T00:00:00'); d.setDate(d.getDate() + n * 7); return d.toISOString().slice(0, 10); } function fmtDate(iso: string): string { return new Date(iso + 'T00:00:00').toLocaleDateString('en-GB', { day: 'numeric', month: 'short' }); } const STATUS_COLORS: Record = { planned: 'default', in_progress: 'primary', completed: 'success', cancelled: 'error', substituted: 'warning', }; // ─── Lesson card ────────────────────────────────────────────────────────────── function LessonCard({ lesson }: { lesson: Lesson }) { return ( {lesson.class_name || lesson.period_code} {lesson.subject && ( {lesson.subject}{lesson.year_group ? ` · Y${lesson.year_group}` : ''} )} {lesson.start_time ? `${lesson.start_time}–${lesson.end_time}` : lesson.period_name} {lesson.week_cycle && ( )} {lesson.teacher_name && ( {lesson.teacher_name} )} ); } // ─── Main page ──────────────────────────────────────────────────────────────── const StudentLessonsPage: React.FC = () => { const { accessToken } = useAuth(); const [weekStart, setWeekStart] = useState(toMonday(new Date())); const [days, setDays] = useState([]); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); const load = useCallback(async (ws: string) => { if (!accessToken) return; setLoading(true); setError(null); try { const res = await fetch( `${API_BASE}/timetable/student/lessons?week_start=${ws}&weeks=1`, { headers: { Authorization: `Bearer ${accessToken}` } } ); const data = await res.json(); if (data.status === 'ok') setDays(data.days); else setError(data.message || 'Failed to load lessons'); } catch (e: any) { setError(e.message); } finally { setLoading(false); } }, [accessToken]); useEffect(() => { load(weekStart); }, [weekStart, load]); const totalLessons = days.reduce((s, d) => s + d.lessons.length, 0); const weekLabel = days.length > 0 ? `${fmtDate(days[0].date)} – ${fmtDate(days[days.length - 1].date)}` : ''; return ( {/* Header */} My Lessons {weekLabel} · {totalLessons} lesson{totalLessons !== 1 ? 's' : ''} setWeekStart(toMonday(new Date()))}> setWeekStart(ws => addWeeks(ws, -1))}> setWeekStart(ws => addWeeks(ws, 1))}> {error && {error}} {loading ? ( ) : ( {days.map(day => ( {day.day_of_week.slice(0, 3)} {fmtDate(day.date)} {day.lessons.length === 0 ? ( No lessons ) : ( day.lessons.map(lesson => ( )) )} ))} )} ); }; export default StudentLessonsPage;