photobooth funktionen im event admin verlinkt, gäste pwa zeigt photobooth nur noch an, wenn diese aktiviert ist. kontaktformular optimiert. teilen-link mit iMessage und whatsapp erweitert.
This commit is contained in:
@@ -10,7 +10,8 @@ import { Button } from '@/components/ui/button';
|
||||
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@/components/ui/card';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { Textarea } from '@/components/ui/textarea';
|
||||
import { ArrowRight, Camera, QrCode, ShieldCheck, Sparkles, Smartphone } from 'lucide-react';
|
||||
import { ArrowRight, Camera, QrCode, ShieldCheck, Sparkles, Smartphone, Loader2, CheckCircle2 } from 'lucide-react';
|
||||
import { usePage } from '@inertiajs/react';
|
||||
|
||||
interface Package {
|
||||
id: number;
|
||||
@@ -34,10 +35,12 @@ const Home: React.FC<Props> = ({ packages }) => {
|
||||
variant: heroCtaVariant,
|
||||
trackClick: trackHeroCtaClick,
|
||||
} = useCtaExperiment('home_hero_cta');
|
||||
const { flash } = usePage<{ flash?: { success?: string } }>().props;
|
||||
const { data, setData, post, processing, errors, reset } = useForm({
|
||||
name: '',
|
||||
email: '',
|
||||
message: '',
|
||||
nickname: '',
|
||||
});
|
||||
|
||||
const heroBulletsRaw = t('home.hero_bullets', { returnObjects: true });
|
||||
@@ -447,14 +450,54 @@ const Home: React.FC<Props> = ({ packages }) => {
|
||||
<section id="contact" className="bg-gray-50 py-20 px-4 dark:bg-gray-950/80">
|
||||
<div className="container mx-auto max-w-4xl">
|
||||
<Card className="border-gray-200/70 bg-white/95 shadow-lg shadow-rose-200/40 dark:border-gray-800/60 dark:bg-gray-900/80">
|
||||
<CardHeader className="text-center">
|
||||
<Badge className="mx-auto mb-3 w-fit bg-rose-100 px-3 py-1 text-xs font-semibold uppercase text-rose-600 dark:bg-rose-500/20 dark:text-rose-200">
|
||||
{t('home.contact_title')}
|
||||
</Badge>
|
||||
<CardTitle className="text-2xl md:text-3xl">{t('home.contact_lead')}</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<form onSubmit={handleSubmit} className="space-y-6">
|
||||
<CardHeader className="text-center">
|
||||
<Badge className="mx-auto mb-3 w-fit bg-rose-100 px-3 py-1 text-xs font-semibold uppercase text-rose-600 dark:bg-rose-500/20 dark:text-rose-200">
|
||||
{t('home.contact_title')}
|
||||
</Badge>
|
||||
<CardTitle className="text-2xl md:text-3xl">{t('home.contact_lead')}</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
{flash?.success ? (
|
||||
<div className="mb-4 flex items-center gap-2 rounded-xl border border-emerald-200/70 bg-emerald-50 px-3 py-2 text-sm text-emerald-800 dark:border-emerald-500/40 dark:bg-emerald-500/10 dark:text-emerald-100">
|
||||
<CheckCircle2 className="h-4 w-4" />
|
||||
<span>{flash.success}</span>
|
||||
</div>
|
||||
) : null}
|
||||
<div className="grid gap-6 lg:grid-cols-[1fr,1.1fr]">
|
||||
<div className="space-y-3 rounded-2xl border border-rose-100/70 bg-rose-50/50 p-5 text-left text-sm text-slate-700 shadow-inner dark:border-rose-500/20 dark:bg-rose-500/5 dark:text-slate-200">
|
||||
<p className="text-xs font-semibold uppercase tracking-wide text-rose-500 dark:text-rose-200">
|
||||
{t('home.contact_title')}
|
||||
</p>
|
||||
<p className="text-base font-semibold text-slate-900 dark:text-white">{t('home.contact_lead')}</p>
|
||||
<ul className="space-y-2">
|
||||
<li className="flex items-start gap-3">
|
||||
<div className="mt-0.5 h-2.5 w-2.5 rounded-full bg-rose-500" />
|
||||
<span>{t('home.hero_bullets.0', 'Antwort in <24h')}</span>
|
||||
</li>
|
||||
<li className="flex items-start gap-3">
|
||||
<div className="mt-0.5 h-2.5 w-2.5 rounded-full bg-rose-500" />
|
||||
<span>{t('home.hero_bullets.1', 'Keine Weitergabe, kein Tracking')}</span>
|
||||
</li>
|
||||
<li className="flex items-start gap-3">
|
||||
<div className="mt-0.5 h-2.5 w-2.5 rounded-full bg-rose-500" />
|
||||
<span>{t('home.contact_privacy')}</span>
|
||||
</li>
|
||||
</ul>
|
||||
<div className="rounded-xl border border-white/60 bg-white/80 p-3 text-xs font-medium text-slate-700 shadow-sm dark:border-white/10 dark:bg-white/10 dark:text-slate-100">
|
||||
{t('home.contact_privacy')}
|
||||
</div>
|
||||
</div>
|
||||
<form onSubmit={handleSubmit} className="space-y-6">
|
||||
<input
|
||||
type="text"
|
||||
name="nickname"
|
||||
value={data.nickname}
|
||||
onChange={(event) => setData('nickname', event.target.value)}
|
||||
className="hidden"
|
||||
tabIndex={-1}
|
||||
autoComplete="off"
|
||||
aria-hidden
|
||||
/>
|
||||
<div className="grid gap-4 md:grid-cols-2">
|
||||
<div className="flex flex-col gap-2">
|
||||
<label htmlFor="name" className="text-sm font-semibold text-gray-600 dark:text-gray-200">
|
||||
@@ -467,9 +510,11 @@ const Home: React.FC<Props> = ({ packages }) => {
|
||||
className="h-12 rounded-xl border-gray-200/70 bg-white/90 shadow-inner shadow-gray-200/40 focus-visible:ring-rose-300/60 dark:border-gray-700 dark:bg-gray-900/70"
|
||||
autoComplete="name"
|
||||
required
|
||||
aria-invalid={Boolean(errors.name)}
|
||||
aria-describedby={errors.name ? 'contact-name-error' : undefined}
|
||||
/>
|
||||
{errors.name && (
|
||||
<p className="text-sm font-medium text-rose-600 dark:text-rose-300">{errors.name}</p>
|
||||
<p id="contact-name-error" className="text-sm font-medium text-rose-600 dark:text-rose-300">{errors.name}</p>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex flex-col gap-2">
|
||||
@@ -484,9 +529,11 @@ const Home: React.FC<Props> = ({ packages }) => {
|
||||
className="h-12 rounded-xl border-gray-200/70 bg-white/90 shadow-inner shadow-gray-200/40 focus-visible:ring-rose-300/60 dark:border-gray-700 dark:bg-gray-900/70"
|
||||
autoComplete="email"
|
||||
required
|
||||
aria-invalid={Boolean(errors.email)}
|
||||
aria-describedby={errors.email ? 'contact-email-error' : undefined}
|
||||
/>
|
||||
{errors.email && (
|
||||
<p className="text-sm font-medium text-rose-600 dark:text-rose-300">{errors.email}</p>
|
||||
<p id="contact-email-error" className="text-sm font-medium text-rose-600 dark:text-rose-300">{errors.email}</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
@@ -494,31 +541,41 @@ const Home: React.FC<Props> = ({ packages }) => {
|
||||
<label htmlFor="message" className="text-sm font-semibold text-gray-600 dark:text-gray-200">
|
||||
{t('home.message_label')} *
|
||||
</label>
|
||||
<Textarea
|
||||
id="message"
|
||||
rows={5}
|
||||
value={data.message}
|
||||
onChange={(event) => setData('message', event.target.value)}
|
||||
className="rounded-xl border-gray-200/70 bg-white/90 shadow-inner shadow-gray-200/40 focus-visible:ring-rose-300/60 dark:border-gray-700 dark:bg-gray-900/70"
|
||||
required
|
||||
/>
|
||||
{errors.message && (
|
||||
<p className="text-sm font-medium text-rose-600 dark:text-rose-300">{errors.message}</p>
|
||||
)}
|
||||
<Textarea
|
||||
id="message"
|
||||
rows={5}
|
||||
value={data.message}
|
||||
onChange={(event) => setData('message', event.target.value)}
|
||||
className="rounded-xl border-gray-200/70 bg-white/90 shadow-inner shadow-gray-200/40 focus-visible:ring-rose-300/60 dark:border-gray-700 dark:bg-gray-900/70"
|
||||
required
|
||||
aria-invalid={Boolean(errors.message)}
|
||||
aria-describedby={errors.message ? 'contact-message-error' : undefined}
|
||||
/>
|
||||
{errors.message && (
|
||||
<p id="contact-message-error" className="text-sm font-medium text-rose-600 dark:text-rose-300">{errors.message}</p>
|
||||
)}
|
||||
</div>
|
||||
<div className="space-y-3 text-sm text-muted-foreground">
|
||||
<p>{t('home.contact_privacy')}</p>
|
||||
<Button
|
||||
type="submit"
|
||||
disabled={processing}
|
||||
className="h-12 w-full rounded-full bg-gradient-to-r from-[#ff5f87] via-[#ec4899] to-[#6366f1] text-base font-semibold text-white shadow-[0_18px_35px_-18px_rgba(236,72,153,0.7)] transition hover:from-[#ff4470] hover:via-[#ec4899] hover:to-[#4f46e5] disabled:cursor-not-allowed disabled:opacity-60"
|
||||
>
|
||||
{processing ? (
|
||||
<span className="flex items-center justify-center gap-2">
|
||||
<Loader2 className="h-4 w-4 animate-spin" />
|
||||
{t('home.sending')}
|
||||
</span>
|
||||
) : (
|
||||
t('home.send')
|
||||
)}
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div className="space-y-3 text-sm text-muted-foreground">
|
||||
<p>{t('home.contact_privacy')}</p>
|
||||
<Button
|
||||
type="submit"
|
||||
disabled={processing}
|
||||
className="h-12 w-full rounded-full bg-gradient-to-r from-[#ff5f87] via-[#ec4899] to-[#6366f1] text-base font-semibold text-white shadow-[0_18px_35px_-18px_rgba(236,72,153,0.7)] transition hover:from-[#ff4470] hover:via-[#ec4899] hover:to-[#4f46e5] disabled:cursor-not-allowed disabled:opacity-60"
|
||||
>
|
||||
{processing ? t('home.sending') : t('home.send')}
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user