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

+33
View File
@@ -0,0 +1,33 @@
@import 'tailwindcss';
@source '../../resources/views/**/*.blade.php';
@source '../../vendor/laravel/framework/src/Illuminate/Pagination/resources/views/*.blade.php';
@theme {
--color-ink: #111b15;
--color-stone: #f4f6f4;
--color-surface: #ffffff;
--color-muted: #6c7870;
--color-line: #e1e7e2;
--color-accent: #10b981;
--color-accent-foreground: #047857;
--color-accent-loyalty: #f59e0b;
--color-danger: #ef4444;
--color-warning: #f59e0b;
--color-status-confirmed: #10b981;
--color-status-pending: #f59e0b;
--color-status-progress: #2563eb;
--color-status-cancelled: #ef4444;
--color-status-completed: #6c7870;
--radius-jumbo: 1rem;
--radius-tile: 0.75rem;
--font-sans: Inter, ui-sans-serif, system-ui, sans-serif;
}
@layer base {
html { -webkit-text-size-adjust: 100%; }
body { @apply bg-stone text-ink antialiased; }
:focus-visible { @apply ring-ink ring-offset-stone ring-2 ring-offset-2 outline-none; }
}
+1
View File
@@ -0,0 +1 @@
//
@@ -0,0 +1,3 @@
<x-layouts.public :business="$business">
<main class="bg-stone text-ink min-h-screen flex flex-col px-6 py-12"><div class="flex-1 flex flex-col justify-center max-w-md mx-auto w-full"><header class="mb-10"><a href="{{ route('auth.signin') }}" class="w-10 h-10 rounded-full border border-line flex items-center justify-center mb-8"><i class="fa-solid fa-arrow-left text-sm"></i></a><h1 class="text-3xl font-bold tracking-tight">Reset Password</h1><p class="text-muted mt-2">Enter your email and we'll send you a link to reset your password.</p></header>@if (session('status'))<div class="mb-6 rounded-2xl bg-accent/10 p-4 text-sm text-accent-foreground">{{ session('status') }}</div>@endif<form method="POST" action="{{ route('auth.forgot.store') }}" class="space-y-6">@csrf<div><label class="block text-[10px] font-bold uppercase tracking-widest text-muted mb-2 ml-1">Email Address</label><input name="email" type="email" value="{{ old('email') }}" placeholder="name@example.com" required class="w-full bg-surface border border-line rounded-xl px-5 py-4 focus:ring-2 focus:ring-ink outline-none transition-all"></div><button type="submit" class="w-full bg-ink text-white py-5 rounded-full font-bold uppercase tracking-widest hover:bg-black transition-all shadow-lg">Send Reset Link</button></form></div></main>
</x-layouts.public>
+17
View File
@@ -0,0 +1,17 @@
<x-layouts.public :business="$business">
<main class="bg-stone text-ink min-h-screen flex flex-col px-6 py-12">
<div class="flex-1 max-w-md mx-auto w-full">
<header class="mb-10"><a href="{{ route('public.home') }}" class="w-10 h-10 rounded-full border border-line flex items-center justify-center mb-8"><i class="fa-solid fa-arrow-left text-sm"></i></a><h1 class="text-3xl font-bold tracking-tight">Create Account</h1><p class="text-muted mt-2">Join {{ $business->shortName ?: $business->name }} to track your appointments and loyalty.</p></header>
@if ($errors->any())<div class="mb-5 rounded-2xl border border-red-200 bg-red-50 p-4 text-sm text-red-700">{{ $errors->first() }}</div>@endif
<form method="POST" action="{{ route('auth.register.store') }}" class="space-y-4">@csrf
<div class="grid grid-cols-2 gap-4"><div><label class="block text-[10px] font-bold uppercase tracking-widest text-muted mb-2 ml-1">First Name</label><input name="firstName" value="{{ old('firstName') }}" type="text" placeholder="John" required class="w-full bg-surface border border-line rounded-xl px-5 py-4 focus:ring-2 focus:ring-ink outline-none transition-all"></div><div><label class="block text-[10px] font-bold uppercase tracking-widest text-muted mb-2 ml-1">Last Name</label><input name="lastName" value="{{ old('lastName') }}" type="text" placeholder="Doe" required class="w-full bg-surface border border-line rounded-xl px-5 py-4 focus:ring-2 focus:ring-ink outline-none transition-all"></div></div>
<div><label class="block text-[10px] font-bold uppercase tracking-widest text-muted mb-2 ml-1">Email Address</label><input name="email" value="{{ old('email') }}" type="email" placeholder="name@example.com" required class="w-full bg-surface border border-line rounded-xl px-5 py-4 focus:ring-2 focus:ring-ink outline-none transition-all"></div>
<div><label class="block text-[10px] font-bold uppercase tracking-widest text-muted mb-2 ml-1">Phone Number</label><input name="phone" value="{{ old('phone') }}" type="tel" placeholder="+1 (555) 000-0000" class="w-full bg-surface border border-line rounded-xl px-5 py-4 focus:ring-2 focus:ring-ink outline-none transition-all"></div>
<div><label class="block text-[10px] font-bold uppercase tracking-widest text-muted mb-2 ml-1">Password</label><input name="password" type="password" placeholder="••••••••" required class="w-full bg-surface border border-line rounded-xl px-5 py-4 focus:ring-2 focus:ring-ink outline-none transition-all"></div>
<div><label class="block text-[10px] font-bold uppercase tracking-widest text-muted mb-2 ml-1">Confirm Password</label><input name="password_confirmation" type="password" placeholder="••••••••" required class="w-full bg-surface border border-line rounded-xl px-5 py-4 focus:ring-2 focus:ring-ink outline-none transition-all"></div>
<p class="text-[10px] text-muted leading-relaxed px-1">By creating an account, you agree to our <a href="#" class="underline">Terms of Service</a> and <a href="#" class="underline">Privacy Policy</a>.</p><button type="submit" class="w-full bg-ink text-white py-5 rounded-full font-bold uppercase tracking-widest hover:bg-black transition-all shadow-lg mt-4">Sign Up</button>
</form>
<p class="mt-10 text-center text-sm text-muted">Already have an account? <a href="{{ route('auth.signin') }}" class="text-ink font-bold border-b border-ink">Log in</a></p>
</div>
</main>
</x-layouts.public>
+21
View File
@@ -0,0 +1,21 @@
<x-layouts.public :business="$business">
<main class="bg-stone text-ink min-h-screen flex flex-col p-6">
<div class="flex-1 flex flex-col justify-center max-w-md mx-auto w-full">
<header class="mb-12">
<a href="{{ route('public.home') }}" class="w-16 h-16 bg-ink text-white rounded-[1.25rem] flex items-center justify-center text-3xl mb-8 shadow-xl shadow-ink/20"><i class="fa-solid fa-scissors"></i></a>
<h1 class="text-4xl font-bold tracking-tight mb-2">Welcome</h1>
<p class="text-muted leading-relaxed">Please enter your credentials to access your appointments.</p>
</header>
@if ($errors->any())<div class="mb-5 rounded-2xl border border-red-200 bg-red-50 p-4 text-sm text-red-700">{{ $errors->first() }}</div>@endif
<form method="POST" action="{{ route('auth.signin.store') }}" class="space-y-4">
@csrf
<div><label class="block text-[10px] font-bold uppercase tracking-[0.2em] text-muted mb-2 ml-1">Email Address</label><div class="relative"><i class="fa-regular fa-envelope absolute left-5 top-1/2 -translate-y-1/2 text-muted"></i><input name="email" type="email" value="{{ old('email') }}" placeholder="name@example.com" required autofocus class="w-full bg-white border border-line rounded-2xl pl-12 pr-5 py-4 focus:ring-2 focus:ring-ink outline-none transition-all"></div></div>
<div><div class="flex justify-between items-center mb-2 ml-1"><label class="text-[10px] font-bold uppercase tracking-[0.2em] text-muted">Password</label><a href="{{ route('auth.forgot') }}" class="text-[10px] font-bold uppercase tracking-[0.2em] text-muted">Forgot?</a></div><div class="relative"><i class="fa-solid fa-lock absolute left-5 top-1/2 -translate-y-1/2 text-muted"></i><input name="password" type="password" placeholder="••••••••" required class="w-full bg-white border border-line rounded-2xl pl-12 pr-12 py-4 focus:ring-2 focus:ring-ink outline-none transition-all"></div></div>
<label class="flex items-center gap-2 text-xs text-muted"><input name="remember" type="checkbox" value="1" class="rounded border-line text-accent"> Remember me</label>
<button type="submit" class="w-full bg-ink text-white py-5 rounded-full font-bold uppercase tracking-[0.15em] hover:bg-black transition-all shadow-xl shadow-ink/10 mt-6">Sign In</button>
</form>
<div class="mt-10"><div class="relative flex items-center justify-center mb-8"><div class="absolute inset-0 flex items-center"><div class="w-full border-t border-line"></div></div><span class="relative bg-stone px-4 text-[10px] font-bold text-muted uppercase tracking-[0.2em]">Or continue with</span></div><div class="grid grid-cols-2 gap-4"><button type="button" class="flex items-center justify-center gap-3 bg-white border border-line py-4 rounded-2xl hover:bg-stone/50 transition-all font-bold text-xs uppercase tracking-widest"><i class="fa-brands fa-google text-red-500"></i> Google</button><button type="button" class="flex items-center justify-center gap-3 bg-white border border-line py-4 rounded-2xl hover:bg-stone/50 transition-all font-bold text-xs uppercase tracking-widest"><i class="fa-brands fa-apple"></i> Apple</button></div></div>
<p class="mt-12 text-center text-sm text-muted">Don't have an account? <a href="{{ route('auth.register') }}" class="text-ink font-bold border-b-2 border-ink">Create one</a></p>
</div>
</main>
</x-layouts.public>
+3
View File
@@ -0,0 +1,3 @@
<x-layouts.public :business="$business">
<main class="mx-auto flex min-h-screen max-w-md flex-col justify-center px-6 py-12 text-center"><a href="{{ route('auth.signin') }}" class="absolute left-6 top-6 flex h-10 w-10 items-center justify-center rounded-full border border-line bg-white"><i class="fa-solid fa-arrow-left text-sm"></i></a><div class="mx-auto flex h-16 w-16 items-center justify-center rounded-2xl bg-ink text-2xl text-white"><i class="fa-solid fa-envelope"></i></div><h1 class="mt-8 text-3xl font-black tracking-tight">Verify your account</h1><p class="mt-3 text-sm leading-6 text-muted">Check your email for a verification link to finish setting up your account.</p><button type="button" class="mt-8 w-full rounded-full bg-ink py-5 text-xs font-bold uppercase tracking-widest text-white">Resend email</button><a href="{{ route('auth.signin') }}" class="mt-6 text-xs font-bold uppercase tracking-widest text-muted">Back to sign in</a></main>
</x-layouts.public>
+3
View File
@@ -0,0 +1,3 @@
<x-layouts.public :business="$business">
<main class="relative flex min-h-screen flex-col justify-end overflow-hidden bg-ink px-6 pb-12 text-white"><img src="{{ $business->welcomeBackgroundMobileUrl ?: 'https://storage.googleapis.com/uxpilot-auth.appspot.com/gen_7e6e0f551f0f4e45e0f1b6ea0c1acb39.png' }}" alt="{{ $business->name }}" class="absolute inset-0 h-full w-full object-cover opacity-60"><div class="absolute inset-0 bg-gradient-to-t from-ink via-ink/40 to-ink/10"></div><div class="relative z-10"><div class="mb-10 flex h-16 w-16 items-center justify-center rounded-2xl bg-white text-3xl text-ink"><i class="fa-solid fa-scissors"></i></div><p class="text-xs font-bold uppercase tracking-[0.3em] text-white/60">{{ $business->shortName ?: $business->name }}</p><h1 class="mt-3 text-5xl font-black tracking-tight">Welcome</h1><p class="mt-4 max-w-xs text-sm leading-6 text-white/70">Book your next appointment in a few taps.</p><div class="mt-10 space-y-3"><a href="{{ route('auth.register') }}" class="block w-full rounded-full bg-white py-5 text-center text-xs font-bold uppercase tracking-widest text-ink">Create account</a><a href="{{ route('auth.signin') }}" class="block w-full rounded-full border border-white/30 py-5 text-center text-xs font-bold uppercase tracking-widest text-white">Sign in</a><a href="{{ route('public.home') }}" class="block py-3 text-center text-xs font-bold uppercase tracking-widest text-white/60">Continue as guest</a></div></div></main>
</x-layouts.public>
@@ -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>
@@ -0,0 +1,18 @@
@props(['business' => null])
<!doctype html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="{{ $business?->themeColor ?? '#111b15' }}">
<title>{{ $business?->name ?? 'Book an Appointment' }}</title>
<script>window.FontAwesomeConfig = { autoReplaceSvg: 'nest' };</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/js/all.min.js" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
@vite(['resources/css/app.css', 'resources/js/app.js'])
</head>
<body class="min-h-screen bg-stone text-ink">
{{ $slot }}
</body>
</html>
@@ -0,0 +1,15 @@
@props(['business'])
<!doctype html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="#111b15">
<title>{{ $business->shortName ?: $business->name }} · Staff</title>
@vite(['resources/css/app.css', 'resources/js/app.js'])
</head>
<body class="min-h-screen bg-ink text-white">
{{ $slot }}
</body>
</html>
@@ -0,0 +1,11 @@
@props(['tone' => 'default'])
@php
$classes = match ($tone) {
'accent' => 'bg-emerald-50 text-accent-foreground',
'loyalty' => 'bg-amber-50 text-amber-800',
default => 'bg-stone text-muted',
};
@endphp
<span {{ $attributes->merge(['class' => "inline-flex items-center rounded-full px-3 py-1 text-[10px] font-bold uppercase tracking-widest {$classes}"]) }}>{{ $slot }}</span>
@@ -0,0 +1,24 @@
@props(['variant' => 'primary', 'href' => null, 'size' => 'md'])
@php
$classes = match ($variant) {
'secondary' => 'border border-line bg-white text-ink hover:bg-stone',
'accent' => 'bg-accent text-white hover:brightness-95',
'ghost' => 'text-ink hover:bg-stone',
default => 'bg-ink text-white shadow-lg shadow-ink/10 hover:bg-black',
};
$sizeClasses = match ($size) {
'sm' => 'h-10 px-4 text-[10px]',
default => 'h-12 px-6 text-xs',
};
@endphp
@if ($href)
<a href="{{ $href }}" {{ $attributes->except('size')->merge(['class' => "inline-flex items-center justify-center gap-2 rounded-md font-bold uppercase tracking-widest transition-all {$sizeClasses} {$classes}"]) }}>
{{ $slot }}
</a>
@else
<button {{ $attributes->except('size')->merge(['class' => "inline-flex items-center justify-center gap-2 rounded-md font-bold uppercase tracking-widest transition-all {$sizeClasses} {$classes}"]) }}>
{{ $slot }}
</button>
@endif
@@ -0,0 +1,3 @@
<div {{ $attributes->merge(['class' => 'rounded-md border border-line bg-white shadow-sm']) }}>
{{ $slot }}
</div>
@@ -0,0 +1 @@
<x-layouts.public :business="$business"><main class="mx-auto max-w-2xl px-5 pb-16 pt-8 lg:px-10"><a href="{{ route('customer.appointments') }}" class="text-xs font-bold uppercase tracking-widest text-muted">← Appointments</a><div class="mt-12"><p class="text-[10px] font-bold uppercase tracking-[0.3em] text-accent-foreground">Appointment details</p><h1 class="mt-3 text-4xl font-black tracking-tight">{{ $appointment->startAt->setTimezone($business->timezone)->format('l, j F') }}</h1><p class="mt-3 text-sm text-muted">{{ $appointment->startAt->setTimezone($business->timezone)->format('g:i A') }} · with {{ $appointment->staff->user?->name ?: 'your barber' }}</p></div><x-ui.card class="mt-8 p-6"><p class="text-sm font-bold">{{ $appointment->services->pluck('service.name')->join(', ') }}</p><p class="mt-3 text-sm text-muted">Status: {{ str_replace('_', ' ', ucfirst(strtolower($appointment->status->value))) }}</p><p class="mt-5 border-t border-line pt-5 text-sm font-bold">Total £{{ number_format((float) $appointment->services->sum('priceAtBooking') - (float) ($appointment->discountAmount ?? 0), 2) }}</p></x-ui.card>@if (in_array($appointment->status->value, ['PENDING', 'CONFIRMED']))<form method="POST" action="{{ route('customer.appointments.cancel', $appointment->id) }}" class="mt-6">@csrf<button class="text-xs font-bold uppercase tracking-widest text-danger">Cancel appointment</button></form>@endif</main></x-layouts.public>
@@ -0,0 +1,13 @@
<x-layouts.public :business="$business">
@php($upcoming = $appointments->filter(fn ($appointment) => $appointment->startAt->isFuture() && ! in_array($appointment->status->value, ['CANCELLED', 'COMPLETED']))->values())
@php($past = $appointments->reject(fn ($appointment) => $upcoming->contains('id', $appointment->id))->values())
<div class="mx-auto min-h-screen max-w-md bg-stone pb-28 text-ink">
<header class="sticky top-0 z-40 border-b border-line bg-white px-6 py-6"><h1 class="mb-5 text-2xl font-bold tracking-tight">Appointments</h1><div class="flex gap-2 rounded-full bg-stone p-1"><button id="tab-upcoming" onclick="switchTab('upcoming')" class="flex-1 rounded-full bg-ink py-2.5 text-xs font-bold uppercase tracking-widest text-white">Upcoming</button><button id="tab-past" onclick="switchTab('past')" class="flex-1 rounded-full py-2.5 text-xs font-bold uppercase tracking-widest text-muted">Past</button></div></header>
<main class="mt-6 space-y-4 px-6">
<div id="content-upcoming" class="space-y-4">@forelse ($upcoming as $appointment)<article class="rounded-jumbo border border-line bg-white p-5 shadow-sm"><div class="mb-4 flex items-start justify-between"><span class="rounded-full bg-accent/10 px-3 py-1 text-[10px] font-bold uppercase tracking-widest text-accent">{{ str_replace('_', ' ', strtolower($appointment->status->value)) }}</span><div class="text-right"><p class="text-sm font-bold">{{ $appointment->startAt->setTimezone($business->timezone)->format('D, M j') }}</p><p class="text-xs text-muted">{{ $appointment->startAt->setTimezone($business->timezone)->format('g:i A') }}</p></div></div><div class="mb-4 flex items-center gap-3"><div class="flex h-10 w-10 items-center justify-center rounded-full bg-stone"><i class="fa-solid fa-scissors"></i></div><div><h3 class="text-sm font-bold">{{ $appointment->services->pluck('service.name')->join(', ') }}</h3><p class="text-xs text-muted">with {{ $appointment->staff->user?->name ?: 'your barber' }}</p></div></div><div class="flex gap-2 border-t border-line pt-4"><a href="{{ route('customer.appointments.show', $appointment->id) }}" class="flex-1 rounded-lg bg-stone py-2.5 text-center text-xs font-bold uppercase tracking-widest">Details</a>@if (in_array($appointment->status->value, ['PENDING', 'CONFIRMED']))<form class="flex-1" method="POST" action="{{ route('customer.appointments.cancel', $appointment->id) }}">@csrf<button class="w-full rounded-lg border border-red-200 py-2.5 text-xs font-bold uppercase tracking-widest text-red-500">Cancel</button></form>@endif</div></article>@empty<div class="flex flex-col items-center px-6 py-16 text-center"><div class="mb-5 flex h-16 w-16 items-center justify-center rounded-full border border-line bg-white text-2xl text-muted"><i class="fa-regular fa-calendar"></i></div><h3 class="mb-1 text-base font-bold">No upcoming appointments</h3><p class="mb-6 text-sm text-muted">Book your next visit in a few taps.</p><a href="{{ route('booking.services') }}" class="rounded-full bg-ink px-8 py-3.5 text-xs font-bold uppercase tracking-widest text-white">Book now</a></div>@endforelse</div>
<div id="content-past" class="hidden space-y-4">@forelse ($past as $appointment)<article class="flex rounded-jumbo border border-line bg-white p-4"><div class="flex-1 pr-4"><span class="mb-3 inline-block rounded-full bg-stone px-3 py-1 text-[10px] font-bold uppercase tracking-widest text-muted">{{ str_replace('_', ' ', strtolower($appointment->status->value)) }}</span><h3 class="mb-1 text-sm font-bold">{{ $appointment->services->pluck('service.name')->join(', ') }}</h3><p class="mb-3 text-xs text-muted">{{ $appointment->startAt->setTimezone($business->timezone)->format('D, M j · g:i A') }}</p><a href="{{ route('booking.services') }}" class="inline-block rounded-lg bg-ink px-5 py-2.5 text-xs font-bold uppercase tracking-widest text-white">Book again</a></div><div class="flex w-16 flex-col items-center justify-center border-l border-line pl-4 text-center"><span class="text-[10px] uppercase text-muted">{{ $appointment->startAt->setTimezone($business->timezone)->format('M') }}</span><span class="text-2xl font-light">{{ $appointment->startAt->setTimezone($business->timezone)->format('j') }}</span></div></article>@empty<p class="py-16 text-center text-sm text-muted">No past appointments yet.</p>@endforelse</div>
</main>
<nav class="fixed bottom-0 left-0 right-0 z-50 mx-auto flex max-w-md items-center justify-between border-t border-line bg-white px-5 py-2"><a href="{{ route('customer.dashboard') }}" class="flex flex-col items-center gap-1 text-muted"><i class="fa-solid fa-house text-xl"></i><span class="text-[10px] font-bold uppercase tracking-widest">Home</span></a><a href="{{ route('customer.appointments') }}" class="flex flex-col items-center gap-1 text-ink"><i class="fa-solid fa-calendar-check text-xl"></i><span class="text-[10px] font-bold uppercase tracking-widest">Bookings</span></a><a href="{{ route('customer.profile') }}" class="flex flex-col items-center gap-1 text-muted"><i class="fa-solid fa-user text-xl"></i><span class="text-[10px] font-bold uppercase tracking-widest">Settings</span></a></nav>
</div>
<script>function switchTab(tab){const upcoming=document.getElementById('content-upcoming'),past=document.getElementById('content-past'),upBtn=document.getElementById('tab-upcoming'),pastBtn=document.getElementById('tab-past');const isUpcoming=tab==='upcoming';upcoming.classList.toggle('hidden',!isUpcoming);past.classList.toggle('hidden',isUpcoming);upBtn.classList.toggle('bg-ink',isUpcoming);upBtn.classList.toggle('text-white',isUpcoming);upBtn.classList.toggle('text-muted',!isUpcoming);pastBtn.classList.toggle('bg-ink',!isUpcoming);pastBtn.classList.toggle('text-white',!isUpcoming);pastBtn.classList.toggle('text-muted',isUpcoming)}</script>
</x-layouts.public>
@@ -0,0 +1,22 @@
<x-layouts.public :business="$business">
<div class="mx-auto min-h-screen max-w-md bg-stone pb-28 text-ink">
<header class="flex items-center justify-between px-6 pb-4 pt-10">
<div><p class="text-xs font-medium text-muted">{{ now($business->timezone)->format('H') < 12 ? 'Good morning' : (now($business->timezone)->format('H') < 18 ? 'Good afternoon' : 'Good evening') }}</p><h1 class="text-2xl font-bold tracking-tight">{{ $profile?->firstName ?: $user->name }}</h1><span class="sr-only">Good to see you, {{ $profile?->firstName ?: $user->name }}</span></div>
<div class="flex items-center gap-3"><a href="{{ route('customer.notifications') }}" class="relative flex h-11 w-11 items-center justify-center rounded-full border border-line bg-white"><i class="fa-regular fa-bell"></i></a><a href="{{ route('customer.profile') }}" class="flex h-11 w-11 items-center justify-center rounded-full border border-line bg-ink text-white"><i class="fa-solid fa-user"></i></a></div>
</header>
<main class="space-y-6 px-6">
@if ($appointments->first())
@php($next = $appointments->first())
<a href="{{ route('customer.appointments.show', $next->id) }}" class="relative block overflow-hidden rounded-jumbo bg-ink p-6 text-white shadow-xl"><div class="relative z-10"><div class="mb-6 flex items-center justify-between"><span class="text-[10px] font-bold uppercase tracking-widest text-white/50">Your next visit</span><span class="rounded-full bg-accent/20 px-3 py-1 text-[10px] font-bold uppercase tracking-widest text-accent">{{ ucfirst(strtolower($next->status->value)) }}</span></div><div class="mb-6 flex items-center gap-4"><div class="flex h-14 w-14 items-center justify-center rounded-full border-2 border-white/20 bg-white/10"><i class="fa-solid fa-scissors"></i></div><div><h2 class="text-lg font-bold">{{ $next->services->pluck('service.name')->join(', ') }}</h2><p class="text-sm text-white/60">with {{ $next->staff->user?->name ?: 'your barber' }}</p></div></div><div class="flex items-center justify-between border-t border-white/10 pt-5"><div><p class="text-sm font-bold">{{ $next->startAt->setTimezone($business->timezone)->format('D, M j · g:i A') }}</p><p class="mt-0.5 text-[10px] uppercase tracking-widest text-white/50">{{ $business->name }}</p></div><span class="flex items-center gap-1 text-xs font-bold uppercase tracking-widest text-white/60">Details <i class="fa-solid fa-chevron-right text-[10px]"></i></span></div></div><div class="absolute -bottom-10 -right-10 h-40 w-40 rounded-full bg-accent/10 blur-3xl"></div></a>
@endif
<div class="grid grid-cols-2 gap-3"><a href="{{ route('booking.services') }}" class="flex flex-col gap-3 rounded-jumbo border border-line bg-white p-5"><div class="flex h-10 w-10 items-center justify-center rounded-xl bg-stone"><i class="fa-solid fa-rotate-right"></i></div><span class="text-sm font-bold">Book again</span></a><a href="{{ route('booking.services') }}" class="flex flex-col gap-3 rounded-jumbo border border-line bg-white p-5"><div class="flex h-10 w-10 items-center justify-center rounded-xl bg-stone"><i class="fa-solid fa-plus"></i></div><span class="text-sm font-bold">Book new</span></a></div>
@if ($loyaltySummary)
@php($threshold = max(1, $loyaltySummary['threshold']))
<a href="{{ route('customer.loyalty') }}" class="block rounded-jumbo border border-line bg-white p-5"><div class="mb-4 flex items-center justify-between"><div class="flex items-center gap-3"><div class="flex h-10 w-10 items-center justify-center rounded-xl bg-amber-50 text-amber-500"><i class="fa-solid fa-award"></i></div><div><p class="text-sm font-bold">Loyalty card</p><p class="text-[11px] text-muted">{{ max(0, $threshold - $loyaltySummary['currentStamps']) }} more visits until your reward</p></div></div><i class="fa-solid fa-chevron-right text-[10px] text-muted"></i></div><div class="h-2 w-full overflow-hidden rounded-full bg-stone"><div class="h-full rounded-full bg-amber-500" style="width: {{ min(100, ($loyaltySummary['currentStamps'] / $threshold) * 100) }}%"></div></div></a>
@endif
<section><div class="mb-4 flex items-center justify-between px-1"><h3 class="text-[10px] font-bold uppercase tracking-widest text-muted">Your barbers</h3><a href="{{ route('public.home') }}#details" class="border-b border-ink text-[10px] font-bold uppercase tracking-widest">See all</a></div><div class="flex gap-5 overflow-x-auto no-scrollbar">@forelse ($business->staff->where('status.value', 'ACTIVE')->take(4) as $member)<div class="w-20 shrink-0 text-center"><div class="mb-2 flex h-20 w-20 items-center justify-center rounded-full border border-line bg-white text-xl"><i class="fa-solid fa-user"></i></div><p class="text-xs font-medium">{{ Str::before($member->user?->name ?: 'Barber', ' ') }}</p></div>@empty<p class="text-sm text-muted">Your shop team will appear here.</p>@endforelse</div></section>
<section><div class="mb-4 flex items-center justify-between px-1"><h3 class="text-[10px] font-bold uppercase tracking-widest text-muted">Popular services</h3><a href="{{ route('public.home') }}#services" class="border-b border-ink text-[10px] font-bold uppercase tracking-widest">See all</a></div><div class="divide-y divide-line overflow-hidden rounded-jumbo border border-line bg-white">@foreach ($business->serviceCategories->flatMap->services->where('isActive', true)->take(3) as $service)<div class="flex items-center justify-between px-5 py-4"><div><p class="text-sm font-bold">{{ $service->name }}</p><p class="mt-0.5 text-xs text-muted">{{ $service->durationMinutes }}m</p></div><span class="text-sm font-bold">£{{ number_format((float) $service->price, 2) }}</span></div>@endforeach</div></section>
</main>
<nav class="fixed bottom-0 left-0 right-0 z-50 mx-auto flex max-w-md items-center justify-between border-t border-line bg-white px-5 py-2"><a href="{{ route('customer.dashboard') }}" class="flex flex-col items-center gap-1 text-ink"><i class="fa-solid fa-house text-xl"></i><span class="text-[10px] font-bold uppercase tracking-widest">Home</span></a><a href="{{ route('customer.appointments') }}" class="flex flex-col items-center gap-1 text-muted"><i class="fa-solid fa-calendar-check text-xl"></i><span class="text-[10px] font-bold uppercase tracking-widest">Bookings</span></a><a href="{{ route('customer.profile') }}" class="flex flex-col items-center gap-1 text-muted"><i class="fa-solid fa-user text-xl"></i><span class="text-[10px] font-bold uppercase tracking-widest">Settings</span></a></nav>
</div>
</x-layouts.public>
@@ -0,0 +1,13 @@
<x-layouts.public :business="$business">
<div class="mx-auto min-h-screen max-w-md bg-stone pb-28 text-ink">
<header class="flex items-center justify-between px-6 pb-4 pt-10"><a href="{{ route('customer.dashboard') }}" class="flex h-11 w-11 items-center justify-center rounded-full border border-line bg-white"><i class="fa-solid fa-arrow-left text-sm"></i></a><h1 class="text-xl font-bold tracking-tight">Loyalty Rewards</h1><div class="w-11"></div></header>
<main class="px-5 pt-2">
@if (! $summary)<div class="rounded-jumbo border border-line bg-white p-6 text-sm text-muted">{{ $business->shortName ?: $business->name }} hasn’t enabled a loyalty programme yet.</div>@else
@php($threshold = max(1, $summary['threshold']))
<div class="relative mb-10 aspect-[1.65/1] overflow-hidden rounded-2xl border-[3px] border-amber-500 bg-[#141414] p-4 text-white shadow-2xl"><div class="flex items-center justify-between"><h2 class="text-xl font-black italic tracking-tight">{{ $summary['programme']->cardTitleText ?: 'Loyalty Card' }}</h2><span class="rounded border border-amber-500/30 px-2 py-0.5 text-[8px] font-bold uppercase tracking-widest text-amber-400">Member</span></div><div class="mt-2 h-0.5 w-10 bg-amber-500"></div><div class="mt-4 grid grid-cols-5 gap-2">@for ($i = 1; $i <= $threshold; $i++)<div class="flex aspect-square items-center justify-center rounded-full {{ $i <= $summary['currentStamps'] ? 'bg-white text-ink' : 'border-2 border-dashed border-white/20 bg-[#2a2a2a]' }}">@if ($i <= $summary['currentStamps'])<i class="fa-solid fa-mustache text-xs"></i>@endif</div>@endfor</div><p class="absolute bottom-3 left-0 right-0 text-center text-[7px] font-bold uppercase tracking-[0.18em] text-white/40">{{ $summary['programme']->termsLine ?: 'Earn stamps with every eligible visit' }}</p></div>
<div class="space-y-5"><div class="rounded-3xl border border-line bg-white p-6 text-center shadow-sm"><h3 class="mb-1 text-lg font-bold">Almost there{{ $customer->firstName ? ', '.$customer->firstName : '' }}!</h3><p class="text-sm text-muted">Complete {{ max(0, $threshold - $summary['currentStamps']) }} more visits to unlock your reward.</p><div class="mt-5 h-2 w-full overflow-hidden rounded-full bg-stone"><div class="h-full rounded-full bg-amber-500" style="width: {{ min(100, ($summary['currentStamps'] / $threshold) * 100) }}%"></div></div><p class="mt-2 text-xs text-muted">{{ $summary['currentStamps'] }} of {{ $threshold }} visits completed</p></div><div class="rounded-3xl border border-line bg-white p-6 shadow-sm"><h4 class="mb-5 text-xs font-bold uppercase tracking-widest text-muted">How it works</h4><div class="space-y-4">@foreach (['Book your appointment through the shop.', 'Show this digital card to your barber after your visit.', 'Your barber adds a stamp to your card instantly.'] as $index => $step)<div class="flex items-start gap-4"><div class="flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-stone text-xs font-bold">{{ $index + 1 }}</div><p class="pt-1 text-xs leading-relaxed text-muted">{{ $step }}</p></div>@endforeach</div></div></div>
@endif
</main>
<nav class="fixed bottom-0 left-0 right-0 z-50 mx-auto flex max-w-md items-center justify-between border-t border-line bg-white px-5 py-2"><a href="{{ route('customer.dashboard') }}" class="flex flex-col items-center gap-1 text-muted"><i class="fa-solid fa-house text-xl"></i><span class="text-[10px] font-bold uppercase tracking-widest">Home</span></a><a href="{{ route('customer.appointments') }}" class="flex flex-col items-center gap-1 text-muted"><i class="fa-solid fa-calendar-check text-xl"></i><span class="text-[10px] font-bold uppercase tracking-widest">Bookings</span></a><a href="{{ route('customer.loyalty') }}" class="flex flex-col items-center gap-1 text-ink"><i class="fa-solid fa-user text-xl"></i><span class="text-[10px] font-bold uppercase tracking-widest">Settings</span></a></nav>
</div>
</x-layouts.public>
@@ -0,0 +1,4 @@
<x-layouts.public :business="$business">
<header class="mx-auto flex max-w-6xl items-center justify-between px-5 py-5 lg:px-10"><a href="{{ route('customer.dashboard') }}" class="text-xs font-bold uppercase tracking-widest text-muted">← Account</a><a href="{{ route('customer.loyalty') }}" class="text-xs font-bold uppercase tracking-widest text-muted">Loyalty</a></header>
<main class="mx-auto max-w-3xl px-5 pb-16 pt-10 lg:px-10 lg:pt-16"><p class="text-[10px] font-bold uppercase tracking-[0.3em] text-accent-foreground">Updates</p><h1 class="mt-3 text-4xl font-black tracking-tight">Notifications</h1><div class="mt-8 space-y-3">@forelse ($notifications as $notification)<x-ui.card class="p-5 {{ $notification->readAt ? 'opacity-60' : '' }}"><div class="flex items-start justify-between gap-5"><div><p class="text-sm font-bold">{{ $notification->subject ?: 'Update from '.$business->shortName }}</p><p class="mt-2 text-sm leading-6 text-muted">{{ $notification->bodyText }}</p><p class="mt-3 text-xs text-muted">{{ $notification->createdAt->diffForHumans() }}</p></div>@if (! $notification->readAt)<form method="POST" action="{{ route('customer.notifications.read', $notification->id) }}">@csrf<button class="text-[10px] font-bold uppercase tracking-widest text-accent-foreground">Mark read</button></form>@endif</div></x-ui.card>@empty<x-ui.card class="p-6"><p class="text-sm text-muted">You’re all caught up.</p></x-ui.card>@endforelse</div></main>
</x-layouts.public>
@@ -0,0 +1 @@
<x-layouts.public :business="$business"><main class="mx-auto max-w-2xl px-5 pb-16 pt-8 lg:px-10"><a href="{{ route('customer.dashboard') }}" class="text-xs font-bold uppercase tracking-widest text-muted">← Account</a><p class="mt-12 text-[10px] font-bold uppercase tracking-[0.3em] text-accent-foreground">Your details</p><h1 class="mt-3 text-4xl font-black tracking-tight">Profile</h1>@if (session('status'))<div class="mt-6 rounded-tile bg-accent p-4 text-sm font-bold text-ink">{{ session('status') }}</div>@endif<form method="POST" action="{{ route('customer.profile.update') }}" class="mt-8 space-y-5 rounded-jumbo bg-white p-6">@csrf @method('PUT')<div class="grid gap-5 sm:grid-cols-2"><label class="text-sm font-bold">First name<input name="firstName" value="{{ $profile->firstName }}" required class="mt-2 w-full rounded-tile border border-line px-4 py-3"></label><label class="text-sm font-bold">Last name<input name="lastName" value="{{ $profile->lastName }}" required class="mt-2 w-full rounded-tile border border-line px-4 py-3"></label></div><label class="block text-sm font-bold">Email address<input value="{{ $profile->email }}" disabled class="mt-2 w-full rounded-tile border border-line bg-stone px-4 py-3 text-muted"></label><label class="block text-sm font-bold">Phone<input name="phone" value="{{ $profile->phone }}" class="mt-2 w-full rounded-tile border border-line px-4 py-3"></label><x-ui.button type="submit">Save profile</x-ui.button></form></main></x-layouts.public>
+1
View File
@@ -0,0 +1 @@
<x-layouts.public :business="null"><main class="mx-auto flex min-h-screen max-w-xl flex-col justify-center px-5 py-16 lg:px-10"><p class="text-[10px] font-bold uppercase tracking-[0.3em] text-accent-foreground">NextChair setup</p><h1 class="mt-3 text-4xl font-black tracking-tight">Create your business</h1><p class="mt-4 text-sm leading-6 text-muted">Set up the first business owner and start configuring your booking workspace.</p>@if (session('status'))<div class="mt-6 rounded-tile bg-accent p-4 text-sm font-bold text-ink">{{ session('status') }}</div><a href="{{ route('auth.signin') }}" class="mt-6 text-sm font-bold text-accent-foreground underline">Sign in</a>@else @if ($errors->any())<div class="mt-6 rounded-tile border border-red-200 bg-red-50 p-4 text-sm text-red-700">{{ $errors->first() }}</div>@endif<form method="POST" action="{{ route('install.store') }}" class="mt-8 space-y-5">@csrf<label class="block text-sm font-bold">Business name<input name="businessName" required class="mt-2 w-full rounded-tile border border-line bg-white px-4 py-3"></label><label class="block text-sm font-bold">Business slug<input name="slug" required placeholder="my-barbershop" class="mt-2 w-full rounded-tile border border-line bg-white px-4 py-3"></label><label class="block text-sm font-bold">Domain <span class="font-normal text-muted">(optional)</span><input name="domain" placeholder="book.example.com" class="mt-2 w-full rounded-tile border border-line bg-white px-4 py-3"></label><div class="grid gap-5 sm:grid-cols-2"><label class="block text-sm font-bold">Owner name<input name="adminName" required class="mt-2 w-full rounded-tile border border-line bg-white px-4 py-3"></label><label class="block text-sm font-bold">Owner email<input name="adminEmail" type="email" required class="mt-2 w-full rounded-tile border border-line bg-white px-4 py-3"></label></div><label class="block text-sm font-bold">Password<input name="password" type="password" required class="mt-2 w-full rounded-tile border border-line bg-white px-4 py-3"></label><label class="block text-sm font-bold">Confirm password<input name="password_confirmation" type="password" required class="mt-2 w-full rounded-tile border border-line bg-white px-4 py-3"></label><x-ui.button type="submit" class="w-full">Finish setup</x-ui.button></form>@endif</main></x-layouts.public>
+16
View File
@@ -0,0 +1,16 @@
<!doctype html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="{{ $business?->themeColor ?? '#111b15' }}">
<title>{{ $business?->name ?? 'Book an Appointment' }}</title>
<script>window.FontAwesomeConfig = { autoReplaceSvg: 'nest' };</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/js/all.min.js" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
@vite(['resources/css/app.css', 'resources/js/app.js'])
</head>
<body class="min-h-screen bg-stone text-ink">
{{ $slot }}
</body>
</html>
+13
View File
@@ -0,0 +1,13 @@
<!doctype html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="#111b15">
<title>{{ $business->shortName ?: $business->name }} · Staff</title>
@vite(['resources/css/app.css', 'resources/js/app.js'])
</head>
<body class="min-h-screen bg-ink text-white">
{{ $slot }}
</body>
</html>
@@ -0,0 +1,7 @@
<x-layouts.public>
<main class="mx-auto flex min-h-screen max-w-xl flex-col justify-center px-6 py-16">
<p class="text-[10px] font-bold uppercase tracking-[0.3em] text-accent-foreground">NextChair Manager</p>
<h1 class="mt-4 text-4xl font-black tracking-tight">Platform operations</h1>
<p class="mt-4 text-sm leading-6 text-muted">Tenant administration is being migrated into the Laravel application. Deployment and server controls are intentionally excluded.</p>
</main>
</x-layouts.public>
@@ -0,0 +1 @@
<x-layouts.staff :business="$business"><main class="mx-auto max-w-3xl px-5 py-8 sm:px-8 lg:px-12 lg:py-12"><a href="{{ route('owner.services') }}" class="text-xs font-bold uppercase tracking-widest text-white/60">← Services</a><p class="mt-12 text-[10px] font-bold uppercase tracking-[0.3em] text-accent">Scheduling policy</p><h1 class="mt-3 text-4xl font-black tracking-tight">Booking rules</h1>@if (session('status'))<div class="mt-6 rounded-tile bg-accent p-4 text-sm font-bold text-ink">{{ session('status') }}</div>@endif<form method="POST" action="{{ route('owner.booking-rules.update') }}" class="mt-8 space-y-5 rounded-jumbo bg-white p-6 text-ink">@csrf @method('PUT')<div class="grid gap-5 sm:grid-cols-2"><label class="text-sm font-bold">Minimum notice (minutes)<input name="minNoticeMinutes" type="number" value="{{ $rules->minNoticeMinutes }}" class="mt-2 w-full rounded-tile border border-line px-4 py-3"></label><label class="text-sm font-bold">Max advance (days)<input name="maxAdvanceDays" type="number" value="{{ $rules->maxAdvanceDays }}" class="mt-2 w-full rounded-tile border border-line px-4 py-3"></label><label class="text-sm font-bold">Slot interval<select name="slotIntervalMinutes" class="mt-2 w-full rounded-tile border border-line px-4 py-3"><option value="15">15 minutes</option><option value="30" @selected($rules->slotIntervalMinutes == 30)>30 minutes</option><option value="60" @selected($rules->slotIntervalMinutes == 60)>60 minutes</option></select></label><label class="text-sm font-bold">Cancellation window (hours)<input name="cancellationWindowHours" type="number" value="{{ $rules->cancellationWindowHours ?? 24 }}" class="mt-2 w-full rounded-tile border border-line px-4 py-3"></label><label class="text-sm font-bold">Reschedule window (hours)<input name="rescheduleWindowHours" type="number" value="{{ $rules->rescheduleWindowHours ?? 24 }}" class="mt-2 w-full rounded-tile border border-line px-4 py-3"></label><label class="text-sm font-bold">Buffer after (minutes)<input name="bufferAfterMinutes" type="number" value="{{ $rules->bufferAfterMinutes ?? 5 }}" class="mt-2 w-full rounded-tile border border-line px-4 py-3"></label></div><input type="hidden" name="bufferBeforeMinutes" value="{{ $rules->bufferBeforeMinutes ?? 0 }}"><label class="flex items-center gap-3 text-sm font-bold"><input type="checkbox" name="allowGuestBooking" value="1" @checked($rules->allowGuestBooking) class="rounded border-line text-accent"> Allow guest booking</label><label class="flex items-center gap-3 text-sm font-bold"><input type="checkbox" name="requireApproval" value="1" @checked($rules->requireApproval) class="rounded border-line text-accent"> Require approval</label><label class="flex items-center gap-3 text-sm font-bold"><input type="checkbox" name="customerCanChooseStaff" value="1" @checked($rules->customerCanChooseStaff) class="rounded border-line text-accent"> Let customers choose staff</label><x-ui.button type="submit">Save rules</x-ui.button></form></main></x-layouts.staff>
@@ -0,0 +1 @@
<x-layouts.staff :business="$business"><main class="mx-auto max-w-3xl px-5 py-8 sm:px-8 lg:px-12 lg:py-12"><a href="{{ route('owner.dashboard') }}" class="text-xs font-bold uppercase tracking-widest text-white/60">← Owner workspace</a><p class="mt-12 text-[10px] font-bold uppercase tracking-[0.3em] text-accent">Business profile</p><h1 class="mt-3 text-4xl font-black tracking-tight">Business details</h1>@if (session('status'))<div class="mt-6 rounded-tile bg-accent p-4 text-sm font-bold text-ink">{{ session('status') }}</div>@endif<form method="POST" action="{{ route('owner.business.update') }}" class="mt-8 space-y-5 rounded-jumbo bg-white p-6 text-ink">@csrf @method('PUT')<div class="grid gap-5 sm:grid-cols-2"><label class="text-sm font-bold">Name<input name="name" value="{{ $business->name }}" required class="mt-2 w-full rounded-tile border border-line px-4 py-3"></label><label class="text-sm font-bold">Short name<input name="shortName" value="{{ $business->shortName }}" class="mt-2 w-full rounded-tile border border-line px-4 py-3"></label></div><label class="block text-sm font-bold">Description<textarea name="description" rows="4" class="mt-2 w-full rounded-tile border border-line px-4 py-3">{{ $business->description }}</textarea></label><div class="grid gap-5 sm:grid-cols-2"><label class="text-sm font-bold">Phone<input name="phone" value="{{ $business->phone }}" class="mt-2 w-full rounded-tile border border-line px-4 py-3"></label><label class="text-sm font-bold">Email<input name="email" type="email" value="{{ $business->email }}" class="mt-2 w-full rounded-tile border border-line px-4 py-3"></label></div><label class="block text-sm font-bold">Website<input name="website" type="url" value="{{ $business->website }}" class="mt-2 w-full rounded-tile border border-line px-4 py-3"></label><div class="grid gap-5 sm:grid-cols-2"><label class="text-sm font-bold">Timezone<input name="timezone" value="{{ $business->timezone }}" required class="mt-2 w-full rounded-tile border border-line px-4 py-3"></label><label class="text-sm font-bold">Currency<input name="currency" value="{{ $business->currency }}" maxlength="3" required class="mt-2 w-full rounded-tile border border-line px-4 py-3"></label></div><x-ui.button type="submit">Save details</x-ui.button></form></main></x-layouts.staff>
+1
View File
@@ -0,0 +1 @@
<x-layouts.staff :business="$business"><main class="mx-auto max-w-3xl px-5 py-8 sm:px-8 lg:px-12 lg:py-12"><a href="{{ route('owner.dashboard') }}" class="text-xs font-bold uppercase tracking-widest text-white/60">← Owner workspace</a><p class="mt-12 text-[10px] font-bold uppercase tracking-[0.3em] text-accent">Opening hours</p><h1 class="mt-3 text-4xl font-black tracking-tight">Business hours</h1>@if (session('status'))<div class="mt-6 rounded-tile bg-accent p-4 text-sm font-bold text-ink">{{ session('status') }}</div>@endif @if ($errors->any())<div class="mt-6 rounded-tile border border-red-200 bg-red-50 p-4 text-sm text-red-700">{{ $errors->first() }}</div>@endif<form method="POST" action="{{ route('owner.hours.update') }}" class="mt-8 space-y-3">@csrf @method('PUT')@foreach ($days as $day)@php($item = $hours->get($day))<div class="grid items-center gap-3 rounded-jumbo bg-white p-4 text-ink sm:grid-cols-[120px_1fr_1fr_auto]"><p class="text-sm font-bold">{{ ucfirst(strtolower($day)) }}</p><input name="{{ strtolower($day) }}_open" type="time" value="{{ $item && $item->opensAtMinutes !== null ? sprintf('%02d:%02d', intdiv($item->opensAtMinutes, 60), $item->opensAtMinutes % 60) : '10:00' }}" class="rounded-tile border border-line px-3 py-2 text-sm"><input name="{{ strtolower($day) }}_close" type="time" value="{{ $item && $item->closesAtMinutes !== null ? sprintf('%02d:%02d', intdiv($item->closesAtMinutes, 60), $item->closesAtMinutes % 60) : '19:00' }}" class="rounded-tile border border-line px-3 py-2 text-sm"><label class="flex items-center gap-2 text-xs font-bold"><input name="{{ strtolower($day) }}_closed" type="checkbox" value="1" @checked($item?->isClosed) class="rounded border-line text-accent"> Closed</label></div>@endforeach<x-ui.button type="submit">Save hours</x-ui.button></form></main></x-layouts.staff>
@@ -0,0 +1,5 @@
<x-layouts.staff :business="$business">
<main class="mx-auto max-w-3xl px-5 py-8 sm:px-8 lg:px-12 lg:py-12"><a href="{{ route('owner.dashboard') }}" class="text-xs font-bold uppercase tracking-widest text-white/60">← Owner workspace</a><p class="mt-12 text-[10px] font-bold uppercase tracking-[0.3em] text-accent">Programme settings</p><h1 class="mt-3 text-4xl font-black tracking-tight">Loyalty</h1>@if (session('status'))<div class="mt-6 rounded-tile bg-accent p-4 text-sm font-bold text-ink">{{ session('status') }}</div>@endif
<form method="POST" action="{{ route('owner.loyalty.update') }}" class="mt-8 space-y-6">@csrf<input type="hidden" name="rewardPosition" value="AFTER_ALL_STAMPS"><input type="hidden" name="cardFont" value="SANS"><input type="hidden" name="cardTitleTextSize" value="MD">@if ($errors->any())<div class="rounded-tile border border-red-200 bg-red-50 p-4 text-sm text-red-700">{{ $errors->first() }}</div>@endif<div class="rounded-jumbo bg-white p-6 text-ink"><label class="flex items-center justify-between gap-4 text-sm font-bold">Enable loyalty<input type="checkbox" name="isEnabled" value="1" @checked(old('isEnabled', $programme->isEnabled)) class="h-5 w-5 rounded border-line text-accent"></label><div class="mt-6 grid gap-5 sm:grid-cols-2"><label class="text-sm font-bold">Stamps required<input name="stampsRequired" type="number" min="1" max="10" value="{{ old('stampsRequired', $programme->stampsRequired) }}" class="mt-2 w-full rounded-tile border border-line px-4 py-3"></label><label class="text-sm font-bold">Reward label<input name="rewardLabel" value="{{ old('rewardLabel', $programme->rewardLabel) }}" placeholder="Free service" class="mt-2 w-full rounded-tile border border-line px-4 py-3"></label></div><div class="mt-5 grid gap-5 sm:grid-cols-2"><label class="text-sm font-bold">Reward type<select name="rewardType" class="mt-2 w-full rounded-tile border border-line px-4 py-3"><option value="PERCENTAGE">Percentage off</option><option value="FIXED_AMOUNT">Fixed amount</option><option value="FREE_SERVICE">Free service</option></select></label><label class="text-sm font-bold">Reward value<input name="rewardValue" type="number" step="0.01" value="{{ old('rewardValue', $programme->rewardValue) }}" class="mt-2 w-full rounded-tile border border-line px-4 py-3"></label></div><label class="mt-5 block text-sm font-bold">Free service<select name="freeServiceId" class="mt-2 w-full rounded-tile border border-line px-4 py-3"><option value="">Choose a service</option>@foreach ($services as $service)<option value="{{ $service->id }}" @selected(old('freeServiceId', $programme->freeServiceId) === $service->id)>{{ $service->name }}</option>@endforeach</select></label></div><div class="rounded-jumbo bg-white p-6 text-ink"><div class="grid gap-5 sm:grid-cols-2"><label class="text-sm font-bold">Card title<input name="cardTitleText" value="{{ old('cardTitleText', $programme->cardTitleText) }}" class="mt-2 w-full rounded-tile border border-line px-4 py-3"></label><label class="text-sm font-bold">Terms line<input name="termsLine" value="{{ old('termsLine', $programme->termsLine) }}" class="mt-2 w-full rounded-tile border border-line px-4 py-3"></label></div></div><x-ui.button type="submit">Save loyalty settings</x-ui.button></form>
</main>
</x-layouts.staff>
+1
View File
@@ -0,0 +1 @@
<x-layouts.staff :business="$business"><main class="mx-auto max-w-6xl px-5 py-8 sm:px-8 lg:px-12 lg:py-12"><a href="{{ route('owner.dashboard') }}" class="text-xs font-bold uppercase tracking-widest text-white/60">← Owner workspace</a><p class="mt-12 text-[10px] font-bold uppercase tracking-[0.3em] text-accent">Business health</p><h1 class="mt-3 text-4xl font-black tracking-tight">Reports</h1><p class="mt-3 text-sm text-white/60">{{ now($business->timezone)->format('F Y') }} to date</p><div class="mt-10 grid gap-3 sm:grid-cols-3"><div class="rounded-jumbo bg-white/10 p-6"><p class="text-xs text-white/50">Appointments</p><p class="mt-3 text-4xl font-black">{{ $appointments->count() }}</p></div><div class="rounded-jumbo bg-white/10 p-6"><p class="text-xs text-white/50">Completed</p><p class="mt-3 text-4xl font-black">{{ $completed->count() }}</p></div><div class="rounded-jumbo bg-accent p-6 text-ink"><p class="text-xs text-ink/60">Recorded revenue</p><p class="mt-3 text-4xl font-black">£{{ number_format($revenue, 2) }}</p></div></div><div class="mt-6 rounded-jumbo bg-white/10 p-6"><p class="text-sm text-white/60">Active team members</p><p class="mt-2 text-3xl font-black">{{ $staffCount }}</p></div></main></x-layouts.staff>
+1
View File
@@ -0,0 +1 @@
<x-layouts.staff :business="$business"><main class="mx-auto max-w-4xl px-5 py-8 sm:px-8 lg:px-12 lg:py-12"><a href="{{ route('owner.dashboard') }}" class="text-xs font-bold uppercase tracking-widest text-white/60">← Owner workspace</a><p class="mt-12 text-[10px] font-bold uppercase tracking-[0.3em] text-accent">Customer voice</p><h1 class="mt-3 text-4xl font-black tracking-tight">Reviews</h1>@if (session('status'))<div class="mt-6 rounded-tile bg-accent p-4 text-sm font-bold text-ink">{{ session('status') }}</div>@endif<div class="mt-8 space-y-3">@forelse ($reviews as $review)<article class="rounded-jumbo bg-white p-6 text-ink"><div class="flex items-center justify-between gap-4"><p class="font-bold">{{ $review->authorName }} · {{ str_repeat('★', $review->rating) }}</p><form method="POST" action="{{ route('owner.reviews.toggle', $review->id) }}">@csrf<button class="text-[10px] font-bold uppercase tracking-widest text-accent-foreground">{{ $review->isHidden ? 'Show' : 'Hide' }}</button></form></div><p class="mt-4 text-sm leading-6 text-muted">{{ $review->text ?: 'Rating only' }}</p></article>@empty<x-ui.card class="p-6"><p class="text-sm text-white/60">Reviews will appear after a Google Places sync is configured.</p></x-ui.card>@endforelse</div></main></x-layouts.staff>
+5
View File
@@ -0,0 +1,5 @@
<x-layouts.staff :business="$business">
<main class="mx-auto max-w-6xl px-5 py-8 sm:px-8 lg:px-12 lg:py-12"><a href="{{ route('owner.dashboard') }}" class="text-xs font-bold uppercase tracking-widest text-white/60">← Owner workspace</a><div class="mt-12 flex flex-wrap items-end justify-between gap-4"><div><p class="text-[10px] font-bold uppercase tracking-[0.3em] text-accent">Catalogue</p><h1 class="mt-3 text-4xl font-black tracking-tight">Services</h1></div><a href="{{ route('owner.booking-rules') }}" class="text-xs font-bold uppercase tracking-widest text-accent">Booking rules →</a></div>@if (session('status'))<div class="mt-6 rounded-tile bg-accent p-4 text-sm font-bold text-ink">{{ session('status') }}</div>@endif
<div class="mt-8 grid gap-8 lg:grid-cols-[1fr_340px]"><div class="space-y-4">@foreach ($categories as $category)<section><h2 class="mb-3 text-sm font-bold uppercase tracking-widest text-white/50">{{ $category->name }}</h2>@foreach ($category->services as $service)<article class="mb-3 rounded-jumbo bg-white p-5 text-ink"><form method="POST" action="{{ route('owner.services.update', $service->id) }}" class="grid gap-4 sm:grid-cols-[1fr_110px_100px_auto] sm:items-end">@csrf @method('PUT')<label class="text-xs font-bold">Service<input name="name" value="{{ $service->name }}" class="mt-2 w-full rounded-tile border border-line px-3 py-2 text-sm"></label><label class="text-xs font-bold">Minutes<input name="durationMinutes" type="number" value="{{ $service->durationMinutes }}" class="mt-2 w-full rounded-tile border border-line px-3 py-2 text-sm"></label><label class="text-xs font-bold">Price<input name="price" type="number" step="0.01" value="{{ $service->price }}" class="mt-2 w-full rounded-tile border border-line px-3 py-2 text-sm"></label><div class="flex gap-2"><input type="hidden" name="isActive" value="{{ $service->isActive ? 1 : 0 }}"><input type="hidden" name="allowOnlineBooking" value="{{ $service->allowOnlineBooking ? 1 : 0 }}"><button class="rounded-md bg-ink px-3 py-2 text-[10px] font-bold uppercase tracking-widest text-white">Save</button></div></form></article>@endforeach</section>@endforeach</div><aside class="rounded-jumbo bg-white p-6 text-ink"><h2 class="text-lg font-bold">Add service</h2><form method="POST" action="{{ route('owner.services.store') }}" class="mt-5 space-y-4">@csrf<label class="block text-xs font-bold">Category<select name="categoryId" class="mt-2 w-full rounded-tile border border-line px-3 py-2 text-sm"><option value="">New category</option>@foreach ($categories as $category)<option value="{{ $category->id }}">{{ $category->name }}</option>@endforeach</select></label><label class="block text-xs font-bold">New category name<input name="categoryName" class="mt-2 w-full rounded-tile border border-line px-3 py-2 text-sm"></label><label class="block text-xs font-bold">Name<input name="name" required class="mt-2 w-full rounded-tile border border-line px-3 py-2 text-sm"></label><label class="block text-xs font-bold">Duration<input name="durationMinutes" type="number" value="30" required class="mt-2 w-full rounded-tile border border-line px-3 py-2 text-sm"></label><label class="block text-xs font-bold">Price<input name="price" type="number" step="0.01" required class="mt-2 w-full rounded-tile border border-line px-3 py-2 text-sm"></label><x-ui.button type="submit" class="w-full">Add service</x-ui.button></form></aside></div>
</main>
</x-layouts.staff>
+1
View File
@@ -0,0 +1 @@
<x-layouts.staff :business="$business"><main class="mx-auto max-w-6xl px-5 py-8 sm:px-8 lg:px-12 lg:py-12"><a href="{{ route('owner.dashboard') }}" class="text-xs font-bold uppercase tracking-widest text-white/60">← Owner workspace</a><div class="mt-12"><p class="text-[10px] font-bold uppercase tracking-[0.3em] text-accent">People</p><h1 class="mt-3 text-4xl font-black tracking-tight">Team</h1></div>@if (session('status'))<div class="mt-6 rounded-tile bg-accent p-4 text-sm font-bold text-ink">{{ session('status') }}</div>@endif<div class="mt-8 grid gap-8 lg:grid-cols-[1fr_340px]"><div class="space-y-3">@foreach ($staff as $member)<article class="flex items-center justify-between rounded-jumbo bg-white p-5 text-ink"><div><p class="text-sm font-bold">{{ $member->user->name ?: $member->user->email }}</p><p class="mt-1 text-xs text-muted">{{ $member->role->name }} · {{ ucfirst(strtolower($member->status->value)) }}</p></div><span class="text-[10px] font-bold uppercase tracking-widest text-muted">{{ $member->invitation?->acceptedAt ? 'Accepted' : 'Invite pending' }}</span></article>@endforeach</div><aside class="rounded-jumbo bg-white p-6 text-ink"><h2 class="text-lg font-bold">Add team member</h2><form method="POST" action="{{ route('owner.team.store') }}" class="mt-5 space-y-4">@csrf<div class="grid gap-4 sm:grid-cols-2 lg:grid-cols-1"><label class="block text-xs font-bold">First name<input name="firstName" required class="mt-2 w-full rounded-tile border border-line px-3 py-2 text-sm"></label><label class="block text-xs font-bold">Last name<input name="lastName" required class="mt-2 w-full rounded-tile border border-line px-3 py-2 text-sm"></label></div><label class="block text-xs font-bold">Email<input name="email" type="email" required class="mt-2 w-full rounded-tile border border-line px-3 py-2 text-sm"></label><x-ui.button type="submit" class="w-full">Add member</x-ui.button></form></aside></div></main></x-layouts.staff>
+19
View File
@@ -0,0 +1,19 @@
<x-layouts.public :business="$business">
@php($location = $business?->locations?->first())
@php($hero = $business?->coverImageUrl ?: 'https://storage.googleapis.com/uxpilot-auth.appspot.com/gen_6f41884203_51631d7a07f0b3a6.png')
<div class="bg-stone text-ink overflow-x-hidden pb-32">
<section class="relative"><div class="h-72 w-full overflow-hidden bg-ink"><img src="{{ $hero }}" alt="{{ $business?->name }}" class="w-full h-full object-cover"></div><div class="absolute bottom-6 right-6"><button class="bg-white/90 backdrop-blur-sm px-4 py-2 rounded-lg text-[10px] font-bold uppercase tracking-widest shadow-sm"><i class="fa-solid fa-images mr-2"></i>Show all photos</button></div></section>
<div class="flex gap-1 overflow-x-auto py-1 bg-stone no-scrollbar">@forelse ($business?->galleryImages ?? [] as $image)<img src="{{ $image->imageUrl }}" alt="{{ $image->caption ?: 'Shop gallery' }}" class="w-24 h-20 object-cover shrink-0">@empty<div class="w-full h-20 flex items-center justify-center text-xs text-muted">{{ $business?->name ?: 'NextChair' }}</div>@endforelse</div>
<main class="bg-white">
<section class="px-6 py-6"><div class="flex items-start justify-between gap-4"><div><h1 class="text-2xl font-bold tracking-tight mb-1">{{ $business?->name ?: 'Book your next appointment' }}</h1><p class="text-xs text-muted mb-3">{{ $location ? $location->addressLine1.', '.$location->postalCode.', '.$location->city : 'Appointments, services and details in one place.' }}</p></div><a href="{{ route('auth.signin') }}" class="w-10 h-10 rounded-full bg-stone flex items-center justify-center text-ink"><i class="fa-solid fa-user"></i></a></div><div class="flex items-center gap-3 text-sm mb-4"><div class="flex items-center gap-1 text-amber-500"><i class="fa-solid fa-star"></i><i class="fa-solid fa-star"></i><i class="fa-solid fa-star"></i><i class="fa-solid fa-star"></i><i class="fa-solid fa-star"></i></div><span class="font-bold">{{ $business?->googleRating ?: ($business?->reviews?->avg('rating') ?: '5.0') }}</span><a href="#reviews" class="text-blue-600 underline">{{ $business?->googleRatingCount ?: ($business?->reviews?->count() ?: 0) }} reviews</a></div><p class="text-[10px] font-bold uppercase tracking-widest text-muted">{{ $business?->shortName ?: 'Entrepreneur' }}</p></section>
<section class="px-6 py-4 border-t border-line"><button class="w-full flex items-center justify-between group"><div class="flex items-center gap-3"><div class="w-8 h-8 rounded-lg bg-green-50 flex items-center justify-center text-green-600"><i class="fa-solid fa-shield-halved"></i></div><span class="text-sm font-medium">Review policies and safety</span></div><i class="fa-solid fa-chevron-right text-muted"></i></button></section>
<section class="sticky top-0 z-40 bg-white border-b border-line overflow-x-auto no-scrollbar"><div class="flex px-6"><button onclick="switchTab('services')" id="tab-services" class="tab-btn px-4 py-4 text-[10px] font-bold uppercase tracking-[0.15em] border-b-2 border-ink whitespace-nowrap">Services</button><button onclick="switchTab('portfolio')" id="tab-portfolio" class="tab-btn px-4 py-4 text-[10px] font-bold uppercase tracking-[0.15em] border-b-2 border-transparent text-muted whitespace-nowrap">Portfolio</button><button onclick="switchTab('details')" id="tab-details" class="tab-btn px-4 py-4 text-[10px] font-bold uppercase tracking-[0.15em] border-b-2 border-transparent text-muted whitespace-nowrap">Details</button><button onclick="switchTab('reviews')" id="tab-reviews" class="tab-btn px-4 py-4 text-[10px] font-bold uppercase tracking-[0.15em] border-b-2 border-transparent text-muted whitespace-nowrap">Reviews</button></div></section>
<div id="content-services" class="tab-content block"><div class="px-6 py-4"><div class="relative"><i class="fa-solid fa-magnifying-glass absolute left-4 top-1/2 -translate-y-1/2 text-muted"></i><input type="text" placeholder="Search for service" class="w-full bg-stone/50 border border-line rounded-xl pl-12 pr-4 py-4 focus:ring-2 focus:ring-ink outline-none text-sm"></div></div><div class="px-6 flex gap-2 overflow-x-auto no-scrollbar mb-6">@foreach ($categories as $category)<button class="px-4 py-2 rounded-full border {{ $loop->first ? 'border-ink bg-ink text-white' : 'border-line bg-stone text-ink' }} text-[10px] font-bold whitespace-nowrap">{{ $category->name }}</button>@endforeach</div><div class="px-6 space-y-6 pb-12">@forelse ($categories as $category)<div><h3 class="text-sm font-bold mb-4 flex items-center gap-2"><i class="fa-solid fa-thumbs-up text-accent"></i>{{ $category->name }}</h3><div class="space-y-6">@foreach ($category->services as $service)<div class="flex justify-between items-start gap-4 {{ $loop->index ? 'pt-6 border-t border-stone' : '' }}"><div class="flex-1"><h4 class="text-sm font-medium mb-1">{{ $service->name }}</h4><p class="text-xs text-muted">{{ $service->durationMinutes }}m</p></div><div class="text-right"><p class="font-bold mb-2">{{ $business?->currency === 'GBP' ? '£' : $business?->currency }}{{ number_format((float) $service->price, 2) }}</p><a href="{{ route('booking.services') }}" class="inline-block bg-blue-500 text-white px-6 py-2 rounded-lg text-xs font-bold uppercase tracking-widest hover:bg-blue-600">Book</a></div></div>@endforeach</div></div>@empty<p class="text-sm text-muted">Services will appear here once this business is configured.</p>@endforelse</div></div>
<div id="content-portfolio" class="tab-content hidden"><div class="px-6 py-4 flex gap-2 overflow-x-auto no-scrollbar"><button class="px-4 py-2 rounded-full bg-ink text-white text-[10px] font-bold">All</button><button class="px-4 py-2 rounded-full bg-stone text-ink text-[10px] font-bold">Fades</button><button class="px-4 py-2 rounded-full bg-stone text-ink text-[10px] font-bold">Beards</button></div><div class="grid grid-cols-2 gap-1 bg-stone p-1">@forelse (($business?->galleryImages ?? collect())->where('placement.value', 'PORTFOLIO') as $image)<img src="{{ $image->imageUrl }}" alt="{{ $image->caption ?: 'Portfolio' }}" class="w-full aspect-square object-cover">@empty<p class="col-span-2 p-8 text-sm text-muted">Portfolio images will appear here soon.</p>@endforelse</div></div>
<div id="content-details" class="tab-content hidden"><section class="px-6 py-8"><h3 class="text-[10px] font-bold uppercase tracking-widest text-muted mb-4">About Us</h3><p class="text-sm leading-relaxed text-gray-700">{{ $business?->description ?: 'A welcoming space for precise grooming and excellent service.' }}</p></section><section class="px-6 pb-8"><h3 class="text-[10px] font-bold uppercase tracking-widest text-muted mb-6">Staffers</h3><div class="flex gap-6 overflow-x-auto no-scrollbar">@forelse ($business?->staff?->where('status.value', 'ACTIVE') ?? [] as $member)<div class="w-20 shrink-0 text-center"><div class="w-20 h-20 rounded-full bg-stone flex items-center justify-center text-xl font-bold mb-2 border border-line">{{ strtoupper(substr($member->user?->name ?: 'S', 0, 1)) }}</div><p class="text-xs font-medium truncate">{{ $member->user?->name ?: 'Staff member' }}</p></div>@empty<p class="text-sm text-muted">Our team will appear here soon.</p>@endforelse</div></section><section class="px-6 pb-8"><h3 class="text-[10px] font-bold uppercase tracking-widest text-muted mb-6">Contact &amp; Business Hours</h3><div class="space-y-4">@foreach ($business?->hours?->sortBy('id') ?? [] as $hours)<div class="flex justify-between items-center text-sm"><span class="text-gray-600">{{ ucfirst(strtolower($hours->dayOfWeek)) }}</span><span class="font-bold">{{ $hours->isClosed ? 'Closed' : sprintf('%02d:%02d - %02d:%02d', intdiv($hours->opensAtMinutes, 60), $hours->opensAtMinutes % 60, intdiv($hours->closesAtMinutes, 60), $hours->closesAtMinutes % 60) }}</span></div>@endforeach</div></section><section class="px-6 pb-12"><h3 class="text-[10px] font-bold uppercase tracking-widest text-muted mb-4">Venue Amenities</h3><div class="grid grid-cols-2 gap-4"><div class="flex items-center gap-3 text-sm"><i class="fa-solid fa-car text-muted"></i><span>Free Parking</span></div><div class="flex items-center gap-3 text-sm"><i class="fa-solid fa-wifi text-muted"></i><span>Guest WiFi</span></div></div></section></div>
<div id="content-reviews" class="tab-content hidden p-6" id="reviews"><h3 class="text-lg font-bold mb-4">Reviews</h3>@forelse ($business?->reviews ?? [] as $review)<article class="border-b border-line py-4"><p class="text-sm font-bold">{{ $review->authorName }} <span class="text-amber-500">{{ str_repeat('★', $review->rating) }}</span></p><p class="mt-2 text-sm text-muted">{{ $review->text ?: 'Rating only' }}</p></article>@empty<p class="text-sm text-muted">Reviews will appear after the shop connects Google.</p>@endforelse</div>
</main>
<nav class="fixed bottom-0 left-0 right-0 z-50 bg-white border-t border-line py-4 px-10 flex justify-between items-center"><a href="{{ route('public.home') }}" class="flex flex-col items-center gap-1 text-ink"><i class="fa-solid fa-house text-xl"></i><span class="text-[10px] font-bold uppercase tracking-widest">Home</span></a><a href="{{ auth()->check() ? route('customer.appointments') : route('auth.signin') }}" class="flex flex-col items-center gap-1 text-muted hover:text-ink"><i class="fa-solid fa-calendar-check text-xl"></i><span class="text-[10px] font-bold uppercase tracking-widest">Bookings</span></a><a href="{{ auth()->check() ? route('customer.dashboard') : route('auth.signin') }}" class="flex flex-col items-center gap-1 text-muted hover:text-ink"><i class="fa-solid fa-user text-xl"></i><span class="text-[10px] font-bold uppercase tracking-widest">{{ auth()->check() ? 'Account' : 'Sign in' }}</span></a></nav>
</div>
<script>function switchTab(tabId){document.querySelectorAll('.tab-content').forEach(c=>{c.classList.add('hidden');c.classList.remove('block')});const content=document.getElementById('content-'+tabId);if(content){content.classList.remove('hidden');content.classList.add('block')}document.querySelectorAll('.tab-btn').forEach(b=>{b.classList.remove('border-ink');b.classList.add('border-transparent','text-muted')});const tab=document.getElementById('tab-'+tabId);if(tab){tab.classList.add('border-ink');tab.classList.remove('border-transparent','text-muted')}}</script>
</x-layouts.public>
+17
View File
@@ -0,0 +1,17 @@
<x-layouts.staff :business="$business">
@if ($isOwner)
@php($totalVisits = $appointments->count())
@php($confirmed = $appointments->where('status.value', 'CONFIRMED')->count())
<div class="min-h-screen bg-stone pb-32 text-ink">
<header class="fixed left-0 right-0 top-0 z-50 flex items-center justify-between border-b border-line bg-white/80 px-6 py-6 backdrop-blur-md"><a href="{{ route('public.home') }}" class="flex h-10 w-10 items-center justify-center rounded-full border border-line"><i class="fa-solid fa-arrow-left text-sm"></i></a><h1 class="text-lg font-bold tracking-tight">Business Dashboard</h1><form method="POST" action="{{ route('auth.signout') }}">@csrf<button class="flex h-10 w-10 items-center justify-center rounded-full border border-line"><i class="fa-solid fa-right-from-bracket text-sm"></i></button></form></header>
<main class="mx-auto mt-24 max-w-md space-y-8 px-6"><section class="grid grid-cols-2 gap-3"><div class="rounded-jumbo border border-line bg-white p-5 shadow-sm"><span class="mb-1 block text-[10px] font-bold uppercase tracking-widest text-muted">Total visits</span><p class="text-2xl font-bold">{{ $totalVisits }}</p><span class="text-[8px] font-bold text-accent">Today</span></div><div class="rounded-jumbo border border-line bg-white p-5 shadow-sm"><span class="mb-1 block text-[10px] font-bold uppercase tracking-widest text-muted">Confirmed</span><p class="text-2xl font-bold">{{ $confirmed }}</p><span class="text-[8px] font-bold text-accent">Today</span></div></section>
<section><h3 class="mb-4 ml-1 text-[10px] font-bold uppercase tracking-widest text-muted">Top services</h3><div class="overflow-hidden rounded-jumbo border border-line bg-white">@php($serviceCounts = $appointments->flatMap->services->groupBy('service.name')->map->count()->sortDesc()->take(3)) @forelse ($serviceCounts as $name => $count)<div class="flex items-center justify-between border-b border-line px-6 py-4 last:border-0"><span class="text-sm font-bold">{{ $name }}</span><span class="text-xs text-muted">{{ $count }} visit{{ $count === 1 ? '' : 's' }}</span></div>@empty<div class="px-6 py-4 text-sm text-muted">Your most popular services will appear here.</div>@endforelse</div></section>
<section><div class="mb-4 flex items-end justify-between px-1"><h3 class="text-[10px] font-bold uppercase tracking-widest text-muted">Staff performance</h3><a href="{{ route('owner.team') }}" class="border-b border-ink text-[10px] font-bold uppercase tracking-widest">Manage team</a></div><div class="space-y-3">@forelse ($business->staff->where('status.value', 'ACTIVE')->take(4) as $member)<div class="flex items-center gap-4 rounded-jumbo border border-line bg-white p-4"><div class="flex h-10 w-10 items-center justify-center rounded-full bg-stone"><i class="fa-solid fa-user"></i></div><div class="flex-1"><p class="text-sm font-bold">{{ $member->user?->name ?: 'Team member' }}</p><div class="mt-2 h-1.5 w-full overflow-hidden rounded-full bg-stone"><div class="h-full w-4/5 bg-accent"></div></div></div><span class="text-xs font-bold">{{ $member->user?->name ? 'Active' : '—' }}</span></div>@empty<p class="text-sm text-muted">Add team members to see performance.</p>@endforelse</div></section>
<section class="rounded-jumbo bg-ink p-6 text-white"><h3 class="mb-2 text-lg font-bold">Booking rules</h3><p class="mb-6 text-xs text-white/60">Manage cancellation policies, booking windows, and lead times.</p><a href="{{ route('owner.booking-rules') }}" class="block w-full rounded-xl bg-white py-3 text-center text-xs font-bold uppercase tracking-widest text-ink">Update rules</a></section>
</main>
<nav class="fixed bottom-0 left-0 right-0 z-50 flex items-center justify-between border-t border-white/5 bg-[#0c0c0c] px-10 py-4 text-gray-400"><a href="{{ route('staff.dashboard') }}" class="flex flex-col items-center gap-1 text-white"><i class="fa-solid fa-calendar-days text-xl"></i><span class="text-[10px] font-medium">Calendar</span></a><a href="{{ route('staff.dashboard') }}" class="flex flex-col items-center gap-1"><i class="fa-solid fa-scissors text-xl"></i><span class="text-[10px] font-medium">Current</span></a><a href="{{ route('owner.team') }}" class="flex flex-col items-center gap-1"><i class="fa-solid fa-users text-xl"></i><span class="text-[10px] font-medium">Clients</span></a><a href="{{ route('owner.business') }}" class="flex flex-col items-center gap-1"><i class="fa-solid fa-gear text-xl"></i><span class="text-[10px] font-medium">Settings</span></a></nav>
</div>
@else
<div class="mx-auto min-h-screen max-w-7xl px-5 py-8 text-white sm:px-8 lg:px-12 lg:py-12"><header class="flex items-start justify-between gap-5"><div><p class="text-[10px] font-bold uppercase tracking-[0.3em] text-accent">Staff workspace</p><h1 class="mt-3 text-4xl font-black tracking-tight">Good morning, {{ $staff->user?->name ?: 'there' }}</h1><p class="mt-2 text-sm text-white/60">{{ now($business->timezone)->format('l, j F Y') }}</p></div><form method="POST" action="{{ route('auth.signout') }}">@csrf<button class="rounded-full px-4 py-2 text-xs font-bold uppercase tracking-widest text-white/70 hover:bg-white/10">Sign out</button></form></header><section class="mt-10 grid gap-3 sm:grid-cols-3"><div class="rounded-jumbo bg-white/10 p-5"><p class="text-xs text-white/50">Today’s appointments</p><p class="mt-3 text-3xl font-black">{{ $appointments->count() }}</p></div><div class="rounded-jumbo bg-white/10 p-5"><p class="text-xs text-white/50">Confirmed</p><p class="mt-3 text-3xl font-black">{{ $appointments->where('status.value', 'CONFIRMED')->count() }}</p></div><div class="rounded-jumbo bg-accent p-5 text-ink"><p class="text-xs text-ink/60">Next appointment</p><p class="mt-3 text-lg font-black">{{ $appointments->first()?->startAt->setTimezone($business->timezone)->format('g:i A') ?: 'None yet' }}</p></div></section><section class="mt-10"><h2 class="text-xl font-bold">Today’s schedule</h2><div class="mt-5 space-y-3">@forelse ($appointments as $appointment)<article class="flex flex-col justify-between gap-4 rounded-jumbo bg-white p-5 text-ink sm:flex-row sm:items-center"><div><p class="text-sm font-bold">{{ $appointment->startAt->setTimezone($business->timezone)->format('g:i A') }} · {{ $appointment->customer->firstName }} {{ $appointment->customer->lastName }}</p><p class="mt-2 text-sm text-muted">{{ $appointment->services->pluck('service.name')->join(', ') }}</p></div><span class="rounded-full bg-stone px-3 py-1 text-[10px] font-bold uppercase tracking-widest text-muted">{{ ucfirst(strtolower($appointment->status->value)) }}</span></article>@empty<div class="rounded-jumbo border border-white/10 p-8 text-center text-sm text-white/60">Your schedule is clear today.</div>@endforelse</div></section></div>
@endif
</x-layouts.staff>
+223
View File
@@ -0,0 +1,223 @@
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{{ config('app.name', 'Laravel') }}</title>
@fonts
<!-- Styles / Scripts -->
@if (file_exists(public_path('build/manifest.json')) || file_exists(public_path('hot')))
@vite(['resources/css/app.css', 'resources/js/app.js'])
@else
<style>
/*! tailwindcss v4.0.7 | MIT License | https://tailwindcss.com */ @layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-space-x-reverse:0;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-duration:initial;--tw-ease:initial;--tw-content:""}}}@layer theme{:root,:host{--font-sans:"Instrument Sans", ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--font-serif:ui-serif, Georgia, Cambria, "Times New Roman", Times, serif;--font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--color-red-50:oklch(97.1% .013 17.38);--color-red-100:oklch(93.6% .032 17.717);--color-red-200:oklch(88.5% .062 18.334);--color-red-300:oklch(80.8% .114 19.571);--color-red-400:oklch(70.4% .191 22.216);--color-red-500:oklch(63.7% .237 25.331);--color-red-600:oklch(57.7% .245 27.325);--color-red-700:oklch(50.5% .213 27.518);--color-red-800:oklch(44.4% .177 26.899);--color-red-900:oklch(39.6% .141 25.723);--color-red-950:oklch(25.8% .092 26.042);--color-orange-50:oklch(98% .016 73.684);--color-orange-100:oklch(95.4% .038 75.164);--color-orange-200:oklch(90.1% .076 70.697);--color-orange-300:oklch(83.7% .128 66.29);--color-orange-400:oklch(75% .183 55.934);--color-orange-500:oklch(70.5% .213 47.604);--color-orange-600:oklch(64.6% .222 41.116);--color-orange-700:oklch(55.3% .195 38.402);--color-orange-800:oklch(47% .157 37.304);--color-orange-900:oklch(40.8% .123 38.172);--color-orange-950:oklch(26.6% .079 36.259);--color-amber-50:oklch(98.7% .022 95.277);--color-amber-100:oklch(96.2% .059 95.617);--color-amber-200:oklch(92.4% .12 95.746);--color-amber-300:oklch(87.9% .169 91.605);--color-amber-400:oklch(82.8% .189 84.429);--color-amber-500:oklch(76.9% .188 70.08);--color-amber-600:oklch(66.6% .179 58.318);--color-amber-700:oklch(55.5% .163 48.998);--color-amber-800:oklch(47.3% .137 46.201);--color-amber-900:oklch(41.4% .112 45.904);--color-amber-950:oklch(27.9% .077 45.635);--color-yellow-50:oklch(98.7% .026 102.212);--color-yellow-100:oklch(97.3% .071 103.193);--color-yellow-200:oklch(94.5% .129 101.54);--color-yellow-300:oklch(90.5% .182 98.111);--color-yellow-400:oklch(85.2% .199 91.936);--color-yellow-500:oklch(79.5% .184 86.047);--color-yellow-600:oklch(68.1% .162 75.834);--color-yellow-700:oklch(55.4% .135 66.442);--color-yellow-800:oklch(47.6% .114 61.907);--color-yellow-900:oklch(42.1% .095 57.708);--color-yellow-950:oklch(28.6% .066 53.813);--color-lime-50:oklch(98.6% .031 120.757);--color-lime-100:oklch(96.7% .067 122.328);--color-lime-200:oklch(93.8% .127 124.321);--color-lime-300:oklch(89.7% .196 126.665);--color-lime-400:oklch(84.1% .238 128.85);--color-lime-500:oklch(76.8% .233 130.85);--color-lime-600:oklch(64.8% .2 131.684);--color-lime-700:oklch(53.2% .157 131.589);--color-lime-800:oklch(45.3% .124 130.933);--color-lime-900:oklch(40.5% .101 131.063);--color-lime-950:oklch(27.4% .072 132.109);--color-green-50:oklch(98.2% .018 155.826);--color-green-100:oklch(96.2% .044 156.743);--color-green-200:oklch(92.5% .084 155.995);--color-green-300:oklch(87.1% .15 154.449);--color-green-400:oklch(79.2% .209 151.711);--color-green-500:oklch(72.3% .219 149.579);--color-green-600:oklch(62.7% .194 149.214);--color-green-700:oklch(52.7% .154 150.069);--color-green-800:oklch(44.8% .119 151.328);--color-green-900:oklch(39.3% .095 152.535);--color-green-950:oklch(26.6% .065 152.934);--color-emerald-50:oklch(97.9% .021 166.113);--color-emerald-100:oklch(95% .052 163.051);--color-emerald-200:oklch(90.5% .093 164.15);--color-emerald-300:oklch(84.5% .143 164.978);--color-emerald-400:oklch(76.5% .177 163.223);--color-emerald-500:oklch(69.6% .17 162.48);--color-emerald-600:oklch(59.6% .145 163.225);--color-emerald-700:oklch(50.8% .118 165.612);--color-emerald-800:oklch(43.2% .095 166.913);--color-emerald-900:oklch(37.8% .077 168.94);--color-emerald-950:oklch(26.2% .051 172.552);--color-teal-50:oklch(98. Line truncated
</style>
@endif
</head>
<body class="bg-[#FDFDFC] dark:bg-[#0a0a0a] text-[#1b1b18] flex p-6 lg:p-8 items-center lg:justify-center min-h-screen flex-col">
<header class="w-full lg:max-w-4xl max-w-[335px] text-sm mb-6 not-has-[nav]:hidden">
@if (Route::has('login'))
<nav class="flex items-center justify-end gap-4">
@auth
<a
href="{{ url('/dashboard') }}"
class="inline-block px-5 py-1.5 dark:text-[#EDEDEC] border-[#19140035] hover:border-[#1915014a] border text-[#1b1b18] dark:border-[#3E3E3A] dark:hover:border-[#62605b] rounded-sm text-sm leading-normal"
>
Dashboard
</a>
@else
<a
href="{{ route('login') }}"
class="inline-block px-5 py-1.5 dark:text-[#EDEDEC] text-[#1b1b18] border border-transparent hover:border-[#19140035] dark:hover:border-[#3E3E3A] rounded-sm text-sm leading-normal"
>
Log in
</a>
@if (Route::has('register'))
<a
href="{{ route('register') }}"
class="inline-block px-5 py-1.5 dark:text-[#EDEDEC] border-[#19140035] hover:border-[#1915014a] border text-[#1b1b18] dark:border-[#3E3E3A] dark:hover:border-[#62605b] rounded-sm text-sm leading-normal">
Register
</a>
@endif
@endauth
</nav>
@endif
</header>
<div class="flex items-center justify-center w-full transition-opacity opacity-100 duration-750 lg:grow starting:opacity-0">
<main class="flex max-w-[335px] w-full flex-col-reverse lg:max-w-4xl lg:flex-row">
<div class="text-[13px] leading-[20px] flex-1 p-6 pb-6 lg:p-20 lg:pb-10 bg-white dark:bg-[#161615] dark:text-[#EDEDEC] shadow-[inset_0px_0px_0px_1px_rgba(26,26,0,0.16)] dark:shadow-[inset_0px_0px_0px_1px_#fffaed2d] rounded-bl-lg rounded-br-lg lg:rounded-tl-lg lg:rounded-br-none">
<h1 class="mb-1 font-medium">Let's get started</h1>
<p class="mb-2 text-[#706f6c] dark:text-[#A1A09A]">With so many options available to you,<br /> we suggest you start with the following:</p>
<ul class="flex flex-col mb-4 lg:mb-6">
<li class="flex items-center gap-4 py-2 relative before:border-l before:border-[#e3e3e0] dark:before:border-[#3E3E3A] before:top-1/2 before:bottom-0 before:left-[0.4rem] before:absolute">
<span class="relative py-1 bg-white dark:bg-[#161615]">
<span class="flex items-center justify-center rounded-full bg-[#FDFDFC] dark:bg-[#161615] shadow-[0px_0px_1px_0px_rgba(0,0,0,0.03),0px_1px_2px_0px_rgba(0,0,0,0.06)] w-3.5 h-3.5 border dark:border-[#3E3E3A] border-[#e3e3e0]">
<span class="rounded-full bg-[#dbdbd7] dark:bg-[#3E3E3A] w-1.5 h-1.5"></span>
</span>
</span>
<span>
Read the
<a href="https://laravel.com/docs" target="_blank" class="inline-flex items-center space-x-1 font-medium underline underline-offset-4 text-[#f53003] dark:text-[#FF4433] ml-1">
<span>Documentation</span>
<svg
width="10"
height="11"
viewBox="0 0 10 11"
fill="none"
xmlns="http://www.w3.org/2000/svg"
class="w-2.5 h-2.5"
>
<path
d="M7.70833 6.95834V2.79167H3.54167M2.5 8L7.5 3.00001"
stroke="currentColor"
stroke-linecap="square"
/>
</svg>
</a>
</span>
</li>
<li class="flex items-center gap-4 py-2 relative before:border-l before:border-[#e3e3e0] dark:before:border-[#3E3E3A] before:bottom-1/2 before:top-0 before:left-[0.4rem] before:absolute">
<span class="relative py-1 bg-white dark:bg-[#161615]">
<span class="flex items-center justify-center rounded-full bg-[#FDFDFC] dark:bg-[#161615] shadow-[0px_0px_1px_0px_rgba(0,0,0,0.03),0px_1px_2px_0px_rgba(0,0,0,0.06)] w-3.5 h-3.5 border dark:border-[#3E3E3A] border-[#e3e3e0]">
<span class="rounded-full bg-[#dbdbd7] dark:bg-[#3E3E3A] w-1.5 h-1.5"></span>
</span>
</span>
<span>
Watch video tutorials at
<a href="https://laracasts.com" target="_blank" class="inline-flex items-center space-x-1 font-medium underline underline-offset-4 text-[#f53003] dark:text-[#FF4433] ml-1">
<span>Laracasts</span>
<svg
width="10"
height="11"
viewBox="0 0 10 11"
fill="none"
xmlns="http://www.w3.org/2000/svg"
class="w-2.5 h-2.5"
>
<path
d="M7.70833 6.95834V2.79167H3.54167M2.5 8L7.5 3.00001"
stroke="currentColor"
stroke-linecap="square"
/>
</svg>
</a>
</span>
</li>
</ul>
<ul class="flex gap-3 text-sm leading-normal">
<li>
<a href="https://cloud.laravel.com" target="_blank" class="inline-block dark:bg-[#eeeeec] dark:border-[#eeeeec] dark:text-[#1C1C1A] dark:hover:bg-white dark:hover:border-white hover:bg-black hover:border-black px-5 py-1.5 bg-[#1b1b18] rounded-sm border border-black text-white text-sm leading-normal">
Deploy now
</a>
</li>
</ul>
<p class="mt-6 lg:mt-10 text-[#706f6c] dark:text-[#A1A09A]">
v{{ app()->version() }}
<a href="https://github.com/laravel/framework/blob/13.x/CHANGELOG.md" target="_blank" class="inline-flex items-center space-x-1 font-medium underline underline-offset-4 text-[#f53003] dark:text-[#FF4433] ml-1">
<span>View changelog</span>
<svg
width="10"
height="11"
viewBox="0 0 10 11"
fill="none"
xmlns="http://www.w3.org/2000/svg"
class="w-2.5 h-2.5"
>
<path
d="M7.70833 6.95834V2.79167H3.54167M2.5 8L7.5 3.00001"
stroke="currentColor"
stroke-linecap="square"
/>
</svg>
</a>
</p>
</div>
<div class="bg-[#fff2f2] dark:bg-[#1D0002] relative lg:-ml-px -mb-px lg:mb-0 rounded-t-lg lg:rounded-t-none lg:rounded-r-lg aspect-[335/364] lg:aspect-auto w-full lg:w-[438px] shrink-0 overflow-hidden">
{{-- Laravel Logo --}}
<svg class="w-full text-[#F53003] dark:text-[#F61500] transition-all translate-y-0 opacity-100 max-w-none duration-750 starting:opacity-0 motion-safe:starting:translate-y-6" viewBox="0 0 438 104" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M17.2036 -3H0V102.197H49.5189V86.7187H17.2036V-3Z" fill="currentColor" />
<path d="M110.256 41.6337C108.061 38.1275 104.945 35.3731 100.905 33.3681C96.8667 31.3647 92.8016 30.3618 88.7131 30.3618C83.4247 30.3618 78.5885 31.3389 74.201 33.2923C69.8111 35.2456 66.0474 37.928 62.9059 41.3333C59.7643 44.7401 57.3198 48.6726 55.5754 53.1293C53.8287 57.589 52.9572 62.274 52.9572 67.1813C52.9572 72.1925 53.8287 76.8995 55.5754 81.3069C57.3191 85.7173 59.7636 89.6241 62.9059 93.0293C66.0474 96.4361 69.8119 99.1155 74.201 101.069C78.5885 103.022 83.4247 103.999 88.7131 103.999C92.8016 103.999 96.8667 102.997 100.905 100.994C104.945 98.9911 108.061 96.2359 110.256 92.7282V102.195H126.563V32.1642H110.256V41.6337ZM108.76 75.7472C107.762 78.4531 106.366 80.8078 104.572 82.8112C102.776 84.8161 100.606 86.4183 98.0637 87.6206C95.5202 88.823 92.7004 89.4238 89.6103 89.4238C86.5178 89.4238 83.7252 88.823 81.2324 87.6206C78.7388 86.4183 76.5949 84.8161 74.7998 82.8112C73.004 80.8078 71.6319 78.4531 70.6856 75.7472C69.7356 73.0421 69.2644 70.1868 69.2644 67.1821C69.2644 64.1758 69.7356 61.3205 70.6856 58.6154C71.6319 55.9102 73.004 53.5571 74.7998 51.5522C76.5949 49.5495 78.738 47.9451 81.2324 46.7427C83.7252 45.5404 86.5178 44.9396 89.6103 44.9396C92.7012 44.9396 95.5202 45.5404 98.0637 46.7427C100.606 47.9451 102.776 49.5487 104.572 51.5522C106.367 53.5571 107.762 55.9102 108.76 58.6154C109.756 61.3205 110.256 64.1758 110.256 67.1821C110.256 70.1868 109.756 73.0421 108.76 75.7472Z" fill="currentColor" />
<path d="M242.805 41.6337C240.611 38.1275 237.494 35.3731 233.455 33.3681C229.416 31.3647 225.351 30.3618 221.262 30.3618C215.974 30.3618 211.138 31.3389 206.75 33.2923C202.36 35.2456 198.597 37.928 195.455 41.3333C192.314 44.7401 189.869 48.6726 188.125 53.1293C186.378 57.589 185.507 62.274 185.507 67.1813C185.507 72.1925 186.378 76.8995 188.125 81.3069C189.868 85.7173 192.313 89.6241 195.455 93.0293C198.597 96.4361 202.361 99.1155 206.75 101.069C211.138 103.022 215.974 103.999 221.262 103.999C225.351 103.999 229.416 102.997 233.455 100.994C237.494 98.9911 240.611 96.2359 242.805 92.7282V102.195H259.112V32.1642H242.805V41.6337ZM241.31 75.7472C240.312 78.4531 238.916 80.8078 237.122 82.8112C235.326 84.8161 233.156 86.4183 230.614 87.6206C228.07 88.823 225.251 89.4238 222.16 89.4238C219.068 89.4238 216.275 88.823 213.782 87.6206C211.289 86.4183 209.145 84.8161 207.35 82.8112C205.554 80.8078 204.182 78.4531 203.236 75.7472C202.286 73.0421 201.814 70.1868 201.814 67.1821C201.814 64.1758 202.286 61.3205 203.236 58.6154C204.182 55.9102 205.554 53.5571 207.35 51.5522C209.145 49.5495 211.288 47.9451 213.782 46.7427C216.275 45.5404 219.068 44.9396 222.16 44.9396C225.251 44.9396 228.07 45.5404 230.614 46.7427C233.156 47.9451 235.326 49.5487 237.122 51.5522C238.917 53.5571 240.312 55.9102 241.31 58.6154C242.306 61.3205 242.806 64.1758 242.806 67.1821C242.805 70.1868 242.305 73.0421 241.31 75.7472Z" fill="currentColor" />
<path d="M438 -3H421.694V102.197H438V-3Z" fill="currentColor" />
<path d="M139.43 102.197H155.735V48.2834H183.712V32.1665H139.43V102.197Z" fill="currentColor" />
<path d="M324.49 32.1665L303.995 85.794L283.498 32.1665H266.983L293.748 102.197H314.242L341.006 32.1665H324.49Z" fill="currentColor" />
<path d="M376.571 30.3656C356.603 30.3656 340.797 46.8497 340.797 67.1828C340.797 89.6597 356.094 104 378.661 104C391.29 104 399.354 99.1488 409.206 88.5848L398.189 80.0226C398.183 80.031 389.874 90.9895 377.468 90.9895C363.048 90.9895 356.977 79.3111 356.977 73.269H411.075C413.917 50.1328 398.775 30.3656 376.571 30.3656ZM357.02 61.0967C357.145 59.7487 359.023 43.3761 376.442 43.3761C393.861 43.3761 395.978 59.7464 396.099 61.0967H357.02Z" fill="currentColor" />
</svg>
{{-- 13 --}}
<svg class="w-[438px] max-w-none relative -mt-[6.6rem] -ml-8 lg:ml-0 [--stroke-color:#1B1B18] dark:[--stroke-color:#FF750F]" viewBox="0 0 440 392" fill="none" xmlns="http://www.w3.org/2000/svg">
<g class="mix-blend-darken dark:mix-blend-normal transition-all delay-300 opacity-100 duration-750 starting:opacity-0 text-[#1B1B18] dark:text-black">
<mask id="path-1-mask" maskUnits="userSpaceOnUse" x="-0.328613" y="103" width="338" height="299" fill="black">
<rect fill="white" x="-0.328613" y="103" width="338" height="299"/>
<path d="M234.936 400.8C204.136 400.8 178.936 392.4 159.336 375.6C140.136 358.8 130.536 337 130.536 310.2H200.736C200.736 318.2 203.736 324.8 209.736 330C215.736 335.2 223.736 337.8 233.736 337.8C243.336 337.8 251.136 335 257.136 329.4C263.536 323.8 266.736 316.6 266.736 307.8C266.736 299.8 263.936 293.2 258.336 288C252.736 282.8 245.536 280.2 236.736 280.2H199.536V218.4H236.736C243.536 218.4 249.336 216 254.136 211.2C258.936 206.4 261.336 200.4 261.336 193.2C261.336 184.8 258.736 178.2 253.536 173.4C248.336 168.6 241.736 166.2 233.736 166.2C226.536 166.2 220.336 168.4 215.136 172.8C210.336 177.2 207.936 182.8 207.936 189.6H141.336C141.336 164.8 150.136 144.6 167.736 129C185.336 113 207.936 105 235.536 105C263.136 105 285.536 112.2 302.736 126.6C320.336 141 329.136 160 329.136 183.6C329.136 200.8 324.536 214.8 315.336 225.6C306.136 236 294.336 243.2 279.936 247.2C297.136 252 310.736 260.2 320.736 271.8C331.136 283.4 336.336 298 336.336 315.6C336.336 340.4 326.936 360.8 308.136 376.8C289.336 392.8 264.936 400.8 234.936 400.8Z"/>
<path d="M26.8714 167.6H1.67139V105.2H94.6714V400.2H26.8714V167.6Z"/>
</mask>
<path d="M234.936 400.8C204.136 400.8 178.936 392.4 159.336 375.6C140.136 358.8 130.536 337 130.536 310.2H200.736C200.736 318.2 203.736 324.8 209.736 330C215.736 335.2 223.736 337.8 233.736 337.8C243.336 337.8 251.136 335 257.136 329.4C263.536 323.8 266.736 316.6 266.736 307.8C266.736 299.8 263.936 293.2 258.336 288C252.736 282.8 245.536 280.2 236.736 280.2H199.536V218.4H236.736C243.536 218.4 249.336 216 254.136 211.2C258.936 206.4 261.336 200.4 261.336 193.2C261.336 184.8 258.736 178.2 253.536 173.4C248.336 168.6 241.736 166.2 233.736 166.2C226.536 166.2 220.336 168.4 215.136 172.8C210.336 177.2 207.936 182.8 207.936 189.6H141.336C141.336 164.8 150.136 144.6 167.736 129C185.336 113 207.936 105 235.536 105C263.136 105 285.536 112.2 302.736 126.6C320.336 141 329.136 160 329.136 183.6C329.136 200.8 324.536 214.8 315.336 225.6C306.136 236 294.336 243.2 279.936 247.2C297.136 252 310.736 260.2 320.736 271.8C331.136 283.4 336.336 298 336.336 315.6C336.336 340.4 326.936 360.8 308.136 376.8C289.336 392.8 264.936 400.8 234.936 400.8Z" fill="currentColor"/>
<path d="M26.8714 167.6H1.67139V105.2H94.6714V400.2H26.8714V167.6Z" fill="currentColor"/>
<path d="M234.936 400.8C204.136 400.8 178.936 392.4 159.336 375.6C140.136 358.8 130.536 337 130.536 310.2H200.736C200.736 318.2 203.736 324.8 209.736 330C215.736 335.2 223.736 337.8 233.736 337.8C243.336 337.8 251.136 335 257.136 329.4C263.536 323.8 266.736 316.6 266.736 307.8C266.736 299.8 263.936 293.2 258.336 288C252.736 282.8 245.536 280.2 236.736 280.2H199.536V218.4H236.736C243.536 218.4 249.336 216 254.136 211.2C258.936 206.4 261.336 200.4 261.336 193.2C261.336 184.8 258.736 178.2 253.536 173.4C248.336 168.6 241.736 166.2 233.736 166.2C226.536 166.2 220.336 168.4 215.136 172.8C210.336 177.2 207.936 182.8 207.936 189.6H141.336C141.336 164.8 150.136 144.6 167.736 129C185.336 113 207.936 105 235.536 105C263.136 105 285.536 112.2 302.736 126.6C320.336 141 329.136 160 329.136 183.6C329.136 200.8 324.536 214.8 315.336 225.6C306.136 236 294.336 243.2 279.936 247.2C297.136 252 310.736 260.2 320.736 271.8C331.136 283.4 336.336 298 336.336 315.6C336.336 340.4 326.936 360.8 308.136 376.8C289.336 392.8 264.936 400.8 234.936 400.8Z" stroke="var(--stroke-color)" stroke-width="2.4" mask="url(#path-1-mask)"/>
<path d="M26.8714 167.6H1.67139V105.2H94.6714V400.2H26.8714V167.6Z" stroke="var(--stroke-color)" stroke-width="2.4" mask="url(#path-1-mask)"/>
</g>
<g class="transition-all delay-400 opacity-100 duration-750 starting:opacity-0 motion-safe:starting:-translate-x-[26px] text-[#F3BEC7] dark:text-[#4B0600]">
<mask id="path-2-mask" maskUnits="userSpaceOnUse" x="25.3357" y="103" width="338" height="299" fill="black">
<rect fill="white" x="25.3357" y="103" width="338" height="299"/>
<path d="M260.6 400.8C229.8 400.8 204.6 392.4 185 375.6C165.8 358.8 156.2 337 156.2 310.2H226.4C226.4 318.2 229.4 324.8 235.4 330C241.4 335.2 249.4 337.8 259.4 337.8C269 337.8 276.8 335 282.8 329.4C289.2 323.8 292.4 316.6 292.4 307.8C292.4 299.8 289.6 293.2 284 288C278.4 282.8 271.2 280.2 262.4 280.2H225.2V218.4H262.4C269.2 218.4 275 216 279.8 211.2C284.6 206.4 287 200.4 287 193.2C287 184.8 284.4 178.2 279.2 173.4C274 168.6 267.4 166.2 259.4 166.2C252.2 166.2 246 168.4 240.8 172.8C236 177.2 233.6 182.8 233.6 189.6H167C167 164.8 175.8 144.6 193.4 129C211 113 233.6 105 261.2 105C288.8 105 311.2 112.2 328.4 126.6C346 141 354.8 160 354.8 183.6C354.8 200.8 350.2 214.8 341 225.6C331.8 236 320 243.2 305.6 247.2C322.8 252 336.4 260.2 346.4 271.8C356.8 283.4 362 298 362 315.6C362 340.4 352.6 360.8 333.8 376.8C315 392.8 290.6 400.8 260.6 400.8Z"/>
<path d="M52.5357 167.6H27.3357V105.2H120.336V400.2H52.5357V167.6Z"/>
</mask>
<path d="M260.6 400.8C229.8 400.8 204.6 392.4 185 375.6C165.8 358.8 156.2 337 156.2 310.2H226.4C226.4 318.2 229.4 324.8 235.4 330C241.4 335.2 249.4 337.8 259.4 337.8C269 337.8 276.8 335 282.8 329.4C289.2 323.8 292.4 316.6 292.4 307.8C292.4 299.8 289.6 293.2 284 288C278.4 282.8 271.2 280.2 262.4 280.2H225.2V218.4H262.4C269.2 218.4 275 216 279.8 211.2C284.6 206.4 287 200.4 287 193.2C287 184.8 284.4 178.2 279.2 173.4C274 168.6 267.4 166.2 259.4 166.2C252.2 166.2 246 168.4 240.8 172.8C236 177.2 233.6 182.8 233.6 189.6H167C167 164.8 175.8 144.6 193.4 129C211 113 233.6 105 261.2 105C288.8 105 311.2 112.2 328.4 126.6C346 141 354.8 160 354.8 183.6C354.8 200.8 350.2 214.8 341 225.6C331.8 236 320 243.2 305.6 247.2C322.8 252 336.4 260.2 346.4 271.8C356.8 283.4 362 298 362 315.6C362 340.4 352.6 360.8 333.8 376.8C315 392.8 290.6 400.8 260.6 400.8Z" fill="currentColor"/>
<path d="M52.5357 167.6H27.3357V105.2H120.336V400.2H52.5357V167.6Z" fill="currentColor"/>
<path d="M260.6 400.8C229.8 400.8 204.6 392.4 185 375.6C165.8 358.8 156.2 337 156.2 310.2H226.4C226.4 318.2 229.4 324.8 235.4 330C241.4 335.2 249.4 337.8 259.4 337.8C269 337.8 276.8 335 282.8 329.4C289.2 323.8 292.4 316.6 292.4 307.8C292.4 299.8 289.6 293.2 284 288C278.4 282.8 271.2 280.2 262.4 280.2H225.2V218.4H262.4C269.2 218.4 275 216 279.8 211.2C284.6 206.4 287 200.4 287 193.2C287 184.8 284.4 178.2 279.2 173.4C274 168.6 267.4 166.2 259.4 166.2C252.2 166.2 246 168.4 240.8 172.8C236 177.2 233.6 182.8 233.6 189.6H167C167 164.8 175.8 144.6 193.4 129C211 113 233.6 105 261.2 105C288.8 105 311.2 112.2 328.4 126.6C346 141 354.8 160 354.8 183.6C354.8 200.8 350.2 214.8 341 225.6C331.8 236 320 243.2 305.6 247.2C322.8 252 336.4 260.2 346.4 271.8C356.8 283.4 362 298 362 315.6C362 340.4 352.6 360.8 333.8 376.8C315 392.8 290.6 400.8 260.6 400.8Z" stroke="var(--stroke-color)" stroke-width="2.4" mask="url(#path-2-mask)"/>
<path d="M52.5357 167.6H27.3357V105.2H120.336V400.2H52.5357V167.6Z" stroke="var(--stroke-color)" stroke-width="2.4" mask="url(#path-2-mask)"/>
</g>
<g class="mix-blend-color dark:mix-blend-hard-light transition-all delay-400 opacity-100 duration-750 starting:opacity-0 motion-safe:starting:-translate-x-[51px] text-[#F8B803] dark:text-[#391800]">
<mask id="path-3-mask" maskUnits="userSpaceOnUse" x="51" y="103" width="338" height="299" fill="black">
<rect fill="white" x="51" y="103" width="338" height="299"/>
<path d="M286.264 400.8C255.464 400.8 230.264 392.4 210.664 375.6C191.464 358.8 181.864 337 181.864 310.2H252.064C252.064 318.2 255.064 324.8 261.064 330C267.064 335.2 275.064 337.8 285.064 337.8C294.664 337.8 302.464 335 308.464 329.4C314.864 323.8 318.064 316.6 318.064 307.8C318.064 299.8 315.264 293.2 309.664 288C304.064 282.8 296.864 280.2 288.064 280.2H250.864V218.4H288.064C294.864 218.4 300.664 216 305.464 211.2C310.264 206.4 312.664 200.4 312.664 193.2C312.664 184.8 310.064 178.2 304.864 173.4C299.664 168.6 293.064 166.2 285.064 166.2C277.864 166.2 271.664 168.4 266.464 172.8C261.664 177.2 259.264 182.8 259.264 189.6H192.664C192.664 164.8 201.464 144.6 219.064 129C236.664 113 259.264 105 286.864 105C314.464 105 336.864 112.2 354.064 126.6C371.664 141 380.464 160 380.464 183.6C380.464 200.8 375.864 214.8 366.664 225.6C357.464 236 345.664 243.2 331.264 247.2C348.464 252 362.064 260.2 372.064 271.8C382.464 283.4 387.664 298 387.664 315.6C387.664 340.4 378.264 360.8 359.464 376.8C340.664 392.8 316.264 400.8 286.264 400.8Z"/>
<path d="M78.2 167.6H53V105.2H146V400.2H78.2V167.6Z"/>
</mask>
<path d="M286.264 400.8C255.464 400.8 230.264 392.4 210.664 375.6C191.464 358.8 181.864 337 181.864 310.2H252.064C252.064 318.2 255.064 324.8 261.064 330C267.064 335.2 275.064 337.8 285.064 337.8C294.664 337.8 302.464 335 308.464 329.4C314.864 323.8 318.064 316.6 318.064 307.8C318.064 299.8 315.264 293.2 309.664 288C304.064 282.8 296.864 280.2 288.064 280.2H250.864V218.4H288.064C294.864 218.4 300.664 216 305.464 211.2C310.264 206.4 312.664 200.4 312.664 193.2C312.664 184.8 310.064 178.2 304.864 173.4C299.664 168.6 293.064 166.2 285.064 166.2C277.864 166.2 271.664 168.4 266.464 172.8C261.664 177.2 259.264 182.8 259.264 189.6H192.664C192.664 164.8 201.464 144.6 219.064 129C236.664 113 259.264 105 286.864 105C314.464 105 336.864 112.2 354.064 126.6C371.664 141 380.464 160 380.464 183.6C380.464 200.8 375.864 214.8 366.664 225.6C357.464 236 345.664 243.2 331.264 247.2C348.464 252 362.064 260.2 372.064 271.8C382.464 283.4 387.664 298 387.664 315.6C387.664 340.4 378.264 360.8 359.464 376.8C340.664 392.8 316.264 400.8 286.264 400.8Z" fill="currentColor"/>
<path d="M78.2 167.6H53V105.2H146V400.2H78.2V167.6Z" fill="currentColor"/>
<path d="M286.264 400.8C255.464 400.8 230.264 392.4 210.664 375.6C191.464 358.8 181.864 337 181.864 310.2H252.064C252.064 318.2 255.064 324.8 261.064 330C267.064 335.2 275.064 337.8 285.064 337.8C294.664 337.8 302.464 335 308.464 329.4C314.864 323.8 318.064 316.6 318.064 307.8C318.064 299.8 315.264 293.2 309.664 288C304.064 282.8 296.864 280.2 288.064 280.2H250.864V218.4H288.064C294.864 218.4 300.664 216 305.464 211.2C310.264 206.4 312.664 200.4 312.664 193.2C312.664 184.8 310.064 178.2 304.864 173.4C299.664 168.6 293.064 166.2 285.064 166.2C277.864 166.2 271.664 168.4 266.464 172.8C261.664 177.2 259.264 182.8 259.264 189.6H192.664C192.664 164.8 201.464 144.6 219.064 129C236.664 113 259.264 105 286.864 105C314.464 105 336.864 112.2 354.064 126.6C371.664 141 380.464 160 380.464 183.6C380.464 200.8 375.864 214.8 366.664 225.6C357.464 236 345.664 243.2 331.264 247.2C348.464 252 362.064 260.2 372.064 271.8C382.464 283.4 387.664 298 387.664 315.6C387.664 340.4 378.264 360.8 359.464 376.8C340.664 392.8 316.264 400.8 286.264 400.8Z" stroke="var(--stroke-color)" stroke-width="2.4" mask="url(#path-3-mask)"/>
<path d="M78.2 167.6H53V105.2H146V400.2H78.2V167.6Z" stroke="var(--stroke-color)" stroke-width="2.4" mask="url(#path-3-mask)"/>
</g>
<g class="mix-blend-multiply dark:mix-blend-normal transition-all delay-400 opacity-100 duration-750 starting:opacity-0 motion-safe:starting:-translate-x-[78px] text-[#F3BEC7] dark:text-[#733000]">
<mask id="path-4-mask" maskUnits="userSpaceOnUse" x="76.6643" y="103" width="338" height="299" fill="black">
<rect fill="white" x="76.6643" y="103" width="338" height="299"/>
<path d="M311.929 400.8C281.129 400.8 255.929 392.4 236.329 375.6C217.129 358.8 207.529 337 207.529 310.2H277.729C277.729 318.2 280.729 324.8 286.729 330C292.729 335.2 300.729 337.8 310.729 337.8C320.329 337.8 328.129 335 334.129 329.4C340.529 323.8 343.729 316.6 343.729 307.8C343.729 299.8 340.929 293.2 335.329 288C329.729 282.8 322.529 280.2 313.729 280.2H276.529V218.4H313.729C320.529 218.4 326.329 216 331.129 211.2C335.929 206.4 338.329 200.4 338.329 193.2C338.329 184.8 335.729 178.2 330.529 173.4C325.329 168.6 318.729 166.2 310.729 166.2C303.529 166.2 297.329 168.4 292.129 172.8C287.329 177.2 284.929 182.8 284.929 189.6H218.329C218.329 164.8 227.129 144.6 244.729 129C262.329 113 284.929 105 312.529 105C340.129 105 362.529 112.2 379.729 126.6C397.329 141 406.129 160 406.129 183.6C406.129 200.8 401.529 214.8 392.329 225.6C383.129 236 371.329 243.2 356.929 247.2C374.129 252 387.729 260.2 397.729 271.8C408.129 283.4 413.329 298 413.329 315.6C413.329 340.4 403.929 360.8 385.129 376.8C366.329 392.8 341.929 400.8 311.929 400.8Z"/>
<path d="M103.864 167.6H78.6643V105.2H171.664V400.2H103.864V167.6Z"/>
</mask>
<path d="M311.929 400.8C281.129 400.8 255.929 392.4 236.329 375.6C217.129 358.8 207.529 337 207.529 310.2H277.729C277.729 318.2 280.729 324.8 286.729 330C292.729 335.2 300.729 337.8 310.729 337.8C320.329 337.8 328.129 335 334.129 329.4C340.529 323.8 343.729 316.6 343.729 307.8C343.729 299.8 340.929 293.2 335.329 288C329.729 282.8 322.529 280.2 313.729 280.2H276.529V218.4H313.729C320.529 218.4 326.329 216 331.129 211.2C335.929 206.4 338.329 200.4 338.329 193.2C338.329 184.8 335.729 178.2 330.529 173.4C325.329 168.6 318.729 166.2 310.729 166.2C303.529 166.2 297.329 168.4 292.129 172.8C287.329 177.2 284.929 182.8 284.929 189.6H218.329C218.329 164.8 227.129 144.6 244.729 129C262.329 113 284.929 105 312.529 105C340.129 105 362.529 112.2 379.729 126.6C397.329 141 406.129 160 406.129 183.6C406.129 200.8 401.529 214.8 392.329 225.6C383.129 236 371.329 243.2 356.929 247.2C374.129 252 387.729 260.2 397.729 271.8C408.129 283.4 413.329 298 413.329 315.6C413.329 340.4 403.929 360.8 385.129 376.8C366.329 392.8 341.929 400.8 311.929 400.8Z" fill="currentColor"/>
<path d="M103.864 167.6H78.6643V105.2H171.664V400.2H103.864V167.6Z" fill="currentColor"/>
<path d="M311.929 400.8C281.129 400.8 255.929 392.4 236.329 375.6C217.129 358.8 207.529 337 207.529 310.2H277.729C277.729 318.2 280.729 324.8 286.729 330C292.729 335.2 300.729 337.8 310.729 337.8C320.329 337.8 328.129 335 334.129 329.4C340.529 323.8 343.729 316.6 343.729 307.8C343.729 299.8 340.929 293.2 335.329 288C329.729 282.8 322.529 280.2 313.729 280.2H276.529V218.4H313.729C320.529 218.4 326.329 216 331.129 211.2C335.929 206.4 338.329 200.4 338.329 193.2C338.329 184.8 335.729 178.2 330.529 173.4C325.329 168.6 318.729 166.2 310.729 166.2C303.529 166.2 297.329 168.4 292.129 172.8C287.329 177.2 284.929 182.8 284.929 189.6H218.329C218.329 164.8 227.129 144.6 244.729 129C262.329 113 284.929 105 312.529 105C340.129 105 362.529 112.2 379.729 126.6C397.329 141 406.129 160 406.129 183.6C406.129 200.8 401.529 214.8 392.329 225.6C383.129 236 371.329 243.2 356.929 247.2C374.129 252 387.729 260.2 397.729 271.8C408.129 283.4 413.329 298 413.329 315.6C413.329 340.4 403.929 360.8 385.129 376.8C366.329 392.8 341.929 400.8 311.929 400.8Z" stroke="var(--stroke-color)" stroke-width="2.4" mask="url(#path-4-mask)"/>
<path d="M103.864 167.6H78.6643V105.2H171.664V400.2H103.864V167.6Z" stroke="var(--stroke-color)" stroke-width="2.4" mask="url(#path-4-mask)"/>
</g>
<g class="mix-blend-hard-light transition-all delay-400 opacity-100 duration-750 starting:opacity-0 motion-safe:starting:-translate-x-[102px] text-[#F3BEC7] dark:text-[#4B0600]">
<mask id="path-5-mask" maskUnits="userSpaceOnUse" x="102.329" y="103" width="338" height="299" fill="black">
<rect fill="white" x="102.329" y="103" width="338" height="299"/>
<path d="M337.593 400.8C306.793 400.8 281.593 392.4 261.993 375.6C242.793 358.8 233.193 337 233.193 310.2H303.393C303.393 318.2 306.393 324.8 312.393 330C318.393 335.2 326.393 337.8 336.393 337.8C345.993 337.8 353.793 335 359.793 329.4C366.193 323.8 369.393 316.6 369.393 307.8C369.393 299.8 366.593 293.2 360.993 288C355.393 282.8 348.193 280.2 339.393 280.2H302.193V218.4H339.393C346.193 218.4 351.993 216 356.793 211.2C361.593 206.4 363.993 200.4 363.993 193.2C363.993 184.8 361.393 178.2 356.193 173.4C350.993 168.6 344.393 166.2 336.393 166.2C329.193 166.2 322.993 168.4 317.793 172.8C312.993 177.2 310.593 182.8 310.593 189.6H243.993C243.993 164.8 252.793 144.6 270.393 129C287.993 113 310.593 105 338.193 105C365.793 105 388.193 112.2 405.393 126.6C422.993 141 431.793 160 431.793 183.6C431.793 200.8 427.193 214.8 417.993 225.6C408.793 236 396.993 243.2 382.593 247.2C399.793 252 413.393 260.2 423.393 271.8C433.793 283.4 438.993 298 438.993 315.6C438.993 340.4 429.593 360.8 410.793 376.8C391.993 392.8 367.593 400.8 337.593 400.8Z"/>
<path d="M129.529 167.6H104.329V105.2H197.329V400.2H129.529V167.6Z"/>
</mask>
<path d="M337.593 400.8C306.793 400.8 281.593 392.4 261.993 375.6C242.793 358.8 233.193 337 233.193 310.2H303.393C303.393 318.2 306.393 324.8 312.393 330C318.393 335.2 326.393 337.8 336.393 337.8C345.993 337.8 353.793 335 359.793 329.4C366.193 323.8 369.393 316.6 369.393 307.8C369.393 299.8 366.593 293.2 360.993 288C355.393 282.8 348.193 280.2 339.393 280.2H302.193V218.4H339.393C346.193 218.4 351.993 216 356.793 211.2C361.593 206.4 363.993 200.4 363.993 193.2C363.993 184.8 361.393 178.2 356.193 173.4C350.993 168.6 344.393 166.2 336.393 166.2C329.193 166.2 322.993 168.4 317.793 172.8C312.993 177.2 310.593 182.8 310.593 189.6H243.993C243.993 164.8 252.793 144.6 270.393 129C287.993 113 310.593 105 338.193 105C365.793 105 388.193 112.2 405.393 126.6C422.993 141 431.793 160 431.793 183.6C431.793 200.8 427.193 214.8 417.993 225.6C408.793 236 396.993 243.2 382.593 247.2C399.793 252 413.393 260.2 423.393 271.8C433.793 283.4 438.993 298 438.993 315.6C438.993 340.4 429.593 360.8 410.793 376.8C391.993 392.8 367.593 400.8 337.593 400.8Z" fill="currentColor"/>
<path d="M129.529 167.6H104.329V105.2H197.329V400.2H129.529V167.6Z" fill="currentColor"/>
<path d="M337.593 400.8C306.793 400.8 281.593 392.4 261.993 375.6C242.793 358.8 233.193 337 233.193 310.2H303.393C303.393 318.2 306.393 324.8 312.393 330C318.393 335.2 326.393 337.8 336.393 337.8C345.993 337.8 353.793 335 359.793 329.4C366.193 323.8 369.393 316.6 369.393 307.8C369.393 299.8 366.593 293.2 360.993 288C355.393 282.8 348.193 280.2 339.393 280.2H302.193V218.4H339.393C346.193 218.4 351.993 216 356.793 211.2C361.593 206.4 363.993 200.4 363.993 193.2C363.993 184.8 361.393 178.2 356.193 173.4C350.993 168.6 344.393 166.2 336.393 166.2C329.193 166.2 322.993 168.4 317.793 172.8C312.993 177.2 310.593 182.8 310.593 189.6H243.993C243.993 164.8 252.793 144.6 270.393 129C287.993 113 310.593 105 338.193 105C365.793 105 388.193 112.2 405.393 126.6C422.993 141 431.793 160 431.793 183.6C431.793 200.8 427.193 214.8 417.993 225.6C408.793 236 396.993 243.2 382.593 247.2C399.793 252 413.393 260.2 423.393 271.8C433.793 283.4 438.993 298 438.993 315.6C438.993 340.4 429.593 360.8 410.793 376.8C391.993 392.8 367.593 400.8 337.593 400.8Z" stroke="var(--stroke-color)" stroke-width="2.4" mask="url(#path-5-mask)"/>
<path d="M129.529 167.6H104.329V105.2H197.329V400.2H129.529V167.6Z" stroke="var(--stroke-color)" stroke-width="2.4" mask="url(#path-5-mask)"/>
</g>
</svg>
<div class="absolute inset-0 rounded-t-lg lg:rounded-t-none lg:rounded-r-lg shadow-[inset_0px_0px_0px_1px_rgba(26,26,0,0.16)] dark:shadow-[inset_0px_0px_0px_1px_#fffaed2d]"></div>
</div>
</main>
</div>
@if (Route::has('login'))
<div class="h-14.5 hidden lg:block"></div>
@endif
</body>
</html>