Les parents doivent pouvoir suivre la scolarité de leurs enfants (notes, emploi du temps, devoirs). Cela nécessite un lien formalisé entre le compte parent et le compte élève, géré par les administrateurs. Le lien est établi soit manuellement via l'interface d'administration, soit automatiquement lors de l'activation du compte parent lorsque l'invitation inclut un élève cible. Ce lien conditionne l'accès aux données scolaires de l'enfant (autorisations vérifiées par un voter dédié).
180 lines
5.0 KiB
Svelte
180 lines
5.0 KiB
Svelte
<script lang="ts">
|
|
import type { DemoData } from '$types';
|
|
import demoData from '$lib/data/demo-data.json';
|
|
import DashboardParent from '$lib/components/organisms/Dashboard/DashboardParent.svelte';
|
|
import DashboardTeacher from '$lib/components/organisms/Dashboard/DashboardTeacher.svelte';
|
|
import DashboardStudent from '$lib/components/organisms/Dashboard/DashboardStudent.svelte';
|
|
import DashboardAdmin from '$lib/components/organisms/Dashboard/DashboardAdmin.svelte';
|
|
import ChildSelector from '$lib/components/organisms/ChildSelector/ChildSelector.svelte';
|
|
import { getActiveRole, getIsLoading } from '$features/roles/roleContext.svelte';
|
|
|
|
type DashboardView = 'parent' | 'teacher' | 'student' | 'admin';
|
|
|
|
const ROLE_TO_VIEW: Record<string, DashboardView> = {
|
|
ROLE_PARENT: 'parent',
|
|
ROLE_PROF: 'teacher',
|
|
ROLE_ELEVE: 'student',
|
|
ROLE_ADMIN: 'admin',
|
|
ROLE_SUPER_ADMIN: 'admin',
|
|
ROLE_VIE_SCOLAIRE: 'admin',
|
|
ROLE_SECRETARIAT: 'admin'
|
|
};
|
|
|
|
// Fallback demo role when not authenticated or roles not loaded
|
|
let demoRole = $state<DashboardView>('parent');
|
|
|
|
// Use real role context if available, otherwise fallback to demo
|
|
let dashboardView = $derived<DashboardView>(
|
|
ROLE_TO_VIEW[getActiveRole() ?? ''] ?? demoRole
|
|
);
|
|
|
|
// True when roles come from the API (user is authenticated)
|
|
let hasRoleContext = $derived(getActiveRole() !== null);
|
|
|
|
// True when role loading has started (indicates an authenticated user)
|
|
let isRoleLoading = $derived(getIsLoading());
|
|
|
|
// Simulated first login detection (in real app, this comes from API)
|
|
let isFirstLogin = $state(true);
|
|
|
|
// Serenity score preference (in real app, this is stored in backend)
|
|
let serenityEnabled = $state(true);
|
|
|
|
// Use demo data for now (no real data available yet)
|
|
const hasRealData = false;
|
|
|
|
// Selected child for parent dashboard (will drive data fetching when real API is connected)
|
|
let _selectedChildId = $state<string | null>(null);
|
|
|
|
// Demo child name for personalized messages
|
|
let childName = $state('Emma');
|
|
|
|
function handleChildSelected(childId: string) {
|
|
_selectedChildId = childId;
|
|
}
|
|
|
|
function handleToggleSerenity(enabled: boolean) {
|
|
serenityEnabled = enabled;
|
|
}
|
|
|
|
// Cast demo data to proper type
|
|
const typedDemoData = demoData as DemoData;
|
|
|
|
function switchDemoRole(role: DashboardView) {
|
|
demoRole = role;
|
|
isFirstLogin = false;
|
|
}
|
|
</script>
|
|
|
|
<svelte:head>
|
|
<title>Tableau de bord - Classeo</title>
|
|
</svelte:head>
|
|
|
|
<!-- Loading state when roles are being fetched -->
|
|
{#if isRoleLoading}
|
|
<div class="loading-state">
|
|
<div class="spinner"></div>
|
|
<p>Chargement du tableau de bord...</p>
|
|
</div>
|
|
{:else if !hasRoleContext && !isRoleLoading}
|
|
<!-- Demo role switcher shown when not authenticated (no role context from API) -->
|
|
<!-- The RoleSwitcher in the header handles multi-role switching for authenticated users -->
|
|
<div class="demo-controls">
|
|
<span class="demo-label">Démo - Changer de rôle :</span>
|
|
<button class:active={demoRole === 'parent'} onclick={() => switchDemoRole('parent')}>Parent</button>
|
|
<button class:active={demoRole === 'teacher'} onclick={() => switchDemoRole('teacher')}>Enseignant</button>
|
|
<button class:active={demoRole === 'student'} onclick={() => switchDemoRole('student')}>Élève</button>
|
|
<button class:active={demoRole === 'admin'} onclick={() => switchDemoRole('admin')}>Admin</button>
|
|
</div>
|
|
{/if}
|
|
|
|
{#if dashboardView === 'parent'}
|
|
{#if hasRoleContext}
|
|
<ChildSelector onChildSelected={handleChildSelected} />
|
|
{/if}
|
|
<DashboardParent
|
|
demoData={typedDemoData}
|
|
{isFirstLogin}
|
|
isLoading={false}
|
|
{hasRealData}
|
|
{serenityEnabled}
|
|
{childName}
|
|
onToggleSerenity={handleToggleSerenity}
|
|
/>
|
|
{:else if dashboardView === 'teacher'}
|
|
<DashboardTeacher isLoading={false} {hasRealData} />
|
|
{:else if dashboardView === 'student'}
|
|
<DashboardStudent demoData={typedDemoData} isLoading={false} {hasRealData} isMinor={true} />
|
|
{:else if dashboardView === 'admin'}
|
|
<DashboardAdmin
|
|
isLoading={false}
|
|
{hasRealData}
|
|
establishmentName="École Alpha"
|
|
/>
|
|
{/if}
|
|
|
|
<style>
|
|
.loading-state {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: center;
|
|
padding: 3rem;
|
|
text-align: center;
|
|
}
|
|
|
|
.spinner {
|
|
width: 2rem;
|
|
height: 2rem;
|
|
border: 3px solid #e5e7eb;
|
|
border-top-color: #3b82f6;
|
|
border-radius: 50%;
|
|
animation: spin 0.8s linear infinite;
|
|
}
|
|
|
|
@keyframes spin {
|
|
to {
|
|
transform: rotate(360deg);
|
|
}
|
|
}
|
|
|
|
.demo-controls {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 0.5rem;
|
|
padding: 0.75rem 1rem;
|
|
margin-bottom: 1rem;
|
|
background: #fef3c7;
|
|
border: 1px solid #fcd34d;
|
|
border-radius: 0.5rem;
|
|
flex-wrap: wrap;
|
|
}
|
|
|
|
.demo-label {
|
|
font-size: 0.875rem;
|
|
font-weight: 500;
|
|
color: #92400e;
|
|
}
|
|
|
|
.demo-controls button {
|
|
padding: 0.375rem 0.75rem;
|
|
font-size: 0.75rem;
|
|
font-weight: 500;
|
|
background: white;
|
|
border: 1px solid #d1d5db;
|
|
border-radius: 0.375rem;
|
|
cursor: pointer;
|
|
transition: all 0.15s;
|
|
}
|
|
|
|
.demo-controls button:hover {
|
|
background: #f3f4f6;
|
|
}
|
|
|
|
.demo-controls button.active {
|
|
background: #3b82f6;
|
|
border-color: #3b82f6;
|
|
color: white;
|
|
}
|
|
</style>
|