85 lines
8.1 KiB
Vue
85 lines
8.1 KiB
Vue
<template>
|
||
<div class="max-w-5xl mx-auto px-4 sm:px-6 lg:px-8 py-12">
|
||
<h1 class="text-3xl sm:text-4xl font-bold mb-2" style="color: var(--text)">Mietanfrage</h1>
|
||
<p class="mb-8" style="color: var(--secondary)">Überprüfen Sie Ihre Geräteauswahl und senden Sie die Anfrage ab.</p>
|
||
<div v-if="submitted" class="hms-card p-8 text-center" role="status">
|
||
<div class="inline-flex items-center justify-center w-16 h-16 rounded-full mb-4" :style="{ background: 'var(--color-success-bg)', color: 'var(--color-success)' }"><svg class="w-8 h-8" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/></svg></div>
|
||
<h2 class="text-xl font-semibold mb-2" style="color: var(--text)">Mietanfrage übermittelt</h2>
|
||
<p class="mb-6" style="color: var(--secondary)">Vielen Dank! Wir melden uns innerhalb von 24 Stunden mit einem unverbindlichen Angebot.</p>
|
||
<div class="flex flex-col sm:flex-row gap-4 justify-center"><button @click="navigate('/mietkatalog')" class="hms-btn hms-btn-secondary">Weiter stöbern</button><button @click="navigate('/')" class="hms-btn hms-btn-primary">Zur Startseite</button></div>
|
||
</div>
|
||
<EmptyState v-else-if="cartItems.length === 0" icon="🛒" title="Warenkorb ist leer" message="Fügen Sie Geräte aus dem Mietkatalog hinzu, um eine Mietanfrage zu stellen." action-label="Zum Mietkatalog" @action="navigate('/mietkatalog')" />
|
||
<div v-else class="grid lg:grid-cols-3 gap-8">
|
||
<div class="lg:col-span-2 space-y-4">
|
||
<div v-for="(item, index) in cartItems" :key="index" class="hms-card p-4 sm:p-6">
|
||
<div class="flex gap-4">
|
||
<div class="w-20 h-20 rounded-lg flex items-center justify-center flex-shrink-0 text-2xl" style="background: var(--surface); color: var(--secondary)">📦</div>
|
||
<div class="flex-1 min-w-0">
|
||
<div class="flex items-start justify-between gap-2"><div><h3 class="font-semibold text-sm sm:text-base" style="color: var(--text)">{{ item.name }}</h3><div class="text-xs mt-0.5" style="color: var(--secondary)">{{ item.equipment_id }}</div></div>
|
||
<button @click="removeItem(item.equipment_id)" class="p-1" style="color: var(--secondary)" :aria-label="item.name + ' entfernen'"><svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"/></svg></button>
|
||
</div>
|
||
<div class="flex flex-wrap items-center gap-3 mt-3"><div class="flex items-center gap-2"><button @click="decrementQuantity(item.equipment_id)" class="w-7 h-7 rounded border flex items-center justify-center" style="border-color: var(--border-strong); color: var(--text-muted)" aria-label="Anzahl verringern">−</button><span class="w-8 text-center text-sm font-medium" style="color: var(--text)">{{ item.quantity }}</span><button @click="incrementQuantity(item.equipment_id)" class="w-7 h-7 rounded border flex items-center justify-center" style="border-color: var(--border-strong); color: var(--text-muted)" aria-label="Anzahl erhöhen">+</button></div></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<button @click="clearCart" class="text-sm hover:text-[var(--color-error)]" style="color: var(--secondary)">Warenkorb leeren</button>
|
||
</div>
|
||
<div>
|
||
<div class="hms-card p-6 sticky top-20">
|
||
<h2 class="text-lg font-semibold mb-4" style="color: var(--text)">Anfrage senden</h2>
|
||
<div class="text-sm mb-4 pb-4 border-b" :style="{ borderColor: 'var(--border)', color: 'var(--secondary)' }"><div class="flex justify-between mb-1"><span>Geräte gesamt:</span><span class="font-medium" style="color: var(--text)">{{ totalCount }}</span></div><div class="flex justify-between"><span>Positionen:</span><span class="font-medium" style="color: var(--text)">{{ cartItems.length }}</span></div></div>
|
||
<form @submit.prevent="submitRequest" novalidate>
|
||
<div class="space-y-3">
|
||
<div><label for="req-name" class="block text-xs font-medium mb-1" style="color: var(--secondary)">Name <span style="color: var(--color-error)">*</span></label><input id="req-name" v-model="form.name" type="text" :class="['hms-input text-sm', errors.name ? 'hms-input-error' : '']" placeholder="Ihr Name" /><p v-if="errors.name" class="text-xs mt-1" style="color: var(--color-error)">{{ errors.name }}</p></div>
|
||
<div><label for="req-email" class="block text-xs font-medium mb-1" style="color: var(--secondary)">E-Mail <span style="color: var(--color-error)">*</span></label><input id="req-email" v-model="form.email" type="email" :class="['hms-input text-sm', errors.email ? 'hms-input-error' : '']" placeholder="ihre@email.de" /><p v-if="errors.email" class="text-xs mt-1" style="color: var(--color-error)">{{ errors.email }}</p></div>
|
||
<div><label for="req-phone" class="block text-xs font-medium mb-1" style="color: var(--secondary)">Telefon</label><input id="req-phone" v-model="form.phone" type="tel" class="hms-input text-sm" placeholder="+49 ..." /></div>
|
||
<div><label for="req-date" class="block text-xs font-medium mb-1" style="color: var(--secondary)">Veranstaltungsdatum <span style="color: var(--color-error)">*</span></label><input id="req-date" v-model="form.event_date" type="date" :class="['hms-input text-sm', errors.event_date ? 'hms-input-error' : '']" /><p v-if="errors.event_date" class="text-xs mt-1" style="color: var(--color-error)">{{ errors.event_date }}</p></div>
|
||
<div><label for="req-location" class="block text-xs font-medium mb-1" style="color: var(--secondary)">Veranstaltungsort <span style="color: var(--color-error)">*</span></label><input id="req-location" v-model="form.event_location" type="text" :class="['hms-input text-sm', errors.event_location ? 'hms-input-error' : '']" placeholder="Ort / Location" /><p v-if="errors.event_location" class="text-xs mt-1" style="color: var(--color-error)">{{ errors.event_location }}</p></div>
|
||
<div><label for="req-message" class="block text-xs font-medium mb-1" style="color: var(--secondary)">Anmerkung</label><textarea id="req-message" v-model="form.message" rows="3" class="hms-input text-sm" placeholder="Zusätzliche Informationen..."></textarea></div>
|
||
<button type="submit" :disabled="submitting" class="hms-btn hms-btn-primary w-full py-3"><span v-if="submitting" class="hms-spinner" style="width:18px;height:18px;border-width:2px"></span><span v-else>Anfrage absenden</span></button>
|
||
<p class="text-xs text-center" style="color: var(--secondary)">Unverbindlich – Angebot innerhalb 24 Std.</p>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
|
||
<script setup lang="ts">
|
||
import { reactive, ref } from 'vue'
|
||
import { useCart } from '~/composables/useCart'
|
||
|
||
const { items: cartItems, totalCount, removeItem, incrementQuantity, decrementQuantity, clearCart } = useCart()
|
||
|
||
const submitting = ref(false)
|
||
const submitted = ref(false)
|
||
const form = reactive({ name: '', email: '', phone: '', event_date: '', event_location: '', message: '' })
|
||
const errors = reactive<Record<string, string>>({})
|
||
|
||
function navigate(route: string) {
|
||
navigateTo(route)
|
||
if (import.meta.client) window.scrollTo(0, 0)
|
||
}
|
||
function validate(): boolean {
|
||
const e: Record<string, string> = {}
|
||
if (!form.name.trim()) e.name = 'Name ist erforderlich'
|
||
if (!form.email.trim()) e.email = 'E-Mail ist erforderlich'
|
||
else if (!/^\S+@\S+\.\S+$/.test(form.email)) e.email = 'Ungültige E-Mail'
|
||
if (!form.event_date) e.event_date = 'Veranstaltungsdatum erforderlich'
|
||
if (!form.event_location.trim()) e.event_location = 'Veranstaltungsort erforderlich'
|
||
Object.keys(errors).forEach(k => delete errors[k])
|
||
Object.assign(errors, e)
|
||
return Object.keys(e).length === 0
|
||
}
|
||
function submitRequest() {
|
||
if (!validate()) return
|
||
submitting.value = true
|
||
setTimeout(() => {
|
||
submitting.value = false
|
||
submitted.value = true
|
||
clearCart()
|
||
}, 1800)
|
||
}
|
||
</script>
|