217 lines
13 KiB
PHP
217 lines
13 KiB
PHP
@php
|
||
use Illuminate\Support\Facades\Storage;
|
||
|
||
$bgUrl = $page->background_image !== null
|
||
? Storage::disk('public')->url($page->background_image)
|
||
: null;
|
||
$logoUrl = $page->logo_image !== null
|
||
? Storage::disk('public')->url($page->logo_image)
|
||
: null;
|
||
$phase = $page->isBeforeStart() ? 'before' : ($page->isExpired() ? 'expired' : 'active');
|
||
@endphp
|
||
|
||
@extends('layouts.public')
|
||
|
||
@section('content')
|
||
<div class="relative min-h-screen w-full overflow-x-hidden">
|
||
@if ($bgUrl !== null)
|
||
<div
|
||
class="absolute inset-0 bg-cover bg-center bg-no-repeat"
|
||
style="background-image: url('{{ e($bgUrl) }}')"
|
||
aria-hidden="true"
|
||
></div>
|
||
@else
|
||
<div
|
||
class="absolute inset-0 bg-gradient-to-br from-slate-950 via-slate-900 to-slate-950"
|
||
aria-hidden="true"
|
||
></div>
|
||
@endif
|
||
|
||
<div class="absolute inset-0 bg-black/30" aria-hidden="true"></div>
|
||
|
||
<div class="relative z-10 flex min-h-screen items-center justify-center px-4 py-6 sm:px-6 sm:py-10">
|
||
<div
|
||
class="animate-preregister-in w-full max-w-3xl rounded-3xl border border-white/20 bg-black/60 px-5 py-8 shadow-[0_25px_60px_-15px_rgba(0,0,0,0.65)] backdrop-blur-[4px] sm:px-10 sm:py-10"
|
||
x-cloak
|
||
x-data="publicPreregisterPage(@js([
|
||
'phase' => $phase,
|
||
'startAtMs' => $page->start_date->getTimestamp() * 1000,
|
||
'phoneEnabled' => (bool) $page->phone_enabled,
|
||
'subscribeUrl' => route('public.subscribe', ['publicPage' => $page]),
|
||
'csrfToken' => csrf_token(),
|
||
'genericError' => __('Something went wrong. Please try again.'),
|
||
'labelDay' => __('day'),
|
||
'labelDays' => __('days'),
|
||
'invalidEmailMsg' => __('Please enter a valid email address.'),
|
||
'invalidPhoneMsg' => __('Please enter a valid phone number (8–15 digits).'),
|
||
]))"
|
||
>
|
||
<div class="flex flex-col items-center text-center">
|
||
@if ($logoUrl !== null)
|
||
<div class="mb-4 flex w-full justify-center sm:mb-5">
|
||
<img
|
||
src="{{ e($logoUrl) }}"
|
||
alt=""
|
||
class="max-h-32 w-auto object-contain object-center drop-shadow-[0_8px_32px_rgba(0,0,0,0.45)] sm:max-h-44 md:max-h-48"
|
||
width="384"
|
||
height="192"
|
||
>
|
||
</div>
|
||
@endif
|
||
|
||
<h1 class="w-full max-w-none text-balance text-2xl font-bold leading-snug tracking-tight text-festival sm:text-3xl">
|
||
{{ $page->heading }}
|
||
</h1>
|
||
|
||
@if (filled($page->intro_text))
|
||
<div
|
||
x-show="phase === 'before' || phase === 'active'"
|
||
x-cloak
|
||
class="mt-0 w-full max-w-none whitespace-pre-line text-[15px] leading-[1.65] text-white sm:text-base sm:leading-relaxed"
|
||
>
|
||
{{ trim($page->intro_text) }}
|
||
</div>
|
||
@endif
|
||
</div>
|
||
|
||
{{-- Before start: countdown --}}
|
||
<div x-show="phase === 'before'" x-cloak class="mt-8 space-y-6 sm:mt-10">
|
||
<div
|
||
class="grid grid-cols-4 gap-3 rounded-2xl border border-white/15 bg-black/35 px-3 py-4 text-center shadow-inner sm:gap-4 sm:px-4 sm:py-5"
|
||
role="timer"
|
||
aria-live="polite"
|
||
>
|
||
<div>
|
||
<div class="font-mono text-2xl font-semibold tabular-nums text-white sm:text-3xl" x-text="pad(days)"></div>
|
||
<div class="mt-2 text-[10px] uppercase tracking-wider text-white/65 sm:text-xs" x-text="days === 1 ? labelDay : labelDays"></div>
|
||
</div>
|
||
<div>
|
||
<div class="font-mono text-2xl font-semibold tabular-nums text-white sm:text-3xl" x-text="pad(hours)"></div>
|
||
<div class="mt-2 text-[10px] uppercase tracking-wider text-white/65 sm:text-xs">{{ __('hrs') }}</div>
|
||
</div>
|
||
<div>
|
||
<div class="font-mono text-2xl font-semibold tabular-nums text-white sm:text-3xl" x-text="pad(minutes)"></div>
|
||
<div class="mt-2 text-[10px] uppercase tracking-wider text-white/65 sm:text-xs">{{ __('mins') }}</div>
|
||
</div>
|
||
<div>
|
||
<div class="font-mono text-2xl font-semibold tabular-nums text-white sm:text-3xl" x-text="pad(seconds)"></div>
|
||
<div class="mt-2 text-[10px] uppercase tracking-wider text-white/65 sm:text-xs">{{ __('secs') }}</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
{{-- Active: registration form --}}
|
||
<div x-show="phase === 'active'" x-cloak class="mt-8 sm:mt-10">
|
||
<form x-ref="form" class="space-y-4" @submit.prevent="submitForm()">
|
||
<div x-show="formError !== ''" x-cloak class="rounded-xl border border-amber-400/50 bg-amber-500/15 px-4 py-3 text-sm leading-snug text-amber-50" x-text="formError"></div>
|
||
|
||
<div class="grid grid-cols-1 gap-4 sm:grid-cols-2">
|
||
<div>
|
||
<label for="first_name" class="sr-only">{{ __('First name') }}</label>
|
||
<input
|
||
id="first_name"
|
||
type="text"
|
||
name="first_name"
|
||
autocomplete="given-name"
|
||
required
|
||
maxlength="255"
|
||
x-model="first_name"
|
||
class="min-h-[48px] w-full rounded-xl border border-white/35 bg-white/15 px-4 py-3 text-[15px] text-white placeholder-white/55 shadow-sm transition duration-200 ease-out focus:border-festival focus:outline-none focus:ring-2 focus:ring-festival/45"
|
||
placeholder="{{ __('First name') }}"
|
||
>
|
||
<p x-show="fieldErrors.first_name" x-cloak class="mt-2 text-sm text-red-200" x-text="fieldErrors.first_name ? fieldErrors.first_name[0] : ''"></p>
|
||
</div>
|
||
|
||
<div>
|
||
<label for="last_name" class="sr-only">{{ __('Last name') }}</label>
|
||
<input
|
||
id="last_name"
|
||
type="text"
|
||
name="last_name"
|
||
autocomplete="family-name"
|
||
required
|
||
maxlength="255"
|
||
x-model="last_name"
|
||
class="min-h-[48px] w-full rounded-xl border border-white/35 bg-white/15 px-4 py-3 text-[15px] text-white placeholder-white/55 shadow-sm transition duration-200 ease-out focus:border-festival focus:outline-none focus:ring-2 focus:ring-festival/45"
|
||
placeholder="{{ __('Last name') }}"
|
||
>
|
||
<p x-show="fieldErrors.last_name" x-cloak class="mt-2 text-sm text-red-200" x-text="fieldErrors.last_name ? fieldErrors.last_name[0] : ''"></p>
|
||
</div>
|
||
</div>
|
||
|
||
<div>
|
||
<label for="email" class="sr-only">{{ __('Email') }}</label>
|
||
<input
|
||
id="email"
|
||
type="email"
|
||
name="email"
|
||
autocomplete="email"
|
||
required
|
||
maxlength="255"
|
||
x-model="email"
|
||
class="min-h-[48px] w-full rounded-xl border border-white/35 bg-white/15 px-4 py-3 text-[15px] text-white placeholder-white/55 shadow-sm transition duration-200 ease-out focus:border-festival focus:outline-none focus:ring-2 focus:ring-festival/45"
|
||
placeholder="{{ __('Email') }}"
|
||
>
|
||
<p x-show="fieldErrors.email" x-cloak class="mt-2 text-sm text-red-200" x-text="fieldErrors.email ? fieldErrors.email[0] : ''"></p>
|
||
</div>
|
||
|
||
<div x-show="phoneEnabled">
|
||
<label for="phone" class="sr-only">{{ __('Phone (optional)') }}</label>
|
||
<input
|
||
id="phone"
|
||
type="tel"
|
||
name="phone"
|
||
autocomplete="tel"
|
||
maxlength="20"
|
||
x-model="phone"
|
||
class="min-h-[48px] w-full rounded-xl border border-white/35 bg-white/15 px-4 py-3 text-[15px] text-white placeholder-white/55 shadow-sm transition duration-200 ease-out focus:border-festival focus:outline-none focus:ring-2 focus:ring-festival/45"
|
||
placeholder="{{ __('Phone (optional)') }}"
|
||
>
|
||
<p x-show="fieldErrors.phone" x-cloak class="mt-2 text-sm text-red-200" x-text="fieldErrors.phone ? fieldErrors.phone[0] : ''"></p>
|
||
</div>
|
||
|
||
<button
|
||
type="submit"
|
||
class="mt-2 min-h-[52px] w-full rounded-xl bg-festival px-6 py-3.5 text-base font-bold tracking-wide text-white shadow-lg shadow-festival/30 transition duration-200 ease-out hover:scale-[1.02] hover:brightness-110 focus:outline-none focus:ring-2 focus:ring-festival focus:ring-offset-2 focus:ring-offset-black/80 active:scale-[0.99] disabled:cursor-not-allowed disabled:opacity-60 disabled:hover:scale-100 sm:min-h-[56px] sm:text-lg"
|
||
:disabled="submitting"
|
||
>
|
||
<span x-show="!submitting">{{ __('public.register_button') }}</span>
|
||
<span x-show="submitting" x-cloak>{{ __('Sending…') }}</span>
|
||
</button>
|
||
</form>
|
||
</div>
|
||
|
||
{{-- Thank you (after successful AJAX) --}}
|
||
<div x-show="phase === 'thanks'" x-cloak class="mt-8 sm:mt-10">
|
||
<p class="whitespace-pre-line text-center text-base leading-relaxed text-white/95 sm:text-lg" x-text="thankYouMessage"></p>
|
||
</div>
|
||
|
||
{{-- Expired --}}
|
||
<div x-show="phase === 'expired'" x-cloak class="mt-8 space-y-6 sm:mt-10">
|
||
@if (filled($page->expired_message))
|
||
<div class="whitespace-pre-line text-center text-[15px] leading-[1.65] text-white/92 sm:text-base sm:leading-relaxed">
|
||
{{ $page->expired_message }}
|
||
</div>
|
||
@else
|
||
<p class="text-center text-[15px] leading-relaxed text-white/92 sm:text-base">{{ __('This pre-registration period has ended.') }}</p>
|
||
@endif
|
||
|
||
@if (filled($page->ticketshop_url))
|
||
<div class="text-center">
|
||
<a
|
||
href="{{ e($page->ticketshop_url) }}"
|
||
class="inline-flex min-h-[52px] items-center justify-center rounded-xl bg-festival px-8 py-3.5 text-base font-bold tracking-wide text-white shadow-lg shadow-festival/30 transition duration-200 ease-out hover:scale-[1.02] hover:brightness-110 focus:outline-none focus:ring-2 focus:ring-festival focus:ring-offset-2 focus:ring-offset-black/80 active:scale-[0.99]"
|
||
target="_blank"
|
||
rel="noopener noreferrer"
|
||
>
|
||
{{ __('Visit ticket shop') }}
|
||
<span class="ml-1" aria-hidden="true">→</span>
|
||
</a>
|
||
</div>
|
||
@endif
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
@endsection
|