diff --git a/src/pages/timetable/TaughtLessonsPage.tsx b/src/pages/timetable/TaughtLessonsPage.tsx index e5ce7d7..ffccb49 100644 --- a/src/pages/timetable/TaughtLessonsPage.tsx +++ b/src/pages/timetable/TaughtLessonsPage.tsx @@ -1,12 +1,14 @@ import React, { useEffect, useState, useCallback } from 'react'; +import { useNavigate } from 'react-router-dom'; import { Box, Typography, Button, CircularProgress, Alert, Chip, Dialog, DialogTitle, DialogContent, DialogActions, TextField, Select, MenuItem, FormControl, InputLabel, - Divider, IconButton, Tooltip, + Divider, IconButton, Tooltip, List, ListItemButton, ListItemText, + InputAdornment, } from '@mui/material'; import { - ChevronLeft, ChevronRight, Today, EditNote, + ChevronLeft, ChevronRight, Today, EditNote, LibraryAdd, Search, OpenInNew, } from '@mui/icons-material'; import { useAuth } from '../../contexts/AuthContext'; @@ -152,9 +154,10 @@ function LessonEditDialog({ lesson, onClose, onSave }: EditDialogProps) { interface LessonCardProps { lesson: Lesson; onEdit: (l: Lesson) => void; + onAssignPlan: (l: Lesson) => void; } -function LessonCard({ lesson, onEdit }: LessonCardProps) { +function LessonCard({ lesson, onEdit, onAssignPlan }: LessonCardProps) { return ( {lesson.class_name || lesson.period_code} - - onEdit(lesson)} sx={{ ml: 0.5, p: 0.25 }}> - - - + + + onAssignPlan(lesson)} sx={{ p: 0.25 }}> + + + + + onEdit(lesson)} sx={{ p: 0.25 }}> + + + + {lesson.subject && ( @@ -212,6 +222,7 @@ function LessonCard({ lesson, onEdit }: LessonCardProps) { const TaughtLessonsPage: React.FC = () => { const { accessToken } = useAuth(); + const navigate = useNavigate(); const [weekStart, setWeekStart] = useState(toMonday(new Date())); const [days, setDays] = useState([]); const [loading, setLoading] = useState(false); @@ -219,6 +230,11 @@ const TaughtLessonsPage: React.FC = () => { const [materializing, setMaterializing] = useState(false); const [materializeResult, setMaterializeResult] = useState(null); const [editingLesson, setEditingLesson] = useState(null); + const [assigningLesson, setAssigningLesson] = useState(null); + const [plans, setPlans] = useState<{ id: string; title: string; subject: string | null }[]>([]); + const [planSearch, setPlanSearch] = useState(''); + const [assignSaving, setAssignSaving] = useState(false); + const [assignResult, setAssignResult] = useState(null); const loadLessons = useCallback(async (ws: string) => { if (!accessToken) return; @@ -281,10 +297,51 @@ const TaughtLessonsPage: React.FC = () => { loadLessons(weekStart); }; + const openAssignDialog = async (lesson: Lesson) => { + setAssigningLesson(lesson); + setPlanSearch(''); + setAssignResult(null); + if (plans.length === 0) { + try { + const res = await fetch(`${API_BASE}/lessons/plans`, { + headers: { Authorization: `Bearer ${accessToken}` }, + }); + const data = await res.json(); + if (Array.isArray(data)) setPlans(data); + } catch { /* silently ignore */ } + } + }; + + const handleAssignPlan = async (planId: string) => { + if (!assigningLesson) return; + setAssignSaving(true); + try { + const res = await fetch(`${API_BASE}/lessons/plans/${planId}/deliver`, { + method: 'POST', + headers: { Authorization: `Bearer ${accessToken}`, 'Content-Type': 'application/json' }, + body: JSON.stringify({ taught_lesson_id: assigningLesson.id }), + }); + const data = await res.json(); + if (data.id) { + setAssignResult('Plan linked ✓'); + setTimeout(() => { setAssigningLesson(null); setAssignResult(null); }, 1200); + } else { + setAssignResult(data.detail || 'Failed to link plan'); + } + } catch (e: any) { + setAssignResult(e.message); + } finally { + setAssignSaving(false); + } + }; + + const filteredPlans = plans.filter(p => + !planSearch || p.title.toLowerCase().includes(planSearch.toLowerCase()) + || (p.subject || '').toLowerCase().includes(planSearch.toLowerCase()) + ); + const totalLessons = days.reduce((sum, d) => sum + d.lessons.length, 0); - // Format week label - const weekDates = days.filter(d => d.lessons.length > 0 || true).map(d => d.date); const weekLabel = days.length > 0 ? `${formatDate(days[0].date)} – ${formatDate(days[days.length - 1].date)}` : ''; @@ -369,6 +426,7 @@ const TaughtLessonsPage: React.FC = () => { key={lesson.id} lesson={lesson} onEdit={setEditingLesson} + onAssignPlan={openAssignDialog} /> )) )} @@ -382,6 +440,71 @@ const TaughtLessonsPage: React.FC = () => { onClose={() => setEditingLesson(null)} onSave={handleSaveLesson} /> + + {/* Assign Plan dialog */} + setAssigningLesson(null)} maxWidth="sm" fullWidth> + + Assign Lesson Plan + {assigningLesson && ( + + {assigningLesson.class_name || assigningLesson.period_code} · {assigningLesson.date} + + )} + + + {assignResult ? ( + + {assignResult} + + ) : null} + setPlanSearch(e.target.value)} + InputProps={{ + startAdornment: , + }} + sx={{ mb: 1 }} + /> + {plans.length === 0 ? ( + + No lesson plans yet.{' '} + + + ) : ( + + {filteredPlans.map(p => ( + handleAssignPlan(p.id)} + disabled={assignSaving} + sx={{ borderRadius: 1, mb: 0.25 }} + > + + {assignSaving && } + + ))} + + )} + + + + + + ); };