feat: migrate app state to bootstrap endpoint
app-ci-deploy / test-build-deploy (push) Has been cancelled

Use GET /me/bootstrap as the primary authenticated state source per ADR-0003. AuthContext now fetches and exposes typed bootstrapData, Header and class/detail admin checks use bootstrap permissions/roles, dashboard surfaces onboarding/calendar/timetable/graph status, and graph navigation derives school setup state from bootstrap instead of /school/status.

Refs: t_44353587
This commit is contained in:
2026-05-28 19:07:07 +01:00
parent 67e47fc47f
commit 65ce1bede8
6 changed files with 270 additions and 81 deletions
+6 -11
View File
@@ -116,7 +116,7 @@ function AddStudentDialog({ open, onClose, onAdd, accessToken, existingIds }: Ad
const ClassDetailPage: React.FC = () => {
const { classId } = useParams<{ classId: string }>();
const navigate = useNavigate();
const { accessToken, user } = useAuth();
const { accessToken, user, bootstrapData } = useAuth();
const [cls, setCls] = useState<ClassDetail | null>(null);
const [loading, setLoading] = useState(true);
@@ -131,24 +131,19 @@ const ClassDetailPage: React.FC = () => {
setLoading(true);
setError(null);
try {
const [clsRes, roleRes] = await Promise.all([
fetch(`${API_BASE}/classes/${classId}`, {
headers: { Authorization: `Bearer ${accessToken}` },
}).then(r => r.json()),
fetch(`${API_BASE}/school/status`, {
headers: { Authorization: `Bearer ${accessToken}` },
}).then(r => r.json()),
]);
const clsRes = await fetch(`${API_BASE}/classes/${classId}`, {
headers: { Authorization: `Bearer ${accessToken}` },
}).then(r => r.json());
if (clsRes.id) setCls(clsRes);
else setError(clsRes.detail || 'Class not found');
const role = roleRes.user_role || '';
const role = bootstrapData?.active_institute?.membership_role || '';
setIsAdmin(role === 'school_admin' || role === 'department_head');
} catch (e: any) {
setError(e.message);
} finally {
setLoading(false);
}
}, [accessToken, classId]);
}, [accessToken, classId, bootstrapData]);
useEffect(() => { load(); }, [load]);