Redesign Settings page with centered layout, hero, and grouped sections.
Deploy Ladill Frontdesk / deploy (push) Successful in 36s
Deploy Ladill Frontdesk / deploy (push) Successful in 36s
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -3,30 +3,38 @@
|
||||
$settings = $organization->settings ?? [];
|
||||
@endphp
|
||||
|
||||
<h1 class="text-xl font-semibold text-slate-900">Settings</h1>
|
||||
<p class="text-sm text-slate-500">{{ $organization->name }}</p>
|
||||
<div class="mx-auto max-w-3xl space-y-6">
|
||||
<x-frontdesk.page-hero
|
||||
badge="Organization · Kiosk · Notifications"
|
||||
title="Settings"
|
||||
description="Configure branding, reception workflows, host alerts, and integrations for {{ $organization->name }}."
|
||||
:stats="[
|
||||
['value' => $isPro ? ($plan['label'] ?? 'Pro') : 'Free', 'label' => 'Plan'],
|
||||
['value' => number_format($branchCount), 'label' => 'Branches'],
|
||||
['value' => number_format($monthlyUsage->email_count), 'label' => 'Emails this month'],
|
||||
]" />
|
||||
|
||||
@if ($canManage)
|
||||
<section class="mt-6 max-w-2xl rounded-2xl border border-slate-200 bg-white p-5">
|
||||
<div class="flex flex-wrap items-start justify-between gap-4">
|
||||
<section class="rounded-2xl border border-slate-200 bg-white p-5 sm:p-6">
|
||||
<div class="flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between">
|
||||
<div>
|
||||
<h2 class="text-sm font-semibold text-slate-900">Plan</h2>
|
||||
<p class="mt-1 text-sm text-slate-600">
|
||||
<h2 class="text-sm font-semibold text-slate-900">Plan & usage</h2>
|
||||
<p class="mt-1 text-sm leading-6 text-slate-600">
|
||||
@if ($isPro)
|
||||
<span class="font-medium text-indigo-700">{{ $plan['label'] ?? 'Pro' }}</span> — unlimited branches & kiosks, integrations, and unlimited host emails (SMS still billed per segment).
|
||||
<span class="font-medium text-indigo-700">{{ $plan['label'] ?? 'Pro' }}</span> — unlimited branches and kiosks, integrations, and unlimited host emails (SMS still billed per segment).
|
||||
@else
|
||||
<span class="font-medium">Free</span> — 1 branch, 1 kiosk, core check-in & badges. Host alerts billed after {{ number_format($freeEmailAllowance) }} free emails/month.
|
||||
<span class="font-medium text-slate-900">Free</span> — one branch, one kiosk, core check-in and badges. Host alerts billed after {{ number_format($freeEmailAllowance) }} free emails per month.
|
||||
@endif
|
||||
</p>
|
||||
</div>
|
||||
@if (! $isPro)
|
||||
<a href="{{ route('frontdesk.pro.index') }}" class="btn-primary text-sm">Upgrade to Pro (GHS {{ number_format($proPriceMinor / 100, 0) }}/mo)</a>
|
||||
<a href="{{ route('frontdesk.pro.index') }}" class="btn-primary shrink-0 text-sm">Upgrade to Pro (GHS {{ number_format($proPriceMinor / 100, 0) }}/mo)</a>
|
||||
@endif
|
||||
</div>
|
||||
<dl class="mt-4 grid gap-3 text-sm sm:grid-cols-2">
|
||||
<dl class="mt-5 grid gap-4 border-t border-slate-100 pt-5 text-sm sm:grid-cols-2">
|
||||
<div>
|
||||
<dt class="text-slate-500">Host emails this month</dt>
|
||||
<dd class="font-medium">
|
||||
<dd class="mt-0.5 font-semibold text-slate-900">
|
||||
@if ($freeEmailAllowance === null)
|
||||
{{ number_format($monthlyUsage->email_count) }} sent (unlimited on Pro)
|
||||
@else
|
||||
@@ -36,22 +44,23 @@
|
||||
</div>
|
||||
<div>
|
||||
<dt class="text-slate-500">Host SMS this month</dt>
|
||||
<dd class="font-medium">{{ number_format($monthlyUsage->sms_count) }} sent</dd>
|
||||
<dd class="mt-0.5 font-semibold text-slate-900">{{ number_format($monthlyUsage->sms_count) }} sent</dd>
|
||||
</div>
|
||||
</dl>
|
||||
<p class="mt-3 text-xs text-slate-500">
|
||||
<p class="mt-4 text-xs leading-5 text-slate-500">
|
||||
Email {{ $emailCostFormatted }} each after free allowance · SMS from {{ $smsCostFormatted }} per segment — charged to your
|
||||
<a href="{{ route('frontdesk.wallet') }}" class="text-indigo-600 underline">Ladill wallet</a>.
|
||||
Hosts are notified via email or phone on their profile; linking a Ladill account is optional (in-app bell only).
|
||||
<a href="{{ route('frontdesk.wallet') }}" class="font-medium text-indigo-600 underline">Ladill wallet</a>.
|
||||
Hosts are notified via email or phone on their profile; linking a Ladill account is optional.
|
||||
</p>
|
||||
</section>
|
||||
@endif
|
||||
|
||||
<form method="POST" action="{{ route('frontdesk.settings.update') }}" enctype="multipart/form-data" class="mt-6 max-w-2xl space-y-6">
|
||||
<form method="POST" action="{{ route('frontdesk.settings.update') }}" enctype="multipart/form-data" class="space-y-6">
|
||||
@csrf @method('PUT')
|
||||
|
||||
<section class="rounded-2xl border border-slate-200 bg-white p-5 space-y-4">
|
||||
<section class="rounded-2xl border border-slate-200 bg-white p-5 sm:p-6">
|
||||
<h2 class="text-sm font-semibold text-slate-900">Organization</h2>
|
||||
<div class="mt-4 space-y-4">
|
||||
@if ($canManage)
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-slate-700">Name</label>
|
||||
@@ -81,16 +90,24 @@
|
||||
class="mt-3 block w-full text-sm text-slate-600 file:mr-3 file:rounded-lg file:border-0 file:bg-indigo-50 file:px-3 file:py-2 file:text-sm file:font-medium file:text-indigo-700">
|
||||
</div>
|
||||
@else
|
||||
<dl class="text-sm space-y-2">
|
||||
<div class="flex justify-between"><dt class="text-slate-500">Name</dt><dd>{{ $organization->name }}</dd></div>
|
||||
<div class="flex justify-between"><dt class="text-slate-500">Timezone</dt><dd>{{ $organization->timezone }}</dd></div>
|
||||
<dl class="divide-y divide-slate-100 text-sm">
|
||||
<div class="flex justify-between gap-4 py-3">
|
||||
<dt class="text-slate-500">Name</dt>
|
||||
<dd class="font-medium text-slate-900">{{ $organization->name }}</dd>
|
||||
</div>
|
||||
<div class="flex justify-between gap-4 py-3">
|
||||
<dt class="text-slate-500">Timezone</dt>
|
||||
<dd class="font-medium text-slate-900">{{ $organization->timezone }}</dd>
|
||||
</div>
|
||||
</dl>
|
||||
@endif
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@if ($canManage)
|
||||
<section class="rounded-2xl border border-slate-200 bg-white p-5 space-y-4">
|
||||
<h2 class="text-sm font-semibold text-slate-900">Reception & kiosk</h2>
|
||||
<section class="rounded-2xl border border-slate-200 bg-white p-5 sm:p-6">
|
||||
<h2 class="text-sm font-semibold text-slate-900">Reception & kiosk</h2>
|
||||
<div class="mt-4 space-y-5">
|
||||
<div class="grid gap-4 sm:grid-cols-2">
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-slate-700">Badge expiry (hours)</label>
|
||||
@@ -100,34 +117,47 @@
|
||||
<label class="block text-sm font-medium text-slate-700">Kiosk inactivity reset (seconds)</label>
|
||||
<input type="number" name="kiosk_reset_seconds" value="{{ old('kiosk_reset_seconds', $settings['kiosk_reset_seconds'] ?? 120) }}" min="30" max="600" class="mt-1 w-full rounded-lg border-slate-300 text-sm">
|
||||
</div>
|
||||
<div>
|
||||
<div class="sm:col-span-2">
|
||||
<label class="block text-sm font-medium text-slate-700">Contractor badge expiry (hours)</label>
|
||||
<input type="number" name="contractor_badge_expiry_hours" value="{{ old('contractor_badge_expiry_hours', data_get($settings, 'type_badge_expiry_hours.contractor', 12)) }}" min="1" max="24" class="mt-1 w-full rounded-lg border-slate-300 text-sm">
|
||||
<input type="number" name="contractor_badge_expiry_hours" value="{{ old('contractor_badge_expiry_hours', data_get($settings, 'type_badge_expiry_hours.contractor', 12)) }}" min="1" max="24" class="mt-1 w-full max-w-xs rounded-lg border-slate-300 text-sm">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-slate-700">Visitor policy</label>
|
||||
<textarea name="visitor_policy" rows="4" class="mt-1 w-full rounded-lg border-slate-300 text-sm">{{ old('visitor_policy', $settings['visitor_policy'] ?? '') }}</textarea>
|
||||
<p class="mt-1 text-xs text-slate-500">Shown to guests during kiosk check-in when policies must be accepted.</p>
|
||||
<textarea name="visitor_policy" rows="4" class="mt-2 w-full rounded-lg border-slate-300 text-sm">{{ old('visitor_policy', $settings['visitor_policy'] ?? '') }}</textarea>
|
||||
</div>
|
||||
<label class="flex items-center gap-2 text-sm">
|
||||
<input type="checkbox" name="employee_kiosk_enabled" value="1"
|
||||
|
||||
<label class="flex items-start gap-3 rounded-xl border border-slate-200 bg-slate-50 px-4 py-3 text-sm text-slate-700">
|
||||
<input type="checkbox" name="employee_kiosk_enabled" value="1" class="mt-0.5"
|
||||
@checked(old('employee_kiosk_enabled', $settings['employee_kiosk_enabled'] ?? true))>
|
||||
Enable employee sign-in on kiosk (code + PIN)
|
||||
<span>
|
||||
<span class="font-medium text-slate-900">Employee sign-in on kiosk</span>
|
||||
<span class="mt-0.5 block text-xs text-slate-500">Allow staff to sign in with employee code and PIN.</span>
|
||||
</span>
|
||||
</label>
|
||||
|
||||
<div class="rounded-xl border border-slate-200 p-4">
|
||||
<h2 class="text-sm font-semibold text-slate-900">Ladill Queue</h2>
|
||||
<p class="mt-1 text-xs text-slate-500">Manage service queues and counters in Frontdesk. You must also enable Frontdesk integration in Ladill Queue settings.</p>
|
||||
<label class="mt-3 flex items-center gap-2 text-sm">
|
||||
<h3 class="text-sm font-semibold text-slate-900">Ladill Queue</h3>
|
||||
<p class="mt-1 text-xs leading-5 text-slate-500">Manage service queues and counters in Frontdesk. You must also enable Frontdesk integration in Ladill Queue settings.</p>
|
||||
<label class="mt-3 flex items-center gap-2 text-sm text-slate-700">
|
||||
<input type="checkbox" name="queue_integration_enabled" value="1" @checked(data_get($settings, 'queue_integration_enabled'))>
|
||||
Enable Ladill Queue integration
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="rounded-2xl border border-slate-200 bg-white p-5 sm:p-6">
|
||||
<h2 class="text-sm font-semibold text-slate-900">Notifications</h2>
|
||||
<div class="mt-4 space-y-5">
|
||||
<div>
|
||||
<p class="text-sm font-medium text-slate-700">Notification channels</p>
|
||||
<p class="text-sm font-medium text-slate-700">Channels</p>
|
||||
<p class="mt-1 text-xs text-slate-500">Alerts go to each host's email and/or phone — no Ladill account required.</p>
|
||||
<div class="mt-2 flex flex-wrap gap-3">
|
||||
<div class="mt-3 flex flex-wrap gap-4">
|
||||
@foreach ($notificationChannels as $key => $label)
|
||||
<label class="flex items-center gap-2 text-sm">
|
||||
<label class="flex items-center gap-2 text-sm text-slate-700">
|
||||
<input type="checkbox" name="notification_channels[]" value="{{ $key }}"
|
||||
@checked(in_array($key, old('notification_channels', $settings['notification_channels'] ?? ['email'])))>
|
||||
{{ $label }}
|
||||
@@ -135,11 +165,12 @@
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<p class="text-sm font-medium text-slate-700">Notification events</p>
|
||||
<div class="mt-2 grid gap-2 sm:grid-cols-2">
|
||||
|
||||
<div class="border-t border-slate-100 pt-5">
|
||||
<p class="text-sm font-medium text-slate-700">Events</p>
|
||||
<div class="mt-3 grid gap-3 sm:grid-cols-2">
|
||||
@foreach ($notificationEvents as $key => $label)
|
||||
<label class="flex items-center gap-2 text-sm">
|
||||
<label class="flex items-center gap-2 text-sm text-slate-700">
|
||||
<input type="checkbox" name="notification_events[{{ $key }}]" value="1"
|
||||
@checked(old("notification_events.{$key}", data_get($settings, "notification_events.{$key}", true)))>
|
||||
{{ $label }}
|
||||
@@ -147,49 +178,60 @@
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
|
||||
<div class="border-t border-slate-100 pt-5">
|
||||
<label class="block text-sm font-medium text-slate-700">Daily report recipients</label>
|
||||
<input type="text" name="report_daily_recipients" value="{{ old('report_daily_recipients', implode(', ', $settings['report_daily_recipients'] ?? [])) }}" placeholder="admin@example.com, security@example.com" class="mt-1 w-full rounded-lg border-slate-300 text-sm">
|
||||
<input type="text" name="report_daily_recipients" value="{{ old('report_daily_recipients', implode(', ', $settings['report_daily_recipients'] ?? [])) }}" placeholder="admin@example.com, security@example.com" class="mt-2 w-full rounded-lg border-slate-300 text-sm">
|
||||
<p class="mt-1 text-xs text-slate-500">Comma-separated emails for the daily summary report.</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div class="flex justify-end">
|
||||
<button type="submit" class="btn-primary">Save settings</button>
|
||||
</div>
|
||||
@endif
|
||||
</form>
|
||||
|
||||
<div class="mt-8 grid gap-4 lg:grid-cols-3">
|
||||
<section class="overflow-hidden rounded-2xl border border-slate-200 bg-white">
|
||||
<div class="border-b border-slate-100 px-5 py-4 sm:px-6">
|
||||
<h2 class="text-sm font-semibold text-slate-900">Related settings</h2>
|
||||
<p class="mt-1 text-xs text-slate-500">Branches, hardware, templates, and integrations.</p>
|
||||
</div>
|
||||
<div class="grid gap-px bg-slate-100 sm:grid-cols-2">
|
||||
@if ($canManage)
|
||||
<a href="{{ route('frontdesk.branches.index') }}" class="rounded-2xl border border-slate-200 bg-white p-5 hover:border-indigo-300">
|
||||
<h3 class="font-semibold text-slate-900">Branches</h3>
|
||||
<p class="mt-1 text-sm text-slate-500">{{ $branchCount }} branch{{ $branchCount === 1 ? '' : 'es' }}</p>
|
||||
<a href="{{ route('frontdesk.branches.index') }}" class="flex flex-col bg-white px-5 py-4 transition hover:bg-indigo-50/40 sm:px-6">
|
||||
<span class="font-medium text-slate-900">Branches</span>
|
||||
<span class="mt-1 text-sm text-slate-500">{{ $branchCount }} branch{{ $branchCount === 1 ? '' : 'es' }}</span>
|
||||
</a>
|
||||
<a href="{{ route('frontdesk.members.index') }}" class="rounded-2xl border border-slate-200 bg-white p-5 hover:border-indigo-300">
|
||||
<h3 class="font-semibold text-slate-900">Team members</h3>
|
||||
<p class="mt-1 text-sm text-slate-500">Manage roles and access</p>
|
||||
<a href="{{ route('frontdesk.members.index') }}" class="flex flex-col bg-white px-5 py-4 transition hover:bg-indigo-50/40 sm:px-6">
|
||||
<span class="font-medium text-slate-900">Team members</span>
|
||||
<span class="mt-1 text-sm text-slate-500">Roles and access</span>
|
||||
</a>
|
||||
@endif
|
||||
<a href="{{ route('frontdesk.kiosk') }}" class="rounded-2xl border border-slate-200 bg-white p-5 hover:border-indigo-300">
|
||||
<h3 class="font-semibold text-slate-900">Kiosk mode</h3>
|
||||
<p class="mt-1 text-sm text-slate-500">Open self-service check-in</p>
|
||||
<a href="{{ route('frontdesk.kiosk') }}" class="flex flex-col bg-white px-5 py-4 transition hover:bg-indigo-50/40 sm:px-6">
|
||||
<span class="font-medium text-slate-900">Kiosk mode</span>
|
||||
<span class="mt-1 text-sm text-slate-500">Open self-service check-in</span>
|
||||
</a>
|
||||
@if ($canManage)
|
||||
<a href="{{ route('frontdesk.settings.badge') }}" class="rounded-2xl border border-slate-200 bg-white p-5 hover:border-indigo-300">
|
||||
<h3 class="font-semibold text-slate-900">Badge template</h3>
|
||||
<p class="mt-1 text-sm text-slate-500">Layout, photo, and QR settings</p>
|
||||
<a href="{{ route('frontdesk.settings.badge') }}" class="flex flex-col bg-white px-5 py-4 transition hover:bg-indigo-50/40 sm:px-6">
|
||||
<span class="font-medium text-slate-900">Badge template</span>
|
||||
<span class="mt-1 text-sm text-slate-500">Layout, photo, and QR settings</span>
|
||||
</a>
|
||||
<a href="{{ route('frontdesk.integrations.edit') }}" class="rounded-2xl border border-slate-200 bg-white p-5 hover:border-indigo-300">
|
||||
<h3 class="font-semibold text-slate-900">Integrations</h3>
|
||||
<p class="mt-1 text-sm text-slate-500">Webhooks and calendar feeds</p>
|
||||
<a href="{{ route('frontdesk.integrations.edit') }}" class="flex flex-col bg-white px-5 py-4 transition hover:bg-indigo-50/40 sm:px-6">
|
||||
<span class="font-medium text-slate-900">Integrations</span>
|
||||
<span class="mt-1 text-sm text-slate-500">Webhooks and calendar feeds</span>
|
||||
</a>
|
||||
<a href="{{ route('frontdesk.employees.index') }}" class="rounded-2xl border border-slate-200 bg-white p-5 hover:border-indigo-300">
|
||||
<h3 class="font-semibold text-slate-900">Employees</h3>
|
||||
<p class="mt-1 text-sm text-slate-500">Staff roster and kiosk PINs</p>
|
||||
<a href="{{ route('frontdesk.employees.index') }}" class="flex flex-col bg-white px-5 py-4 transition hover:bg-indigo-50/40 sm:px-6">
|
||||
<span class="font-medium text-slate-900">Employees</span>
|
||||
<span class="mt-1 text-sm text-slate-500">Staff roster and kiosk PINs</span>
|
||||
</a>
|
||||
<a href="{{ route('frontdesk.devices.index') }}" class="rounded-2xl border border-slate-200 bg-white p-5 hover:border-indigo-300">
|
||||
<h3 class="font-semibold text-slate-900">Devices</h3>
|
||||
<p class="mt-1 text-sm text-slate-500">Kiosks, printers, and hardware</p>
|
||||
<a href="{{ route('frontdesk.devices.index') }}" class="flex flex-col bg-white px-5 py-4 transition hover:bg-indigo-50/40 sm:px-6">
|
||||
<span class="font-medium text-slate-900">Devices</span>
|
||||
<span class="mt-1 text-sm text-slate-500">Kiosks, printers, and hardware</span>
|
||||
</a>
|
||||
@endif
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</x-app-layout>
|
||||
|
||||
Reference in New Issue
Block a user