Round 18: Seating Chart, Student Avatars, Newsletter, Badges, Deep Styling Polish

This commit is contained in:
Mustafa Cetin committed 2026-07-29 12:38:19 +00:00
1 parent cba8a8e724
commit 0363a40ca0
18 files changed
+1838 -50

No files matched your search

+73
View File
@@ -188,6 +188,8 @@ export interface Student {
lastName: string;
dateOfBirth: string | null;
externalId: string | null;
avatarUrl: string | null;
avatarInitials: string | null;
school: { id: string; name: string };
enrollments: Array<{ classGroup: { id: string; name: string; gradeLevel: number } }>;
_count?: { learningProgressEntries: number; assessmentResults: number };
@@ -207,6 +209,7 @@ export function createStudent(data: {
lastName: string;
dateOfBirth?: string;
externalId?: string;
avatarUrl?: string;
}) {
return apiPost<Student>('/api/students', data);
}
@@ -2994,3 +2997,73 @@ export function checkAndAwardBadges(schoolId: string, studentId: string): Promis
export function seedBadges(schoolId: string): Promise<{ success: boolean }> {
return apiPost<{ success: boolean }>('/api/badge-seed', { schoolId });
}
/* ── Newsletter / School Blog ─────────────────────────────────────── */
export interface NewsletterData {
id: string;
schoolId: string;
authorId: string;
title: string;
content: string;
summary: string | null;
imageUrl: string | null;
category: string;
isPublished: boolean;
publishedAt: string | null;
tags: string | null;
isDemo: boolean;
createdAt: string;
updatedAt: string;
deletedAt: string | null;
author: { id: string; firstName: string; lastName: string };
}
export function fetchNewsletters(schoolId: string, published?: boolean, category?: string, limit?: number): Promise<{ newsletters: NewsletterData[]; total: number }> {
const params = new URLSearchParams({ schoolId });
if (published !== undefined) params.set('published', String(published));
if (category) params.set('category', category);
if (limit) params.set('limit', String(limit));
return apiGet<{ newsletters: NewsletterData[]; total: number }>(`/api/newsletters?${params.toString()}`);
}
export function fetchNewsletter(id: string): Promise<NewsletterData> {
return apiGet<NewsletterData>(`/api/newsletters/${id}`);
}
export function createNewsletter(data: {
schoolId: string;
authorId: string;
title: string;
content: string;
summary?: string;
imageUrl?: string;
category?: string;
tags?: string[];
isDemo?: boolean;
}): Promise<NewsletterData> {
return apiPost<NewsletterData>('/api/newsletters', data);
}
export function updateNewsletter(id: string, data: Partial<{
title: string;
content: string;
summary: string;
imageUrl: string;
category: string;
tags: string[];
}>): Promise<NewsletterData> {
return apiPut<NewsletterData>(`/api/newsletters/${id}`, data);
}
export function publishNewsletter(id: string): Promise<NewsletterData> {
return apiPost<NewsletterData>(`/api/newsletters/${id}`, { action: 'publish' });
}
export function unpublishNewsletter(id: string): Promise<NewsletterData> {
return apiPost<NewsletterData>(`/api/newsletters/${id}`, { action: 'unpublish' });
}
export function deleteNewsletter(id: string): Promise<{ success: boolean }> {
return apiDelete<{ success: boolean }>(`/api/newsletters/${id}`);
}
+88
View File
@@ -3161,6 +3161,7 @@ const de: TranslationDict = {
'seating.no_students': 'Keine Schüler für Sitzplan',
'seating.visual': 'Visueller Sitzplan',
'seating.list': 'Listenansicht',
'seating.teacher_desk': 'Lehrerpult',
// QR Code System
'qr.title': 'QR-Code',
@@ -3229,6 +3230,49 @@ const de: TranslationDict = {
'badges.team_player': 'Teamplayer',
'badges.goal_achiever': 'Zielerreicher',
'badges.eco_warrior': 'Umweltkrieger',
// Newsletter / School Blog
'newsletter.title': 'Schulnachrichten',
'newsletter.create': 'Nachricht erstellen',
'newsletter.published': 'Veröffentlicht',
'newsletter.draft': 'Entwurf',
'newsletter.category': 'Kategorie',
'newsletter.general': 'Allgemein',
'newsletter.academic': 'Akademisch',
'newsletter.sports': 'Sport',
'newsletter.arts': 'Kunst',
'newsletter.events': 'Veranstaltungen',
'newsletter.community': 'Gemeinschaft',
'newsletter.read_more': 'Weiterlesen',
'newsletter.view_all': 'Alle Nachrichten',
'newsletter.cover_image': 'Titelbild',
'newsletter.summary': 'Zusammenfassung',
'newsletter.tags': 'Schlagwörter',
'newsletter.publish': 'Veröffentlichen',
'newsletter.unpublish': 'Veröffentlichung zurückziehen',
'newsletter.share': 'Teilen',
'newsletter.author': 'Autor',
'newsletter.date': 'Datum',
'newsletter.content': 'Inhalt',
'newsletter.no_news': 'Keine Nachrichten verfügbar',
'newsletter.latest': 'Neueste Nachrichten',
'newsletter.school_news': 'Schulnachrichten',
// Avatar / Student Photo
'avatar.title': 'Foto',
'avatar.upload': 'Foto hochladen',
'avatar.initials': 'Initialen',
'avatar.photo': 'Foto',
'avatar.change': 'Foto ändern',
'avatar.remove': 'Foto entfernen',
// German Grade Labels
'grading.sehr_gut': 'Sehr gut',
'grading.gut': 'Gut',
'grading.befriedigend': 'Befriedigend',
'grading.ausreichend': 'Ausreichend',
'grading.mangelhaft': 'Mangelhaft',
'grading.ungenuegend': 'Ungenügend',
};
const en: TranslationDict = {
@@ -6389,6 +6433,7 @@ const en: TranslationDict = {
'seating.no_students': 'No students for seating chart',
'seating.visual': 'Visual Seating',
'seating.list': 'List View',
'seating.teacher_desk': 'Teacher Desk',
// QR Code System
'qr.title': 'QR Code',
@@ -6457,6 +6502,49 @@ const en: TranslationDict = {
'badges.team_player': 'Team Player',
'badges.goal_achiever': 'Goal Achiever',
'badges.eco_warrior': 'Eco Warrior',
// Newsletter / School Blog
'newsletter.title': 'School News',
'newsletter.create': 'Create Newsletter',
'newsletter.published': 'Published',
'newsletter.draft': 'Draft',
'newsletter.category': 'Category',
'newsletter.general': 'General',
'newsletter.academic': 'Academic',
'newsletter.sports': 'Sports',
'newsletter.arts': 'Arts',
'newsletter.events': 'Events',
'newsletter.community': 'Community',
'newsletter.read_more': 'Read More',
'newsletter.view_all': 'View All News',
'newsletter.cover_image': 'Cover Image',
'newsletter.summary': 'Summary',
'newsletter.tags': 'Tags',
'newsletter.publish': 'Publish',
'newsletter.unpublish': 'Unpublish',
'newsletter.share': 'Share',
'newsletter.author': 'Author',
'newsletter.date': 'Date',
'newsletter.content': 'Content',
'newsletter.no_news': 'No news available',
'newsletter.latest': 'Latest News',
'newsletter.school_news': 'School News',
// Avatar / Student Photo
'avatar.title': 'Photo',
'avatar.upload': 'Upload Photo',
'avatar.initials': 'Initials',
'avatar.photo': 'Photo',
'avatar.change': 'Change Photo',
'avatar.remove': 'Remove Photo',
// German Grade Labels
'grading.sehr_gut': 'Sehr gut',
'grading.gut': 'Gut',
'grading.befriedigend': 'Befriedigend',
'grading.ausreichend': 'Ausreichend',
'grading.mangelhaft': 'Mangelhaft',
'grading.ungenuegend': 'Ungenügend',
};
const translations: Record<string, TranslationDict> = { de, en };