membership: refactor form filling, add smoke tests and debug-guard fallback; fix mappings
This commit is contained in:
@@ -4,11 +4,66 @@
|
||||
<h1 class="text-4xl sm:text-5xl font-display font-bold text-gray-900 mb-6">
|
||||
Mitgliedschaft
|
||||
</h1>
|
||||
<div class="w-24 h-1 bg-primary-600 mb-8" />
|
||||
|
||||
<div class="w-24 h-1 bg-primary-600 mb-8"></div>
|
||||
|
||||
<!-- Mitgliedschaftspläne (ohne "Noch Fragen" Box) -->
|
||||
<div class="mb-12">
|
||||
<MembershipNoQuestions />
|
||||
<section id="membership" class="py-16 sm:py-20 bg-gradient-to-b from-gray-50 to-white">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div class="text-center mb-16">
|
||||
<h2 class="text-4xl sm:text-5xl font-display font-bold text-gray-900 mb-4">
|
||||
Mitgliedschaft
|
||||
</h2>
|
||||
<div class="w-24 h-1 bg-primary-600 mx-auto mb-6"></div>
|
||||
<p class="text-xl text-gray-600 max-w-3xl mx-auto">
|
||||
Werden Sie Teil unserer Tischtennis-Familie - Wählen Sie die passende Mitgliedschaft für sich
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="grid md:grid-cols-3 gap-8 max-w-6xl mx-auto">
|
||||
<!-- Mitgliedschaftspläne werden dynamisch geladen -->
|
||||
</div>
|
||||
|
||||
<!-- Satzung Download -->
|
||||
<div class="mt-16 bg-white rounded-2xl shadow-xl p-8 border border-gray-100">
|
||||
<div class="text-center mb-8">
|
||||
<h3 class="text-3xl font-display font-bold text-gray-900 mb-4">
|
||||
Vereinsatzung
|
||||
</h3>
|
||||
<p class="text-xl text-gray-600">
|
||||
Laden Sie unsere aktuelle Vereinsatzung herunter
|
||||
</p>
|
||||
</div>
|
||||
<div class="flex flex-col sm:flex-row gap-4 justify-center items-center">
|
||||
<a
|
||||
href="/documents/satzung.pdf"
|
||||
target="_blank"
|
||||
class="inline-flex items-center px-6 py-3 bg-primary-600 hover:bg-primary-700 text-white font-semibold rounded-lg transition-colors"
|
||||
>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" size="20" class="lucide lucide-file-text-icon mr-2">
|
||||
<path d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"></path>
|
||||
<path d="M14 2v4a2 2 0 0 0 2 2h4"></path>
|
||||
<path d="M10 9H8"></path>
|
||||
<path d="M16 13H8"></path>
|
||||
<path d="M16 17H8"></path>
|
||||
</svg>
|
||||
Satzung herunterladen (PDF)
|
||||
</a>
|
||||
<span class="text-sm text-gray-500">oder</span>
|
||||
<a
|
||||
href="/satzung"
|
||||
class="inline-flex items-center px-6 py-3 bg-gray-100 hover:bg-gray-200 text-gray-900 font-semibold rounded-lg transition-colors"
|
||||
>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" size="20" class="lucide lucide-eye-icon mr-2">
|
||||
<path d="M2 12s3-7 10-7 10 7 10 7-3 7-10 7-10-7-10-7Z"></path>
|
||||
<circle cx="12" cy="12" r="3"></circle>
|
||||
</svg>
|
||||
Online ansehen
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<!-- Aufnahmeantrag Formular -->
|
||||
@@ -17,7 +72,7 @@
|
||||
Beitrittserklärung
|
||||
</h2>
|
||||
|
||||
<form @submit.prevent="submitForm" class="space-y-8">
|
||||
<form id="membershipForm" class="space-y-8">
|
||||
<!-- Persönliche Daten -->
|
||||
<div class="space-y-6">
|
||||
<h3 class="text-xl font-semibold text-gray-900 border-b border-gray-200 pb-2">
|
||||
@@ -32,13 +87,12 @@
|
||||
<p class="text-xs text-gray-500 italic mb-2">Pflichtfeld</p>
|
||||
<input
|
||||
id="nachname"
|
||||
v-model="form.nachname"
|
||||
name="nachname"
|
||||
type="text"
|
||||
required
|
||||
class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary-500 focus:border-primary-500"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="vorname" class="block text-sm font-medium text-gray-700 mb-2">
|
||||
Vorname
|
||||
@@ -46,14 +100,14 @@
|
||||
<p class="text-xs text-gray-500 italic mb-2">Pflichtfeld</p>
|
||||
<input
|
||||
id="vorname"
|
||||
v-model="form.vorname"
|
||||
name="vorname"
|
||||
type="text"
|
||||
required
|
||||
class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary-500 focus:border-primary-500"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div>
|
||||
<label for="strasse" class="block text-sm font-medium text-gray-700 mb-2">
|
||||
Straße und Hausnummer
|
||||
@@ -61,13 +115,13 @@
|
||||
<p class="text-xs text-gray-500 italic mb-2">Pflichtfeld</p>
|
||||
<input
|
||||
id="strasse"
|
||||
v-model="form.strasse"
|
||||
name="strasse"
|
||||
type="text"
|
||||
required
|
||||
class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary-500 focus:border-primary-500"
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
<div>
|
||||
<label for="plz" class="block text-sm font-medium text-gray-700 mb-2">
|
||||
@@ -76,14 +130,13 @@
|
||||
<p class="text-xs text-gray-500 italic mb-2">Pflichtfeld</p>
|
||||
<input
|
||||
id="plz"
|
||||
v-model="form.plz"
|
||||
name="plz"
|
||||
type="text"
|
||||
required
|
||||
pattern="[0-9]{5}"
|
||||
class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary-500 focus:border-primary-500"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="ort" class="block text-sm font-medium text-gray-700 mb-2">
|
||||
Wohnort
|
||||
@@ -91,14 +144,14 @@
|
||||
<p class="text-xs text-gray-500 italic mb-2">Pflichtfeld</p>
|
||||
<input
|
||||
id="ort"
|
||||
v-model="form.ort"
|
||||
name="ort"
|
||||
type="text"
|
||||
required
|
||||
class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary-500 focus:border-primary-500"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
<div>
|
||||
<label for="geburtsdatum" class="block text-sm font-medium text-gray-700 mb-2">
|
||||
@@ -107,26 +160,25 @@
|
||||
<p class="text-xs text-gray-500 italic mb-2">Pflichtfeld</p>
|
||||
<input
|
||||
id="geburtsdatum"
|
||||
v-model="form.geburtsdatum"
|
||||
name="geburtsdatum"
|
||||
type="date"
|
||||
required
|
||||
class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary-500 focus:border-primary-500"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="telefon_privat" class="block text-sm font-medium text-gray-700 mb-2">
|
||||
Telefon (privat)
|
||||
</label>
|
||||
<input
|
||||
id="telefon_privat"
|
||||
v-model="form.telefon_privat"
|
||||
name="telefon_privat"
|
||||
type="tel"
|
||||
class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary-500 focus:border-primary-500"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
<div>
|
||||
<label for="email" class="block text-sm font-medium text-gray-700 mb-2">
|
||||
@@ -135,20 +187,19 @@
|
||||
<p class="text-xs text-gray-500 italic mb-2">Pflichtfeld</p>
|
||||
<input
|
||||
id="email"
|
||||
v-model="form.email"
|
||||
name="email"
|
||||
type="email"
|
||||
required
|
||||
class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary-500 focus:border-primary-500"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="telefon_mobil" class="block text-sm font-medium text-gray-700 mb-2">
|
||||
Telefon (Mobil)
|
||||
</label>
|
||||
<input
|
||||
id="telefon_mobil"
|
||||
v-model="form.telefon_mobil"
|
||||
name="telefon_mobil"
|
||||
type="tel"
|
||||
class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary-500 focus:border-primary-500"
|
||||
/>
|
||||
@@ -161,21 +212,20 @@
|
||||
<h3 class="text-xl font-semibold text-gray-900 border-b border-gray-200 pb-2">
|
||||
Mitgliedschaftsart
|
||||
</h3>
|
||||
|
||||
<div class="space-y-3">
|
||||
<label class="flex items-center">
|
||||
<input
|
||||
v-model="form.mitgliedschaftsart"
|
||||
name="mitgliedschaftsart"
|
||||
type="radio"
|
||||
value="aktiv"
|
||||
checked
|
||||
class="mr-3 text-primary-600 focus:ring-primary-500"
|
||||
/>
|
||||
<span class="text-gray-700">Aktives Mitglied</span>
|
||||
</label>
|
||||
|
||||
<label class="flex items-center">
|
||||
<input
|
||||
v-model="form.mitgliedschaftsart"
|
||||
name="mitgliedschaftsart"
|
||||
type="radio"
|
||||
value="passiv"
|
||||
class="mr-3 text-primary-600 focus:ring-primary-500"
|
||||
@@ -190,7 +240,6 @@
|
||||
<h3 class="text-xl font-semibold text-gray-900 border-b border-gray-200 pb-2">
|
||||
Beitragszahlung
|
||||
</h3>
|
||||
|
||||
<div class="bg-gray-50 p-4 rounded-lg">
|
||||
<p class="text-gray-700 mb-4">
|
||||
Den derzeitigen jährlichen Mitgliedsbeitrag in Höhe von:
|
||||
@@ -204,10 +253,9 @@
|
||||
bitte ich per Lastschrift jährlich von meinem Konto einzuziehen.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<label class="flex items-start">
|
||||
<input
|
||||
v-model="form.lastschrift_erlaubt"
|
||||
name="lastschrift_erlaubt"
|
||||
type="checkbox"
|
||||
required
|
||||
class="mr-3 mt-1 text-primary-600 focus:ring-primary-500"
|
||||
@@ -234,7 +282,7 @@
|
||||
<p class="text-xs text-gray-500 italic mb-2">Pflichtfeld</p>
|
||||
<input
|
||||
id="kontoinhaber"
|
||||
v-model="form.kontoinhaber"
|
||||
name="kontoinhaber"
|
||||
type="text"
|
||||
required
|
||||
class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary-500 focus:border-primary-500"
|
||||
@@ -248,7 +296,7 @@
|
||||
<p class="text-xs text-gray-500 italic mb-2">Pflichtfeld</p>
|
||||
<input
|
||||
id="iban"
|
||||
v-model="form.iban"
|
||||
name="iban"
|
||||
type="text"
|
||||
required
|
||||
placeholder="DE89 3704 0044 0532 0130 00"
|
||||
@@ -262,7 +310,7 @@
|
||||
</label>
|
||||
<input
|
||||
id="bic"
|
||||
v-model="form.bic"
|
||||
name="bic"
|
||||
type="text"
|
||||
placeholder="COBADEFFXXX"
|
||||
class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary-500 focus:border-primary-500"
|
||||
@@ -275,7 +323,7 @@
|
||||
</label>
|
||||
<input
|
||||
id="bank"
|
||||
v-model="form.bank"
|
||||
name="bank"
|
||||
type="text"
|
||||
class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary-500 focus:border-primary-500"
|
||||
/>
|
||||
@@ -287,7 +335,6 @@
|
||||
<h3 class="text-xl font-semibold text-gray-900 border-b border-gray-200 pb-2">
|
||||
Datenschutz und Einverständniserklärung
|
||||
</h3>
|
||||
|
||||
<div class="bg-blue-50 p-4 rounded-lg">
|
||||
<p class="text-sm text-gray-700 mb-4">
|
||||
Der Vereinsvorstand weist darauf hin, dass ausreichende technische Maßnahmen zur Gewährleistung des Datenschutzes getroffen wurden. Dennoch kann bei einer Veröffentlichung von personenbezogenen Mitgliederdaten im Internet ein umfassender Datenschutz nicht garantiert werden.
|
||||
@@ -295,7 +342,7 @@
|
||||
|
||||
<label class="flex items-start">
|
||||
<input
|
||||
v-model="form.datenschutz_einverstanden"
|
||||
name="datenschutz_einverstanden"
|
||||
type="checkbox"
|
||||
required
|
||||
class="mr-3 mt-1 text-primary-600 focus:ring-primary-500"
|
||||
@@ -315,10 +362,9 @@
|
||||
<h3 class="text-xl font-semibold text-gray-900 border-b border-gray-200 pb-2">
|
||||
Vereinssatzung
|
||||
</h3>
|
||||
|
||||
<label class="flex items-start">
|
||||
<input
|
||||
v-model="form.satzung_anerkannt"
|
||||
name="satzung_anerkannt"
|
||||
type="checkbox"
|
||||
required
|
||||
class="mr-3 mt-1 text-primary-600 focus:ring-primary-500"
|
||||
@@ -346,9 +392,8 @@
|
||||
<div class="flex flex-col sm:flex-row gap-4 justify-center pt-6">
|
||||
<button
|
||||
type="button"
|
||||
@click="fillWithDummyData"
|
||||
:disabled="isGenerating"
|
||||
class="px-6 py-3 bg-gray-600 hover:bg-gray-700 disabled:bg-gray-400 disabled:cursor-not-allowed text-white font-semibold rounded-lg transition-colors flex items-center justify-center"
|
||||
id="fillDummyData"
|
||||
class="px-6 py-3 bg-gray-600 hover:bg-gray-700 text-white font-semibold rounded-lg transition-colors flex items-center justify-center"
|
||||
>
|
||||
<svg class="mr-2 h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"></path>
|
||||
@@ -358,14 +403,14 @@
|
||||
|
||||
<button
|
||||
type="submit"
|
||||
:disabled="!isFormValid || isGenerating"
|
||||
class="px-8 py-3 bg-primary-600 hover:bg-primary-700 disabled:bg-gray-400 disabled:cursor-not-allowed text-white font-semibold rounded-lg transition-colors flex items-center justify-center"
|
||||
id="submitBtn"
|
||||
class="px-8 py-3 bg-primary-600 hover:bg-primary-700 text-white font-semibold rounded-lg transition-colors flex items-center justify-center"
|
||||
>
|
||||
<svg v-if="isGenerating" class="animate-spin -ml-1 mr-3 h-5 w-5 text-white" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
|
||||
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
|
||||
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
|
||||
</svg>
|
||||
{{ isGenerating ? 'Formular wird erstellt...' : 'Beitrittsformular erstellen' }}
|
||||
Beitrittsformular erstellen
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
@@ -379,184 +424,97 @@
|
||||
<p class="text-xl text-primary-100 mb-6">
|
||||
Kontaktieren Sie uns - wir beraten Sie gerne persönlich
|
||||
</p>
|
||||
<NuxtLink
|
||||
to="/kontakt"
|
||||
<a
|
||||
href="/kontakt"
|
||||
class="inline-flex items-center px-8 py-4 bg-white text-primary-600 font-semibold rounded-lg hover:bg-gray-100 transition-colors"
|
||||
>
|
||||
Jetzt Kontakt aufnehmen
|
||||
</NuxtLink>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed } from 'vue'
|
||||
// Einfaches JavaScript ohne Vue.js-Reaktivität
|
||||
onMounted(() => {
|
||||
const form = document.getElementById('membershipForm')
|
||||
const fillDummyBtn = document.getElementById('fillDummyData')
|
||||
const submitBtn = document.getElementById('submitBtn')
|
||||
|
||||
const form = ref({
|
||||
// Persönliche Daten
|
||||
nachname: '',
|
||||
vorname: '',
|
||||
strasse: '',
|
||||
plz: '',
|
||||
ort: '',
|
||||
geburtsdatum: '',
|
||||
telefon_privat: '',
|
||||
email: '',
|
||||
telefon_mobil: '',
|
||||
|
||||
// Mitgliedschaftsart
|
||||
mitgliedschaftsart: 'aktiv',
|
||||
|
||||
// Bankdaten
|
||||
kontoinhaber: '',
|
||||
iban: '',
|
||||
bic: '',
|
||||
bank: '',
|
||||
|
||||
// Einverständnisse
|
||||
lastschrift_erlaubt: false,
|
||||
datenschutz_einverstanden: false,
|
||||
satzung_anerkannt: false
|
||||
})
|
||||
// Testdaten füllen
|
||||
fillDummyBtn.addEventListener('click', () => {
|
||||
document.getElementById('nachname').value = 'Mustermann'
|
||||
document.getElementById('vorname').value = 'Max'
|
||||
document.getElementById('strasse').value = 'Musterstraße 123'
|
||||
document.getElementById('plz').value = '60437'
|
||||
document.getElementById('ort').value = 'Frankfurt am Main'
|
||||
document.getElementById('geburtsdatum').value = '1990-05-15'
|
||||
document.getElementById('telefon_privat').value = '069 12345678'
|
||||
document.getElementById('email').value = 'max.mustermann@example.com'
|
||||
document.getElementById('telefon_mobil').value = '0171 1234567'
|
||||
document.getElementById('kontoinhaber').value = 'Max Mustermann'
|
||||
document.getElementById('iban').value = 'DE89 3704 0044 0532 0130 00'
|
||||
document.getElementById('bic').value = 'COBADEFFXXX'
|
||||
document.getElementById('bank').value = 'Commerzbank AG'
|
||||
document.querySelector('input[name="lastschrift_erlaubt"]').checked = true
|
||||
document.querySelector('input[name="datenschutz_einverstanden"]').checked = true
|
||||
document.querySelector('input[name="satzung_anerkannt"]').checked = true
|
||||
})
|
||||
|
||||
const isGenerating = ref(false)
|
||||
|
||||
const isFormValid = computed(() => {
|
||||
return form.value.nachname &&
|
||||
form.value.vorname &&
|
||||
form.value.strasse &&
|
||||
form.value.plz &&
|
||||
form.value.ort &&
|
||||
form.value.geburtsdatum &&
|
||||
form.value.email &&
|
||||
form.value.mitgliedschaftsart &&
|
||||
form.value.kontoinhaber &&
|
||||
form.value.iban &&
|
||||
form.value.lastschrift_erlaubt &&
|
||||
form.value.datenschutz_einverstanden &&
|
||||
form.value.satzung_anerkannt
|
||||
})
|
||||
|
||||
const isVolljaehrig = computed(() => {
|
||||
if (!form.value.geburtsdatum) return true // Default zu volljährig
|
||||
|
||||
const heute = new Date()
|
||||
const geburtsdatum = new Date(form.value.geburtsdatum)
|
||||
const alter = heute.getFullYear() - geburtsdatum.getFullYear()
|
||||
const monatDiff = heute.getMonth() - geburtsdatum.getMonth()
|
||||
|
||||
if (monatDiff < 0 || (monatDiff === 0 && heute.getDate() < geburtsdatum.getDate())) {
|
||||
return alter - 1 >= 18
|
||||
}
|
||||
|
||||
return alter >= 18
|
||||
})
|
||||
|
||||
const fillWithDummyData = () => {
|
||||
// Dummy-Daten für Testzwecke
|
||||
form.value = {
|
||||
// Persönliche Daten
|
||||
nachname: 'Mustermann',
|
||||
vorname: 'Max',
|
||||
strasse: 'Musterstraße 123',
|
||||
plz: '60437',
|
||||
ort: 'Frankfurt am Main',
|
||||
geburtsdatum: '1990-05-15', // Volljährig
|
||||
telefon_privat: '069 12345678',
|
||||
email: 'max.mustermann@example.com',
|
||||
telefon_mobil: '0171 1234567',
|
||||
// Formular absenden
|
||||
form.addEventListener('submit', async (e) => {
|
||||
e.preventDefault()
|
||||
|
||||
// Mitgliedschaftsart
|
||||
mitgliedschaftsart: 'aktiv',
|
||||
submitBtn.disabled = true
|
||||
submitBtn.textContent = 'Formular wird erstellt...'
|
||||
|
||||
// Bankdaten
|
||||
kontoinhaber: 'Max Mustermann',
|
||||
iban: 'DE89 3704 0044 0532 0130 00',
|
||||
bic: 'COBADEFFXXX',
|
||||
bank: 'Commerzbank AG',
|
||||
|
||||
// Einverständnisse
|
||||
lastschrift_erlaubt: true,
|
||||
datenschutz_einverstanden: true,
|
||||
satzung_anerkannt: true
|
||||
}
|
||||
}
|
||||
|
||||
const submitForm = async () => {
|
||||
if (!isFormValid.value) return
|
||||
|
||||
isGenerating.value = true
|
||||
|
||||
try {
|
||||
const response = await $fetch('/api/membership/generate-pdf', {
|
||||
method: 'POST',
|
||||
body: {
|
||||
...form.value,
|
||||
isVolljaehrig: isVolljaehrig.value
|
||||
}
|
||||
})
|
||||
|
||||
if (response.success) {
|
||||
// PDF herunterladen über geschützten Endpoint
|
||||
try {
|
||||
const downloadResponse = await $fetch(response.downloadUrl, {
|
||||
method: 'GET',
|
||||
responseType: 'blob'
|
||||
})
|
||||
|
||||
// Blob zu Download-Link konvertieren
|
||||
const blob = new Blob([downloadResponse], {
|
||||
type: 'application/pdf'
|
||||
})
|
||||
const url = window.URL.createObjectURL(blob)
|
||||
const link = document.createElement('a')
|
||||
link.href = url
|
||||
link.download = `Beitrittserklärung_${form.value.nachname}_${form.value.vorname}.pdf`
|
||||
document.body.appendChild(link)
|
||||
link.click()
|
||||
document.body.removeChild(link)
|
||||
window.URL.revokeObjectURL(url)
|
||||
|
||||
// Erfolgsmeldung
|
||||
alert('Beitrittsformular wurde erfolgreich erstellt und per E-Mail an den Vorstand/Trainer gesendet!')
|
||||
} catch (downloadError) {
|
||||
console.error('Download-Fehler:', downloadError)
|
||||
alert('Formular wurde erfolgreich erstellt und per E-Mail an den Vorstand/Trainer gesendet!\n\nFalls der Download fehlschlägt, können Sie das Formular auch später über den Link in der E-Mail herunterladen.')
|
||||
}
|
||||
try {
|
||||
const formData = new FormData(form)
|
||||
const data = Object.fromEntries(formData.entries())
|
||||
|
||||
// Formular zurücksetzen
|
||||
form.value = {
|
||||
nachname: '',
|
||||
vorname: '',
|
||||
strasse: '',
|
||||
plz: '',
|
||||
ort: '',
|
||||
geburtsdatum: '',
|
||||
telefon_privat: '',
|
||||
email: '',
|
||||
telefon_mobil: '',
|
||||
mitgliedschaftsart: 'aktiv',
|
||||
kontoinhaber: '',
|
||||
iban: '',
|
||||
bic: '',
|
||||
bank: '',
|
||||
lastschrift_erlaubt: false,
|
||||
datenschutz_einverstanden: false,
|
||||
satzung_anerkannt: false
|
||||
// Volljährigkeit prüfen
|
||||
const birthDate = new Date(data.geburtsdatum)
|
||||
const today = new Date()
|
||||
const age = today.getFullYear() - birthDate.getFullYear()
|
||||
const monthDiff = today.getMonth() - birthDate.getMonth()
|
||||
data.isVolljaehrig = age > 18 || (age === 18 && monthDiff >= 0)
|
||||
|
||||
const response = await fetch('/api/membership/generate-pdf', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify(data)
|
||||
})
|
||||
|
||||
const result = await response.json()
|
||||
|
||||
if (result.success) {
|
||||
// PDF herunterladen
|
||||
const downloadResponse = await fetch(result.downloadUrl)
|
||||
const blob = await downloadResponse.blob()
|
||||
|
||||
const url = window.URL.createObjectURL(blob)
|
||||
const a = document.createElement('a')
|
||||
a.href = url
|
||||
a.download = `beitrittserklärung_${Date.now()}.pdf`
|
||||
document.body.appendChild(a)
|
||||
a.click()
|
||||
window.URL.revokeObjectURL(url)
|
||||
document.body.removeChild(a)
|
||||
|
||||
alert('Beitrittsformular erfolgreich erstellt und heruntergeladen!')
|
||||
} else {
|
||||
alert('Fehler beim Erstellen des Formulars: ' + (result.error || 'Unbekannter Fehler'))
|
||||
}
|
||||
} else {
|
||||
alert('Fehler beim Erstellen des Formulars: ' + (response.error || 'Unbekannter Fehler'))
|
||||
} catch (error) {
|
||||
console.error('Fehler:', error)
|
||||
alert('Fehler beim Senden des Formulars: ' + error.message)
|
||||
} finally {
|
||||
submitBtn.disabled = false
|
||||
submitBtn.textContent = 'Beitrittsformular erstellen'
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Fehler:', error)
|
||||
alert('Fehler beim Erstellen des Formulars. Bitte versuchen Sie es erneut.')
|
||||
} finally {
|
||||
isGenerating.value = false
|
||||
}
|
||||
}
|
||||
|
||||
useHead({
|
||||
title: 'Mitgliedschaft - Harheimer TC',
|
||||
})
|
||||
})
|
||||
</script>
|
||||
Reference in New Issue
Block a user