feat: Round 22 - Exam calendar, parent portal, teacher grading, deep styling
- Exam calendar integration: Plan Exam button, countdown badges, exam filter - Parent portal: Children overview, illness approvals, grades, attendance - Teacher grading: Stylus annotation, AI review, bulk grading mode - Deep schlaukopf crawling: AI-powered content extraction from schlaukopf.de - Dashboard: Upcoming exams, AI tips section - Settings: AI provider config, virtual character toggle, management tabs - Layout: Favorites section, notification badges on sidebar items - Auth: VICE_PRINCIPAL demo account, feature showcase - Attendance: Illness report integration - Assessments: Plan exam button, AI test generation - Fixed schoolId auto-detect in counseling and disciplinary APIs - Added MessageSquare import to settings-view - 150+ new i18n keys
This commit is contained in:
1 parent
f1776932d7
commit
2f266a2143
21 files changed
+3140
-34
No files matched your search
@@ -277,17 +277,17 @@ function LeftIllustration({ loginRole }: { loginRole: LoginRole }) {
|
||||
/* ─── Features section below form ───────────────────────────── */
|
||||
function FeaturesSection() {
|
||||
const features = [
|
||||
{ icon: BarChart3, labelKey: 'auth.feature_competencies', color: 'emerald' },
|
||||
{ icon: LockKeyhole, labelKey: 'auth.feature_data_security', color: 'teal' },
|
||||
{ icon: GitBranch, labelKey: 'auth.feature_open_source', color: 'amber' },
|
||||
{ icon: Flower2, labelKey: 'auth.feature_flower', color: 'violet' },
|
||||
{ icon: BarChart3, labelKey: 'auth.feature_grading', descKey: 'auth.feature_grading_desc', color: 'emerald' },
|
||||
{ icon: GraduationCap, labelKey: 'auth.feature_attendance', descKey: 'auth.feature_attendance_desc', color: 'teal' },
|
||||
{ icon: Sparkles, labelKey: 'auth.feature_ai', descKey: 'auth.feature_ai_desc', color: 'violet' },
|
||||
{ icon: Heart, labelKey: 'auth.feature_collaboration', descKey: 'auth.feature_collaboration_desc', color: 'amber' },
|
||||
];
|
||||
|
||||
const colorClasses: Record<string, { bg: string; text: string }> = {
|
||||
emerald: { bg: 'bg-emerald-50 dark:bg-emerald-900/20', text: 'text-emerald-600 dark:text-emerald-400' },
|
||||
teal: { bg: 'bg-teal-50 dark:bg-teal-900/20', text: 'text-teal-600 dark:text-teal-400' },
|
||||
amber: { bg: 'bg-amber-50 dark:bg-amber-900/20', text: 'text-amber-600 dark:text-amber-400' },
|
||||
violet: { bg: 'bg-violet-50 dark:bg-violet-900/20', text: 'text-violet-600 dark:text-violet-400' },
|
||||
const colorClasses: Record<string, { bg: string; text: string; border: string; iconBg: string }> = {
|
||||
emerald: { bg: 'bg-emerald-50 dark:bg-emerald-900/20', text: 'text-emerald-600 dark:text-emerald-400', border: 'border-emerald-200/60 dark:border-emerald-800/40', iconBg: 'bg-gradient-to-br from-emerald-400 to-emerald-500 text-white' },
|
||||
teal: { bg: 'bg-teal-50 dark:bg-teal-900/20', text: 'text-teal-600 dark:text-teal-400', border: 'border-teal-200/60 dark:border-teal-800/40', iconBg: 'bg-gradient-to-br from-teal-400 to-teal-500 text-white' },
|
||||
amber: { bg: 'bg-amber-50 dark:bg-amber-900/20', text: 'text-amber-600 dark:text-amber-400', border: 'border-amber-200/60 dark:border-amber-800/40', iconBg: 'bg-gradient-to-br from-amber-400 to-amber-500 text-white' },
|
||||
violet: { bg: 'bg-violet-50 dark:bg-violet-900/20', text: 'text-violet-600 dark:text-violet-400', border: 'border-violet-200/60 dark:border-violet-800/40', iconBg: 'bg-gradient-to-br from-violet-400 to-violet-500 text-white' },
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -297,6 +297,7 @@ function FeaturesSection() {
|
||||
transition={{ duration: 0.5, delay: 0.6 }}
|
||||
className="mt-6"
|
||||
>
|
||||
<p className="text-xs font-semibold text-gray-500 dark:text-gray-400 uppercase tracking-wider mb-3 text-center">{t('auth.feature_showcase')}</p>
|
||||
<div className="grid grid-cols-2 gap-3">
|
||||
{features.map((f, i) => {
|
||||
const c = colorClasses[f.color];
|
||||
@@ -306,10 +307,15 @@ function FeaturesSection() {
|
||||
initial={{ opacity: 0, y: 10 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.3, delay: 0.7 + i * 0.08 }}
|
||||
className={`flex items-center gap-2.5 px-3 py-2.5 rounded-xl ${c.bg} border border-white/40 dark:border-gray-800/40`}
|
||||
className={`flex items-start gap-2.5 px-3 py-3 rounded-xl ${c.bg} border ${c.border}`}
|
||||
>
|
||||
<f.icon className={`w-4 h-4 ${c.text} shrink-0`} />
|
||||
<span className="text-xs font-medium text-gray-700 dark:text-gray-300 leading-tight">{t(f.labelKey)}</span>
|
||||
<div className={`flex items-center justify-center w-7 h-7 rounded-lg ${c.iconBg} shrink-0 shadow-sm`}>
|
||||
<f.icon className="w-3.5 h-3.5" />
|
||||
</div>
|
||||
<div className="min-w-0">
|
||||
<p className="text-xs font-semibold text-gray-800 dark:text-gray-200 leading-tight">{t(f.labelKey)}</p>
|
||||
<p className="text-[10px] text-gray-500 dark:text-gray-400 leading-tight mt-0.5">{t(f.descKey)}</p>
|
||||
</div>
|
||||
</motion.div>
|
||||
);
|
||||
})}
|
||||
|
||||
Reference in new issue
Block a user