278 lines
8.3 KiB
Vue
278 lines
8.3 KiB
Vue
<script setup>
|
|
import { useSignupForm } from './composables/useSignupForm.js'
|
|
import StepAge from './steps/StepAge.vue'
|
|
import StepContactPerson from './steps/StepContactPerson.vue'
|
|
import StepPersonalData from './steps/StepPersonalData.vue'
|
|
import StepRegistrationMode from './steps/StepRegistrationMode.vue'
|
|
import StepArrival from './steps/StepArrival.vue'
|
|
import StepAddons from './steps/StepAddons.vue'
|
|
import StepPhotoPermissions from './steps/StepPhotoPermissions.vue'
|
|
import StepAllergies from './steps/StepAllergies.vue'
|
|
import StepSummary from './steps/StepSummary.vue'
|
|
import SubmitSuccess from './after-submit/SubmitSuccess.vue'
|
|
import SubmitAlreadyExists from './after-submit/SubmitAlreadyExists.vue'
|
|
|
|
const props = defineProps({
|
|
event: Object,
|
|
participantData: Object,
|
|
localGroups: Array,
|
|
})
|
|
|
|
const emit = defineEmits(['registrationDone'])
|
|
|
|
const {
|
|
currentStep, goToStep, formData, selectedAddons,
|
|
submit, submitting, submitResult, summaryLoading, summaryAmount
|
|
} = useSignupForm(props.event, props.participantData)
|
|
|
|
const steps = [
|
|
{ step: 1, label: 'Alter' },
|
|
{ step: 2, label: 'Kontaktperson' },
|
|
{ step: 3, label: 'Persönliche Daten' },
|
|
{ step: 4, label: 'An-/Abreise' },
|
|
{ step: 5, label: 'Teilnahmegruppe' },
|
|
{ step: 6, label: 'Zusatzoptionen' },
|
|
{ step: 7, label: 'Fotoerlaubnis' },
|
|
{ step: 8, label: 'Allergien' },
|
|
{ step: 9, label: 'Zusammenfassung' },
|
|
]
|
|
</script>
|
|
|
|
<template>
|
|
<div>
|
|
<!-- Nach Submit -->
|
|
<SubmitSuccess
|
|
v-if="submitResult?.status === 'success'"
|
|
:participant="submitResult?.participant"
|
|
:event="event"
|
|
/>
|
|
<SubmitAlreadyExists v-else-if="submitResult?.status === 'exists'" :event="event" />
|
|
|
|
<template v-else>
|
|
<!-- Fortschrittsleiste (ab Step 2) -->
|
|
<div v-if="currentStep > 1" class="signup-progress">
|
|
<div class="signup-progress-pills">
|
|
<template v-for="(s, index) in steps.filter(s => s.step > 1)" :key="s.step">
|
|
<div v-if="index > 0" class="signup-progress-separator"></div>
|
|
<div
|
|
class="signup-pill"
|
|
:class="{
|
|
'signup-pill--active': currentStep === s.step,
|
|
'signup-pill--done': currentStep > s.step,
|
|
'signup-pill--upcoming': currentStep < s.step,
|
|
}"
|
|
@click="currentStep > s.step ? goToStep(s.step) : null"
|
|
>
|
|
<span v-if="currentStep > s.step" class="signup-pill__check">✓</span>
|
|
{{ s.label }}
|
|
</div>
|
|
</template>
|
|
</div>
|
|
<!-- Fortschrittsbalken -->
|
|
<div class="signup-progress-bar">
|
|
<div
|
|
class="signup-progress-bar__fill"
|
|
:style="{ width: ((currentStep - 2) / (steps.length - 2) * 100) + '%' }"
|
|
></div>
|
|
</div>
|
|
|
|
<!-- Mobile Step-Anzeige -->
|
|
<div class="signup-progress-mobile">
|
|
Schritt {{ currentStep - 1 }} von {{ steps.length - 1 }}:
|
|
<strong>{{ steps.find(s => s.step === currentStep)?.label }}</strong>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Steps -->
|
|
<form @submit.prevent="submit">
|
|
<StepAge v-if="currentStep === 1" :event="event" @next="goToStep" />
|
|
<StepContactPerson v-if="currentStep === 2" :formData="formData" :event="event" @next="goToStep" @back="goToStep" />
|
|
<StepPersonalData v-if="currentStep === 3" :formData="formData" :localGroups="localGroups" @next="goToStep" @back="goToStep" />
|
|
<StepArrival v-if="currentStep === 4" :formData="formData" :event="event" @next="goToStep" @back="goToStep" />
|
|
<StepRegistrationMode v-if="currentStep === 5" :formData="formData" :event="event" @next="goToStep" @back="goToStep" />
|
|
<StepAddons v-if="currentStep === 6" :formData="formData" :event="event" :selectedAddons="selectedAddons" @next="goToStep" @back="goToStep" />
|
|
<StepPhotoPermissions v-if="currentStep === 7" :formData="formData" :event="event" @next="goToStep" @back="goToStep" />
|
|
<StepAllergies v-if="currentStep === 8" :formData="formData" :event="event" @next="goToStep" @back="goToStep" />
|
|
<StepSummary
|
|
v-if="currentStep === 9"
|
|
:formData="formData"
|
|
:event="event"
|
|
:summaryAmount="summaryAmount"
|
|
:summaryLoading="summaryLoading"
|
|
:submitting="submitting"
|
|
@back="goToStep"
|
|
@submit="submit"
|
|
/>
|
|
</form>
|
|
</template>
|
|
</div>
|
|
</template>
|
|
|
|
<style>
|
|
/* ─── Progress (Step-Pills) ─── */
|
|
.signup-progress {
|
|
margin-bottom: 28px;
|
|
}
|
|
|
|
.signup-progress-pills {
|
|
display: flex;
|
|
gap: 6px;
|
|
flex-wrap: wrap;
|
|
align-items: center;
|
|
}
|
|
|
|
.signup-progress-separator {
|
|
flex-shrink: 0;
|
|
width: 16px;
|
|
height: 2px;
|
|
background: #e5e7eb;
|
|
border-radius: 1px;
|
|
}
|
|
|
|
.signup-pill {
|
|
padding: 5px 14px;
|
|
border-radius: 999px;
|
|
font-size: 0.78rem;
|
|
font-weight: 600;
|
|
white-space: nowrap;
|
|
border: 2px solid;
|
|
cursor: default;
|
|
}
|
|
|
|
.signup-pill__check { margin-right: 4px; }
|
|
|
|
.signup-pill--active {
|
|
border-color: #2563eb;
|
|
background: #2563eb;
|
|
color: white;
|
|
}
|
|
|
|
.signup-pill--done {
|
|
border-color: #bbf7d0;
|
|
background: #f0fdf4;
|
|
color: #15803d;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.signup-pill--upcoming {
|
|
border-color: #e5e7eb;
|
|
background: #f9fafb;
|
|
color: #9ca3af;
|
|
}
|
|
|
|
.signup-progress-bar {
|
|
margin-top: 10px;
|
|
height: 3px;
|
|
background: #e5e7eb;
|
|
border-radius: 2px;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.signup-progress-bar__fill {
|
|
height: 100%;
|
|
background: linear-gradient(90deg, #2563eb, #3b82f6);
|
|
border-radius: 2px;
|
|
transition: width 0.3s ease;
|
|
}
|
|
|
|
.signup-progress-mobile {
|
|
display: none;
|
|
margin-top: 8px;
|
|
font-size: 0.9rem;
|
|
color: #374151;
|
|
}
|
|
|
|
/* ─── Form-Table ─── */
|
|
.form-table { width: 100%; border-collapse: collapse; }
|
|
.form-table td { padding: 8px 12px 8px 0; vertical-align: top; }
|
|
.form-table td:first-child { width: 220px; color: #374151; font-weight: 500; }
|
|
.form-table input[type="text"],
|
|
.form-table input[type="date"],
|
|
.form-table input[type="email"],
|
|
.form-table input[type="number"],
|
|
.form-table select,
|
|
.form-table textarea {
|
|
width: 100%;
|
|
padding: 6px 10px;
|
|
border: 1px solid #d1d5db;
|
|
border-radius: 6px;
|
|
font-size: 0.95rem;
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
.btn-row { display: flex; gap: 10px; padding-top: 16px; flex-wrap: wrap; }
|
|
.btn-primary {
|
|
padding: 8px 20px;
|
|
background: #2563eb;
|
|
color: white;
|
|
border: none;
|
|
border-radius: 8px;
|
|
font-weight: 600;
|
|
cursor: pointer;
|
|
}
|
|
.btn-primary:disabled { opacity: 0.5; cursor: not-allowed; }
|
|
.btn-secondary {
|
|
padding: 8px 20px;
|
|
background: #f3f4f6;
|
|
color: #374151;
|
|
border: 1px solid #d1d5db;
|
|
border-radius: 8px;
|
|
font-weight: 600;
|
|
cursor: pointer;
|
|
}
|
|
|
|
/* ─── Tablet ─── */
|
|
@media (max-width: 1023px) {
|
|
.form-table td:first-child {
|
|
width: 160px;
|
|
}
|
|
}
|
|
|
|
/* ─── Smartphone ─── */
|
|
@media (max-width: 639px) {
|
|
/* Pills auf Mobile: kompakter, Trennstriche ausblenden */
|
|
.signup-progress-pills {
|
|
display: none;
|
|
}
|
|
.signup-progress-mobile {
|
|
display: block;
|
|
}
|
|
|
|
/* Form-Table: Label oberhalb des Feldes */
|
|
.form-table,
|
|
.form-table tbody,
|
|
.form-table tr {
|
|
display: block;
|
|
width: 100%;
|
|
}
|
|
|
|
.form-table td {
|
|
display: block;
|
|
width: 100% !important;
|
|
padding: 4px 0;
|
|
}
|
|
|
|
.form-table td:first-child {
|
|
width: 100% !important;
|
|
font-weight: 600;
|
|
color: #374151;
|
|
padding-top: 10px;
|
|
}
|
|
|
|
.form-table td[colspan] {
|
|
width: 100% !important;
|
|
}
|
|
|
|
.btn-row {
|
|
flex-direction: column-reverse;
|
|
gap: 8px;
|
|
}
|
|
|
|
.btn-primary,
|
|
.btn-secondary {
|
|
width: 100%;
|
|
padding: 12px 20px;
|
|
}
|
|
}
|
|
</style>
|