Split these files that exceeded the 500-line hard cap: - privacy-policy.ts (965 LOC) -> sections + renderers - academy/api.ts (787 LOC) -> courses + mock-data - whistleblower/api.ts (755 LOC) -> operations + mock-data - vvt-profiling.ts (659 LOC) -> data + logic - cookie-banner.ts (595 LOC) -> config + embed - dsr/types.ts (581 LOC) -> core + api types - tom-generator/rules-engine.ts (560 LOC) -> evaluator + gap-analysis - datapoint-helpers.ts (548 LOC) -> generators + validators Each original file becomes a barrel re-export for backward compatibility. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
158 lines
9.8 KiB
TypeScript
158 lines
9.8 KiB
TypeScript
/**
|
|
* Academy API — Mock Data & SDK Proxy
|
|
*
|
|
* Fallback mock data for development and SDK proxy function
|
|
*/
|
|
|
|
import type {
|
|
Course,
|
|
CourseCategory,
|
|
Enrollment,
|
|
EnrollmentStatus,
|
|
AcademyStatistics,
|
|
} from './types'
|
|
import { isEnrollmentOverdue } from './types'
|
|
import {
|
|
fetchCourses,
|
|
fetchEnrollments,
|
|
fetchAcademyStatistics,
|
|
} from './api-courses'
|
|
|
|
// =============================================================================
|
|
// SDK PROXY FUNCTION
|
|
// =============================================================================
|
|
|
|
export async function fetchSDKAcademyList(): Promise<{
|
|
courses: Course[]
|
|
enrollments: Enrollment[]
|
|
statistics: AcademyStatistics
|
|
}> {
|
|
try {
|
|
const [courses, enrollments, statistics] = await Promise.all([
|
|
fetchCourses(),
|
|
fetchEnrollments(),
|
|
fetchAcademyStatistics()
|
|
])
|
|
|
|
return { courses, enrollments, statistics }
|
|
} catch (error) {
|
|
console.error('Failed to load Academy data from backend, using mock data:', error)
|
|
|
|
const courses = createMockCourses()
|
|
const enrollments = createMockEnrollments()
|
|
const statistics = createMockStatistics(courses, enrollments)
|
|
|
|
return { courses, enrollments, statistics }
|
|
}
|
|
}
|
|
|
|
// =============================================================================
|
|
// MOCK DATA
|
|
// =============================================================================
|
|
|
|
export function createMockCourses(): Course[] {
|
|
const now = new Date()
|
|
|
|
return [
|
|
{
|
|
id: 'course-001',
|
|
title: 'DSGVO-Grundlagen fuer Mitarbeiter',
|
|
description: 'Umfassende Einfuehrung in die Datenschutz-Grundverordnung. Dieses Pflichttraining vermittelt die wichtigsten Grundsaetze des Datenschutzes, Betroffenenrechte und die korrekte Handhabung personenbezogener Daten im Arbeitsalltag.',
|
|
category: 'dsgvo_basics',
|
|
durationMinutes: 90,
|
|
passingScore: 80,
|
|
isActive: true,
|
|
status: 'published',
|
|
requiredForRoles: ['all'],
|
|
createdAt: new Date(now.getTime() - 90 * 24 * 60 * 60 * 1000).toISOString(),
|
|
updatedAt: new Date(now.getTime() - 5 * 24 * 60 * 60 * 1000).toISOString(),
|
|
lessons: [
|
|
{ id: 'lesson-001-01', courseId: 'course-001', order: 1, title: 'Was ist die DSGVO?', type: 'text', contentMarkdown: '# Was ist die DSGVO?\n\nDie Datenschutz-Grundverordnung (DSGVO) ist eine Verordnung der Europaeischen Union...', durationMinutes: 15 },
|
|
{ id: 'lesson-001-02', courseId: 'course-001', order: 2, title: 'Die 7 Grundsaetze der DSGVO', type: 'video', contentMarkdown: 'Videoerklaerung der Grundsaetze: Rechtmaessigkeit, Zweckbindung, Datenminimierung, Richtigkeit, Speicherbegrenzung, Integritaet und Vertraulichkeit, Rechenschaftspflicht.', durationMinutes: 20, videoUrl: '/videos/dsgvo-grundsaetze.mp4' },
|
|
{ id: 'lesson-001-03', courseId: 'course-001', order: 3, title: 'Betroffenenrechte (Art. 15-21)', type: 'text', contentMarkdown: '# Betroffenenrechte\n\nUebersicht der Betroffenenrechte: Auskunft, Berichtigung, Loeschung, Einschraenkung, Datenuebertragbarkeit, Widerspruch.', durationMinutes: 20 },
|
|
{ id: 'lesson-001-04', courseId: 'course-001', order: 4, title: 'Personenbezogene Daten im Arbeitsalltag', type: 'video', contentMarkdown: 'Praxisbeispiele fuer den korrekten Umgang mit personenbezogenen Daten am Arbeitsplatz.', durationMinutes: 15, videoUrl: '/videos/dsgvo-praxis.mp4' },
|
|
{ id: 'lesson-001-05', courseId: 'course-001', order: 5, title: 'Wissenstest: DSGVO-Grundlagen', type: 'quiz', contentMarkdown: 'Testen Sie Ihr Wissen zu den DSGVO-Grundlagen.', durationMinutes: 20 },
|
|
]
|
|
},
|
|
{
|
|
id: 'course-002',
|
|
title: 'IT-Sicherheit & Cybersecurity Awareness',
|
|
description: 'Sensibilisierung fuer IT-Sicherheitsrisiken und Best Practices im Umgang mit Phishing, Passwoertern, Social Engineering und sicherer Kommunikation.',
|
|
category: 'it_security',
|
|
durationMinutes: 60,
|
|
passingScore: 75,
|
|
isActive: true,
|
|
status: 'published',
|
|
requiredForRoles: ['all'],
|
|
createdAt: new Date(now.getTime() - 60 * 24 * 60 * 60 * 1000).toISOString(),
|
|
updatedAt: new Date(now.getTime() - 10 * 24 * 60 * 60 * 1000).toISOString(),
|
|
lessons: [
|
|
{ id: 'lesson-002-01', courseId: 'course-002', order: 1, title: 'Phishing erkennen und vermeiden', type: 'video', contentMarkdown: 'Wie erkennt man Phishing-E-Mails und was tut man im Verdachtsfall?', durationMinutes: 15, videoUrl: '/videos/phishing-awareness.mp4' },
|
|
{ id: 'lesson-002-02', courseId: 'course-002', order: 2, title: 'Sichere Passwoerter und MFA', type: 'text', contentMarkdown: '# Sichere Passwoerter\n\nRichtlinien fuer starke Passwoerter, Passwort-Manager und Multi-Faktor-Authentifizierung.', durationMinutes: 15 },
|
|
{ id: 'lesson-002-03', courseId: 'course-002', order: 3, title: 'Social Engineering und Manipulation', type: 'text', contentMarkdown: '# Social Engineering\n\nMethoden von Angreifern zur Manipulation von Mitarbeitern und Schutzmassnahmen.', durationMinutes: 15 },
|
|
{ id: 'lesson-002-04', courseId: 'course-002', order: 4, title: 'Wissenstest: IT-Sicherheit', type: 'quiz', contentMarkdown: 'Testen Sie Ihr Wissen zur IT-Sicherheit.', durationMinutes: 15 },
|
|
]
|
|
},
|
|
{
|
|
id: 'course-003',
|
|
title: 'AI Literacy - Sicherer Umgang mit KI',
|
|
description: 'Grundlagen kuenstlicher Intelligenz, EU AI Act, verantwortungsvoller Einsatz von KI-Werkzeugen und Risiken bei der Nutzung von Large Language Models (LLMs) im Unternehmen.',
|
|
category: 'ai_literacy',
|
|
durationMinutes: 75,
|
|
passingScore: 70,
|
|
isActive: true,
|
|
status: 'draft',
|
|
requiredForRoles: ['admin', 'data_protection_officer'],
|
|
createdAt: new Date(now.getTime() - 30 * 24 * 60 * 60 * 1000).toISOString(),
|
|
updatedAt: new Date(now.getTime() - 3 * 24 * 60 * 60 * 1000).toISOString(),
|
|
lessons: [
|
|
{ id: 'lesson-003-01', courseId: 'course-003', order: 1, title: 'Was ist Kuenstliche Intelligenz?', type: 'text', contentMarkdown: '# Was ist KI?\n\nGrundlagen von Machine Learning, Deep Learning und Large Language Models in verstaendlicher Sprache.', durationMinutes: 15 },
|
|
{ id: 'lesson-003-02', courseId: 'course-003', order: 2, title: 'Der EU AI Act - Was bedeutet er fuer uns?', type: 'video', contentMarkdown: 'Ueberblick ueber den EU AI Act, Risikoklassen und Anforderungen fuer Unternehmen.', durationMinutes: 20, videoUrl: '/videos/eu-ai-act.mp4' },
|
|
{ id: 'lesson-003-03', courseId: 'course-003', order: 3, title: 'KI-Werkzeuge sicher nutzen', type: 'text', contentMarkdown: '# KI-Werkzeuge sicher nutzen\n\nRichtlinien fuer den Einsatz von ChatGPT, Copilot & Co.', durationMinutes: 20 },
|
|
{ id: 'lesson-003-04', courseId: 'course-003', order: 4, title: 'Wissenstest: AI Literacy', type: 'quiz', contentMarkdown: 'Testen Sie Ihr Wissen zum sicheren Umgang mit KI.', durationMinutes: 20 },
|
|
]
|
|
}
|
|
]
|
|
}
|
|
|
|
export function createMockEnrollments(): Enrollment[] {
|
|
const now = new Date()
|
|
|
|
return [
|
|
{ id: 'enr-001', courseId: 'course-001', userId: 'user-001', userName: 'Maria Fischer', userEmail: 'maria.fischer@example.de', status: 'in_progress', progress: 40, startedAt: new Date(now.getTime() - 10 * 24 * 60 * 60 * 1000).toISOString(), deadline: new Date(now.getTime() + 20 * 24 * 60 * 60 * 1000).toISOString() },
|
|
{ id: 'enr-002', courseId: 'course-002', userId: 'user-002', userName: 'Stefan Mueller', userEmail: 'stefan.mueller@example.de', status: 'completed', progress: 100, startedAt: new Date(now.getTime() - 20 * 24 * 60 * 60 * 1000).toISOString(), completedAt: new Date(now.getTime() - 12 * 24 * 60 * 60 * 1000).toISOString(), certificateId: 'cert-001', deadline: new Date(now.getTime() + 10 * 24 * 60 * 60 * 1000).toISOString() },
|
|
{ id: 'enr-003', courseId: 'course-001', userId: 'user-003', userName: 'Laura Schneider', userEmail: 'laura.schneider@example.de', status: 'not_started', progress: 0, startedAt: new Date(now.getTime() - 2 * 24 * 60 * 60 * 1000).toISOString(), deadline: new Date(now.getTime() + 28 * 24 * 60 * 60 * 1000).toISOString() },
|
|
{ id: 'enr-004', courseId: 'course-003', userId: 'user-004', userName: 'Thomas Wagner', userEmail: 'thomas.wagner@example.de', status: 'expired', progress: 25, startedAt: new Date(now.getTime() - 60 * 24 * 60 * 60 * 1000).toISOString(), deadline: new Date(now.getTime() - 5 * 24 * 60 * 60 * 1000).toISOString() },
|
|
{ id: 'enr-005', courseId: 'course-002', userId: 'user-005', userName: 'Julia Becker', userEmail: 'julia.becker@example.de', status: 'in_progress', progress: 50, startedAt: new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000).toISOString(), deadline: new Date(now.getTime() + 5 * 24 * 60 * 60 * 1000).toISOString() },
|
|
]
|
|
}
|
|
|
|
export function createMockStatistics(courses?: Course[], enrollments?: Enrollment[]): AcademyStatistics {
|
|
const c = courses || createMockCourses()
|
|
const e = enrollments || createMockEnrollments()
|
|
|
|
const completedCount = e.filter(en => en.status === 'completed').length
|
|
const completionRate = e.length > 0 ? Math.round((completedCount / e.length) * 100) : 0
|
|
const overdueCount = e.filter(en => isEnrollmentOverdue(en)).length
|
|
|
|
return {
|
|
totalCourses: c.length,
|
|
totalEnrollments: e.length,
|
|
completionRate,
|
|
overdueCount,
|
|
byCategory: {
|
|
dsgvo_basics: c.filter(co => co.category === 'dsgvo_basics').length,
|
|
it_security: c.filter(co => co.category === 'it_security').length,
|
|
ai_literacy: c.filter(co => co.category === 'ai_literacy').length,
|
|
whistleblower_protection: c.filter(co => co.category === 'whistleblower_protection').length,
|
|
custom: c.filter(co => co.category === 'custom').length,
|
|
},
|
|
byStatus: {
|
|
not_started: e.filter(en => en.status === 'not_started').length,
|
|
in_progress: e.filter(en => en.status === 'in_progress').length,
|
|
completed: e.filter(en => en.status === 'completed').length,
|
|
expired: e.filter(en => en.status === 'expired').length,
|
|
}
|
|
}
|
|
}
|