Files
mareike/app/Domains/Dashboard/Views/PersonalData.vue
T
2026-05-23 18:08:27 +02:00

393 lines
12 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<script setup>
import { reactive, ref } from 'vue'
import { request } from '../../../../resources/js/components/HttpClient.js'
import AppLayout from "../../../../resources/js/layouts/AppLayout.vue";
import ShadowedBox from "../../../Views/Components/ShadowedBox.vue";
import {toast} from "vue3-toastify";
import IbanInput from "../../../Views/Components/IbanInput.vue";
const props = defineProps({
personalData: Object,
})
const form = reactive({
nickname: props.personalData.nickname ?? '',
email: props.personalData.email ?? '',
phone: props.personalData.phone ?? '',
address1: props.personalData.address1 ?? '',
address2: props.personalData.address2 ?? '',
postcode: props.personalData.postcode ?? '',
city: props.personalData.city ?? '',
birthday: props.personalData.birthday ?? '',
tetanusVaccination: props.personalData.tetanusVaccination ?? '',
medications: props.personalData.medications ?? '',
allergies: props.personalData.allergies ?? '',
intolerances: props.personalData.intolerances ?? '',
eatingHabits: props.personalData.eatingHabits ?? '',
swimmingPermission: props.personalData.swimmingPermission ?? '',
firstAidPermission: props.personalData.firstAidPermission ?? '',
bankAccountOwner: props.personalData.bankAccountOwner ?? '',
bankAccountIban: props.personalData.bankAccountIban ?? '',
})
const saving = ref(false)
const successMessage = ref('')
const errorMessage = ref('')
const submit = async () => {
saving.value = true
successMessage.value = ''
errorMessage.value = ''
const result = await request('/api/v1/dashboard/personal-data', {
method: 'POST',
body: { ...form },
})
saving.value = false
if (result?.success) {
toast.success(result.message)
} else {
toast.error(result.message)
}
}
</script>
<template>
<AppLayout title='Persönliche Daten'>
<shadowed-box class="personal-data-box">
<form @submit.prevent="submit">
<!-- Sektion: Stammdaten -->
<fieldset class="pd-fieldset">
<legend>Stammdaten</legend>
<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>
<div class="pd-field">
<label for="nickname">Pfadiname</label>
<input id="nickname" type="text" v-model="form.nickname" />
</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>
.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: 8px 10px;
border: 1px solid #d1d5db;
border-radius: 6px;
font-size: 0.95rem;
box-sizing: border-box;
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>