Felder Validierung für E-Mail, PLZ und Telefonnummer. Eingabe akzeptieren wenn wenniger als 3 Plätze vorhanden sind.
This commit is contained in:
Binary file not shown.
@@ -44,6 +44,10 @@
|
|||||||
let alterFehler = '';
|
let alterFehler = '';
|
||||||
let notenFehler = '';
|
let notenFehler = '';
|
||||||
let sozialverhaltenFehler = '';
|
let sozialverhaltenFehler = '';
|
||||||
|
let emailFehler = '';
|
||||||
|
let telefonFehler = '';
|
||||||
|
let notfallTelefonFehler = '';
|
||||||
|
let plzFehler = '';
|
||||||
|
|
||||||
// Hinweis für IGS/KGS mit Lernentwicklungsbericht
|
// Hinweis für IGS/KGS mit Lernentwicklungsbericht
|
||||||
$: zeigeIgsKgsHinweis =
|
$: zeigeIgsKgsHinweis =
|
||||||
@@ -80,6 +84,92 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Echtzeit-Validierung: E-Mail
|
||||||
|
$: {
|
||||||
|
if (email) {
|
||||||
|
// RFC 5322 konforme E-Mail-Validierung (vereinfacht)
|
||||||
|
const emailRegex = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+$/;
|
||||||
|
if (!emailRegex.test(email)) {
|
||||||
|
emailFehler = 'Bitte gib eine gültige E-Mail-Adresse ein.';
|
||||||
|
} else {
|
||||||
|
emailFehler = '';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
emailFehler = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Echtzeit-Validierung: Telefonnummer
|
||||||
|
// Deutsche Telefonnummern: Festnetz 10-11 Ziffern, Mobil 11-12 Ziffern (mit führender 0)
|
||||||
|
// Erlaubt: Ziffern, Leerzeichen, Bindestriche, Schrägstriche, Klammern, + am Anfang
|
||||||
|
$: {
|
||||||
|
if (telefon) {
|
||||||
|
// Entferne alle Formatierungszeichen für die Ziffernzählung
|
||||||
|
const nurZiffern = telefon.replace(/[\s\-\/\(\)\+]/g, '');
|
||||||
|
|
||||||
|
// Prüfe ob nur erlaubte Zeichen enthalten sind
|
||||||
|
const erlaubteZeichenRegex = /^[\d\s\-\/\(\)\+]+$/;
|
||||||
|
|
||||||
|
if (!erlaubteZeichenRegex.test(telefon)) {
|
||||||
|
telefonFehler = 'Die Telefonnummer enthält ungültige Zeichen.';
|
||||||
|
} else if (!/^\d+$/.test(nurZiffern)) {
|
||||||
|
telefonFehler = 'Die Telefonnummer muss Ziffern enthalten.';
|
||||||
|
} else if (nurZiffern.length < 10) {
|
||||||
|
telefonFehler = 'Die Telefonnummer ist zu kurz (mindestens 10 Ziffern).';
|
||||||
|
} else if (nurZiffern.length > 15) {
|
||||||
|
telefonFehler = 'Die Telefonnummer ist zu lang (maximal 15 Ziffern).';
|
||||||
|
} else {
|
||||||
|
telefonFehler = '';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
telefonFehler = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Echtzeit-Validierung: Notfall-Telefonnummer
|
||||||
|
$: {
|
||||||
|
if (notfallTelefon) {
|
||||||
|
const nurZiffern = notfallTelefon.replace(/[\s\-\/\(\)\+]/g, '');
|
||||||
|
const erlaubteZeichenRegex = /^[\d\s\-\/\(\)\+]+$/;
|
||||||
|
|
||||||
|
if (!erlaubteZeichenRegex.test(notfallTelefon)) {
|
||||||
|
notfallTelefonFehler = 'Die Telefonnummer enthält ungültige Zeichen.';
|
||||||
|
} else if (!/^\d+$/.test(nurZiffern)) {
|
||||||
|
notfallTelefonFehler = 'Die Telefonnummer muss Ziffern enthalten.';
|
||||||
|
} else if (nurZiffern.length < 10) {
|
||||||
|
notfallTelefonFehler = 'Die Telefonnummer ist zu kurz (mindestens 10 Ziffern).';
|
||||||
|
} else if (nurZiffern.length > 15) {
|
||||||
|
notfallTelefonFehler = 'Die Telefonnummer ist zu lang (maximal 15 Ziffern).';
|
||||||
|
} else {
|
||||||
|
notfallTelefonFehler = '';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
notfallTelefonFehler = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Echtzeit-Validierung: PLZ (genau 5 Ziffern für deutsche PLZ)
|
||||||
|
$: {
|
||||||
|
if (plz) {
|
||||||
|
const plzRegex = /^\d{5}$/;
|
||||||
|
if (!plzRegex.test(plz)) {
|
||||||
|
if (!/^\d*$/.test(plz)) {
|
||||||
|
plzFehler = 'Die Postleitzahl darf nur Ziffern enthalten.';
|
||||||
|
} else if (plz.length < 5) {
|
||||||
|
plzFehler = 'Die Postleitzahl muss genau 5 Ziffern haben.';
|
||||||
|
} else if (plz.length > 5) {
|
||||||
|
plzFehler = 'Die Postleitzahl darf maximal 5 Ziffern haben.';
|
||||||
|
} else {
|
||||||
|
plzFehler = 'Bitte gib eine gültige Postleitzahl ein.';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
plzFehler = '';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
plzFehler = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Echtzeit-Validierung: Noten
|
// Echtzeit-Validierung: Noten
|
||||||
$: {
|
$: {
|
||||||
const deutsch = parseInt(noteDeutsch);
|
const deutsch = parseInt(noteDeutsch);
|
||||||
@@ -125,8 +215,18 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prüfen ob Formular gültig ist
|
// Prüfen ob alle erforderlichen Wünsche ausgewählt wurden (abhängig von verfügbaren Dienststellen)
|
||||||
$: formHatFehler = alterFehler !== '' || notenFehler !== '' || sozialverhaltenFehler !== '';
|
$: wuenscheVollstaendig = (() => {
|
||||||
|
const anzahl = filteredDienststellen.length;
|
||||||
|
if (anzahl === 0) return false;
|
||||||
|
if (anzahl === 1) return !!wunsch1Id;
|
||||||
|
if (anzahl === 2) return !!wunsch1Id && !!wunsch2Id;
|
||||||
|
return !!wunsch1Id && !!wunsch2Id && !!wunsch3Id;
|
||||||
|
})();
|
||||||
|
|
||||||
|
// Prüfen ob Formular gültig ist (erweitert um neue Validierungen)
|
||||||
|
$: formHatFehler = alterFehler !== '' || notenFehler !== '' || sozialverhaltenFehler !== '' ||
|
||||||
|
emailFehler !== '' || telefonFehler !== '' || notfallTelefonFehler !== '' || plzFehler !== '';
|
||||||
|
|
||||||
// Dienststellen laden wenn Zeitraum sich ändert
|
// Dienststellen laden wenn Zeitraum sich ändert
|
||||||
async function ladeDienststellen(zeitraumId: string) {
|
async function ladeDienststellen(zeitraumId: string) {
|
||||||
@@ -222,6 +322,10 @@
|
|||||||
alterFehler = '';
|
alterFehler = '';
|
||||||
notenFehler = '';
|
notenFehler = '';
|
||||||
sozialverhaltenFehler = '';
|
sozialverhaltenFehler = '';
|
||||||
|
emailFehler = '';
|
||||||
|
telefonFehler = '';
|
||||||
|
notfallTelefonFehler = '';
|
||||||
|
plzFehler = '';
|
||||||
dienststellen = [];
|
dienststellen = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -300,10 +404,55 @@
|
|||||||
<input bind:value={geburtsdatum} type="date" placeholder="Geburtsdatum" required class="input" />
|
<input bind:value={geburtsdatum} type="date" placeholder="Geburtsdatum" required class="input" />
|
||||||
<input bind:value={strasse} placeholder="Straße" required class="input" />
|
<input bind:value={strasse} placeholder="Straße" required class="input" />
|
||||||
<input bind:value={hausnummer} placeholder="Hausnummer" required class="input" />
|
<input bind:value={hausnummer} placeholder="Hausnummer" required class="input" />
|
||||||
<input bind:value={plz} placeholder="Postleitzahl" required class="input" />
|
|
||||||
|
<!-- PLZ mit Validierung -->
|
||||||
|
<div>
|
||||||
|
<input
|
||||||
|
bind:value={plz}
|
||||||
|
placeholder="Postleitzahl"
|
||||||
|
required
|
||||||
|
class="input"
|
||||||
|
class:input-error={plzFehler}
|
||||||
|
maxlength="5"
|
||||||
|
inputmode="numeric"
|
||||||
|
/>
|
||||||
|
{#if plzFehler}
|
||||||
|
<p class="text-red-600 text-sm mt-1">{plzFehler}</p>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
|
||||||
<input bind:value={ort} placeholder="Ort" required class="input" />
|
<input bind:value={ort} placeholder="Ort" required class="input" />
|
||||||
<input bind:value={telefon} placeholder="Telefonnummer" required class="input col-span-2" />
|
|
||||||
<input bind:value={email} type="email" placeholder="E-Mail-Adresse" required class="input col-span-2" />
|
<!-- Telefonnummer mit Validierung -->
|
||||||
|
<div class="col-span-2">
|
||||||
|
<input
|
||||||
|
bind:value={telefon}
|
||||||
|
type="tel"
|
||||||
|
placeholder="Telefonnummer (z.B. 0511 1234567 oder 0171 1234567)"
|
||||||
|
required
|
||||||
|
class="input"
|
||||||
|
class:input-error={telefonFehler}
|
||||||
|
/>
|
||||||
|
{#if telefonFehler}
|
||||||
|
<p class="text-red-600 text-sm mt-1">{telefonFehler}</p>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- E-Mail mit Validierung -->
|
||||||
|
<div class="col-span-2">
|
||||||
|
<input
|
||||||
|
bind:value={email}
|
||||||
|
type="email"
|
||||||
|
placeholder="E-Mail-Adresse"
|
||||||
|
required
|
||||||
|
class="input"
|
||||||
|
class:input-error={emailFehler}
|
||||||
|
/>
|
||||||
|
{#if emailFehler}
|
||||||
|
<p class="text-red-600 text-sm mt-1">{emailFehler}</p>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
|
||||||
<select bind:value={schulart} required class="input">
|
<select bind:value={schulart} required class="input">
|
||||||
<option value="" disabled selected hidden>Schulart wählen</option>
|
<option value="" disabled selected hidden>Schulart wählen</option>
|
||||||
<option value="Gymnasium">Gymnasium</option>
|
<option value="Gymnasium">Gymnasium</option>
|
||||||
@@ -423,6 +572,22 @@
|
|||||||
Lade verfügbare Dienststellen...
|
Lade verfügbare Dienststellen...
|
||||||
</div>
|
</div>
|
||||||
{:else}
|
{:else}
|
||||||
|
<!-- Hinweis wenn nur begrenzte Auswahl möglich -->
|
||||||
|
{#if zeitraum && filteredDienststellen.length > 0 && filteredDienststellen.length < 3}
|
||||||
|
<div class="p-3 bg-blue-50 border border-blue-200 rounded-xl">
|
||||||
|
<div class="flex items-start">
|
||||||
|
<svg class="w-5 h-5 text-blue-500 mr-2 mt-0.5 flex-shrink-0" fill="currentColor" viewBox="0 0 20 20">
|
||||||
|
<path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a1 1 0 000 2v3a1 1 0 001 1h1a1 1 0 100-2v-3a1 1 0 00-1-1H9z" clip-rule="evenodd" />
|
||||||
|
</svg>
|
||||||
|
<p class="text-sm text-blue-700">
|
||||||
|
Für diesen Zeitraum {filteredDienststellen.length === 1 ? 'ist nur noch 1 Dienststelle' : 'sind nur noch ' + filteredDienststellen.length + ' Dienststellen'} verfügbar.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
<!-- 1. Wunsch - immer anzeigen wenn Dienststellen vorhanden -->
|
||||||
|
{#if filteredDienststellen.length >= 1}
|
||||||
<select bind:value={wunsch1Id} required disabled={!zeitraum} class="input" class:opacity-50={!zeitraum}>
|
<select bind:value={wunsch1Id} required disabled={!zeitraum} class="input" class:opacity-50={!zeitraum}>
|
||||||
<option value="" disabled selected>
|
<option value="" disabled selected>
|
||||||
{zeitraum ? '1. Wunschdienststelle' : 'Bitte zuerst Zeitraum wählen'}
|
{zeitraum ? '1. Wunschdienststelle' : 'Bitte zuerst Zeitraum wählen'}
|
||||||
@@ -431,14 +596,20 @@
|
|||||||
<option value={d.id}>{d.name} ({d.plaetze} {d.plaetze === 1 ? 'Platz' : 'Plätze'} frei)</option>
|
<option value={d.id}>{d.name} ({d.plaetze} {d.plaetze === 1 ? 'Platz' : 'Plätze'} frei)</option>
|
||||||
{/each}
|
{/each}
|
||||||
</select>
|
</select>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
<!-- 2. Wunsch - nur anzeigen wenn mindestens 2 Dienststellen verfügbar -->
|
||||||
|
{#if filteredDienststellen.length >= 2}
|
||||||
<select bind:value={wunsch2Id} required disabled={!zeitraum || !wunsch1Id} class="input" class:opacity-50={!zeitraum || !wunsch1Id}>
|
<select bind:value={wunsch2Id} required disabled={!zeitraum || !wunsch1Id} class="input" class:opacity-50={!zeitraum || !wunsch1Id}>
|
||||||
<option value="" disabled selected>2. Wunschdienststelle</option>
|
<option value="" disabled selected>2. Wunschdienststelle</option>
|
||||||
{#each filteredDienststellen.filter(d => d.id != wunsch1Id) as d}
|
{#each filteredDienststellen.filter(d => d.id != wunsch1Id) as d}
|
||||||
<option value={d.id}>{d.name} ({d.plaetze} {d.plaetze === 1 ? 'Platz' : 'Plätze'} frei)</option>
|
<option value={d.id}>{d.name} ({d.plaetze} {d.plaetze === 1 ? 'Platz' : 'Plätze'} frei)</option>
|
||||||
{/each}
|
{/each}
|
||||||
</select>
|
</select>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
<!-- 3. Wunsch - nur anzeigen wenn mindestens 3 Dienststellen verfügbar -->
|
||||||
|
{#if filteredDienststellen.length >= 3}
|
||||||
<select bind:value={wunsch3Id} required disabled={!zeitraum || !wunsch2Id} class="input" class:opacity-50={!zeitraum || !wunsch2Id}>
|
<select bind:value={wunsch3Id} required disabled={!zeitraum || !wunsch2Id} class="input" class:opacity-50={!zeitraum || !wunsch2Id}>
|
||||||
<option value="" disabled selected>3. Wunschdienststelle</option>
|
<option value="" disabled selected>3. Wunschdienststelle</option>
|
||||||
{#each filteredDienststellen.filter(d => d.id != wunsch1Id && d.id != wunsch2Id) as d}
|
{#each filteredDienststellen.filter(d => d.id != wunsch1Id && d.id != wunsch2Id) as d}
|
||||||
@@ -446,6 +617,7 @@
|
|||||||
{/each}
|
{/each}
|
||||||
</select>
|
</select>
|
||||||
{/if}
|
{/if}
|
||||||
|
{/if}
|
||||||
|
|
||||||
<!-- Hinweis wenn keine Dienststellen verfügbar -->
|
<!-- Hinweis wenn keine Dienststellen verfügbar -->
|
||||||
{#if zeitraum && !isLoadingDienststellen && filteredDienststellen.length === 0}
|
{#if zeitraum && !isLoadingDienststellen && filteredDienststellen.length === 0}
|
||||||
@@ -488,7 +660,21 @@
|
|||||||
<div class="grid grid-cols-2 gap-4">
|
<div class="grid grid-cols-2 gap-4">
|
||||||
<input bind:value={notfallVorname} placeholder="Vorname Notfallkontakt" required class="input" />
|
<input bind:value={notfallVorname} placeholder="Vorname Notfallkontakt" required class="input" />
|
||||||
<input bind:value={notfallNachname} placeholder="Nachname Notfallkontakt" required class="input" />
|
<input bind:value={notfallNachname} placeholder="Nachname Notfallkontakt" required class="input" />
|
||||||
<input bind:value={notfallTelefon} type="tel" placeholder="Mobilnummer Notfallkontakt" required class="input col-span-2" />
|
|
||||||
|
<!-- Notfall-Telefonnummer mit Validierung -->
|
||||||
|
<div class="col-span-2">
|
||||||
|
<input
|
||||||
|
bind:value={notfallTelefon}
|
||||||
|
type="tel"
|
||||||
|
placeholder="Mobilnummer Notfallkontakt (z.B. 0171 1234567)"
|
||||||
|
required
|
||||||
|
class="input"
|
||||||
|
class:input-error={notfallTelefonFehler}
|
||||||
|
/>
|
||||||
|
{#if notfallTelefonFehler}
|
||||||
|
<p class="text-red-600 text-sm mt-1">{notfallTelefonFehler}</p>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -509,13 +695,13 @@
|
|||||||
<!-- Button - deaktiviert bei Validierungsfehlern oder fehlenden Pflichtfeldern -->
|
<!-- Button - deaktiviert bei Validierungsfehlern oder fehlenden Pflichtfeldern -->
|
||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
disabled={formHatFehler || !zeitraum || !wunsch1Id || !wunsch2Id || !wunsch3Id}
|
disabled={formHatFehler || !zeitraum || !wuenscheVollstaendig}
|
||||||
class="w-full py-3 rounded-xl transition-all"
|
class="w-full py-3 rounded-xl transition-all"
|
||||||
class:bg-blue-600={!formHatFehler && zeitraum && wunsch1Id && wunsch2Id && wunsch3Id}
|
class:bg-blue-600={!formHatFehler && zeitraum && wuenscheVollstaendig}
|
||||||
class:hover:bg-blue-700={!formHatFehler && zeitraum && wunsch1Id && wunsch2Id && wunsch3Id}
|
class:hover:bg-blue-700={!formHatFehler && zeitraum && wuenscheVollstaendig}
|
||||||
class:text-white={!formHatFehler && zeitraum && wunsch1Id && wunsch2Id && wunsch3Id}
|
class:text-white={!formHatFehler && zeitraum && wuenscheVollstaendig}
|
||||||
class:bg-gray-400={formHatFehler || !zeitraum || !wunsch1Id || !wunsch2Id || !wunsch3Id}
|
class:bg-gray-400={formHatFehler || !zeitraum || !wuenscheVollstaendig}
|
||||||
class:cursor-not-allowed={formHatFehler || !zeitraum || !wunsch1Id || !wunsch2Id || !wunsch3Id}
|
class:cursor-not-allowed={formHatFehler || !zeitraum || !wuenscheVollstaendig}
|
||||||
>
|
>
|
||||||
Jetzt anmelden
|
Jetzt anmelden
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
Reference in New Issue
Block a user