feat: migrate app state to bootstrap endpoint
app-ci-deploy / test-build-deploy (push) Has been cancelled
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:
+4
-34
@@ -1,4 +1,4 @@
|
||||
import React, { useEffect, useState, useCallback } from 'react';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { useNavigate, useLocation } from 'react-router-dom';
|
||||
import { useAuth } from '../contexts/AuthContext';
|
||||
import {
|
||||
@@ -38,54 +38,24 @@ import { HEADER_HEIGHT } from './Layout';
|
||||
import { logger } from '../debugConfig';
|
||||
import { GraphNavigator } from '../components/navigation/GraphNavigator';
|
||||
|
||||
const API_BASE = import.meta.env.VITE_API_URL || 'http://localhost:8000';
|
||||
|
||||
const Header: React.FC = () => {
|
||||
const theme = useTheme();
|
||||
const navigate = useNavigate();
|
||||
const location = useLocation();
|
||||
const { user, signOut, accessToken } = useAuth();
|
||||
const { user, signOut, bootstrapData } = useAuth();
|
||||
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
|
||||
const [isPlatformAdmin, setIsPlatformAdmin] = useState(false);
|
||||
const [schoolRole, setSchoolRole] = useState<string | null>(null);
|
||||
const [isAuthenticated, setIsAuthenticated] = useState(!!user);
|
||||
const showGraphNavigation = location.pathname === '/single-player';
|
||||
const isPlatformAdmin = bootstrapData?.permissions?.platform_admin ?? false;
|
||||
const schoolRole = bootstrapData?.active_institute?.membership_role ?? null;
|
||||
const isSchoolAdmin = schoolRole === 'school_admin' || schoolRole === 'department_head';
|
||||
|
||||
useEffect(() => {
|
||||
setIsAuthenticated(!!user);
|
||||
}, [user]);
|
||||
|
||||
// Check platform admin status and school role once on login
|
||||
const checkAdminStatus = useCallback(async () => {
|
||||
if (!accessToken) return;
|
||||
// Platform admin check
|
||||
try {
|
||||
const res = await fetch(`${API_BASE}/admin/stats`, {
|
||||
headers: { Authorization: `Bearer ${accessToken}` },
|
||||
});
|
||||
setIsPlatformAdmin(res.ok);
|
||||
} catch {
|
||||
setIsPlatformAdmin(false);
|
||||
}
|
||||
// School role check
|
||||
try {
|
||||
const res = await fetch(`${API_BASE}/school/status`, {
|
||||
headers: { Authorization: `Bearer ${accessToken}` },
|
||||
});
|
||||
if (res.ok) {
|
||||
const data = await res.json();
|
||||
setSchoolRole(data.user_role || null);
|
||||
}
|
||||
} catch {
|
||||
setSchoolRole(null);
|
||||
}
|
||||
}, [accessToken]);
|
||||
|
||||
useEffect(() => {
|
||||
if (accessToken) checkAdminStatus();
|
||||
else { setIsPlatformAdmin(false); setSchoolRole(null); }
|
||||
}, [accessToken, checkAdminStatus]);
|
||||
|
||||
const handleMenuOpen = (event: React.MouseEvent<HTMLElement>) => {
|
||||
setAnchorEl(event.currentTarget);
|
||||
|
||||
Reference in New Issue
Block a user