Round 22: Exam Calendar, Tablet Grading, Student Achievements, Notification Center, Announcements, Styling

- Exam Calendar View: Teacher exam planning with calendar integration
  - Teachers create/modify exams, admin full CRUD, students read-only
  - CalendarEvent integration, 2-week warning, AI test availability badge
  - Monthly/weekly calendar view, list view, statistics

- Tablet Grading View: Stylus annotation and AI grading audit
  - HTML5 Canvas with PointerEvent pressure sensitivity
  - Tool palette: pen, highlighter, eraser, text, stamp
  - Quick grade buttons (German 1-6 scale)
  - AI grading audit with detailed feedback and suggestions

- Student Achievements View: Badges, XP, leaderboard
  - Badge collection grid with category filters
  - Level/XP system with progress bars
  - Leaderboard with opt-in
  - Daily/weekly challenges

- Student Study Planner View: Pomodoro timer, weekly schedule
  - Pomodoro timer with focus score
  - Weekly study schedule with drag-and-drop
  - AI study recommendations
  - Session history and statistics

- Notification Center View: Categories, filters, bulk actions
  - 6 categories, 4 priority levels
  - Real-time polling (10 seconds)
  - Preferences with quiet hours
  - Statistics charts

- School Announcements View: CRUD, read receipts
  - 6 announcement types with gradient headers
  - Pin-to-top, read receipts, target audience
  - Admin/teacher create, students/parents view

- Bug fixes: AnnouncementRead model user relation, User API schoolId field
- i18n: 200+ new keys, breadcrumb navigation fixes
- Styling: Gradient headers, animations, hover effects across all new views
This commit is contained in:
Mustafa Cetin committed 2026-07-29 22:56:40 +00:00
1 parent 9e22214470
commit 490bd0650f
30 files changed
+10844 -31

No files matched your search

+38 -1
View File
@@ -63,6 +63,9 @@ import {
MessageSquare,
Brain,
Sparkles,
Tablet,
CalendarClock,
Timer,
} from 'lucide-react';
import {
Sidebar,
@@ -168,6 +171,12 @@ import AITestsView from './ai-tests-view';
import AIChatWidget from './ai-chat-widget';
import VirtualCharacter from './virtual-character';
import ParentPortalView from './parent-portal-view';
import NotificationCenterView from './notification-center-view';
import SchoolAnnouncementsView from './school-announcements-view';
import TabletGradingView from './tablet-grading-view';
import ExamCalendarView from './exam-calendar-view';
import StudentAchievementsView from './student-achievements-view';
import StudentStudyPlannerView from './student-study-planner-view';
// Dynamic imports for heavy components with loading skeletons
const AnalyticsView = dynamic(() => import('./analytics-view'), {
@@ -232,6 +241,10 @@ const navSections: NavSection[] = [
{ key: 'counseling', icon: Heart, labelKey: 'counseling.title' },
{ key: 'disciplinary', icon: Shield, labelKey: 'disciplinary.title' },
{ key: 'ai-tests', icon: Brain, labelKey: 'ai_tests.title' },
{ key: 'tablet-grading', icon: Tablet, labelKey: 'nav.tablet_grading' },
{ key: 'exam-calendar', icon: CalendarClock, labelKey: 'nav.exam_calendar' },
{ key: 'notification-center', icon: Bell, labelKey: 'nav.notification_center' },
{ key: 'announcements', icon: Megaphone, labelKey: 'nav.announcements' },
],
},
{
@@ -266,7 +279,13 @@ const studentNavSections: NavSection[] = [
{ key: 'communication', icon: MessageSquare, labelKey: 'nav.communication' },
{ key: 'counseling', icon: Heart, labelKey: 'counseling.title' },
{ key: 'ai-tests', icon: Brain, labelKey: 'ai_tests.title' },
{ key: 'tablet-grading', icon: Tablet, labelKey: 'nav.tablet_grading' },
{ key: 'exam-calendar', icon: CalendarClock, labelKey: 'nav.exam_calendar' },
{ key: 'student-achievements', icon: Trophy, labelKey: 'achievements.title' },
{ key: 'student-study-planner', icon: Timer, labelKey: 'study_planner.title' },
{ key: 'resources', icon: FolderOpen, labelKey: 'nav.resources' },
{ key: 'notification-center', icon: Bell, labelKey: 'nav.notification_center' },
{ key: 'announcements', icon: Megaphone, labelKey: 'nav.announcements' },
{ key: 'settings', icon: Settings, labelKey: 'nav.settings' },
],
},
@@ -287,6 +306,10 @@ const parentNavSections: NavSection[] = [
{ key: 'competitions', icon: Trophy, labelKey: 'nav.competitions' },
{ key: 'illness', icon: Heart, labelKey: 'nav.illness' },
{ key: 'communication', icon: MessageSquare, labelKey: 'nav.communication' },
{ key: 'student-achievements', icon: Trophy, labelKey: 'achievements.title' },
{ key: 'student-study-planner', icon: Timer, labelKey: 'study_planner.title' },
{ key: 'notification-center', icon: Bell, labelKey: 'nav.notification_center' },
{ key: 'announcements', icon: Megaphone, labelKey: 'nav.announcements' },
],
},
];
@@ -426,6 +449,12 @@ function renderView(view: ViewName) {
case 'disciplinary': return <DisciplinaryView />;
case 'ai-tests': return <AITestsView />;
case 'parent-portal': return <ParentPortalView />;
case 'notification-center': return <NotificationCenterView />;
case 'announcements': return <SchoolAnnouncementsView />;
case 'tablet-grading': return <TabletGradingView />;
case 'exam-calendar': return <ExamCalendarView />;
case 'student-achievements': return <StudentAchievementsView />;
case 'student-study-planner': return <StudentStudyPlannerView />;
default: return <DashboardView />;
}
}
@@ -1246,7 +1275,15 @@ export default function AppLayout() {
</ScrollArea>
{/* Footer */}
{!notifLoading && notifData && notifData.notifications.length > 0 && (
<div className="px-3 py-2 border-t border-emerald-100/30 dark:border-emerald-900/20 flex gap-2">
<div className="px-3 py-2 border-t border-emerald-100/30 dark:border-emerald-900/20 flex gap-2 flex-wrap">
<Button
variant="ghost"
size="sm"
onClick={() => { setNotifOpen(false); setCurrentView('notification-center'); }}
className="h-7 text-xs text-emerald-600 dark:text-emerald-400 hover:bg-emerald-100 dark:hover:bg-emerald-900/20 font-semibold"
>
<Bell className="w-3 h-3 mr-0.5" /> {t('notif_center.title')}
</Button>
<Button
variant="ghost"
size="sm"