Files
ladill-frontdesk/resources/views/partials/sidebar.blade.php
T
isaaccladandCursor 2883564ccb
Deploy Ladill Frontdesk / deploy (push) Successful in 40s
Use kiosk staff icon for sidebar Employees nav item.
Match the house-with-person icon from the kiosk choose screen and add optional iconViewBox support for non-24px sidebar icons.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-28 22:00:43 +00:00

150 lines
17 KiB
PHP

<div class="flex h-full flex-col bg-white border-r border-slate-200 text-slate-700">
<div class="flex h-16 shrink-0 items-center border-b border-slate-200 px-6">
<a href="{{ route('frontdesk.dashboard') }}" class="flex items-center">
<img src="{{ asset('images/logo/ladillfrontdesk-logo.svg') }}?v={{ @filemtime(public_path('images/logo/ladillfrontdesk-logo.svg')) ?: '1' }}" alt="Ladill Frontdesk" class="h-6 w-auto">
</a>
</div>
@php
$member = auth()->user()
? app(\App\Services\Frontdesk\OrganizationResolver::class)->memberFor(auth()->user())
: null;
$permissions = app(\App\Services\Frontdesk\FrontdeskPermissions::class);
$linkedHost = auth()->user()
? app(\App\Services\Frontdesk\OrganizationResolver::class)->hostFor(auth()->user())
: null;
$linkedEmployee = auth()->user()
? app(\App\Services\Frontdesk\OrganizationResolver::class)->employeeFor(auth()->user())
: null;
$nav = [
['name' => 'Reception', 'route' => route('frontdesk.dashboard'), 'active' => request()->routeIs('frontdesk.dashboard'),
'icon' => '<path stroke-linecap="round" stroke-linejoin="round" d="M2.25 12 11.2 3.05c.44-.44 1.15-.44 1.59 0L21.75 12M4.5 9.75v10.5a.75.75 0 0 0 .75.75H9.75v-6a.75.75 0 0 1 .75-.75h3a.75.75 0 0 1 .75.75v6h4.5a.75.75 0 0 0 .75-.75V9.75" />'],
['name' => 'Check-in', 'route' => route('frontdesk.visits.create'), 'active' => request()->routeIs('frontdesk.visits.create'),
'icon' => '<path stroke-linecap="round" stroke-linejoin="round" d="M18 7.5v3m0 0v3m0-3h3m-3 0h-3m-2.25-4.125a3.375 3.375 0 1 1-6.75 0 3.375 3.375 0 0 1 6.75 0ZM3 19.235v-.11a6.375 6.375 0 0 1 12.75 0v.109A12.318 12.318 0 0 1 9.374 21c-2.331 0-4.512-.645-6.374-1.766l-.001-.109a6.375 6.375 0 0 1 11.964-3.07M12 6.375a3.375 3.375 0 1 1-6.75 0 3.375 3.375 0 0 1 6.75 0Zm8.25 2.25a2.625 2.625 0 1 1-5.25 0 2.625 2.625 0 0 1 5.25 0Z" />'],
['name' => 'Visits', 'route' => route('frontdesk.visits.index'), 'active' => request()->routeIs('frontdesk.visits.*') && !request()->routeIs('frontdesk.visits.create') && !request()->routeIs('frontdesk.visits.schedule*'),
'icon' => '<path stroke-linecap="round" stroke-linejoin="round" d="M6.75 3v2.25M17.25 3v2.25M3 18.75V7.5a2.25 2.25 0 0 1 2.25-2.25h13.5A2.25 2.25 0 0 1 21 7.5v11.25m-18 0A2.25 2.25 0 0 0 5.25 21h13.5A2.25 2.25 0 0 0 21 18.75m-18 0v-7.5A2.25 2.25 0 0 1 5.25 9h13.5A2.25 2.25 0 0 1 21 11.25v7.5" />'],
['name' => 'Schedule', 'route' => route('frontdesk.visits.schedule'), 'active' => request()->routeIs('frontdesk.visits.schedule*'),
'icon' => '<path stroke-linecap="round" stroke-linejoin="round" d="M12 6v6h4.5m4.5 0a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z" />'],
['name' => 'Calendar', 'route' => route('frontdesk.visits.calendar'), 'active' => request()->routeIs('frontdesk.visits.calendar'),
'icon' => '<path stroke-linecap="round" stroke-linejoin="round" d="M6.75 3v2.25M17.25 3v2.25M3 18.75V7.5a2.25 2.25 0 0 1 2.25-2.25h13.5A2.25 2.25 0 0 1 21 7.5v11.25m-18 0A2.25 2.25 0 0 0 5.25 21h13.5A2.25 2.25 0 0 0 21 18.75m-18 0v-7.5A2.25 2.25 0 0 1 5.25 9h13.5A2.25 2.25 0 0 1 21 11.25v7.5" />'],
['name' => 'Visitors', 'route' => route('frontdesk.visitors.index'), 'active' => request()->routeIs('frontdesk.visitors.*'),
'icon' => '<path stroke-linecap="round" stroke-linejoin="round" d="M15 19.128a9.38 9.38 0 0 0 2.625.372 9.337 9.337 0 0 0 4.121-.952 4.125 4.125 0 0 0-7.533-2.493M15 19.128v-.003c0-1.113-.285-2.16-.786-3.07M15 19.128v.106A12.318 12.318 0 0 1 8.624 21c-2.331 0-4.512-.645-6.374-1.766l-.001-.109a6.375 6.375 0 0 1 11.964-3.07M12 6.375a3.375 3.375 0 1 1-6.75 0 3.375 3.375 0 0 1 6.75 0Zm8.25 2.25a2.625 2.625 0 1 1-5.25 0 2.625 2.625 0 0 1 5.25 0Z" />'],
['name' => 'Hosts', 'route' => route('frontdesk.hosts.index'), 'active' => request()->routeIs('frontdesk.hosts.*'),
'icon' => '<path stroke-linecap="round" stroke-linejoin="round" d="M15.75 6a3.75 3.75 0 1 1-7.5 0 3.75 3.75 0 0 1 7.5 0ZM4.501 20.118a7.5 7.5 0 0 1 14.998 0A17.933 17.933 0 0 1 12 21.75c-2.676 0-5.216-.584-7.499-1.632Z" />'],
];
if ($permissions->can($member, 'employees.view')) {
$nav[] = ['name' => 'Employees', 'route' => route('frontdesk.employees.index'), 'active' => request()->routeIs('frontdesk.employees.*'),
'iconViewBox' => '0 0 14 14',
'icon' => '<path stroke-linecap="round" stroke-linejoin="round" d="M7 9.5C8.38071 9.5 9.5 8.38071 9.5 7C9.5 5.61929 8.38071 4.5 7 4.5C5.61929 4.5 4.5 5.61929 4.5 7C4.5 8.38071 5.61929 9.5 7 9.5Z" /><path stroke-linecap="round" stroke-linejoin="round" d="M2.73004 13.4001C3.17628 12.6676 3.80345 12.0622 4.55125 11.6422C5.29905 11.2221 6.14233 11.0015 7.00004 11.0015C7.85775 11.0015 8.70104 11.2221 9.44883 11.6422C10.1966 12.0622 10.8238 12.6676 11.27 13.4001" /><path stroke-linecap="round" stroke-linejoin="round" d="M13.5 6.94C13.501 6.8012 13.473 6.66372 13.4179 6.53632C13.3628 6.40892 13.2818 6.29438 13.18 6.2L7.00002 0.5L0.820023 6.2C0.718248 6.29438 0.637236 6.40892 0.582143 6.53632C0.52705 6.66372 0.499084 6.8012 0.500023 6.94V12.5C0.500023 12.7652 0.60538 13.0196 0.792916 13.2071C0.980452 13.3946 1.23481 13.5 1.50002 13.5H12.5C12.7652 13.5 13.0196 13.3946 13.2071 13.2071C13.3947 13.0196 13.5 12.7652 13.5 12.5V6.94Z" />'];
}
$nav = array_merge($nav, [
['name' => 'Kiosk', 'route' => route('frontdesk.kiosk'), 'active' => request()->routeIs('frontdesk.kiosk') && !request()->routeIs('frontdesk.kiosk.device*'),
'icon' => '<path stroke-linecap="round" stroke-linejoin="round" d="M10.5 1.5H8.25A2.25 2.25 0 0 0 6 3.75v16.5a2.25 2.25 0 0 0 2.25 2.25h7.5A2.25 2.25 0 0 0 18 20.25V3.75a2.25 2.25 0 0 0-2.25-2.25H13.5m-3 0V3h3V1.5m-3 0h3m-3 18.75h3" />'],
]);
if ($linkedHost) {
$nav[] = ['name' => 'Host portal', 'route' => route('frontdesk.host.index'), 'active' => request()->routeIs('frontdesk.host.*'),
'icon' => '<path stroke-linecap="round" stroke-linejoin="round" d="M15.75 6a3.75 3.75 0 1 1-7.5 0 3.75 3.75 0 0 1 7.5 0ZM4.501 20.118a7.5 7.5 0 0 1 14.998 0A17.933 17.933 0 0 1 12 21.75c-2.676 0-5.216-.584-7.499-1.632Z" />'];
}
if ($linkedEmployee) {
$nav[] = ['name' => 'My presence', 'route' => route('frontdesk.employee.portal'), 'active' => request()->routeIs('frontdesk.employee.*'),
'icon' => '<path stroke-linecap="round" stroke-linejoin="round" d="M15 9h3.75M15 12h3.75M15 15h3.75M4.5 19.5h15a2.25 2.25 0 0 0 2.25-2.25V6.75A2.25 2.25 0 0 0 19.5 4.5h-15a2.25 2.25 0 0 0-2.25 2.25v10.5A2.25 2.25 0 0 0 4.5 19.5Zm6-10.125a1.875 1.875 0 1 1-3.75 0 1.875 1.875 0 0 1 3.75 0Zm1.294 6.336a6.721 6.721 0 0 1-3.17.789 6.721 6.721 0 0 1-3.168-.789 3.376 3.376 0 0 1 6.338 0Z" />'];
}
$nav = array_merge($nav, [
['name' => 'Security', 'route' => route('frontdesk.security.index'), 'active' => request()->routeIs('frontdesk.security.*'),
'icon' => '<path stroke-linecap="round" stroke-linejoin="round" d="M9 12.75 11.25 15 15 9.75m-3-7.036A11.959 11.959 0 0 1 3.598 6 11.99 11.99 0 0 0 3 9.749c0 5.592 3.824 10.29 9 11.623 5.176-1.332 9-6.03 9-11.622 0-1.31-.21-2.571-.598-3.751h-.152c-3.196 0-6.1-1.248-8.25-3.285Z" />'],
]);
if ($permissions->can($member, 'reports.view')) {
$nav[] = ['name' => 'Reports', 'route' => route('frontdesk.reports.index'), 'active' => request()->routeIs('frontdesk.reports.*'),
'icon' => '<path stroke-linecap="round" stroke-linejoin="round" d="M3 13.125C3 12.504 3.504 12 4.125 12h2.25c.621 0 1.125.504 1.125 1.125v6.75C7.5 20.496 6.996 21 6.375 21h-2.25A1.125 1.125 0 0 1 3 19.875v-6.75ZM9.75 8.625c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125v11.25c0 .621-.504 1.125-1.125 1.125h-2.25a1.125 1.125 0 0 1-1.125-1.125V8.625ZM16.5 4.125c0-.621.504-1.125 1.125-1.125h2.25C20.496 3 21 3.504 21 4.125v15.75c0 .621-.504 1.125-1.125 1.125h-2.25a1.125 1.125 0 0 1-1.125-1.125V4.125Z" />'];
}
if ($permissions->can($member, 'devices.view')) {
$nav[] = ['name' => 'Devices', 'route' => route('frontdesk.devices.index'), 'active' => request()->routeIs('frontdesk.devices.*'),
'icon' => '<path stroke-linecap="round" stroke-linejoin="round" d="M8.25 3v1.5M4.5 8.25H3m18 0h-1.5M4.5 12H3m18 0h-1.5m-15 3.75H3m18 0h-1.5M8.25 19.5V21M12 3v1.5m0 15V21m3.75-18v1.5m0 15V21" />'];
}
if ($permissions->can($member, 'watchlist.view')) {
$nav[] = ['name' => 'Watchlist', 'route' => route('frontdesk.watchlist.index'), 'active' => request()->routeIs('frontdesk.watchlist.*'),
'icon' => '<path stroke-linecap="round" stroke-linejoin="round" d="M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126ZM12 15.75h.007v.008H12v-.008Z" />'];
}
if ($permissions->can($member, 'audit.view')) {
$nav[] = ['name' => 'Audit log', 'route' => route('frontdesk.audit.index'), 'active' => request()->routeIs('frontdesk.audit.*'),
'icon' => '<path stroke-linecap="round" stroke-linejoin="round" d="M19.5 14.25v-2.625a3.375 3.375 0 0 0-3.375-3.375h-1.5A1.125 1.125 0 0 1 13.5 7.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H8.25m0 12.75h7.5m-7.5 3H12M10.5 2.25H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 0 0-9-9Z" />'];
}
$complianceNav = [];
if ($permissions->can($member, 'compliance.restore')) {
$complianceNav[] = ['name' => 'Recovery', 'route' => route('frontdesk.compliance.recovery'), 'active' => request()->routeIs('frontdesk.compliance.*'),
'icon' => '<path stroke-linecap="round" stroke-linejoin="round" d="M16.023 9.348h4.992v-.001M2.985 19.644v-4.992m0 0h4.992m-4.993 0 3.181 3.183a8.25 8.25 0 0 0 13.803-3.7M4.031 9.865a8.25 8.25 0 0 1 13.803-3.7l3.181 3.182m0-4.991v4.99" />'];
}
$adminNav = [];
if ($permissions->can($member, 'admin.branches.view')) {
$adminNav[] = ['name' => 'Branches', 'route' => route('frontdesk.branches.index'), 'active' => request()->routeIs('frontdesk.branches.*') || request()->routeIs('frontdesk.buildings.*') || request()->routeIs('frontdesk.desks.*'),
'icon' => '<path stroke-linecap="round" stroke-linejoin="round" d="M3.75 21h16.5M4.5 3h15M5.25 3v18m13.5-18v18M9 6.75h1.5m-1.5 3h1.5m-1.5 3h1.5m-1.5 3h1.5m3-9H15m-1.5 3H15m-1.5 3H15m-1.5 3H15M9 21v-3.375c0-.621.504-1.125 1.125-1.125h3.75c.621 0 1.125.504 1.125 1.125V21" />'];
}
if ($permissions->can($member, 'admin.members.view')) {
$adminNav[] = ['name' => 'Team', 'route' => route('frontdesk.members.index'), 'active' => request()->routeIs('frontdesk.members.*'),
'icon' => '<path stroke-linecap="round" stroke-linejoin="round" d="M18 18.72a9.094 9.094 0 0 0 3.741-.479 3 3 0 0 0-4.682-2.72m.94 3.198.001.031c0 .225-.012.447-.037.666A11.944 11.944 0 0 1 12 21c-2.17 0-4.207-.576-5.963-1.584A6.062 6.062 0 0 1 6 18.719m12 0a5.971 5.971 0 0 0-.941-3.197m0 0A5.995 5.995 0 0 0 12 12.75a5.995 5.995 0 0 0-5.058 2.772m0 0a3 3 0 0 0-4.681 2.72 8.986 8.986 0 0 0 3.74.477m.94-3.197a5.971 5.971 0 0 0-.94 3.197M15 6.75a3 3 0 1 1-6 0 3 3 0 0 1 6 0Zm6 3a2.25 2.25 0 1 1-4.5 0 2.25 2.25 0 0 1 4.5 0Zm-13.5 0a2.25 2.25 0 1 1-4.5 0 2.25 2.25 0 0 1 4.5 0Z" />'];
}
@endphp
<nav class="flex-1 space-y-0.5 overflow-y-auto px-3 py-4">
@foreach($nav as $item)
<a href="{{ $item['route'] }}" class="group flex items-center gap-3 rounded-lg px-3 py-2 text-[13px] transition {{ $item['active'] ? 'bg-indigo-50 text-indigo-700 font-semibold' : 'text-slate-600 hover:bg-slate-50 hover:text-slate-900' }}">
<svg class="h-[18px] w-[18px] shrink-0 {{ $item['active'] ? 'text-indigo-600' : 'text-slate-400' }}" fill="none" viewBox="{{ $item['iconViewBox'] ?? '0 0 24 24' }}" stroke-width="1.5" stroke="currentColor">{!! $item['icon'] !!}</svg>
<span>{{ $item['name'] }}</span>
</a>
@endforeach
@if (count($adminNav) > 0 || count($complianceNav) > 0)
<p class="mb-1 mt-4 px-3 text-[10px] font-semibold uppercase tracking-wider text-slate-400">Compliance</p>
@foreach ($complianceNav as $item)
<a href="{{ $item['route'] }}" class="group flex items-center gap-3 rounded-lg px-3 py-2 text-[13px] transition {{ $item['active'] ? 'bg-indigo-50 text-indigo-700 font-semibold' : 'text-slate-600 hover:bg-slate-50 hover:text-slate-900' }}">
<svg class="h-[18px] w-[18px] shrink-0 {{ $item['active'] ? 'text-indigo-600' : 'text-slate-400' }}" fill="none" viewBox="{{ $item['iconViewBox'] ?? '0 0 24 24' }}" stroke-width="1.5" stroke="currentColor">{!! $item['icon'] !!}</svg>
<span>{{ $item['name'] }}</span>
</a>
@endforeach
@endif
@if (count($adminNav) > 0)
<p class="mb-1 mt-4 px-3 text-[10px] font-semibold uppercase tracking-wider text-slate-400">Administration</p>
@foreach ($adminNav as $item)
<a href="{{ $item['route'] }}" class="group flex items-center gap-3 rounded-lg px-3 py-2 text-[13px] transition {{ $item['active'] ? 'bg-indigo-50 text-indigo-700 font-semibold' : 'text-slate-600 hover:bg-slate-50 hover:text-slate-900' }}">
<svg class="h-[18px] w-[18px] shrink-0 {{ $item['active'] ? 'text-indigo-600' : 'text-slate-400' }}" fill="none" viewBox="{{ $item['iconViewBox'] ?? '0 0 24 24' }}" stroke-width="1.5" stroke="currentColor">{!! $item['icon'] !!}</svg>
<span>{{ $item['name'] }}</span>
</a>
@endforeach
@endif
</nav>
<div class="shrink-0 border-t border-slate-100 px-3 py-3">
<a href="{{ route('frontdesk.settings') }}"
class="group flex items-center gap-3 rounded-lg px-3 py-2 text-[13px] transition {{ request()->routeIs('frontdesk.settings') && ! request()->routeIs('frontdesk.pro.*') ? 'bg-indigo-50 text-indigo-700 font-semibold' : 'text-slate-600 hover:bg-slate-50 hover:text-slate-900' }}">
<svg class="h-[18px] w-[18px] shrink-0 {{ request()->routeIs('frontdesk.settings') && ! request()->routeIs('frontdesk.pro.*') ? 'text-indigo-600' : 'text-slate-400' }}" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M9.594 3.94c.09-.542.56-.94 1.11-.94h2.593c.55 0 1.02.398 1.11.94l.213 1.281c.063.374.313.686.645.87.074.04.147.083.22.127.325.196.72.257 1.075.124l1.217-.456a1.125 1.125 0 0 1 1.37.49l1.296 2.247a1.125 1.125 0 0 1-.26 1.431l-1.003.827c-.293.241-.438.613-.43.992a7.723 7.723 0 0 1 0 .255c-.008.378.137.75.43.991l1.004.827c.424.35.534.955.26 1.43l-1.298 2.247a1.125 1.125 0 0 1-1.369.491l-1.217-.456c-.355-.133-.75-.072-1.076.124a6.47 6.47 0 0 1-.22.128c-.331.183-.581.495-.644.869l-.213 1.281c-.09.543-.56.94-1.11.94h-2.594c-.55 0-1.019-.398-1.11-.94l-.213-1.281c-.062-.374-.312-.686-.644-.87a6.52 6.52 0 0 1-.22-.127c-.325-.196-.72-.257-1.076-.124l-1.217.456a1.125 1.125 0 0 1-1.369-.49l-1.297-2.247a1.125 1.125 0 0 1 .26-1.431l1.004-.827c.292-.241.437-.613.43-.992a6.932 6.932 0 0 1 0-.255c.007-.378-.138-.75-.43-.991l-1.004-.827a1.125 1.125 0 0 1-.26-1.43l1.297-2.247a1.125 1.125 0 0 1 1.37-.491l1.216.456c.356.133.751.072 1.076-.124.072-.044.146-.086.22-.128.332-.183.582-.495.644-.869l.214-1.281Z" /><path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z" />
</svg>
<span class="flex-1 truncate">Settings</span>
</a>
@php $proActive = request()->routeIs('frontdesk.pro.*'); @endphp
@if (! empty($isPro))
<a href="{{ route('frontdesk.pro.index') }}" class="group mt-0.5 flex items-center gap-3 rounded-lg px-3 py-2 text-[13px] transition {{ $proActive ? 'bg-indigo-50 text-indigo-700 font-semibold' : 'text-slate-600 hover:bg-slate-50 hover:text-slate-900' }}">
<svg class="h-[18px] w-[18px] shrink-0 text-amber-500" viewBox="0 0 24 24" fill="currentColor"><path d="M12 2.25c.3 0 .58.18.7.46l2.36 5.5 5.96.5a.75.75 0 0 1 .43 1.31l-4.53 3.9 1.36 5.83a.75.75 0 0 1-1.12.81L12 17.77l-5.16 3a.75.75 0 0 1-1.12-.81l1.36-5.83-4.53-3.9a.75.75 0 0 1 .43-1.31l5.96-.5 2.36-5.5c.12-.28.4-.46.7-.46Z"/></svg>
<span>Frontdesk Pro</span>
</a>
@else
<a href="{{ route('frontdesk.pro.index') }}" class="group mt-0.5 flex items-center gap-3 rounded-lg bg-gradient-to-r from-indigo-600 to-emerald-500 px-3 py-2 text-[13px] font-semibold text-white shadow-sm transition hover:opacity-95">
<svg class="h-[18px] w-[18px] shrink-0" viewBox="0 0 24 24" fill="currentColor"><path d="M12 2.25c.3 0 .58.18.7.46l2.36 5.5 5.96.5a.75.75 0 0 1 .43 1.31l-4.53 3.9 1.36 5.83a.75.75 0 0 1-1.12.81L12 17.77l-5.16 3a.75.75 0 0 1-1.12-.81l1.36-5.83-4.53-3.9a.75.75 0 0 1 .43-1.31l5.96-.5 2.36-5.5c.12-.28.4-.46.7-.46Z"/></svg>
<span>Upgrade to Pro</span>
</a>
@endif
</div>
</div>