PHP Rebuild
CI / ci (push) Canceled after 0s

Initial PHP rebuild of the app
This commit is contained in:
Stefan Lazic committed 2026-09-05 08:21:33 +01:00
1 parent 8a2b211069
commit 2ef3654841
690 files changed
+33944 -12046

No files matched your search

@@ -0,0 +1,10 @@
<x-layouts.public :business="$business">
<main class="mx-auto flex min-h-screen max-w-xl flex-col justify-center px-5 py-16 text-center lg:px-10">
<div class="mx-auto flex h-16 w-16 items-center justify-center rounded-full bg-accent text-3xl font-black text-white">✓</div>
<p class="mt-8 text-[10px] font-bold uppercase tracking-[0.3em] text-accent-foreground">{{ $appointment->status->value === 'PENDING' ? 'Request received' : 'Booking confirmed' }}</p>
<h1 class="mt-3 text-4xl font-black tracking-tight">You’re all set</h1>
<p class="mt-4 text-sm leading-6 text-muted">{{ $appointment->customer->firstName }}, your appointment at {{ $business->name }} is booked for {{ $appointment->startAt->setTimezone($business->timezone)->format('l, j F · g:i A') }}.</p>
<x-ui.card class="mt-8 p-6 text-left"><p class="text-sm font-bold">{{ $appointment->services->pluck('service.name')->join(', ') }}</p><p class="mt-2 text-sm text-muted">with {{ $appointment->staff->user?->name ?: 'your barber' }}</p><p class="mt-5 border-t border-line pt-4 text-xs text-muted">A confirmation link has been created for this booking.</p></x-ui.card>
<x-ui.button class="mt-6 w-full" href="{{ route('public.home') }}">Done</x-ui.button>
</main>
</x-layouts.public>
+14
View File
@@ -0,0 +1,14 @@
<x-layouts.public :business="$business">
<main class="mx-auto min-h-screen max-w-xl px-5 pb-16 pt-8 lg:px-10">
<a href="{{ route('booking.time') }}" class="text-xs font-bold uppercase tracking-widest text-muted">← Time</a>
<div class="mt-10"><p class="text-[10px] font-bold uppercase tracking-widest text-muted">Step 3 of 4</p><h1 class="mt-2 text-3xl font-black tracking-tight">Your details</h1><p class="mt-3 text-sm text-muted">We’ll use these details to send your booking confirmation.</p></div>
<form method="POST" action="{{ route('booking.details.store') }}" class="mt-8 space-y-4 rounded-md border border-line bg-white p-6 shadow-sm">
@csrf
@foreach ([['firstName', 'First name', 'text'], ['lastName', 'Last name', 'text'], ['email', 'Email address', 'email'], ['phone', 'Phone number (optional)', 'tel']] as [$name, $label, $type])
<label class="block"><span class="mb-2 ml-1 block text-[10px] font-bold uppercase tracking-widest text-muted">{{ $label }}</span><input name="{{ $name }}" type="{{ $type }}" value="{{ old($name) }}" class="w-full rounded-md border border-line px-4 py-3 text-sm outline-none focus:border-ink" @required(in_array($name, ['firstName', 'lastName', 'email']))>@error($name)<span class="mt-1 block text-xs text-danger">{{ $message }}</span>@enderror</label>
@endforeach
<label class="block"><span class="mb-2 ml-1 block text-[10px] font-bold uppercase tracking-widest text-muted">Notes (optional)</span><textarea name="notes" rows="4" class="w-full rounded-md border border-line px-4 py-3 text-sm outline-none focus:border-ink">{{ old('notes') }}</textarea></label>
<x-ui.button class="mt-3 w-full" type="submit">Review booking</x-ui.button>
</form>
</main>
</x-layouts.public>
@@ -0,0 +1,7 @@
<x-layouts.public :business="app(\App\Services\Tenant\TenantContext::class)->business()">
<main class="mx-auto flex min-h-screen max-w-xl flex-col justify-center px-6 py-16">
<a href="{{ route('public.home') }}" class="text-xs font-bold uppercase tracking-widest text-muted">← Back</a>
<h1 class="mt-8 text-4xl font-black tracking-tight">Choose your service</h1>
<p class="mt-4 text-sm leading-6 text-muted">The booking journey is the next migration slice. The legacy flow remains available in <code>legacy-nextjs</code> while it is being rebuilt with Blade and Alpine.</p>
</main>
</x-layouts.public>
+13
View File
@@ -0,0 +1,13 @@
<x-layouts.public :business="$business">
<main class="mx-auto min-h-screen max-w-xl px-5 pb-16 pt-8 lg:px-10">
<a href="{{ route('booking.details') }}" class="text-xs font-bold uppercase tracking-widest text-muted">← Your details</a>
<div class="mt-10"><p class="text-[10px] font-bold uppercase tracking-widest text-muted">Step 4 of 4</p><h1 class="mt-2 text-3xl font-black tracking-tight">Review booking</h1></div>
<div class="mt-8 space-y-3">
<x-ui.card class="p-6"><p class="text-[10px] font-bold uppercase tracking-widest text-muted">Services</p>@foreach ($services as $service)<div class="mt-3 flex justify-between gap-3 text-sm"><span>{{ $service->name }} <span class="text-muted">· {{ $service->durationMinutes }}m</span></span><strong>£{{ number_format((float) $service->price, 2) }}</strong></div>@endforeach</x-ui.card>
<x-ui.card class="p-6"><p class="text-[10px] font-bold uppercase tracking-widest text-muted">When &amp; who</p><p class="mt-3 text-sm font-bold">{{ \Carbon\CarbonImmutable::parse($draft['time']['startAt'])->setTimezone($business->timezone)->format('l, j F · g:i A') }}</p><p class="mt-1 text-sm text-muted">with {{ $staff->user?->name ?: 'your barber' }}</p><p class="mt-4 border-t border-line pt-4 text-sm">{{ $draft['customer']['firstName'] }} {{ $draft['customer']['lastName'] }}<br><span class="text-muted">{{ $draft['customer']['email'] }}</span></p></x-ui.card>
<div class="flex items-center justify-between px-1 pt-3"><span class="text-sm font-bold">Total</span><span class="text-2xl font-black">£{{ number_format((float) $total, 2) }}</span></div>
</div>
@if ($errors->any()) <div class="mt-5 rounded-md border border-danger/20 bg-red-50 p-4 text-sm text-red-800">{{ $errors->first() }}</div> @endif
<form method="POST" action="{{ route('booking.confirm') }}" class="mt-6"><button class="inline-flex h-12 w-full items-center justify-center rounded-md bg-ink px-6 text-xs font-bold uppercase tracking-widest text-white shadow-lg shadow-ink/10 hover:bg-black" type="submit">Confirm booking</button>@csrf</form>
</main>
</x-layouts.public>
@@ -0,0 +1,29 @@
<x-layouts.public :business="$business">
<main class="mx-auto min-h-screen max-w-3xl px-5 pb-16 pt-8 lg:px-10">
<a href="{{ route('public.home') }}" class="text-xs font-bold uppercase tracking-widest text-muted">← {{ $business->shortName ?: $business->name }}</a>
<div class="mt-10 flex items-end justify-between gap-4">
<div><p class="text-[10px] font-bold uppercase tracking-widest text-muted">Step 1 of 4</p><h1 class="mt-2 text-3xl font-black tracking-tight">Choose your service</h1></div>
<span class="text-xs text-muted">{{ $categories->sum(fn ($category) => $category->services->count()) }} available</span>
</div>
@if ($errors->any()) <div class="mt-5 rounded-md border border-danger/20 bg-red-50 p-4 text-sm text-red-800">{{ $errors->first() }}</div> @endif
<form method="POST" action="{{ route('booking.services.store') }}" class="mt-8 space-y-6">
@csrf
@forelse ($categories as $category)
<section>
<h2 class="mb-3 text-[10px] font-bold uppercase tracking-widest text-muted">{{ $category->name }}</h2>
<div class="space-y-3">
@foreach ($category->services as $service)
<label class="flex cursor-pointer items-center justify-between gap-4 rounded-md border border-line bg-white p-5 shadow-sm transition has-checked:border-ink has-checked:ring-1 has-checked:ring-ink">
<span class="flex items-center gap-4"><input type="checkbox" name="serviceIds[]" value="{{ $service->id }}" class="h-5 w-5 accent-ink"><span><strong class="block text-sm">{{ $service->name }}</strong><span class="mt-1 block text-xs text-muted">{{ $service->durationMinutes }} minutes</span></span></span>
<span class="text-sm font-bold">{{ $business->currency === 'GBP' ? '£' : $business->currency }}{{ number_format((float) $service->price, 2) }}</span>
</label>
@endforeach
</div>
</section>
@empty
<div class="rounded-md border border-line bg-white p-6 text-sm text-muted">No services are currently available to book.</div>
@endforelse
<div class="sticky bottom-4 pt-3"><x-ui.button class="w-full" type="submit">Continue to barber &amp; time</x-ui.button></div>
</form>
</main>
</x-layouts.public>
+19
View File
@@ -0,0 +1,19 @@
<x-layouts.public :business="$business">
<main class="mx-auto min-h-screen max-w-3xl px-5 pb-16 pt-8 lg:px-10">
<a href="{{ route('booking.services') }}" class="text-xs font-bold uppercase tracking-widest text-muted">← Services</a>
<div class="mt-10"><p class="text-[10px] font-bold uppercase tracking-widest text-muted">Step 2 of 4</p><h1 class="mt-2 text-3xl font-black tracking-tight">Pick a time</h1><p class="mt-3 text-sm text-muted">{{ $services->pluck('name')->join(', ') }}</p></div>
@if ($errors->any()) <div class="mt-5 rounded-md border border-danger/20 bg-red-50 p-4 text-sm text-red-800">{{ $errors->first() }}</div> @endif
<div class="mt-8 flex items-center justify-between rounded-md border border-line bg-white p-4"><a class="text-xl" href="{{ route('booking.time', ['date' => $date->subDay()->toDateString()]) }}" aria-label="Previous day">←</a><span class="text-sm font-bold">{{ $date->format('l, j F Y') }}</span><a class="text-xl" href="{{ route('booking.time', ['date' => $date->addDay()->toDateString()]) }}" aria-label="Next day">→</a></div>
<div class="mt-5 grid gap-3 sm:grid-cols-2">
@forelse ($slots as $slot)
<form method="POST" action="{{ route('booking.time.store') }}">
@csrf
<input type="hidden" name="staffId" value="{{ $slot['staffId'] }}">
<button type="submit" name="startAt" value="{{ $slot['startAt'] }}" class="w-full rounded-md border border-line bg-white p-4 text-left shadow-sm transition hover:-translate-y-0.5 hover:border-ink"><span class="block text-sm font-bold">{{ $slot['label'] }}</span><span class="mt-1 block text-xs text-muted">{{ $slot['staffName'] }}</span></button>
</form>
@empty
<div class="rounded-md border border-line bg-white p-6 text-sm text-muted sm:col-span-2">There are no available times on this date. Try another day.</div>
@endforelse
</div>
</main>
</x-layouts.public>