Deploy Ladill Frontdesk / deploy (push) Successful in 1m16s
Surface hardware kiosk provision in plan benefits, upgrade banners, and settings copy so paid tiers clearly include supplied visitor kiosks.
217 lines
15 KiB
PHP
217 lines
15 KiB
PHP
<x-app-layout title="Settings">
|
|
@php
|
|
$settings = $organization->settings ?? [];
|
|
@endphp
|
|
|
|
<x-settings.page description="Configure branding, reception workflows, host alerts, and integrations for {{ $organization->name }}.">
|
|
@if ($canManage)
|
|
<x-settings.card title="Plan & usage" description="Subscription limits and notification billing for {{ $organization->name }}.">
|
|
<div class="flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between">
|
|
<p class="text-sm leading-6 text-slate-600">
|
|
@if ($hasPaidPlan)
|
|
<span class="font-medium text-indigo-700">{{ $plan['label'] ?? 'Pro' }}</span> — Ladill-provided visitor kiosks, unlimited kiosk software, integrations, and unlimited host emails, billed per branch (SMS still billed per segment).
|
|
@if ($billedBranches > 0)
|
|
Billed for {{ $billedBranches }} {{ str('branch')->plural($billedBranches) }}
|
|
({{ $activeBranchCount }} active).
|
|
@endif
|
|
@else
|
|
<span class="font-medium text-slate-900">Free</span> — one branch (setup only), one kiosk, owner-only access. Multi-branch and team require Pro. Host alerts billed after {{ number_format($freeEmailAllowance) }} free emails per month.
|
|
@endif
|
|
</p>
|
|
@if (! $hasPaidPlan)
|
|
<a href="{{ route('frontdesk.pro.index') }}" class="btn-primary shrink-0 text-sm">Upgrade to Pro (GHS {{ number_format($proPriceMinor / 100, 0) }}/branch/mo)</a>
|
|
@else
|
|
<a href="{{ route('frontdesk.pro.index') }}" class="btn-secondary shrink-0 text-sm">Manage plan</a>
|
|
@endif
|
|
</div>
|
|
<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="mt-0.5 font-semibold text-slate-900">
|
|
@if ($freeEmailAllowance === null)
|
|
{{ number_format($monthlyUsage->email_count) }} sent (unlimited on paid plans)
|
|
@else
|
|
{{ number_format($monthlyUsage->email_count) }} / {{ number_format($freeEmailAllowance) }} free
|
|
@endif
|
|
</dd>
|
|
</div>
|
|
<div>
|
|
<dt class="text-slate-500">Host SMS this month</dt>
|
|
<dd class="mt-0.5 font-semibold text-slate-900">{{ number_format($monthlyUsage->sms_count) }} sent</dd>
|
|
</div>
|
|
</dl>
|
|
<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="font-medium text-indigo-600 underline">Ladill wallet</a>.
|
|
</p>
|
|
</x-settings.card>
|
|
@endif
|
|
|
|
@if ($canViewBranches || $canViewTeam)
|
|
<div class="grid gap-4 sm:grid-cols-2">
|
|
@if ($canViewBranches)
|
|
<a href="{{ route('frontdesk.branches.index') }}"
|
|
class="group rounded-2xl border border-slate-200 bg-white p-5 shadow-sm transition hover:border-indigo-200 hover:shadow-md">
|
|
<div class="flex items-start justify-between gap-3">
|
|
<div>
|
|
<p class="text-sm font-semibold text-slate-900 group-hover:text-indigo-700">Branches</p>
|
|
<p class="mt-1 text-sm text-slate-500">Locations, buildings, and reception desks.</p>
|
|
</div>
|
|
@if (! $hasBranchesFeature)
|
|
<span class="shrink-0 rounded-full bg-amber-50 px-2 py-0.5 text-[10px] font-semibold uppercase tracking-wide text-amber-700">Pro</span>
|
|
@endif
|
|
</div>
|
|
<p class="mt-4 text-xs font-medium text-indigo-600">
|
|
{{ $hasBranchesFeature ? 'Manage branches →' : 'Upgrade to unlock →' }}
|
|
</p>
|
|
</a>
|
|
@endif
|
|
@if ($canViewTeam)
|
|
<a href="{{ route('frontdesk.members.index') }}"
|
|
class="group rounded-2xl border border-slate-200 bg-white p-5 shadow-sm transition hover:border-indigo-200 hover:shadow-md">
|
|
<div class="flex items-start justify-between gap-3">
|
|
<div>
|
|
<p class="text-sm font-semibold text-slate-900 group-hover:text-indigo-700">Team</p>
|
|
<p class="mt-1 text-sm text-slate-500">Invite colleagues and assign Frontdesk roles.</p>
|
|
</div>
|
|
@if (! $hasTeamFeature)
|
|
<span class="shrink-0 rounded-full bg-amber-50 px-2 py-0.5 text-[10px] font-semibold uppercase tracking-wide text-amber-700">Pro</span>
|
|
@endif
|
|
</div>
|
|
<p class="mt-4 text-xs font-medium text-indigo-600">
|
|
{{ $hasTeamFeature ? 'Manage team →' : 'Upgrade to unlock →' }}
|
|
</p>
|
|
</a>
|
|
@endif
|
|
</div>
|
|
@endif
|
|
|
|
<form method="POST" action="{{ route('frontdesk.settings.update') }}" enctype="multipart/form-data" class="space-y-6">
|
|
@csrf @method('PUT')
|
|
|
|
<x-settings.card title="Organization" description="Name, timezone, and branding shown on kiosks and badges.">
|
|
<div class="space-y-4">
|
|
@if ($canManage)
|
|
<div>
|
|
<label class="block text-sm font-medium text-slate-700">Name</label>
|
|
<input type="text" name="name" value="{{ old('name', $organization->name) }}" required class="mt-1 w-full rounded-lg border-slate-300 text-sm">
|
|
</div>
|
|
<div>
|
|
<label class="block text-sm font-medium text-slate-700">Timezone</label>
|
|
<select name="timezone" class="mt-1 w-full rounded-lg border-slate-300 text-sm">
|
|
@foreach (timezone_identifiers_list() as $tz)
|
|
<option value="{{ $tz }}" @selected(old('timezone', $organization->timezone) === $tz)>{{ $tz }}</option>
|
|
@endforeach
|
|
</select>
|
|
</div>
|
|
<div>
|
|
<label class="block text-sm font-medium text-slate-700">Company logo</label>
|
|
<p class="mt-1 text-xs text-slate-500">PNG, JPG, WebP, or SVG up to 2 MB.</p>
|
|
@if (\App\Support\OrganizationBranding::hasCustomLogo($organization))
|
|
<img src="{{ \App\Support\OrganizationBranding::logoUrl($organization) }}"
|
|
alt="{{ $organization->name }}"
|
|
class="mt-3 h-12 w-auto max-w-xs rounded-lg border border-slate-200 bg-white object-contain p-2">
|
|
<label class="mt-3 flex items-center gap-2 text-sm text-slate-600">
|
|
<input type="checkbox" name="remove_logo" value="1" @checked(old('remove_logo'))>
|
|
Remove custom logo
|
|
</label>
|
|
@endif
|
|
<input type="file" name="logo" accept="image/png,image/jpeg,image/webp,image/svg+xml"
|
|
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="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>
|
|
</x-settings.card>
|
|
|
|
@if ($canManage)
|
|
<x-settings.card title="Reception & kiosk" description="Badge timing, visitor policy, and kiosk behaviour.">
|
|
<div class="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>
|
|
<input type="number" name="badge_expiry_hours" value="{{ old('badge_expiry_hours', $settings['badge_expiry_hours'] ?? 8) }}" min="1" max="24" class="mt-1 w-full rounded-lg border-slate-300 text-sm">
|
|
</div>
|
|
<div>
|
|
<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 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 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-2 w-full rounded-lg border-slate-300 text-sm">{{ old('visitor_policy', $settings['visitor_policy'] ?? '') }}</textarea>
|
|
</div>
|
|
<label class="flex items-start gap-3 rounded-xl border border-slate-100 bg-slate-50 px-4 py-3 text-sm">
|
|
<input type="checkbox" name="employee_kiosk_enabled" value="1" class="mt-0.5"
|
|
@checked(old('employee_kiosk_enabled', $settings['employee_kiosk_enabled'] ?? true))>
|
|
<span>
|
|
<span class="font-semibold text-slate-900">Employee sign-in on kiosk</span>
|
|
<span class="mt-0.5 block text-slate-600">Allow staff to sign in with employee code and PIN.</span>
|
|
</span>
|
|
</label>
|
|
<div class="rounded-xl border border-slate-100 bg-slate-50 px-4 py-3">
|
|
<p class="font-semibold text-slate-900">Ladill Queue</p>
|
|
<p class="mt-0.5 text-sm text-slate-600">Enable queue management in Frontdesk. Also turn on Frontdesk integration in Ladill Queue.</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>
|
|
</x-settings.card>
|
|
|
|
<x-settings.card title="Notifications" description="How hosts are alerted when visitors arrive.">
|
|
<div class="space-y-5">
|
|
<div>
|
|
<p class="text-sm font-medium text-slate-700">Channels</p>
|
|
<div class="mt-3 flex flex-wrap gap-4">
|
|
@foreach ($notificationChannels as $key => $label)
|
|
<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 }}
|
|
</label>
|
|
@endforeach
|
|
</div>
|
|
</div>
|
|
<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 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 }}
|
|
</label>
|
|
@endforeach
|
|
</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-2 w-full rounded-lg border-slate-300 text-sm">
|
|
</div>
|
|
</div>
|
|
</x-settings.card>
|
|
|
|
<div class="flex justify-end">
|
|
<button type="submit" class="btn-primary">Save settings</button>
|
|
</div>
|
|
@endif
|
|
</form>
|
|
</x-settings.page>
|
|
</x-app-layout>
|