[dyad] SchulOS markalama kabul kriterlerini doğrulama

This commit is contained in:
[dyad] committed 2026-08-02 01:55:22 +02:00
1 parent 0b0481a4d0
commit 5e66bae15b
57 files changed
+195 -191

No files matched your search

+1 -1
View File
@@ -59,7 +59,7 @@ export default function CompliancePage() {
<Card className="border-emerald-200 bg-emerald-50">
<CardContent className="pt-6">
<p className="text-emerald-800 mb-4">
✓ Compliance onboarding completed successfully! Your school is now ready to use ExaMetra.
✓ Compliance onboarding completed successfully! Your school is now ready to use SchulOS.
</p>
<button
onClick={() => router.push("/admin/compliance-overview")}
+1 -1
View File
@@ -1,4 +1,4 @@
// CompetenceTrack — Announcement Read Receipt API
// SchulOS — Announcement Read Receipt API
import { NextResponse } from 'next/server';
import { db } from '@/lib/db';
import { getSession } from '@/lib/auth';
+1 -1
View File
@@ -51,7 +51,7 @@ export async function POST(request: Request) {
teacherName: `${session.user?.firstName || 'Frau'} ${session.user?.lastName || 'Muster'}`,
date: new Date().toLocaleDateString('de-DE'),
score: '85%',
schoolName: 'CompetenceTrack Schule',
schoolName: 'SchulOS Schule',
subjectName: 'Mathematik',
behaviorDescription: 'Beschreibung des Vorfalls',
behaviorCategory: 'Störung',
+2 -2
View File
@@ -253,7 +253,7 @@ export async function GET() {
const exportData: Record<string, unknown> = {
exportMetadata: {
exportDate: new Date().toISOString(),
platform: 'CompetenceTrack',
platform: 'SchulOS',
legalBasis: 'DSGVO Art. 20 - Recht auf Datenübertragbarkeit',
userId: user.id,
},
@@ -285,7 +285,7 @@ export async function GET() {
return NextResponse.json(exportData, {
headers: {
'Content-Disposition': `attachment; filename="competencetrack-data-export-${new Date().toISOString().split('T')[0]}.json"`,
'Content-Disposition': `attachment; filename="schulos-data-export-${new Date().toISOString().split('T')[0]}.json"`,
},
});
} catch (error) {
+1 -1
View File
@@ -1,4 +1,4 @@
// CompetenceTrack — Single Notification API
// SchulOS — Single Notification API
import { NextResponse } from 'next/server';
import { db } from '@/lib/db';
import { getSession } from '@/lib/auth';
@@ -1,4 +1,4 @@
// CompetenceTrack — Notification Preferences API
// SchulOS — Notification Preferences API
import { NextResponse } from 'next/server';
import { db } from '@/lib/db';
import { getSession } from '@/lib/auth';
+1 -1
View File
@@ -1,4 +1,4 @@
// CompetenceTrack — Notifications API (DB-backed, Enhanced)
// SchulOS — Notifications API (DB-backed, Enhanced)
import { NextResponse } from 'next/server';
import { db } from '@/lib/db';
import { getSession } from '@/lib/auth';
+2 -2
View File
@@ -337,7 +337,7 @@ function generatePrintHtml(report: Record<string, unknown>, template: string): s
</style>
</head>
<body>
<div class="watermark">CompetenceTrack</div>
<div class="watermark">SchulOS</div>
<button class="print-btn no-print" onclick="window.print()">Drucken / Print</button>
<div class="header">
@@ -364,7 +364,7 @@ function generatePrintHtml(report: Record<string, unknown>, template: string): s
${gradesHtml}
<div class="footer">
<p>CompetenceTrack — Kompetenzbericht · ${new Date().toLocaleDateString('de-DE')}</p>
<p>SchulOS — Kompetenzbericht · ${new Date().toLocaleDateString('de-DE')}</p>
</div>
<div class="eco-footer">
Digital erstellt — Papier sparen, Umwelt schutzen
+2 -2
View File
@@ -126,8 +126,8 @@ export async function POST(request: Request) {
{
schoolId: school.id,
name: 'welcome',
subject: 'Willkommen bei CompetenceTrack',
body: '<h1>Willkommen bei CompetenceTrack!</h1><p>Hallo {{studentName}},</p><p>du wurdest für die Schule {{schoolName}} registriert.</p><p>Deine Zugangsdaten:</p><p>E-Mail: {{email}}</p><p>Bitte melde dich an und ändere dein Passwort.</p><p>Mit freundlichen Grüßen,<br>{{schoolName}}</p>',
subject: 'Willkommen bei SchulOS',
body: '<h1>Willkommen bei SchulOS!</h1><p>Hallo {{studentName}},</p><p>du wurdest für die Schule {{schoolName}} registriert.</p><p>Deine Zugangsdaten:</p><p>E-Mail: {{email}}</p><p>Bitte melde dich an und ändere dein Passwort.</p><p>Mit freundlichen Grüßen,<br>{{schoolName}}</p>',
isDefault: true,
},
];
+5 -5
View File
@@ -15,19 +15,19 @@ const geistMono = Geist_Mono({
});
export const metadata: Metadata = {
title: "CompetenceTrack — Free Competency & Grading Platform",
title: "SchulOS — Free Competency & Grading Platform",
description: "Open-Source School Software for Competency-Based Assessment and Grading. Built with Next.js, TypeScript, and shadcn/ui.",
keywords: ["CompetenceTrack", "competency", "grading", "school", "education", "Next.js", "TypeScript", "shadcn/ui"],
authors: [{ name: "CompetenceTrack Team" }],
keywords: ["SchulOS", "competency", "grading", "school", "education", "Next.js", "TypeScript", "shadcn/ui"],
authors: [{ name: "SchulOS Team" }],
manifest: "/manifest.json",
icons: {
icon: "https://z-cdn.chatglm.cn/z-ai/static/logo.svg",
icon: "/logo.svg",
apple: "/icon-192.png",
},
appleWebApp: {
capable: true,
statusBarStyle: "default",
title: "CompetenceTrack",
title: "SchulOS",
},
};
+3 -3
View File
@@ -975,7 +975,7 @@ export default function AppLayout() {
</div>
)}
<div className="group-data-[collapsible=icon]:hidden">
<h2 className="text-lg font-bold text-gray-900 dark:text-gray-100 leading-tight">{schoolBranding?.name || 'CompetenceTrack'}</h2>
<h2 className="text-lg font-bold text-gray-900 dark:text-gray-100 leading-tight">{schoolBranding?.name || 'SchulOS'}</h2>
<p className="text-[10px] text-emerald-600/70 dark:text-emerald-400/50 leading-tight">{t('app.subtitle')}</p>
</div>
</motion.div>
@@ -1409,7 +1409,7 @@ export default function AppLayout() {
<div className="flex items-center justify-between text-xs text-emerald-600/60 dark:text-emerald-400/40">
<span className="flex items-center gap-1">
<Leaf className="h-3 w-3 text-emerald-500" />
CompetenceTrack — {t('footer.copyright')}
SchulOS — {t('footer.copyright')}
</span>
<span className="flex items-center gap-2">
<span className="hidden sm:inline">{t('footer.version')} · {t('footer.oss')}</span>
@@ -1609,7 +1609,7 @@ export default function AppLayout() {
{t('polish.help')}
</DialogTitle>
<DialogDescription className="text-xs text-gray-500 dark:text-gray-400">
CompetenceTrack · {t('footer.version')}
SchulOS · {t('footer.version')}
</DialogDescription>
</DialogHeader>
<div className="space-y-2 text-sm">
+1 -1
View File
@@ -3295,7 +3295,7 @@ export default function DashboardView() {
<div className="hidden sm:flex flex-col items-end gap-1 shrink-0">
<Badge className="bg-emerald-100 text-emerald-700 dark:bg-emerald-900/30 dark:text-emerald-300 text-xs">
<GraduationCap className="h-3 w-3 mr-1" />
{currentUser?.schoolId ? t('nav.classes') : 'CompetenceTrack'}
{currentUser?.schoolId ? t('nav.classes') : 'SchulOS'}
</Badge>
<span className="text-[10px] text-gray-400 dark:text-gray-500">
{t('dashboard.total_students')}: {data.stats.totalStudents} · {t('dashboard.total_classes')}: {data.stats.totalClasses}
+1 -1
View File
@@ -244,7 +244,7 @@ export default function OnboardingTour({ open, onClose }: OnboardingTourProps) {
{/* Hidden title for accessibility */}
<DialogHeader className="sr-only">
<VisuallyHidden>
<DialogTitle>CompetenceTrack Onboarding Tour</DialogTitle>
<DialogTitle>SchulOS Onboarding Tour</DialogTitle>
</VisuallyHidden>
</DialogHeader>
{/* Close button */}
+1 -1
View File
@@ -1762,7 +1762,7 @@ function generatePrintHTML(
return `
<div class="report-card-page">
<div class="header">
<h1>${school?.name ?? 'CompetenceTrack'}</h1>
<h1>${school?.name ?? 'SchulOS'}</h1>
${school?.motto ? `<p class="motto">${school.motto}</p>` : ''}
<h2>Zeugnis / Report Card</h2>
<p>Schuljahr: ${report.schoolYear.label}</p>
+1 -1
View File
@@ -534,7 +534,7 @@ export default function SchoolLibraryView() {
<p><strong>${t('library.due_date')}:</strong> ${new Date(checkout.dueDate).toLocaleDateString()}</p>
<p><strong>${t('library.condition')}:</strong> ${checkout.condition}</p>
<hr/>
<p style="text-align:center; font-size: 12px;">CompetenceTrack - ${t('library.title')}</p>
<p style="text-align:center; font-size: 12px;">SchulOS - ${t('library.title')}</p>
</body></html>
`);
printWindow.document.close();
+7 -7
View File
@@ -732,7 +732,7 @@ function PrivacyTab({ currentUser }: { currentUser: { id: string; role: string;
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = `competencetrack-data-export-${new Date().toISOString().split('T')[0]}.json`;
a.download = `schulos-data-export-${new Date().toISOString().split('T')[0]}.json`;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
@@ -866,7 +866,7 @@ function PrivacyTab({ currentUser }: { currentUser: { id: string; role: string;
<Mail className="h-4 w-4 text-gray-600 dark:text-gray-400" />
<h4 className="text-sm font-semibold text-gray-700 dark:text-gray-300">{t('dsgvo.contact_dpo')}</h4>
</div>
<p className="text-sm text-gray-600 dark:text-gray-400">datenschutz@competencetrack.org</p>
<p className="text-sm text-gray-600 dark:text-gray-400">datenschutz@schulos.org</p>
</div>
</CardContent>
</Card>
@@ -1070,12 +1070,12 @@ function PrivacyTab({ currentUser }: { currentUser: { id: string; role: string;
className="min-h-[44px] rounded-xl border-violet-200 dark:border-violet-900/30 text-violet-700 dark:text-violet-300 hover:bg-violet-50 dark:hover:bg-violet-900/20 font-semibold"
onClick={() => {
// Generate a simple DPA template as a downloadable text file
const dpaTemplate = `Auftragsverarbeitungsvertrag (AVV)\ngemäß Art. 28 DSGVO\n\nVerantwortliche Stelle (Schule):\n[Name der Schule]\n[Adresse]\n\nAuftragsverarbeiter:\nCompetenceTrack\n[Adresse]\n\n1. Gegenstand und Dauer der Verarbeitung\nDer Auftragsverarbeiter verarbeitet personenbezogene Daten im Auftrag der verantwortlichen Stelle gemäß den Bestimmungen dieses Vertrages.\n\n2. Art und Zweck der Verarbeitung\n- Bereitstellung und Betrieb der CompetenceTrack-Plattform\n- Verwaltung von Schüler- und Klassendaten\n- Dokumentation von Lernfortschritten\n- Erstellung von Zeugnissen und Berichten\n\n3. Art der personenbezogenen Daten\n- Name, E-Mail-Adresse\n- Schülereinschreibungsdaten\n- Lernfortschrittsdaten\n- Bewertungsdaten\n- Anwesenheitsdaten\n\n4. Betroffene Personenkreise\n- Schülerinnen und Schüler\n- Lehrkräfte\n- Eltern / Erziehungsberechtigte\n\n5. Technisch-organisatorische Maßnahmen\nDer Auftragsverarbeiter implementiert angemessene technisch-organisatorische Maßnahmen gemäß Art. 32 DSGVO.\n\n6. Löschung und Rückgabe von Daten\nNach Beendigung des Auftragsverhältnisses werden alle personenbezogenen Daten gelöscht.\n\n7. Kontrolle durch die verantwortliche Stelle\nDie verantwortliche Stelle hat das Recht, die Einhaltung der Maßnahmen zu kontrollieren.\n\n8. Unterauftragsverhältnisse\nEine Weitergabe an Unterauftragnehmer bedarf der vorherigen Zustimmung der verantwortlichen Stelle.\n\nOrt, Datum: _______________\n\nUnterschrift Verantwortliche Stelle: _______________\nUnterschrift Auftragsverarbeiter: _______________`;
const dpaTemplate = `Auftragsverarbeitungsvertrag (AVV)\ngemäß Art. 28 DSGVO\n\nVerantwortliche Stelle (Schule):\n[Name der Schule]\n[Adresse]\n\nAuftragsverarbeiter:\nSchulOS\n[Adresse]\n\n1. Gegenstand und Dauer der Verarbeitung\nDer Auftragsverarbeiter verarbeitet personenbezogene Daten im Auftrag der verantwortlichen Stelle gemäß den Bestimmungen dieses Vertrages.\n\n2. Art und Zweck der Verarbeitung\n- Bereitstellung und Betrieb der SchulOS-Plattform\n- Verwaltung von Schüler- und Klassendaten\n- Dokumentation von Lernfortschritten\n- Erstellung von Zeugnissen und Berichten\n\n3. Art der personenbezogenen Daten\n- Name, E-Mail-Adresse\n- Schülereinschreibungsdaten\n- Lernfortschrittsdaten\n- Bewertungsdaten\n- Anwesenheitsdaten\n\n4. Betroffene Personenkreise\n- Schülerinnen und Schüler\n- Lehrkräfte\n- Eltern / Erziehungsberechtigte\n\n5. Technisch-organisatorische Maßnahmen\nDer Auftragsverarbeiter implementiert angemessene technisch-organisatorische Maßnahmen gemäß Art. 32 DSGVO.\n\n6. Löschung und Rückgabe von Daten\nNach Beendigung des Auftragsverhältnisses werden alle personenbezogenen Daten gelöscht.\n\n7. Kontrolle durch die verantwortliche Stelle\nDie verantwortliche Stelle hat das Recht, die Einhaltung der Maßnahmen zu kontrollieren.\n\n8. Unterauftragsverhältnisse\nEine Weitergabe an Unterauftragnehmer bedarf der vorherigen Zustimmung der verantwortlichen Stelle.\n\nOrt, Datum: _______________\n\nUnterschrift Verantwortliche Stelle: _______________\nUnterschrift Auftragsverarbeiter: _______________`;
const blob = new Blob([dpaTemplate], { type: 'text/plain;charset=utf-8' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'AVV_CompetenceTrack_Vorlage.txt';
a.download = 'AVV_SchulOS_Vorlage.txt';
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
@@ -1102,7 +1102,7 @@ function PrivacyTab({ currentUser }: { currentUser: { id: string; role: string;
title: 'Verzeichnis von Verarbeitungstätigkeiten',
legalBasis: 'Art. 30 DSGVO',
controller: '[Name der Schule]',
processor: 'CompetenceTrack',
processor: 'SchulOS',
processingActivities: [
{ name: 'Benutzerverwaltung', purpose: 'Bereitstellung der Plattform', dataCategories: 'Name, E-Mail, Rolle', retention: 'Dauer der Nutzung + 30 Tage', legalBasis: 'Art. 6 Abs. 1 lit. b DSGVO' },
{ name: 'Schülerverwaltung', purpose: 'Verwaltung von Klassen und Schülern', dataCategories: 'Name, Geburtsdatum, Geschlecht', retention: 'Dauer der Nutzung + 30 Tage', legalBasis: 'Art. 6 Abs. 1 lit. b DSGVO' },
@@ -5085,7 +5085,7 @@ export default function SettingsView() {
</div>
)}
<div>
<p className="font-bold text-gray-900 dark:text-gray-100" style={{ color: brandingForm.primaryColor }}>{selectedSchool?.name || 'CompetenceTrack'}</p>
<p className="font-bold text-gray-900 dark:text-gray-100" style={{ color: brandingForm.primaryColor }}>{selectedSchool?.name || 'SchulOS'}</p>
<p className="text-xs text-gray-500 dark:text-gray-400">{brandingForm.motto || t('app.subtitle')}</p>
</div>
</div>
@@ -5444,7 +5444,7 @@ export default function SettingsView() {
<div className="p-4 rounded-xl border border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-900">
<p className="text-sm font-semibold text-gray-700 dark:text-gray-300 mb-1">{t('email.template_subject')}: {emailPreviewTemplate.subject}</p>
<div className="mt-3 p-3 rounded-xl bg-gray-50 dark:bg-gray-800/50 text-sm max-h-64 overflow-y-auto scrollbar-education">
{emailPreviewTemplate.body.replace(/\{\{studentName\}\}/g, 'Max Mustermann').replace(/\{\{className\}\}/g, 'Klasse 5a').replace(/\{\{teacherName\}\}/g, 'Frau Muster').replace(/\{\{date\}\}/g, new Date().toLocaleDateString()).replace(/\{\{schoolName\}\}/g, 'CompetenceTrack Schule').replace(/\{\{subjectName\}\}/g, 'Mathematik').replace(/\{\{score\}\}/g, '85%')}
{emailPreviewTemplate.body.replace(/\{\{studentName\}\}/g, 'Max Mustermann').replace(/\{\{className\}\}/g, 'Klasse 5a').replace(/\{\{teacherName\}\}/g, 'Frau Muster').replace(/\{\{date\}\}/g, new Date().toLocaleDateString()).replace(/\{\{schoolName\}\}/g, 'SchulOS Schule').replace(/\{\{subjectName\}\}/g, 'Mathematik').replace(/\{\{score\}\}/g, '85%')}
</div>
</div>
<div className="space-y-2">
+1 -1
View File
@@ -378,7 +378,7 @@ function exportStudentCsv(data: StudentDetailData) {
const rows: string[] = [];
// Header section
rows.push('CompetenceTrack - Student Export');
rows.push('SchulOS - Student Export');
rows.push(`Student,${studentName}`);
rows.push(`Class,${primaryClass}`);
rows.push(`School,${schoolName}`);
+1 -1
View File
@@ -1,4 +1,4 @@
// CompetenceTrack — API Client
// SchulOS — API Client
// All API calls go through these helpers
/* ── Generic helpers ──────────────────────────────────────────────── */
+1 -1
View File
@@ -1,4 +1,4 @@
// CompetenceTrack — Audit Logging Middleware
// SchulOS — Audit Logging Middleware
// Provides logAudit() and withAuditLog() helpers for recording all data modifications
import { db } from '@/lib/db';
+1 -1
View File
@@ -1,4 +1,4 @@
// CompetenceTrack — Badge Auto-Award Check Utility
// SchulOS — Badge Auto-Award Check Utility
// Checks if a student meets requirements for auto-awarded badges
import { db } from '@/lib/db';
+1 -1
View File
@@ -1,4 +1,4 @@
// CompetenceTrack — In-memory API response cache utility
// SchulOS — In-memory API response cache utility
// Provides TTL-based caching for API responses to reduce redundant fetches
interface CacheEntry<T> {
+25 -25
View File
@@ -1,11 +1,11 @@
// CompetenceTrack — i18n (German + English)
// SchulOS — i18n (German + English)
// Simple translation system: t(key) returns the string for the current locale
type TranslationDict = Record<string, string>;
const de: TranslationDict = {
// App branding
'app.name': 'CompetenceTrack',
'app.name': 'SchulOS',
'app.subtitle': 'Freie Kompetenz- & Benotungsplattform für Schulen',
'app.tagline': 'Open-Source Software für kompetenzorientierte Beurteilung',
@@ -56,7 +56,7 @@ const de: TranslationDict = {
'auth.password': 'Passwort',
'auth.firstName': 'Vorname',
'auth.lastName': 'Nachname',
'auth.login_title': 'Bei CompetenceTrack anmelden',
'auth.login_title': 'Bei SchulOS anmelden',
'auth.register_title': 'Neues Konto erstellen',
'auth.login_subtitle': 'Geben Sie Ihre Zugangsdaten ein',
'auth.register_subtitle': 'Erstellen Sie ein kostenloses Konto',
@@ -440,7 +440,7 @@ const de: TranslationDict = {
// Onboarding checklist
'onboarding.title': 'Erste Schritte',
'onboarding.subtitle': 'Follow these steps to set up CompetenceTrack',
'onboarding.subtitle': 'Follow these steps to set up SchulOS',
'onboarding.step_create_class': 'Erstellen Sie Ihre erste Klasse',
'onboarding.step_assign_grid': 'Weisen Sie ein Kompetenzraster zu',
'onboarding.step_add_students': 'Fügen Sie Schüler hinzu',
@@ -478,7 +478,7 @@ const de: TranslationDict = {
'classes.assign_no_templates': 'Keine passenden Raster gefunden.',
// Footer
'footer.copyright': 'CompetenceTrack — Freie Schulsoftware',
'footer.copyright': 'SchulOS — Freie Schulsoftware',
'footer.version': 'Version 1.0',
'footer.oss': 'Open Source',
'sidebar.eco_message': 'Papier sparen, Umwelt schutzen',
@@ -1732,7 +1732,7 @@ const de: TranslationDict = {
'notifications.days_ago': 'vor {days} Tagen',
// Onboarding
'onboarding.welcome_title': 'Willkommen bei CompetenceTrack!',
'onboarding.welcome_title': 'Willkommen bei SchulOS!',
'onboarding.welcome_desc': 'Ihre freie Kompetenz- & Benotungsplattform für Schulen. Lassen Sie uns eine kurze Einführung machen.',
'onboarding.dashboard_title': 'Dashboard',
'onboarding.dashboard_desc': 'Hier sehen Sie einen Überblick über alle Klassen, Schüler und aktuelle Aktivitäten. Nutzen Sie die Schnellaktionen für häufige Aufgaben.',
@@ -1743,7 +1743,7 @@ const de: TranslationDict = {
'onboarding.reports_title': 'Berichte',
'onboarding.reports_desc': 'Erstellen Sie Zeugnis- und Entwicklungsberichte. Exportieren Sie diese als PDF oder drucken Sie sie direkt.',
'onboarding.done_title': 'Fertig!',
'onboarding.done_desc': 'Sie sind bereit, CompetenceTrack zu nutzen. Bei Fragen klicken Sie auf das Hilfe-Symbol in der Kopfzeile.',
'onboarding.done_desc': 'Sie sind bereit, SchulOS zu nutzen. Bei Fragen klicken Sie auf das Hilfe-Symbol in der Kopfzeile.',
'onboarding.skip': 'Überspringen',
'onboarding.next': 'Weiter',
'onboarding.back': 'Zurück',
@@ -1764,7 +1764,7 @@ const de: TranslationDict = {
'onboarding.parents_title': 'Elternkommunikation',
'onboarding.parents_desc': 'Kommunizieren Sie mit Eltern über den Lernfortschritt. Senden Sie Berichte und halten Sie den Dialog aufrecht.',
'onboarding.environmental_title': 'Umweltschutz',
'onboarding.environmental_desc': 'CompetenceTrack spart Papier: Jeder digitale Eintrag ersetzt ca. 50 Seiten Papier. Danke für Ihren Beitrag zum Umweltschutz!',
'onboarding.environmental_desc': 'SchulOS spart Papier: Jeder digitale Eintrag ersetzt ca. 50 Seiten Papier. Danke für Ihren Beitrag zum Umweltschutz!',
// Batch deletion (progress entries)
'progress.batch_select': 'Auswählen',
@@ -2728,10 +2728,10 @@ const de: TranslationDict = {
'pwa.back_online_desc': 'Ihre Verbindung wurde wiederhergestellt.',
'pwa.cached_data': 'Cache-Daten',
'pwa.install_app': 'App installieren',
'pwa.install_app_desc': 'CompetenceTrack als App auf Ihrem Gerät installieren.',
'pwa.install_app_desc': 'SchulOS als App auf Ihrem Gerät installieren.',
'pwa.install': 'Installieren',
'pwa.installed': 'App installiert',
'pwa.installed_desc': 'CompetenceTrack wurde erfolgreich als App installiert.',
'pwa.installed_desc': 'SchulOS wurde erfolgreich als App installiert.',
'pwa.install_accepted': 'Installation gestartet',
'pwa.update_available': 'Update verfügbar',
'pwa.update_available_desc': 'Eine neue Version ist verfügbar. Laden Sie die Seite neu.',
@@ -3300,7 +3300,7 @@ const de: TranslationDict = {
'events.view_all': 'Alle Veranstaltungen',
// Onboarding Tour (24 steps) - DE
'onboarding.step_1_title': 'Willkommen bei CompetenceTrack!',
'onboarding.step_1_title': 'Willkommen bei SchulOS!',
'onboarding.step_1_desc': 'Ihre freie Kompetenz- & Benotungsplattform für Schulen. Lassen Sie uns eine kurze Einführung machen.',
'onboarding.step_2_title': 'Dashboard',
'onboarding.step_2_desc': 'Hier sehen Sie einen Überblick über alle Klassen, Schüler und aktuelle Aktivitäten. Nutzen Sie die Schnellaktionen und Kennzahlen.',
@@ -3349,7 +3349,7 @@ const de: TranslationDict = {
'onboarding.step_24_title': 'Einstellungen',
'onboarding.step_24_desc': 'Passen Sie die Plattform an: Schulprofil, Branding, Backup und Datenverwaltung.',
'onboarding.celebration': 'Sie sind bereit!',
'onboarding.complete': 'Sie haben die Tour abgeschlossen. Viel Erfolg mit CompetenceTrack!',
'onboarding.complete': 'Sie haben die Tour abgeschlossen. Viel Erfolg mit SchulOS!',
'onboarding.previous': 'Zurück',
'onboarding.dont_show_again': 'Nicht mehr anzeigen',
'onboarding.restart_tour': 'Tour erneut starten',
@@ -3676,7 +3676,7 @@ const de: TranslationDict = {
'dsgvo.dpa_desc': 'Vertrag zur Auftragsdatenverarbeitung gemäß Art. 28 DSGVO',
'dsgvo.data_register': 'Verzeichnis von Verarbeitungstätigkeiten',
'dsgvo.data_register_desc': 'Übersicht aller Verarbeitungstätigkeiten gemäß Art. 30 DSGVO',
'dsgvo.privacy_policy_text': 'Die nachfolgende Datenschutzerklärung gilt für die Nutzung der Plattform CompetenceTrack. Verantwortlich für die Datenverarbeitung ist die jeweilige Schule.',
'dsgvo.privacy_policy_text': 'Die nachfolgende Datenschutzerklärung gilt für die Nutzung der Plattform SchulOS. Verantwortlich für die Datenverarbeitung ist die jeweilige Schule.',
'dsgvo.data_collected_list': 'Name, E-Mail-Adresse, Passwort (verschlüsselt), Rollenzuordnung, Klassen- und Fächerverknüpfungen, Lernfortschritte, Bewertungen, Anwesenheitsdaten, Notizen und Zeugnisse.',
'dsgvo.data_purpose_list': 'Bereitstellung und Betrieb der Plattform, Verwaltung von Schülern und Klassen, Dokumentation von Lernfortschritten, Erstellung von Zeugnissen und Berichten, Kommunikation mit Eltern.',
'dsgvo.data_retention_list': 'Nutzerdaten werden für die Dauer der Nutzung gespeichert. Nach Löschung des Kontos werden die Daten nach Ablauf der 30-tägigen Widerspruchsfrist unwiderruflich gelöscht. Auswertungsdaten werden nach 3 Jahren anonymisiert.',
@@ -6654,7 +6654,7 @@ const de: TranslationDict = {
const en: TranslationDict = {
// App branding
'app.name': 'CompetenceTrack',
'app.name': 'SchulOS',
'app.subtitle': 'Free Competency & Grading Platform for Schools',
'app.tagline': 'Open-Source Software for Competency-Based Assessment',
@@ -6705,7 +6705,7 @@ const en: TranslationDict = {
'auth.password': 'Password',
'auth.firstName': 'First Name',
'auth.lastName': 'Last Name',
'auth.login_title': 'Sign in to CompetenceTrack',
'auth.login_title': 'Sign in to SchulOS',
'auth.register_title': 'Create a new account',
'auth.login_subtitle': 'Enter your credentials',
'auth.register_subtitle': 'Create a free account',
@@ -7089,7 +7089,7 @@ const en: TranslationDict = {
// Onboarding checklist
'onboarding.title': 'Getting Started',
'onboarding.subtitle': 'Follow these steps to set up CompetenceTrack',
'onboarding.subtitle': 'Follow these steps to set up SchulOS',
'onboarding.step_create_class': 'Create your first class',
'onboarding.step_assign_grid': 'Assign a competency grid',
'onboarding.step_add_students': 'Add students',
@@ -7127,7 +7127,7 @@ const en: TranslationDict = {
'classes.assign_no_templates': 'No matching templates found.',
// Footer
'footer.copyright': 'CompetenceTrack — Free School Software',
'footer.copyright': 'SchulOS — Free School Software',
'footer.version': 'Version 1.0',
'footer.oss': 'Open Source',
'sidebar.eco_message': 'Save paper, protect the environment',
@@ -8381,7 +8381,7 @@ const en: TranslationDict = {
'notifications.days_ago': '{days} days ago',
// Onboarding
'onboarding.welcome_title': 'Welcome to CompetenceTrack!',
'onboarding.welcome_title': 'Welcome to SchulOS!',
'onboarding.welcome_desc': 'Your free competency & grading platform for schools. Let\'s take a quick tour.',
'onboarding.dashboard_title': 'Dashboard',
'onboarding.dashboard_desc': 'Here you see an overview of all classes, students and current activities. Use quick actions for common tasks.',
@@ -8392,7 +8392,7 @@ const en: TranslationDict = {
'onboarding.reports_title': 'Reports',
'onboarding.reports_desc': 'Create report cards and development reports. Export as PDF or print directly.',
'onboarding.done_title': 'Done!',
'onboarding.done_desc': 'You\'re ready to use CompetenceTrack. For questions, click the help icon in the header.',
'onboarding.done_desc': 'You\'re ready to use SchulOS. For questions, click the help icon in the header.',
'onboarding.skip': 'Skip',
'onboarding.next': 'Next',
'onboarding.back': 'Back',
@@ -8413,7 +8413,7 @@ const en: TranslationDict = {
'onboarding.parents_title': 'Parent Communication',
'onboarding.parents_desc': 'Communicate with parents about learning progress. Send reports and maintain an ongoing dialogue.',
'onboarding.environmental_title': 'Environmental Protection',
'onboarding.environmental_desc': 'CompetenceTrack saves paper: Each digital entry replaces ~50 pages of paper. Thank you for contributing to environmental protection!',
'onboarding.environmental_desc': 'SchulOS saves paper: Each digital entry replaces ~50 pages of paper. Thank you for contributing to environmental protection!',
// Batch deletion (progress entries)
'progress.batch_select': 'Select',
@@ -9376,10 +9376,10 @@ const en: TranslationDict = {
'pwa.back_online_desc': 'Your connection has been restored.',
'pwa.cached_data': 'Cached data',
'pwa.install_app': 'Install App',
'pwa.install_app_desc': 'Install CompetenceTrack as an app on your device.',
'pwa.install_app_desc': 'Install SchulOS as an app on your device.',
'pwa.install': 'Install',
'pwa.installed': 'App installed',
'pwa.installed_desc': 'CompetenceTrack has been successfully installed as an app.',
'pwa.installed_desc': 'SchulOS has been successfully installed as an app.',
'pwa.install_accepted': 'Installation started',
'pwa.update_available': 'Update available',
'pwa.update_available_desc': 'A new version is available. Reload the page to update.',
@@ -9948,7 +9948,7 @@ const en: TranslationDict = {
'events.view_all': 'View All Events',
// Onboarding Tour (24 steps) - EN
'onboarding.step_1_title': 'Welcome to CompetenceTrack!',
'onboarding.step_1_title': 'Welcome to SchulOS!',
'onboarding.step_1_desc': 'Your free competency & grading platform for schools. Let\'s take a quick tour.',
'onboarding.step_2_title': 'Dashboard',
'onboarding.step_2_desc': 'Here you see an overview of all classes, students and current activities. Use quick actions and key metrics.',
@@ -9997,7 +9997,7 @@ const en: TranslationDict = {
'onboarding.step_24_title': 'Settings',
'onboarding.step_24_desc': 'Customize the platform: school profile, branding, backup and data management.',
'onboarding.celebration': 'You\'re all set!',
'onboarding.complete': 'You\'ve completed the tour. Good luck with CompetenceTrack!',
'onboarding.complete': 'You\'ve completed the tour. Good luck with SchulOS!',
'onboarding.previous': 'Previous',
'onboarding.dont_show_again': 'Don\'t show again',
'onboarding.restart_tour': 'Restart tour',
@@ -10324,7 +10324,7 @@ const en: TranslationDict = {
'dsgvo.dpa_desc': 'Data processing agreement pursuant to Art. 28 GDPR',
'dsgvo.data_register': 'Register of Processing Activities',
'dsgvo.data_register_desc': 'Overview of all processing activities pursuant to Art. 30 GDPR',
'dsgvo.privacy_policy_text': 'The following privacy policy applies to the use of the CompetenceTrack platform. The respective school is responsible for data processing.',
'dsgvo.privacy_policy_text': 'The following privacy policy applies to the use of the SchulOS platform. The respective school is responsible for data processing.',
'dsgvo.data_collected_list': 'Name, email address, password (encrypted), role assignment, class and subject associations, learning progress, assessments, attendance data, notes and reports.',
'dsgvo.data_purpose_list': 'Provision and operation of the platform, management of students and classes, documentation of learning progress, creation of reports, communication with parents.',
'dsgvo.data_retention_list': 'User data is stored for the duration of use. After account deletion, data is permanently deleted after the 30-day objection period. Analytics data is anonymized after 3 years.',
+1 -1
View File
@@ -1,4 +1,4 @@
// CompetenceTrack — Notification Helper
// SchulOS — Notification Helper
// Server-side utility for creating notifications in the database
// Also pushes notifications via WebSocket service
+1 -1
View File
@@ -1,4 +1,4 @@
// CompetenceTrack — Offline Cache for Notebook Data
// SchulOS — Offline Cache for Notebook Data
// Stores notebook data in localStorage for offline access
const NOTEBOOK_CACHE_KEY = 'ct_notebook_cache';
+2 -2
View File
@@ -1,4 +1,4 @@
// CompetenceTrack — QR Code Generation Utility
// SchulOS — QR Code Generation Utility
// Generates QR codes as base64 PNG images using canvas
export type QRCodeType = 'student' | 'class' | 'attendance' | 'event';
@@ -17,7 +17,7 @@ export interface QRCodeData {
* Build a URL string from QR code data that can be encoded into a QR code
*/
export function buildQRCodeUrl(data: QRCodeData): string {
const base = typeof window !== 'undefined' ? window.location.origin : 'https://competencetrack.app';
const base = typeof window !== 'undefined' ? window.location.origin : 'https://schulos.app';
switch (data.type) {
case 'student':
return `${base}/?student=${data.id}`;
+1 -1
View File
@@ -1,4 +1,4 @@
// CompetenceTrack — API Rate Limiting Middleware
// SchulOS — API Rate Limiting Middleware
// In-memory rate limiting with configurable limits per endpoint
interface RateLimitEntry {
+1 -1
View File
@@ -1,4 +1,4 @@
// CompetenceTrack — Zustand Store
// SchulOS — Zustand Store
import { create } from 'zustand';
import { setLocale, getLocale } from '@/lib/i18n';
+1 -1
View File
@@ -1,4 +1,4 @@
// CompetenceTrack — WebSocket Hook
// SchulOS — WebSocket Hook
// Real-time collaboration and push notifications via Socket.IO
'use client';