From 63d6d1bbca2f5392bef2c7396f38cf354080b642 Mon Sep 17 00:00:00 2001 From: kcar Date: Wed, 27 May 2026 12:58:33 +0100 Subject: [PATCH] fix(nav): trim burger menu, fix MyClasses for teachers, fix NotFound crash - Header: trim menu to My Work section (My Lessons, My Classes, Lesson Plans), School Admin (gated), Platform Admin (gated) - MyClassesPage: fix loading/error state destructure (classesLoading not myClassesLoading) - NotFound: fix ErrorOutline -> ErrorOutlineIcon to prevent 404 page crash - timetableService: getMyClasses now calls both /me/teacher and /me/student, merges with role annotation - timetableStore: myClasses type updated to ClassWithRole[] - timetable.types: add ClassWithRole interface and code/institute_id optional fields to Class Co-Authored-By: Claude Sonnet 4.6 --- src/pages/Header.tsx | 111 +------------------------- src/pages/timetable/MyClassesPage.tsx | 4 +- src/pages/user/NotFound.tsx | 2 +- src/services/timetableService.ts | 27 ++++++- src/stores/timetableStore.ts | 3 +- src/types/timetable.types.ts | 9 +++ 6 files changed, 42 insertions(+), 114 deletions(-) diff --git a/src/pages/Header.tsx b/src/pages/Header.tsx index ece77e5..c0a7e5f 100644 --- a/src/pages/Header.tsx +++ b/src/pages/Header.tsx @@ -219,9 +219,9 @@ const Header: React.FC = () => { , , - // Timetable Section + // My Work Section { fontSize: '0.75rem' }} > - Timetable & Classes + My Work , - handleNavigation('/timetable')}> - - - - - , - handleNavigation('/classes')}> - - - - - , handleNavigation('/my-classes')}> @@ -262,15 +244,6 @@ const Header: React.FC = () => { secondary="Manage your classes" /> , - handleNavigation('/enrollment-requests')}> - - - - - , handleNavigation('/my-lessons')}> @@ -289,16 +262,7 @@ const Header: React.FC = () => { secondary="Plan and manage lessons" /> , - handleNavigation('/student-lessons')}> - - - - - , - , + , // School Admin Section ...(isSchoolAdmin ? [ @@ -331,71 +295,6 @@ const Header: React.FC = () => { , ] : []), - // Features Section - - Features - , - handleNavigation('/calendar')}> - - - - - , - handleNavigation('/teacher-planner')}> - - - - - , - handleNavigation('/exam-marker')}> - - - - - , - , - - // Utilities Section - - Utilities - , - handleNavigation('/settings')}> - - - - - , - handleNavigation('/search')}> - - - - - , - // Platform Admin Section ...(isPlatformAdmin ? [ , @@ -420,8 +319,6 @@ const Header: React.FC = () => { ] : []), - // Authentication Section - , diff --git a/src/pages/timetable/MyClassesPage.tsx b/src/pages/timetable/MyClassesPage.tsx index d8a6105..0d9f976 100644 --- a/src/pages/timetable/MyClassesPage.tsx +++ b/src/pages/timetable/MyClassesPage.tsx @@ -8,8 +8,8 @@ const MyClassesPage: React.FC = () => { const { profile } = useUser(); const { myClasses, - myClassesLoading, - myClassesError, + classesLoading: myClassesLoading, + classesError: myClassesError, fetchMyClasses, } = useTimetableStore(); diff --git a/src/pages/user/NotFound.tsx b/src/pages/user/NotFound.tsx index 4d95fbe..f078faf 100644 --- a/src/pages/user/NotFound.tsx +++ b/src/pages/user/NotFound.tsx @@ -36,7 +36,7 @@ function NotFound() { gap: 3 }} > - + 404 diff --git a/src/services/timetableService.ts b/src/services/timetableService.ts index 4ba3193..ad4e7c9 100644 --- a/src/services/timetableService.ts +++ b/src/services/timetableService.ts @@ -2,6 +2,7 @@ import axios from 'axios'; import { supabase } from '../supabaseClient'; import { Class, + ClassWithRole, ClassWithRelations, ClassFilters, Timetable, @@ -79,10 +80,30 @@ export const classService = { await axios.delete(`${API_BASE}/database/timetable/classes/${classId}`, { headers }); }, - async getMyClasses(): Promise { + async getMyClasses(): Promise { const headers = await getAuthHeaders(); - const response = await axios.get(`${API_BASE}/database/timetable/classes/me/student`, { headers }); - return response.data.classes; + const [teacherRes, studentRes] = await Promise.allSettled([ + axios.get(`${API_BASE}/database/timetable/classes/me/teacher`, { headers }), + axios.get(`${API_BASE}/database/timetable/classes/me/student`, { headers }), + ]); + const teacherClasses: ClassWithRole[] = teacherRes.status === 'fulfilled' + ? (teacherRes.value.data.classes || []).map((c: Class) => ({ + ...c, + class_id: c.id, + role: 'teacher' as const, + status: 'active', + })) + : []; + const studentClasses: ClassWithRole[] = studentRes.status === 'fulfilled' + ? (studentRes.value.data.classes || []).map((c: Class) => ({ + ...c, + class_id: c.id, + role: 'student' as const, + status: 'active', + })) + : []; + const seen = new Set(teacherClasses.map(c => c.id)); + return [...teacherClasses, ...studentClasses.filter(c => !seen.has(c.id))]; }, async getMyTeachingClasses(): Promise { diff --git a/src/stores/timetableStore.ts b/src/stores/timetableStore.ts index 7314e24..1c9b04a 100644 --- a/src/stores/timetableStore.ts +++ b/src/stores/timetableStore.ts @@ -2,6 +2,7 @@ import { create } from 'zustand'; import { devtools, persist } from 'zustand/middleware'; import { Class, + ClassWithRole, ClassWithRelations, Timetable, TimetableWithRelations, @@ -21,7 +22,7 @@ interface TimetableState { // Classes classes: Class[]; currentClass: ClassWithRelations | null; - myClasses: Class[]; + myClasses: ClassWithRole[]; myTeachingClasses: Class[]; classesLoading: boolean; classesError: string | null; diff --git a/src/types/timetable.types.ts b/src/types/timetable.types.ts index f54cce0..01179be 100644 --- a/src/types/timetable.types.ts +++ b/src/types/timetable.types.ts @@ -27,6 +27,15 @@ export interface Class { created_at: string; updated_at: string; is_active: boolean; + code?: string; + institute_id?: string; +} + +export interface ClassWithRole extends Class { + role: 'teacher' | 'student' | 'assistant'; + status: string; + class_id?: string; + is_primary_teacher?: boolean; } export interface ClassTeacher {