diff --git a/app/Http/Controllers/Frontdesk/BranchController.php b/app/Http/Controllers/Frontdesk/BranchController.php
index 40e664d..c5ac166 100644
--- a/app/Http/Controllers/Frontdesk/BranchController.php
+++ b/app/Http/Controllers/Frontdesk/BranchController.php
@@ -24,7 +24,13 @@ class BranchController extends Controller
->orderBy('name')
->get();
- return view('frontdesk.admin.branches.index', compact('branches', 'organization'));
+ $heroStats = [
+ 'total' => $branches->count(),
+ 'active' => $branches->where('is_active', true)->count(),
+ 'buildings' => $branches->sum('buildings_count'),
+ ];
+
+ return view('frontdesk.admin.branches.index', compact('branches', 'organization', 'heroStats'));
}
public function create(Request $request): View
diff --git a/app/Http/Controllers/Frontdesk/DeviceController.php b/app/Http/Controllers/Frontdesk/DeviceController.php
index 52f5d90..31eb963 100644
--- a/app/Http/Controllers/Frontdesk/DeviceController.php
+++ b/app/Http/Controllers/Frontdesk/DeviceController.php
@@ -27,10 +27,23 @@ class DeviceController extends Controller
->orderBy('name')
->paginate(25);
+ $statsQuery = Device::owned($this->ownerRef($request))
+ ->where('organization_id', $organization->id);
+
+ $heroStats = [
+ 'total' => (clone $statsQuery)->count(),
+ 'online' => (clone $statsQuery)
+ ->where('status', 'online')
+ ->where('last_online_at', '>=', now()->subMinutes(10))
+ ->count(),
+ 'kiosks' => (clone $statsQuery)->where('type', 'kiosk')->count(),
+ ];
+
return view('frontdesk.devices.index', [
'organization' => $organization,
'devices' => $devices,
'deviceTypes' => config('frontdesk.device_types'),
+ 'heroStats' => $heroStats,
'canManage' => app(\App\Services\Frontdesk\FrontdeskPermissions::class)
->can($this->member($request), 'devices.manage'),
]);
diff --git a/app/Http/Controllers/Frontdesk/EmployeeController.php b/app/Http/Controllers/Frontdesk/EmployeeController.php
index 845a724..57bfc1c 100644
--- a/app/Http/Controllers/Frontdesk/EmployeeController.php
+++ b/app/Http/Controllers/Frontdesk/EmployeeController.php
@@ -6,6 +6,7 @@ use App\Http\Controllers\Controller;
use App\Http\Controllers\Frontdesk\Concerns\ScopesToAccount;
use App\Models\Branch;
use App\Models\Employee;
+use App\Models\EmployeePresence;
use App\Models\EmployeePresenceEvent;
use App\Models\Host;
use App\Models\Member;
@@ -35,7 +36,17 @@ class EmployeeController extends Controller
$this->scopeToBranch($request, $employees);
$employees = $employees->paginate(25);
- return view('frontdesk.employees.index', compact('employees', 'organization'));
+ $statsQuery = Employee::owned($this->ownerRef($request))
+ ->where('organization_id', $organization->id);
+ $this->scopeToBranch($request, $statsQuery);
+
+ $heroStats = [
+ 'total' => (clone $statsQuery)->count(),
+ 'on_site' => (clone $statsQuery)->whereHas('presence', fn ($q) => $q->where('status', EmployeePresence::STATUS_ON_SITE))->count(),
+ 'active' => (clone $statsQuery)->where('active', true)->count(),
+ ];
+
+ return view('frontdesk.employees.index', compact('employees', 'organization', 'heroStats'));
}
public function create(Request $request): View
diff --git a/app/Http/Controllers/Frontdesk/HostController.php b/app/Http/Controllers/Frontdesk/HostController.php
index 67366a8..a62289f 100644
--- a/app/Http/Controllers/Frontdesk/HostController.php
+++ b/app/Http/Controllers/Frontdesk/HostController.php
@@ -25,7 +25,17 @@ class HostController extends Controller
$this->scopeToBranch($request, $hosts);
$hosts = $hosts->orderBy('name')->paginate(25);
- return view('frontdesk.hosts.index', compact('hosts', 'organization'));
+ $statsQuery = Host::owned($this->ownerRef($request))
+ ->where('organization_id', $organization->id);
+ $this->scopeToBranch($request, $statsQuery);
+
+ $heroStats = [
+ 'total' => (clone $statsQuery)->count(),
+ 'available' => (clone $statsQuery)->where('is_available', true)->count(),
+ 'departments' => (clone $statsQuery)->whereNotNull('department')->where('department', '!=', '')->distinct()->count('department'),
+ ];
+
+ return view('frontdesk.hosts.index', compact('hosts', 'organization', 'heroStats'));
}
public function create(Request $request): View
diff --git a/app/Http/Controllers/Frontdesk/MemberController.php b/app/Http/Controllers/Frontdesk/MemberController.php
index a5c7eae..0fe8dde 100644
--- a/app/Http/Controllers/Frontdesk/MemberController.php
+++ b/app/Http/Controllers/Frontdesk/MemberController.php
@@ -26,10 +26,19 @@ class MemberController extends Controller
->orderBy('created_at')
->get();
+ $adminRoles = ['super_admin', 'org_admin', 'branch_admin'];
+
+ $heroStats = [
+ 'total' => $members->count(),
+ 'admins' => $members->whereIn('role', $adminRoles)->count(),
+ 'branch_scoped' => $members->whereNotNull('branch_id')->count(),
+ ];
+
return view('frontdesk.admin.members.index', [
'members' => $members,
'organization' => $organization,
'roles' => config('frontdesk.roles'),
+ 'heroStats' => $heroStats,
]);
}
diff --git a/app/Http/Controllers/Frontdesk/VisitController.php b/app/Http/Controllers/Frontdesk/VisitController.php
index 808e6e1..4e3e57d 100644
--- a/app/Http/Controllers/Frontdesk/VisitController.php
+++ b/app/Http/Controllers/Frontdesk/VisitController.php
@@ -42,7 +42,17 @@ class VisitController extends Controller
->paginate(25)
->withQueryString();
- return view('frontdesk.visits.index', compact('visits', 'organization'));
+ $statsQuery = Visit::owned($this->ownerRef($request))
+ ->where('organization_id', $organization->id);
+ $this->scopeToBranch($request, $statsQuery);
+
+ $heroStats = [
+ 'on_site' => (clone $statsQuery)->whereIn('status', Visit::ACTIVE_STATUSES)->count(),
+ 'today' => (clone $statsQuery)->whereDate('checked_in_at', today())->count(),
+ 'total' => (clone $statsQuery)->count(),
+ ];
+
+ return view('frontdesk.visits.index', compact('visits', 'organization', 'heroStats'));
}
public function calendar(Request $request): View
diff --git a/resources/views/components/frontdesk/page-hero.blade.php b/resources/views/components/frontdesk/page-hero.blade.php
new file mode 100644
index 0000000..a8ea8f0
--- /dev/null
+++ b/resources/views/components/frontdesk/page-hero.blade.php
@@ -0,0 +1,39 @@
+@props([
+ 'badge',
+ 'title',
+ 'description' => null,
+ 'stats' => [],
+])
+
+
merge(['class' => 'relative overflow-hidden rounded-2xl border border-slate-200 bg-white']) }}>
+
+
+
+
+
+ {{ $badge }}
+
+
{{ $title }}
+ @if ($description)
+
{{ $description }}
+ @endif
+ @isset($actions)
+
+ {{ $actions }}
+
+ @endisset
+
+
+ @if (count($stats) > 0)
+
+ @endif
+
+
+
diff --git a/resources/views/frontdesk/admin/branches/index.blade.php b/resources/views/frontdesk/admin/branches/index.blade.php
index c86ebce..92ee23d 100644
--- a/resources/views/frontdesk/admin/branches/index.blade.php
+++ b/resources/views/frontdesk/admin/branches/index.blade.php
@@ -1,25 +1,49 @@
-
-
-
Branches
- @if (app(\App\Services\Frontdesk\FrontdeskPermissions::class)->can(auth()->user() ? app(\App\Services\Frontdesk\OrganizationResolver::class)->memberFor(auth()->user(), $organization) : null, 'admin.branches.manage'))
-
Add branch
- @endif
-
+@php
+ $canManageBranches = app(\App\Services\Frontdesk\FrontdeskPermissions::class)->can(
+ auth()->user() ? app(\App\Services\Frontdesk\OrganizationResolver::class)->memberFor(auth()->user(), $organization) : null,
+ 'admin.branches.manage'
+ );
+@endphp
-
- @forelse ($branches as $branch)
-
-
-
{{ $branch->name }}
-
{{ $branch->address ?? 'No address' }} · {{ $branch->buildings_count }} building(s)
-
-
+
+
+
+ @if ($canManageBranches)
+
+
+
+ Add branch
+
+
+ @endif
+
+
+
+
+
All branches
- @empty
-
No branches yet.
- @endforelse
+ @forelse ($branches as $branch)
+
+
+
{{ $branch->name }}
+
{{ $branch->address ?? 'No address' }} · {{ $branch->buildings_count }} building(s)
+
+
+
+ @empty
+
No branches yet.
+ @endforelse
+
diff --git a/resources/views/frontdesk/admin/members/index.blade.php b/resources/views/frontdesk/admin/members/index.blade.php
index 273b786..2995bc1 100644
--- a/resources/views/frontdesk/admin/members/index.blade.php
+++ b/resources/views/frontdesk/admin/members/index.blade.php
@@ -1,36 +1,53 @@
-
-
+
+
+
+
+
+
+ Add member
+
+
+
-
-
-
- | Member | Role | Branch | |
-
-
- @foreach ($members as $member)
- @php
- $display = str_contains($member->user_ref, '@')
- ? $member->user_ref
- : (\App\Models\User::where('public_id', $member->user_ref)->value('email') ?? $member->user_ref);
- @endphp
-
- | {{ $display }} |
- {{ $roles[$member->role] ?? $member->role }} |
- {{ $member->branch?->name ?? 'All branches' }} |
-
- @if ($member->user_ref !== auth()->user()->public_id)
-
- @endif
- |
-
- @endforeach
-
-
+
+
+
Team members
+
+
+
+ | Member | Role | Branch | |
+
+
+ @foreach ($members as $member)
+ @php
+ $display = str_contains($member->user_ref, '@')
+ ? $member->user_ref
+ : (\App\Models\User::where('public_id', $member->user_ref)->value('email') ?? $member->user_ref);
+ @endphp
+
+ | {{ $display }} |
+ {{ $roles[$member->role] ?? $member->role }} |
+ {{ $member->branch?->name ?? 'All branches' }} |
+
+ @if ($member->user_ref !== auth()->user()->public_id)
+
+ @endif
+ |
+
+ @endforeach
+
+
+
diff --git a/resources/views/frontdesk/devices/index.blade.php b/resources/views/frontdesk/devices/index.blade.php
index 48af78d..6b19099 100644
--- a/resources/views/frontdesk/devices/index.blade.php
+++ b/resources/views/frontdesk/devices/index.blade.php
@@ -1,58 +1,73 @@
-
-
-
Devices
-
Kiosks, printers, and reception hardware
-
- @if ($canManage)
-
Add device
- @endif
-
+
+
+ @if ($canManage)
+
+
+
+ Add device
+
+
+ @endif
+
-
-
-
-
- | Name |
- Type |
- Status |
- Desk / branch |
- Last online |
- |
-
-
-
- @forelse ($devices as $device)
+
+
+
All devices
+
+
+
- | {{ $device->name }} |
- {{ $deviceTypes[$device->type] ?? $device->type }} |
-
-
- {{ $device->isOnline() ? 'Online' : ucfirst($device->status) }}
-
- |
-
- {{ $device->receptionDesk?->name ?? '—' }}
- @if ($device->branch)
- · {{ $device->branch->name }}
- @endif
- |
- {{ $device->last_online_at?->diffForHumans() ?? 'Never' }} |
-
- @if ($canManage)
- Edit
- @endif
- @if ($device->type === 'kiosk' && $device->device_token)
- Open kiosk
- @endif
- |
+ Name |
+ Type |
+ Status |
+ Desk / branch |
+ Last online |
+ |
- @empty
- | No devices registered yet. |
- @endforelse
-
-
+
+
+ @forelse ($devices as $device)
+
+ | {{ $device->name }} |
+ {{ $deviceTypes[$device->type] ?? $device->type }} |
+
+
+ {{ $device->isOnline() ? 'Online' : ucfirst($device->status) }}
+
+ |
+
+ {{ $device->receptionDesk?->name ?? '—' }}
+ @if ($device->branch)
+ · {{ $device->branch->name }}
+ @endif
+ |
+ {{ $device->last_online_at?->diffForHumans() ?? 'Never' }} |
+
+ @if ($canManage)
+ Edit
+ @endif
+ @if ($device->type === 'kiosk' && $device->device_token)
+ Open kiosk
+ @endif
+ |
+
+ @empty
+ | No devices registered yet. |
+ @endforelse
+
+
+ @if ($devices->hasPages())
+
{{ $devices->links() }}
+ @endif
+
-
- {{ $devices->links() }}
diff --git a/resources/views/frontdesk/employees/index.blade.php b/resources/views/frontdesk/employees/index.blade.php
index f3af7d3..6294c93 100644
--- a/resources/views/frontdesk/employees/index.blade.php
+++ b/resources/views/frontdesk/employees/index.blade.php
@@ -1,54 +1,71 @@
-
-
Employees
-
-
Export attendance
-
Import CSV
-
Add employee
+
+
+
+ Export attendance
+ Import CSV
+
+
+ Add employee
+
+
+
+
+
+
+
All employees
+
+
+
+
+ | Name |
+ Code |
+ Department |
+ Status |
+ |
+
+
+
+ @forelse ($employees as $employee)
+ @php
+ $presence = $employee->presence;
+ $status = $presence?->status ?? 'off_site';
+ $statusLabel = config('frontdesk.employee_presence_statuses.'.$status, $status);
+ @endphp
+
+ | {{ $employee->full_name }} |
+ {{ $employee->employee_code }} |
+ {{ $employee->department ?? '—' }} |
+
+
+ {{ $statusLabel }}
+
+ @if ($presence?->destination)
+ {{ $presence->destination }}
+ @endif
+ |
+
+ Badge
+ Edit
+ |
+
+ @empty
+ | No employees yet. Add staff who will sign in at the kiosk. |
+ @endforelse
+
+
+ @if ($employees->hasPages())
+
{{ $employees->links() }}
+ @endif
-
-
-
-
-
- | Name |
- Code |
- Department |
- Status |
- |
-
-
-
- @forelse ($employees as $employee)
- @php
- $presence = $employee->presence;
- $status = $presence?->status ?? 'off_site';
- $statusLabel = config('frontdesk.employee_presence_statuses.'.$status, $status);
- @endphp
-
- | {{ $employee->full_name }} |
- {{ $employee->employee_code }} |
- {{ $employee->department ?? '—' }} |
-
-
- {{ $statusLabel }}
-
- @if ($presence?->destination)
- {{ $presence->destination }}
- @endif
- |
-
- Badge
- Edit
- |
-
- @empty
- | No employees yet. Add staff who will sign in at the kiosk. |
- @endforelse
-
-
-
-
{{ $employees->links() }}
diff --git a/resources/views/frontdesk/hosts/index.blade.php b/resources/views/frontdesk/hosts/index.blade.php
index 2254d85..c21d5c3 100644
--- a/resources/views/frontdesk/hosts/index.blade.php
+++ b/resources/views/frontdesk/hosts/index.blade.php
@@ -1,36 +1,55 @@
-
+
+
+
+
+
+ Add host
+
+
+
-
-
-
-
- | Name |
- Department |
- Office |
- Contact |
- |
-
-
-
- @forelse ($hosts as $host)
+
+
+
All hosts
+
+
+
- | {{ $host->name }} |
- {{ $host->department ?? '—' }} |
- {{ $host->office ?? '—' }} |
- {{ $host->email ?? $host->phone ?? '—' }} |
-
- Edit
- |
+ Name |
+ Department |
+ Office |
+ Contact |
+ |
- @empty
- | No hosts yet. Add your first host to enable visitor notifications. |
- @endforelse
-
-
+
+
+ @forelse ($hosts as $host)
+
+ | {{ $host->name }} |
+ {{ $host->department ?? '—' }} |
+ {{ $host->office ?? '—' }} |
+ {{ $host->email ?? $host->phone ?? '—' }} |
+
+ Edit
+ |
+
+ @empty
+ | No hosts yet. Add your first host to enable visitor notifications. |
+ @endforelse
+
+
+ @if ($hosts->hasPages())
+
{{ $hosts->links() }}
+ @endif
+
- {{ $hosts->links() }}
diff --git a/resources/views/frontdesk/visits/index.blade.php b/resources/views/frontdesk/visits/index.blade.php
index 3ca3e28..d1cbe9e 100644
--- a/resources/views/frontdesk/visits/index.blade.php
+++ b/resources/views/frontdesk/visits/index.blade.php
@@ -1,51 +1,65 @@
-
-
Visits
- @include('frontdesk.partials.reception-quick-actions', [
- 'desktopSchedule' => 'Schedule',
- 'desktopCheckIn' => 'Check in',
- 'scheduleLabel' => 'Schedule visit',
- 'checkInLabel' => 'Check in visitor',
- ])
-
+
+
+
+ Schedule visit
+
+
+ Check in visitor
+
+
+
-
+
-
-
-
-
- | Visitor |
- Host |
- Type |
- Status |
- Time |
-
-
-
- @forelse ($visits as $visit)
-
- | {{ $visit->visitor->full_name }} |
- {{ $visit->host?->name ?? '—' }} |
- {{ str_replace('_', ' ', $visit->visitor_type) }} |
- {{ str_replace('_', ' ', $visit->status) }} |
- {{ $visit->checked_in_at?->format('M j, g:i A') ?? $visit->scheduled_at?->format('M j, g:i A') ?? $visit->created_at->format('M j, g:i A') }} |
+
+
+
Visit history
+
+
+
+
+ | Visitor |
+ Host |
+ Type |
+ Status |
+ Time |
- @empty
- | No visits yet. |
- @endforelse
-
-
+
+
+ @forelse ($visits as $visit)
+
+ | {{ $visit->visitor->full_name }} |
+ {{ $visit->host?->name ?? '—' }} |
+ {{ str_replace('_', ' ', $visit->visitor_type) }} |
+ {{ str_replace('_', ' ', $visit->status) }} |
+ {{ $visit->checked_in_at?->format('M j, g:i A') ?? $visit->scheduled_at?->format('M j, g:i A') ?? $visit->created_at->format('M j, g:i A') }} |
+
+ @empty
+ | No visits yet. |
+ @endforelse
+
+
+ @if ($visits->hasPages())
+
{{ $visits->links() }}
+ @endif
+
-
- {{ $visits->links() }}