Round 20: Student Portal, District Management, userId field, styling enhancements, bug fixes
- Added userId field to Student model with User relation - Created Student Portal view with 6 tabs (competencies, goals, achievements, schedule, homework, feedback) - Created StudentGoal model + CRUD API with role-based access - Created District Management view with CRUD, analytics, school assignment - Enhanced auth page: animated gradient, floating particles, glassmorphism, staggered entrance - Enhanced dashboard: time-based greeting, animated stat cards, class overview, school branding - Enhanced student portal: hero section, circular progress, streak counter, celebration particles - Fixed student-goals API 403 for STUDENT role (name-matching fallback for legacy data) - Added userId filter to students API with OR fallback - Added nav.student-portal i18n key - 100+ new i18n keys in DE and EN - All lint checks pass
This commit is contained in:
1 parent
9680cc9244
commit
04ae7aa80c
23 files changed
+4624
-2868
No files matched your search
+230
@@ -493,6 +493,22 @@ const de: TranslationDict = {
|
||||
|
||||
// New styling keys
|
||||
'dashboard.start_here': 'Jetzt beginnen!',
|
||||
'dashboard.greeting_morning': 'Guten Morgen',
|
||||
'dashboard.greeting_afternoon': 'Guten Tag',
|
||||
'dashboard.greeting_evening': 'Guten Abend',
|
||||
'dashboard.school_branding': 'Schulprofil',
|
||||
'dashboard.school_branding_desc': 'Ihre Schule im Überblick',
|
||||
'dashboard.competency_progress': 'Kompetenzfortschritt',
|
||||
'dashboard.competency_progress_desc': 'Aktuelle Entwicklung der Kompetenzniveaus',
|
||||
'dashboard.paper_saved_pages': 'Seiten',
|
||||
'dashboard.paper_saved_trees': 'Baeume gerettet',
|
||||
'dashboard.paper_saved_co2': 'kg CO2 eingespart',
|
||||
'dashboard.daily_tip': 'Tipp des Tages',
|
||||
'dashboard.class_overview_grid': 'Klassenuebersicht',
|
||||
'dashboard.class_overview_grid_desc': 'Schnellzugriff auf alle Klassen',
|
||||
'dashboard.activity_timeline': 'Aktivitaetenverlauf',
|
||||
'dashboard.activity_timeline_desc': 'Neueste Eintraege im Zeitverlauf',
|
||||
'dashboard.updated_at': 'Aktualisiert',
|
||||
'date.today': 'Heute',
|
||||
'date.yesterday': 'Gestern',
|
||||
'date.days_ago': '{count} Tage zuvor',
|
||||
@@ -511,6 +527,7 @@ const de: TranslationDict = {
|
||||
'header.notifications': 'Aktivitäten',
|
||||
'auth.feature_reports': 'Berichte & Zeugnisse',
|
||||
'auth.feature_flower': 'Kompetenzblume',
|
||||
'auth.feature_data_security': 'Datenschutz & Sicherheit',
|
||||
'flower.hide_average': 'Vergleich aus',
|
||||
'flower.show_average': 'Vergleich an',
|
||||
'flower.download_png': 'Als PNG',
|
||||
@@ -2665,6 +2682,41 @@ const de: TranslationDict = {
|
||||
'district.total_students': 'Gesamtschüler',
|
||||
'district.total_classes': 'Gesamtklassen',
|
||||
'district.total_teachers': 'Gesamtlehrer',
|
||||
'district.management': 'Bezirksverwaltung',
|
||||
'district.overview': 'Übersicht',
|
||||
'district.teacher_count': 'Anzahl Lehrer',
|
||||
'district.add_district': 'Bezirk hinzufügen',
|
||||
'district.edit_district': 'Bezirk bearbeiten',
|
||||
'district.delete_district': 'Bezirk löschen',
|
||||
'district.no_schools': 'Keine Schulen vorhanden',
|
||||
'district.remove_school': 'Schule entfernen',
|
||||
'district.performance_comparison': 'Leistungsvergleich',
|
||||
'district.recent_activity': 'Letzte Aktivität',
|
||||
'district.active': 'Aktiv',
|
||||
'district.inactive': 'Inaktiv',
|
||||
'district.details': 'Details',
|
||||
'district.save_success': 'Bezirk erfolgreich gespeichert',
|
||||
'district.delete_success': 'Bezirk erfolgreich gelöscht',
|
||||
'district.school_assigned': 'Schule erfolgreich zugeordnet',
|
||||
'district.school_removed': 'Schule erfolgreich entfernt',
|
||||
'district.unassigned_schools': 'Nicht zugeordnete Schulen',
|
||||
'district.no_unassigned_schools': 'Alle Schulen sind zugeordnet',
|
||||
'district.all_schools': 'Alle Schulen',
|
||||
'district.search_districts': 'Bezirke durchsuchen',
|
||||
'district.overview_stats': 'Bezirksstatistik',
|
||||
'district.avg_performance': 'Durchschnittliche Leistung',
|
||||
'district.school_type': 'Schultyp',
|
||||
'district.select_district': 'Bezirk auswählen',
|
||||
'district.district_info': 'Bezirksinformationen',
|
||||
'district.activity_created': 'Bezirk erstellt',
|
||||
'district.activity_updated': 'Bezirk aktualisiert',
|
||||
'district.activity_school_added': 'Schule hinzugefügt',
|
||||
'district.activity_school_removed': 'Schule entfernt',
|
||||
'district.performance_score': 'Leistungswert',
|
||||
'district.attendance_rate': 'Anwesenheitsrate',
|
||||
'district.student_teacher_ratio': 'Schüler-Lehrer-Verhältnis',
|
||||
'nav.districts': 'Bezirksverwaltung',
|
||||
'nav.student-portal': 'Mein Portal',
|
||||
|
||||
// PWA / Offline
|
||||
'pwa.offline': 'Sie sind offline',
|
||||
@@ -3831,6 +3883,69 @@ const de: TranslationDict = {
|
||||
'admin.health_good': 'Gut',
|
||||
'admin.health_warning': 'Warnung',
|
||||
'admin.health_critical': 'Kritisch',
|
||||
|
||||
// Student Portal
|
||||
'student_portal.title': 'Mein Portal',
|
||||
'student_portal.my_competencies': 'Meine Kompetenzen',
|
||||
'student_portal.my_goals': 'Meine Ziele',
|
||||
'student_portal.my_achievements': 'Meine Erfolge',
|
||||
'student_portal.my_schedule': 'Mein Stundenplan',
|
||||
'student_portal.my_homework': 'Meine Hausaufgaben',
|
||||
'student_portal.my_feedback': 'Mein Feedback',
|
||||
'student_portal.goal_set': 'Ziel setzen',
|
||||
'student_portal.goal_progress': 'Zielfortschritt',
|
||||
'student_portal.goal_complete': 'Ziel abschliessen',
|
||||
'student_portal.no_competencies': 'Noch keine Kompetenzdaten vorhanden',
|
||||
'student_portal.no_goals': 'Noch keine Ziele gesetzt',
|
||||
'student_portal.no_achievements': 'Noch keine Erfolge freigeschaltet',
|
||||
'student_portal.points_earned': 'Punkte gesammelt',
|
||||
'student_portal.badges_earned': 'Abzeichen verdient',
|
||||
'student_portal.rewards_available': 'Verfuegbare Belohnungen',
|
||||
'student_portal.today_schedule': 'Heutiger Stundenplan',
|
||||
'student_portal.next_period': 'Naechste Stunde',
|
||||
'student_portal.current_period': 'Aktuelle Stunde',
|
||||
'student_portal.overdue': 'Ueberfaellig',
|
||||
'student_portal.due_today': 'Heute faellig',
|
||||
'student_portal.upcoming': 'Anstehend',
|
||||
'student_portal.mastery_level': 'Kompetenzniveau',
|
||||
'student_portal.level_1': 'Anfaenger',
|
||||
'student_portal.level_2': 'Fortgeschritten',
|
||||
'student_portal.level_3': 'Kompetent',
|
||||
'student_portal.level_4': 'Experte',
|
||||
'student_portal.add_goal': 'Neues Ziel',
|
||||
'student_portal.goal_title': 'Zieltitel',
|
||||
'student_portal.goal_description': 'Zielbeschreibung',
|
||||
'student_portal.target_date': 'Zieldatum',
|
||||
'student_portal.active_goals': 'Aktive Ziele',
|
||||
'student_portal.completed_goals': 'Abgeschlossene Ziele',
|
||||
'student_portal.abandon_goal': 'Ziel aufgeben',
|
||||
'student_portal.update_progress': 'Fortschritt aktualisieren',
|
||||
'student_portal.badge_name': 'Abzeichen',
|
||||
'student_portal.earned_on': 'Verdient am',
|
||||
'student_portal.no_schedule': 'Kein Stundenplan fuer heute',
|
||||
'student_portal.period': 'Stunde',
|
||||
'student_portal.break': 'Pause',
|
||||
'student_portal.no_homework_due': 'Keine Hausaufgaben faellig',
|
||||
'student_portal.no_feedback': 'Noch kein Feedback vorhanden',
|
||||
'student_portal.recent_feedback': 'Letztes Feedback',
|
||||
'student_portal.from_teacher': 'Von',
|
||||
'student_portal.subject': 'Fach',
|
||||
'student_portal.competency_card': 'Kompetenzkarte',
|
||||
'student_portal.progress_bar': 'Fortschrittsbalken',
|
||||
'student_portal.total_points': 'Gesamtpunkte',
|
||||
'student_portal.level': 'Stufe',
|
||||
'student_portal.no_class': 'Keine Klasse',
|
||||
'student_portal.schedule_for': 'Stundenplan fuer',
|
||||
'student_portal.good_morning': 'Guten Morgen',
|
||||
'student_portal.good_afternoon': 'Guten Tag',
|
||||
'student_portal.good_evening': 'Guten Abend',
|
||||
'student_portal.hero_message': 'Weiter so! Jeder Schritt bringt dich naeher an dein Ziel.',
|
||||
'student_portal.streak_days': 'Tage Strich',
|
||||
'student_portal.days': 'Tage',
|
||||
'student_portal.learning_streak': 'Lernstrich',
|
||||
'student_portal.streak_message': 'Tolle Serie! Halte durch, um deine Tagesreihe zu verlaengern.',
|
||||
'student_portal.level_up_progress': 'Aufstiegsfortschritt',
|
||||
'student_portal.level_up_detail': 'Aktuelle Stufe {level} von {max}',
|
||||
};
|
||||
|
||||
const en: TranslationDict = {
|
||||
@@ -4323,6 +4438,22 @@ const en: TranslationDict = {
|
||||
|
||||
// New styling keys
|
||||
'dashboard.start_here': 'Start here!',
|
||||
'dashboard.greeting_morning': 'Good morning',
|
||||
'dashboard.greeting_afternoon': 'Good afternoon',
|
||||
'dashboard.greeting_evening': 'Good evening',
|
||||
'dashboard.school_branding': 'School Profile',
|
||||
'dashboard.school_branding_desc': 'Your school at a glance',
|
||||
'dashboard.competency_progress': 'Competency Progress',
|
||||
'dashboard.competency_progress_desc': 'Current development of competency levels',
|
||||
'dashboard.paper_saved_pages': 'pages',
|
||||
'dashboard.paper_saved_trees': 'trees saved',
|
||||
'dashboard.paper_saved_co2': 'kg CO2 saved',
|
||||
'dashboard.daily_tip': 'Tip of the day',
|
||||
'dashboard.class_overview_grid': 'Class Overview',
|
||||
'dashboard.class_overview_grid_desc': 'Quick access to all classes',
|
||||
'dashboard.activity_timeline': 'Activity Timeline',
|
||||
'dashboard.activity_timeline_desc': 'Latest entries over time',
|
||||
'dashboard.updated_at': 'Updated',
|
||||
'date.today': 'Today',
|
||||
'date.yesterday': 'Yesterday',
|
||||
'date.days_ago': '{count} days ago',
|
||||
@@ -4341,6 +4472,7 @@ const en: TranslationDict = {
|
||||
'header.notifications': 'Activity',
|
||||
'auth.feature_reports': 'Reports & Transcripts',
|
||||
'auth.feature_flower': 'Competence Flower',
|
||||
'auth.feature_data_security': 'Data Security & Privacy',
|
||||
'flower.hide_average': 'Hide Average',
|
||||
'flower.show_average': 'Show Average',
|
||||
'flower.download_png': 'As PNG',
|
||||
@@ -6494,6 +6626,41 @@ const en: TranslationDict = {
|
||||
'district.total_students': 'Total Students',
|
||||
'district.total_classes': 'Total Classes',
|
||||
'district.total_teachers': 'Total Teachers',
|
||||
'district.management': 'District Management',
|
||||
'district.overview': 'Overview',
|
||||
'district.teacher_count': 'Teacher Count',
|
||||
'district.add_district': 'Add District',
|
||||
'district.edit_district': 'Edit District',
|
||||
'district.delete_district': 'Delete District',
|
||||
'district.no_schools': 'No schools found',
|
||||
'district.remove_school': 'Remove School',
|
||||
'district.performance_comparison': 'Performance Comparison',
|
||||
'district.recent_activity': 'Recent Activity',
|
||||
'district.active': 'Active',
|
||||
'district.inactive': 'Inactive',
|
||||
'district.details': 'Details',
|
||||
'district.save_success': 'District saved successfully',
|
||||
'district.delete_success': 'District deleted successfully',
|
||||
'district.school_assigned': 'School assigned successfully',
|
||||
'district.school_removed': 'School removed successfully',
|
||||
'district.unassigned_schools': 'Unassigned Schools',
|
||||
'district.no_unassigned_schools': 'All schools are assigned',
|
||||
'district.all_schools': 'All Schools',
|
||||
'district.search_districts': 'Search districts',
|
||||
'district.overview_stats': 'District Statistics',
|
||||
'district.avg_performance': 'Average Performance',
|
||||
'district.school_type': 'School Type',
|
||||
'district.select_district': 'Select District',
|
||||
'district.district_info': 'District Information',
|
||||
'district.activity_created': 'District created',
|
||||
'district.activity_updated': 'District updated',
|
||||
'district.activity_school_added': 'School added',
|
||||
'district.activity_school_removed': 'School removed',
|
||||
'district.performance_score': 'Performance Score',
|
||||
'district.attendance_rate': 'Attendance Rate',
|
||||
'district.student_teacher_ratio': 'Student-Teacher Ratio',
|
||||
'nav.districts': 'District Management',
|
||||
'nav.student-portal': 'My Portal',
|
||||
|
||||
// PWA / Offline
|
||||
'pwa.offline': 'You are offline',
|
||||
@@ -7660,6 +7827,69 @@ const en: TranslationDict = {
|
||||
'admin.health_good': 'Good',
|
||||
'admin.health_warning': 'Warning',
|
||||
'admin.health_critical': 'Critical',
|
||||
|
||||
// Student Portal
|
||||
'student_portal.title': 'My Portal',
|
||||
'student_portal.my_competencies': 'My Competencies',
|
||||
'student_portal.my_goals': 'My Goals',
|
||||
'student_portal.my_achievements': 'My Achievements',
|
||||
'student_portal.my_schedule': 'My Schedule',
|
||||
'student_portal.my_homework': 'My Homework',
|
||||
'student_portal.my_feedback': 'My Feedback',
|
||||
'student_portal.goal_set': 'Set Goal',
|
||||
'student_portal.goal_progress': 'Goal Progress',
|
||||
'student_portal.goal_complete': 'Complete Goal',
|
||||
'student_portal.no_competencies': 'No competency data yet',
|
||||
'student_portal.no_goals': 'No goals set yet',
|
||||
'student_portal.no_achievements': 'No achievements unlocked yet',
|
||||
'student_portal.points_earned': 'Points Earned',
|
||||
'student_portal.badges_earned': 'Badges Earned',
|
||||
'student_portal.rewards_available': 'Rewards Available',
|
||||
'student_portal.today_schedule': 'Today\'s Schedule',
|
||||
'student_portal.next_period': 'Next Period',
|
||||
'student_portal.current_period': 'Current Period',
|
||||
'student_portal.overdue': 'Overdue',
|
||||
'student_portal.due_today': 'Due Today',
|
||||
'student_portal.upcoming': 'Upcoming',
|
||||
'student_portal.mastery_level': 'Mastery Level',
|
||||
'student_portal.level_1': 'Beginner',
|
||||
'student_portal.level_2': 'Developing',
|
||||
'student_portal.level_3': 'Competent',
|
||||
'student_portal.level_4': 'Expert',
|
||||
'student_portal.add_goal': 'New Goal',
|
||||
'student_portal.goal_title': 'Goal Title',
|
||||
'student_portal.goal_description': 'Goal Description',
|
||||
'student_portal.target_date': 'Target Date',
|
||||
'student_portal.active_goals': 'Active Goals',
|
||||
'student_portal.completed_goals': 'Completed Goals',
|
||||
'student_portal.abandon_goal': 'Abandon Goal',
|
||||
'student_portal.update_progress': 'Update Progress',
|
||||
'student_portal.badge_name': 'Badge',
|
||||
'student_portal.earned_on': 'Earned on',
|
||||
'student_portal.no_schedule': 'No schedule for today',
|
||||
'student_portal.period': 'Period',
|
||||
'student_portal.break': 'Break',
|
||||
'student_portal.no_homework_due': 'No homework due',
|
||||
'student_portal.no_feedback': 'No feedback yet',
|
||||
'student_portal.recent_feedback': 'Recent Feedback',
|
||||
'student_portal.from_teacher': 'From',
|
||||
'student_portal.subject': 'Subject',
|
||||
'student_portal.competency_card': 'Competency Card',
|
||||
'student_portal.progress_bar': 'Progress Bar',
|
||||
'student_portal.total_points': 'Total Points',
|
||||
'student_portal.level': 'Level',
|
||||
'student_portal.no_class': 'No Class',
|
||||
'student_portal.schedule_for': 'Schedule for',
|
||||
'student_portal.good_morning': 'Good Morning',
|
||||
'student_portal.good_afternoon': 'Good Afternoon',
|
||||
'student_portal.good_evening': 'Good Evening',
|
||||
'student_portal.hero_message': 'Keep going! Every step brings you closer to your goal.',
|
||||
'student_portal.streak_days': 'Day Streak',
|
||||
'student_portal.days': 'days',
|
||||
'student_portal.learning_streak': 'Learning Streak',
|
||||
'student_portal.streak_message': 'Great streak! Keep going to extend your daily streak.',
|
||||
'student_portal.level_up_progress': 'Level Up Progress',
|
||||
'student_portal.level_up_detail': 'Current level {level} of {max}',
|
||||
};
|
||||
|
||||
const translations: Record<string, TranslationDict> = { de, en };
|
||||
|
||||
Reference in new issue
Block a user