Anmeldung erfolgreich gesendet!
diff --git a/src/routes/admin/anmeldungen/+page.svelte b/src/routes/admin/anmeldungen/+page.svelte
index a6d5569..690612f 100644
--- a/src/routes/admin/anmeldungen/+page.svelte
+++ b/src/routes/admin/anmeldungen/+page.svelte
@@ -5,7 +5,7 @@
import AnmeldungenTable from '$lib/components/AnmeldungenTable.svelte';
import DienststellenDialog from '$lib/components/DienststellenDialog.svelte';
import AdminHeader from '$lib/components/AdminHeader.svelte';
-
+
interface Anmeldung {
pdfs: { pfad: string }[];
anrede: string;
@@ -15,6 +15,9 @@
noteDeutsch?: string;
noteMathe?: string;
sozialverhalten?: string;
+ notfallVorname?: string;
+ notfallNachname?: string;
+ notfallTelefon?: string;
wunsch1?: { id: number; name: string };
wunsch2?: { id: number; name: string };
wunsch3?: { id: number; name: string };
@@ -43,11 +46,11 @@
let zeitraeume: Zeitraum[] = [];
let isLoading = true;
let error = '';
-
+
// Filter für Status
let statusFilter: 'all' | 'pending' | 'accepted' | 'rejected' = 'all';
let filteredAnmeldungen: Anmeldung[] = [];
-
+
// Dialog state
let showDialog = false;
let selectedAnmeldungId: number | null = null;
@@ -120,9 +123,9 @@ Ihr Praktikumsteam`;
// Zähle angenommene Anmeldungen pro Zeitraum
function getAcceptedCountForZeitraum(zeitraumId: number): number {
- return anmeldungen.filter(a =>
- a.status === 'accepted' &&
- a.zeitraum?.id === zeitraumId
+ return anmeldungen.filter(a =>
+ a.status === 'accepted' &&
+ a.zeitraum?.id === zeitraumId
).length;
}
@@ -130,26 +133,26 @@ Ihr Praktikumsteam`;
try {
isLoading = true;
error = '';
-
+
const res = await fetch('/api/admin/anmeldungen');
-
+
if (!res.ok) {
const errorText = await res.text();
console.error('❌ API Fehler:', res.status, errorText);
throw new Error(`Fehler beim Laden: ${res.status} - ${errorText}`);
}
-
+
const data = await res.json();
-
+
if (!Array.isArray(data)) {
console.error('❌ Antwort ist kein Array:', data);
throw new Error('Antwort vom Server ist kein Array');
}
-
+
anmeldungen = data.map(a => {
return { ...a, status: a.status || 'pending' };
});
-
+
} catch (err) {
error = err instanceof Error ? err.message : 'Unbekannter Fehler';
console.error('❌ Frontend Fehler beim Laden der Anmeldungen:', err);
@@ -172,13 +175,13 @@ Ihr Praktikumsteam`;
async function loadEmailConfig() {
try {
isLoadingEmailConfig = true;
-
+
const res = await fetch('/api/admin/email-config');
-
+
if (!res.ok) {
throw new Error(`Fehler beim Laden der E-Mail-Konfiguration: ${res.status}`);
}
-
+
const config: EmailConfig = await res.json();
emailSubject = config.subject;
emailTemplate = config.template;
@@ -192,7 +195,7 @@ Ihr Praktikumsteam`;
async function saveEmailTemplate() {
try {
isSavingEmailConfig = true;
-
+
const res = await fetch('/api/admin/email-config', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
@@ -247,10 +250,10 @@ Ihr Praktikumsteam`;
}
showDialog = false;
-
+
// E-Mail Vorschau öffnen nach erfolgreichem Annehmen
openEmailPreview(selectedAnmeldungId, event.detail.dienststelleId);
-
+
selectedAnmeldungId = null;
await loadAnmeldungen();
} catch (err) {
@@ -265,16 +268,16 @@ Ihr Praktikumsteam`;
// Dienststelle finden
const dienststelle = availableWishes.find(w => w.id === dienststelleId);
- const dienststelleName = dienststelle
- ? dienststelle.name.replace(/^\d+\.\s*Wunsch:\s*/, '')
- : 'Unbekannte Dienststelle';
+ const dienststelleName = dienststelle
+ ? dienststelle.name.replace(/^\d+\.\s*Wunsch:\s*/, '')
+ : 'Unbekannte Dienststelle';
// E-Mail Text personalisieren
const personalizedEmail = emailTemplate
- .replace(/\{anrede\}/g, anmeldung.anrede)
- .replace(/\{vorname\}/g, anmeldung.vorname)
- .replace(/\{nachname\}/g, anmeldung.nachname)
- .replace(/\{dienststelle\}/g, dienststelleName);
+ .replace(/\{anrede\}/g, anmeldung.anrede)
+ .replace(/\{vorname\}/g, anmeldung.vorname)
+ .replace(/\{nachname\}/g, anmeldung.nachname)
+ .replace(/\{dienststelle\}/g, dienststelleName);
// Modal mit Vorschau öffnen
emailPreviewData = {
@@ -288,11 +291,11 @@ Ihr Praktikumsteam`;
async function copyAndOpenMail() {
if (!emailPreviewData) return;
-
+
try {
await navigator.clipboard.writeText(emailPreviewData.body);
emailCopied = true;
-
+
// Kurz warten, dann Mail öffnen
setTimeout(() => {
const mailtoLink = `mailto:${emailPreviewData!.to}?subject=${encodeURIComponent(emailPreviewData!.subject)}`;
@@ -347,7 +350,7 @@ Ihr Praktikumsteam`;
const blob = await res.blob();
const contentDisposition = res.headers.get('Content-Disposition');
let filename = 'export.xlsx';
-
+
if (contentDisposition) {
const match = contentDisposition.match(/filename="(.+)"/);
if (match) {
@@ -375,18 +378,18 @@ Ihr Praktikumsteam`;
async function handleReject(event: CustomEvent<{id: number}>) {
if (!confirm('Diese Anmeldung wirklich ablehnen?')) return;
-
+
try {
- const res = await fetch(`/api/admin/anmeldungen?id=${event.detail.id}`, {
+ const res = await fetch(`/api/admin/anmeldungen?id=${event.detail.id}`, {
method: 'PATCH',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ action: 'reject' })
});
-
+
if (!res.ok) {
throw new Error(`Fehler beim Ablehnen: ${res.status}`);
}
-
+
await loadAnmeldungen();
} catch (err) {
error = err instanceof Error ? err.message : 'Fehler beim Ablehnen';
@@ -396,16 +399,16 @@ Ihr Praktikumsteam`;
async function handleDelete(event: CustomEvent<{id: number}>) {
if (!confirm('Diese Anmeldung wirklich löschen?')) return;
-
+
try {
- const res = await fetch(`/api/admin/anmeldungen?id=${event.detail.id}`, {
- method: 'DELETE'
+ const res = await fetch(`/api/admin/anmeldungen?id=${event.detail.id}`, {
+ method: 'DELETE'
});
-
+
if (!res.ok) {
throw new Error(`Fehler beim Löschen: ${res.status}`);
}
-
+
await loadAnmeldungen();
} catch (err) {
error = err instanceof Error ? err.message : 'Fehler beim Löschen';
@@ -430,9 +433,9 @@ Ihr Praktikumsteam`;
-
@@ -442,9 +445,9 @@ Ihr Praktikumsteam`;
-
+
@@ -803,30 +806,30 @@ Ihr Praktikumsteam`;
An:
{emailPreviewData.to}
-
+
Betreff:
{emailPreviewData.subject}
-
+
-
+
{#if emailCopied}
@@ -853,14 +856,14 @@ Ihr Praktikumsteam`;