New Responsive design

This commit is contained in:
2026-05-23 18:08:27 +02:00
parent 3fdbaf0285
commit 0d436d8190
19 changed files with 2152 additions and 607 deletions
+317 -112
View File
@@ -56,132 +56,337 @@ const submit = async () => {
<template>
<AppLayout title='Persönliche Daten'>
<shadowed-box style="width: 95%; margin: 20px auto; padding: 20px; overflow-x: hidden;">
<shadowed-box class="personal-data-box">
<div class="max-w-2xl mx-auto p-6">
<form @submit.prevent="submit">
<table class="form-table" style="width: 90%; margin: 10px;">
<form @submit.prevent="submit">
<!-- Sektion: Stammdaten -->
<fieldset class="pd-fieldset">
<legend>Stammdaten</legend>
<!-- Nicht veränderbare Felder -->
<tr>
<td style="width: 200px; padding: 5px;">Vorname:</td>
<td><span class="text-gray-700">{{ personalData.firstname }}</span></td>
</tr>
<tr>
<td style="width: 200px; padding: 5px;">Nachname:</td>
<td><span class="text-gray-700">{{ personalData.lastname }}</span></td>
</tr>
<div class="pd-grid">
<div class="pd-field pd-field--readonly">
<label>Vorname</label>
<div class="pd-readonly">{{ personalData.firstname }}</div>
</div>
<div class="pd-field pd-field--readonly">
<label>Nachname</label>
<div class="pd-readonly">{{ personalData.lastname }}</div>
</div>
<!-- Veränderbare Felder -->
<tr>
<td>Pfadiname:</td>
<td><input type="text" v-model="form.nickname" /></td>
</tr>
<tr>
<td>E-Mail:</td>
<td><input type="email" v-model="form.email" /></td>
</tr>
<tr>
<td>Telefon:</td>
<td><input type="text" v-model="form.phone" /></td>
</tr>
<tr>
<td>Straße / Hausnummer:</td>
<td><input type="text" v-model="form.address1" /></td>
</tr>
<tr>
<td>Adresszusatz:</td>
<td><input type="text" v-model="form.address2" /></td>
</tr>
<tr>
<td>PLZ:</td>
<td><input type="text" v-model="form.postcode" /></td>
</tr>
<tr>
<td>Ort:</td>
<td><input type="text" v-model="form.city" /></td>
</tr>
<tr>
<td style="width: 200px; padding: 5px;">Geburtsdatum:</td>
<td><input type="date" v-model="form.birthday" /></td>
</tr>
<tr>
<td>Medikamente:</td>
<td><input type="text" v-model="form.medications" /></td>
</tr>
<tr>
<td>Allergien:</td>
<td><input type="text" v-model="form.allergies" /></td>
</tr>
<tr>
<td>Unverträglichkeiten:</td>
<td><input type="text" v-model="form.intolerances" /></td>
</tr>
<tr>
<td>Letzte Tetanus-Impfung:</td>
<td><input type="date" v-model="form.tetanusVaccination" /></td>
</tr>
<tr>
<td>Ernährungsgewohnheiten:</td>
<td>
<select v-model="form.eatingHabits">
<option value="EATING_HABIT_VEGAN">Vegan</option>
<option value="EATING_HABIT_VEGETARIAN">Vegetarisch</option>
<option value="EATING_HABIT_OMNIVOR">Omnivor</option>
</select>
</td>
</tr>
<tr>
<td>Badeerlaubnis:</td>
<td>
<select v-model="form.swimmingPermission">
<option value="SWIMMING_PERMISSION_ALLOWED">Erteilt, kann schwimmen</option>
<option value="SWIMMING_PERMISSION_LIMITED">Erteilt, kann nicht schwimmen</option>
<option value="SWIMMING_PERMISSION_DENIED">Nicht erteilt</option>
</select>
</td>
</tr>
<tr>
<td>Erste-Hilfe-Erlaubnis:</td>
<td>
<select v-model="form.firstAidPermission">
<option value="FIRST_AID_PERMISSION_ALLOWED">Erweiterte Erste Hilfe erlaubt</option>
<option value="FIRST_AID_PERMISSION_DENIED">Erweiterte Erste Hilfe verweigert</option>
</select>
</td>
</tr>
<tr>
<td>Kontoinhaber*in:</td>
<td><input type="text" v-model="form.bankAccountOwner" /></td>
</tr>
<tr>
<td>IBAN:</td>
<td><IbanInput v-model="form.bankAccountIban" /></td>
</tr>
<div class="pd-field">
<label for="nickname">Pfadiname</label>
<input id="nickname" type="text" v-model="form.nickname" />
</div>
<tr>
<td colspan="2" class="btn-row" style="padding-top: 20px;">
<button type="submit" class="button" :disabled="saving">
{{ saving ? 'Wird gespeichert…' : 'Speichern' }}
</button>
</td>
</tr>
</table>
</form>
</div>
<div class="pd-field">
<label for="birthday">Geburtsdatum</label>
<input id="birthday" type="date" v-model="form.birthday" />
</div>
</div>
</fieldset>
<!-- Sektion: Kontakt -->
<fieldset class="pd-fieldset">
<legend>Kontakt</legend>
<div class="pd-grid">
<div class="pd-field">
<label for="email">E-Mail</label>
<input id="email" type="email" v-model="form.email" />
</div>
<div class="pd-field">
<label for="phone">Telefon</label>
<input id="phone" type="text" v-model="form.phone" />
</div>
<div class="pd-field pd-field--full">
<label for="address1">Straße / Hausnummer</label>
<input id="address1" type="text" v-model="form.address1" />
</div>
<div class="pd-field pd-field--full">
<label for="address2">Adresszusatz</label>
<input id="address2" type="text" v-model="form.address2" />
</div>
<div class="pd-field pd-field--narrow">
<label for="postcode">PLZ</label>
<input id="postcode" type="text" v-model="form.postcode" maxlength="5" />
</div>
<div class="pd-field pd-field--wide">
<label for="city">Ort</label>
<input id="city" type="text" v-model="form.city" />
</div>
</div>
</fieldset>
<!-- Sektion: Gesundheit -->
<fieldset class="pd-fieldset">
<legend>Gesundheit</legend>
<div class="pd-grid">
<div class="pd-field pd-field--full">
<label for="medications">Medikamente</label>
<input id="medications" type="text" v-model="form.medications" />
</div>
<div class="pd-field pd-field--full">
<label for="allergies">Allergien</label>
<input id="allergies" type="text" v-model="form.allergies" />
</div>
<div class="pd-field pd-field--full">
<label for="intolerances">Unverträglichkeiten</label>
<input id="intolerances" type="text" v-model="form.intolerances" />
</div>
<div class="pd-field">
<label for="tetanus">Letzte Tetanus-Impfung</label>
<input id="tetanus" type="date" v-model="form.tetanusVaccination" />
</div>
<div class="pd-field">
<label for="eating">Ernährungsgewohnheiten</label>
<select id="eating" v-model="form.eatingHabits">
<option value="EATING_HABIT_VEGAN">Vegan</option>
<option value="EATING_HABIT_VEGETARIAN">Vegetarisch</option>
<option value="EATING_HABIT_OMNIVOR">Omnivor</option>
</select>
</div>
</div>
</fieldset>
<!-- Sektion: Erlaubnisse -->
<fieldset class="pd-fieldset">
<legend>Erlaubnisse</legend>
<div class="pd-grid">
<div class="pd-field pd-field--full">
<label for="swimming">Badeerlaubnis</label>
<select id="swimming" v-model="form.swimmingPermission">
<option value="SWIMMING_PERMISSION_ALLOWED">Erteilt, kann schwimmen</option>
<option value="SWIMMING_PERMISSION_LIMITED">Erteilt, kann nicht schwimmen</option>
<option value="SWIMMING_PERMISSION_DENIED">Nicht erteilt</option>
</select>
</div>
<div class="pd-field pd-field--full">
<label for="firstaid">Erste-Hilfe-Erlaubnis</label>
<select id="firstaid" v-model="form.firstAidPermission">
<option value="FIRST_AID_PERMISSION_ALLOWED">Erweiterte Erste Hilfe erlaubt</option>
<option value="FIRST_AID_PERMISSION_DENIED">Erweiterte Erste Hilfe verweigert</option>
</select>
</div>
</div>
</fieldset>
<!-- Sektion: Bankverbindung -->
<fieldset class="pd-fieldset">
<legend>Bankverbindung</legend>
<div class="pd-grid">
<div class="pd-field pd-field--full">
<label for="owner">Kontoinhaber*in</label>
<input id="owner" type="text" v-model="form.bankAccountOwner" />
</div>
<div class="pd-field pd-field--full">
<label for="iban">IBAN</label>
<IbanInput id="iban" v-model="form.bankAccountIban" />
</div>
</div>
</fieldset>
<div class="pd-actions">
<button type="submit" class="button pd-submit" :disabled="saving">
{{ saving ? 'Wird gespeichert…' : 'Speichern' }}
</button>
</div>
</form>
</shadowed-box>
</AppLayout>
</template>
<style scoped>
textarea {
.personal-data-box {
width: 95%;
margin: 20px auto;
padding: 20px;
overflow-x: hidden;
}
.pd-fieldset {
border: 1px solid #e5e7eb;
border-radius: 10px;
padding: 16px 20px 20px;
margin-bottom: 18px;
background-color: #ffffff;
box-shadow: 0 0 8px #efefef;
}
.pd-fieldset legend {
font-weight: 700;
font-size: 1rem;
padding: 4px 12px;
background-color: #f8fafc;
border: 1px solid #e5e7eb;
border-radius: 8px;
color: #1d4899;
}
/* Grid: 2-spaltig auf Desktop */
.pd-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 14px 20px;
}
.pd-field {
display: flex;
flex-direction: column;
gap: 4px;
min-width: 0;
}
.pd-field--full {
grid-column: 1 / -1;
}
.pd-field--narrow {
grid-column: span 1;
max-width: 180px;
}
.pd-field--wide {
grid-column: span 1;
}
.pd-field label {
font-size: 0.85rem;
font-weight: 600;
color: #374151;
}
.pd-field input,
.pd-field select {
width: 100%;
padding: 6px 10px;
padding: 8px 10px;
border: 1px solid #d1d5db;
border-radius: 6px;
font-size: 0.95rem;
box-sizing: border-box;
resize: vertical;
background-color: #ffffff;
}
.pd-field input:focus,
.pd-field select:focus {
outline: none;
border-color: #1d4899;
}
.pd-readonly {
padding: 8px 10px;
border: 1px dashed #e5e7eb;
border-radius: 6px;
background-color: #f9fafb;
color: #6b7280;
font-size: 0.95rem;
}
.pd-actions {
display: flex;
justify-content: flex-end;
padding-top: 8px;
}
.pd-submit {
padding: 10px 28px;
font-weight: 600;
cursor: pointer;
border: 1px solid #809dd5;
background-color: #ffffff;
}
.pd-submit:hover:not(:disabled) {
background-color: #1d4899;
color: #ffffff;
}
.pd-submit:disabled {
opacity: 0.6;
cursor: not-allowed;
}
/* ─── Tablet (6401023px) ─── */
@media (max-width: 1023px) {
.personal-data-box {
width: 100%;
margin: 10px auto;
padding: 14px;
}
.pd-fieldset {
padding: 12px 14px 16px;
}
.pd-grid {
gap: 12px 16px;
}
}
/* ─── Smartphone (< 640px) ─── */
@media (max-width: 639px) {
.personal-data-box {
width: 100%;
margin: 0;
padding: 10px;
border-radius: 0;
}
.pd-fieldset {
padding: 10px 12px 14px;
margin-bottom: 14px;
}
.pd-fieldset legend {
font-size: 0.9rem;
padding: 3px 10px;
}
/* Grid: 1-spaltig auf Smartphone */
.pd-grid {
grid-template-columns: 1fr;
gap: 10px;
}
/* Auch "narrow" und "wide" werden volle Breite */
.pd-field--narrow,
.pd-field--wide,
.pd-field--full {
grid-column: 1 / -1;
max-width: 100%;
}
.pd-field label {
font-size: 0.82rem;
}
.pd-field input,
.pd-field select {
padding: 10px;
font-size: 1rem; /* iOS Zoom-Prevention bei >=16px */
}
.pd-actions {
justify-content: stretch;
}
.pd-submit {
width: 100%;
padding: 14px;
}
}
</style>