- Report Card Generator: Professional report cards with PDF export - Subject grades table with competency levels - Competency radar chart, teacher comments - Template management, batch generation - Status workflow: draft → review → published → archived - Seating Chart View: Visual classroom layout - Grid-based classroom with desk positions - Multiple layout templates (rows, groups, U-shape, circle) - Click-to-assign student placement - Randomize and smart arrange features - Student info popover - School Library View: Book lending system - Book catalog with search and filter - Checkout system with due dates and renewals - Overdue tracking with notifications - Reservation queue system - Statistics dashboard with charts - Enhanced Parent Portal: Comprehensive dashboard - Child overview with multiple children selector - Academic progress with competency radar chart - Attendance & illness with approval - Communication, schedule, and reports tabs - Bug fixes: i18n breadcrumb keys for new views - Styling: Gradient headers, animations, hover effects across all new views - 200+ i18n keys added, 15+ API routes, 3+ Prisma models
67 lines
1.8 KiB
TypeScript
Executable File
67 lines
1.8 KiB
TypeScript
Executable File
'use client';
|
|
|
|
import React, { useEffect, useRef } from 'react';
|
|
import { useAppStore } from '@/lib/store';
|
|
import { fetchCurrentUser } from '@/lib/api';
|
|
import AuthView from '@/components/auth-view';
|
|
import AppLayout from '@/components/app-layout';
|
|
import CookieConsent from '@/components/cookie-consent';
|
|
|
|
export default function Home() {
|
|
const currentUser = useAppStore((s) => s.currentUser);
|
|
const isLoadingAuth = useAppStore((s) => s.isLoadingAuth);
|
|
const setCurrentUser = useAppStore((s) => s.setCurrentUser);
|
|
const hasCheckedRef = useRef(false);
|
|
|
|
useEffect(() => {
|
|
// Prevent duplicate auth checks: only run once per component lifecycle
|
|
if (hasCheckedRef.current) return;
|
|
hasCheckedRef.current = true;
|
|
|
|
async function checkAuth() {
|
|
try {
|
|
const user = await fetchCurrentUser();
|
|
if (user && !user.error) {
|
|
setCurrentUser(user);
|
|
// Sync locale from user preference
|
|
if (user.locale) {
|
|
useAppStore.getState().setLocale(user.locale);
|
|
}
|
|
} else {
|
|
setCurrentUser(null);
|
|
}
|
|
} catch {
|
|
setCurrentUser(null);
|
|
}
|
|
}
|
|
checkAuth();
|
|
}, []);
|
|
|
|
if (isLoadingAuth) {
|
|
return (
|
|
<div className="min-h-screen flex items-center justify-center bg-gradient-to-br from-emerald-50 via-white to-teal-50 dark:from-gray-950 dark:via-gray-900 dark:to-emerald-950">
|
|
<div className="flex items-center gap-3">
|
|
<div className="h-6 w-6 animate-spin rounded-full border-2 border-emerald-500 border-t-transparent" />
|
|
<span className="text-gray-500 dark:text-gray-400">Loading...</span>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
if (!currentUser) {
|
|
return (
|
|
<>
|
|
<AuthView />
|
|
<CookieConsent />
|
|
</>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<>
|
|
<AppLayout />
|
|
<CookieConsent />
|
|
</>
|
|
);
|
|
}
|