prisma, abgelaufende Zeitraueme nicht anzeigen

This commit is contained in:
titver968
2025-07-26 11:42:13 +02:00
parent 62a46fb0de
commit 1b4f37ec87
3 changed files with 145 additions and 62 deletions

View File

@@ -37,6 +37,7 @@ model Praktikumszeitraum {
bezeichnung String @unique // z. B. "Frühjahr 2025" bezeichnung String @unique // z. B. "Frühjahr 2025"
startDatum DateTime startDatum DateTime
endDatum DateTime endDatum DateTime
anmeldungen Anmeldung[] @relation("PraktikumszeitraumAnmeldungen")
} }
enum Status { enum Status {
@@ -50,12 +51,28 @@ model Anmeldung {
anrede String anrede String
vorname String vorname String
nachname String nachname String
geburtsdatum String // Neu hinzugefügt
strasse String // Neu hinzugefügt
hausnummer String // Neu hinzugefügt
ort String // Neu hinzugefügt
plz String // Neu hinzugefügt
telefon String // Neu hinzugefügt
email String email String
noteDeutsch String? schulart String // Neu hinzugefügt
noteMathe String? schulklasse String? // Neu hinzugefügt
noteDeutsch Int // Geändert von String zu Int
noteMathe Int // Geändert von String zu Int
sozialverhalten String? sozialverhalten String?
motivation String? // Neu hinzugefügt
alter Int? // Neu hinzugefügt für Altersvalidierung
status Status @default(OFFEN) status Status @default(OFFEN)
zugewiesenId Int? // ID der zugewiesenen Dienststelle
// Praktikumszeitraum Relation
praktikumId Int?
praktikum Praktikumszeitraum? @relation("PraktikumszeitraumAnmeldungen", fields: [praktikumId], references: [id])
// Dienststellen Relationen
zugewiesenId Int?
zugewiesen Dienststelle? @relation("Zugewiesen", fields: [zugewiesenId], references: [id]) zugewiesen Dienststelle? @relation("Zugewiesen", fields: [zugewiesenId], references: [id])
wunsch1Id Int? wunsch1Id Int?
wunsch1 Dienststelle? @relation("Wunsch1", fields: [wunsch1Id], references: [id]) wunsch1 Dienststelle? @relation("Wunsch1", fields: [wunsch1Id], references: [id])
@@ -63,7 +80,8 @@ model Anmeldung {
wunsch2 Dienststelle? @relation("Wunsch2", fields: [wunsch2Id], references: [id]) wunsch2 Dienststelle? @relation("Wunsch2", fields: [wunsch2Id], references: [id])
wunsch3Id Int? wunsch3Id Int?
wunsch3 Dienststelle? @relation("Wunsch3", fields: [wunsch3Id], references: [id]) wunsch3 Dienststelle? @relation("Wunsch3", fields: [wunsch3Id], references: [id])
timestamp BigInt
timestamp DateTime @default(now())
pdfs PdfDatei[] pdfs PdfDatei[]
@@map("anmeldungen") @@map("anmeldungen")

View File

@@ -33,6 +33,43 @@
let ablehnungHinweis = ''; let ablehnungHinweis = '';
let showAblehnungModal = false; let showAblehnungModal = false;
let alter = ''; let alter = '';
$: {
if (geburtsdatum && zeitraum && zeitraeume.length > 0) {
const gewaehlterZeitraum = zeitraeume.find(z => z.id == zeitraum);
if (gewaehlterZeitraum) {
const geburt = new Date(geburtsdatum);
const praktikumStart = new Date(gewaehlterZeitraum.startDatum);
let altersberechnung = praktikumStart.getFullYear() - geburt.getFullYear();
const monthDiff = praktikumStart.getMonth() - geburt.getMonth();
if (monthDiff < 0 || (monthDiff === 0 && praktikumStart.getDate() < geburt.getDate())) {
altersberechnung--;
}
alter = altersberechnung.toString();
}
}
}
$: filteredDienststellen = (dienststellen ?? []).filter(d => {
if (d.plaetze <= 0) return false;
// PK Mitte nur anzeigen wenn mindestens 18 Jahre alt
if (d.name.includes('PK Mitte') || d.name.toLowerCase().includes('polizeikommissariat mitte')) {
return parseInt(alter) >= 18;
}
return true;
}
);
$: filteredZeitraeume = (zeitraeume ?? []).filter(zeitraum => {
const heute = new Date();
const startDatum = new Date(zeitraum.startDatum);
// Nur Zeiträume anzeigen, die noch nicht gestartet haben
return startDatum > heute;
});
let startDatum = ''; let startDatum = '';
$: hideSozialVerhalten = $: hideSozialVerhalten =
@@ -107,11 +144,19 @@
data.append('noteMathe', noteMathe); data.append('noteMathe', noteMathe);
data.append('sozialverhalten', sozialverhalten); data.append('sozialverhalten', sozialverhalten);
data.append('schulklasse', schulklasse); data.append('schulklasse', schulklasse);
data.append('alter', alter);
for (const pdf of pdfDateien) { for (const pdf of pdfDateien) {
data.append('pdfs', pdf); data.append('pdfs', pdf);
} }
const altersWert = parseInt(alter);
if (isNaN(altersWert) || altersWert < 14) {
ablehnungHinweis = 'Du musst mindestens 14 Jahre alt sein, um ein Praktikum beginnen zu können. Bewirb dich gern erneut, wenn du das Mindestalter erreicht hast.';
showAblehnungModal = true;
return;
}
const deutsch = parseInt(noteDeutsch); const deutsch = parseInt(noteDeutsch);
const mathe = parseInt(noteMathe); const mathe = parseInt(noteMathe);
@@ -216,7 +261,7 @@
<div class="grid grid-cols-1 gap-4"> <div class="grid grid-cols-1 gap-4">
<select bind:value={zeitraum} required class="input"> <select bind:value={zeitraum} required class="input">
<option value="" disabled selected hidden>Wunschzeitraum fürs Praktikum</option> <option value="" disabled selected hidden>Wunschzeitraum fürs Praktikum</option>
{#each zeitraeume ?? [] as d} {#each filteredZeitraeume as d}
<option <option
value={d.id}>{d.bezeichnung} ({new Date(d.startDatum).toLocaleDateString('de-DE', { day: '2-digit', month: '2-digit', year: 'numeric' })} - {new Date(d.endDatum).toLocaleDateString('de-DE', { day: '2-digit', month: '2-digit', year: 'numeric' })}) value={d.id}>{d.bezeichnung} ({new Date(d.startDatum).toLocaleDateString('de-DE', { day: '2-digit', month: '2-digit', year: 'numeric' })} - {new Date(d.endDatum).toLocaleDateString('de-DE', { day: '2-digit', month: '2-digit', year: 'numeric' })})
</option> </option>
@@ -231,25 +276,21 @@
<div class="grid grid-cols-1 gap-4"> <div class="grid grid-cols-1 gap-4">
<select bind:value={wunsch1Id} required> <select bind:value={wunsch1Id} required>
<option value="" disabled selected>1. Wunschdienststelle</option> <option value="" disabled selected>1. Wunschdienststelle</option>
{#each (dienststellen ?? []).filter(d => d.plaetze > 0) as d} {#each filteredDienststellen as d}
<option value={d.id}>{d.name}</option> <option value={d.id}>{d.name}</option>
{/each} {/each}
</select> </select>
<select bind:value={wunsch2Id} required> <select bind:value={wunsch2Id} required>
<option value="" disabled selected>2. Wunschdienststelle</option> <option value="" disabled selected>2. Wunschdienststelle</option>
{#each (dienststellen ?? []).filter(d => d.plaetze > 0 && d.id !== wunsch1Id) as d} {#each filteredDienststellen.filter(d => d.id !== wunsch1Id) as d}
<option value={d.id}>{d.name}</option> <option value={d.id}>{d.name}</option>
{/each} {/each}
</select> </select>
<select bind:value={wunsch3Id} required> <select bind:value={wunsch3Id} required>
<option value="" disabled selected>3. Wunschdienststelle</option> <option value="" disabled selected>3. Wunschdienststelle</option>
{#each (dienststellen ?? []).filter(d => {#each filteredDienststellen.filter(d => d.id !== wunsch1Id && d.id !== wunsch2Id) as d}
d.plaetze > 0 &&
d.id !== wunsch1Id &&
d.id !== wunsch2Id
) as d}
<option value={d.id}>{d.name}</option> <option value={d.id}>{d.name}</option>
{/each} {/each}
</select> </select>
@@ -309,6 +350,17 @@
</div> </div>
{/if} {/if}
{#if alter}
<div class="text-sm text-gray-600">
Alter zu Praktikumsbeginn: {alter} Jahre
{#if parseInt(alter) < 14}
<span class="text-red-600 font-semibold">
(Mindestalter 14 Jahre erforderlich)
</span>
{/if}
</div>
{/if}
{#if fehler} {#if fehler}
<p class="text-red-600">{fehler}</p> <p class="text-red-600">{fehler}</p>
{/if} {/if}

View File

@@ -5,14 +5,16 @@ import { json } from '@sveltejs/kit';
const prisma = new PrismaClient(); const prisma = new PrismaClient();
export async function POST({ request }) { export async function POST({ request }: RequestEvent) {
const formData = await request.formData(); const formData = await request.formData();
const get = (key: string) => formData.get(key)?.toString() ?? ''; const get = (key: string) => formData.get(key)?.toString() ?? '';
const pdfs = formData.getAll('pdfs') as File[]; // const pdfs = formData.getAll('pdfs') as File[];
const pdfFiles = formData.getAll('pdfs') as File[];
const pdfData = [];
const gespeichertePfade: string[] = []; // const gespeichertePfade: string[] = [];
const noteDeutsch = Number(get('noteDeutsch')); const noteDeutsch = Number(get('noteDeutsch'));
const noteMathe = Number(get('noteMathe')); const noteMathe = Number(get('noteMathe'));
@@ -20,46 +22,57 @@ export async function POST({ request }) {
return json({ error: 'Bitte gib gültige Noten an.' }, { status: 400 }); return json({ error: 'Bitte gib gültige Noten an.' }, { status: 400 });
} }
for (const pdf of pdfs) { for (const file of pdfFiles) {
if (pdf.size > 0 && pdf.type === 'application/pdf') { if (file.size > 0 && file.type === 'application/pdf') {
const buffer = Buffer.from(await pdf.arrayBuffer()); const buffer = Buffer.from(await file.arrayBuffer());
const dateiname = `${randomUUID()}.pdf`; const filename = `${randomUUID()}.pdf`;
const pfad = `/uploads/${dateiname}`; const uploadPath = `/uploads/${filename}`;
await writeFile(`static${pfad}`, buffer); await writeFile(`static${uploadPath}`, buffer);
gespeichertePfade.push(pfad); pdfData.push({ pfad: uploadPath });
} }
} }
try { try {
await prisma.anmeldung.create({ const anmeldung = await prisma.anmeldung.create({
data: { data: {
anrede: get('anrede'), // Persönliche Daten
vorname: get('vorname'), anrede: formData.get('anrede') as string,
nachname: get('nachname'), vorname: formData.get('vorname') as string,
geburtsdatum: get('geburtsdatum'), nachname: formData.get('nachname') as string,
strasse: get('strasse'), geburtsdatum: formData.get('geburtsdatum') as string,
hausnummer: get('hausnummer'), // Adresse
ort: get('ort'), strasse: formData.get('strasse') as string,
plz: get('plz'), hausnummer: formData.get('hausnummer') as string,
telefon: get('telefon'), ort: formData.get('ort') as string,
email: get('email'), plz: formData.get('plz') as string,
noteDeutsch, // Kontakt
noteMathe, telefon: formData.get('telefon') as string,
sozialverhalten: get('sozialverhalten'), email: formData.get('email') as string,
praktikumId: Number(formData.get('praktikumId')), // Schule
schulart: get('schulart'), schulart: formData.get('schulart') as string,
motivation: get('motivation'), schulklasse: formData.get('schulklasse') as string,
wunsch1Id: parseInt(get('wunsch1Id')), noteDeutsch: parseInt(formData.get('noteDeutsch') as string),
wunsch2Id: parseInt(get('wunsch2Id')), noteMathe: parseInt(formData.get('noteMathe') as string),
wunsch3Id: parseInt(get('wunsch3Id')), sozialverhalten: formData.get('sozialverhalten') as string || null,
// Praktikum
praktikumId: parseInt(formData.get('zeitraum') as string),
motivation: formData.get('motivation') as string || '',
// Wünsche
wunsch1Id: parseInt(formData.get('wunsch1Id') as string),
wunsch2Id: parseInt(formData.get('wunsch2Id') as string),
wunsch3Id: parseInt(formData.get('wunsch3Id') as string),
// Alter (falls vom Frontend gesendet)
alter: formData.get('alter') ? parseInt(formData.get('alter') as string) : null,
// System
zugewiesenId: null,
// timestamp wird automatisch durch @default(now()) gesetzt
pdfs: { pdfs: {
create: gespeichertePfade.map((pfad) => ({ pfad })) create: pdfData
}, }
zugewiesenId: null
} }
}); });
return json({ success: true }); return json({ success: true, anmeldung });
} catch (err: unknown) { } catch (err: unknown) {
if (err instanceof Error && (err as { code?: string }).code === 'P2002') { if (err instanceof Error && (err as { code?: string }).code === 'P2002') {
return json({ error: 'Diese E-Mail wurde bereits verwendet.' }, { status: 400 }); return json({ error: 'Diese E-Mail wurde bereits verwendet.' }, { status: 400 });