From f995606649d9fd976ff9ac4e3fd59195cc8aeadc Mon Sep 17 00:00:00 2001 From: isaacclad Date: Sun, 5 Jul 2026 20:45:30 +0000 Subject: [PATCH] Add hero sections to Visits, Hosts, Employees, Devices, Branches, and Team index pages. Co-authored-by: Cursor --- .../Frontdesk/BranchController.php | 8 +- .../Frontdesk/DeviceController.php | 13 ++ .../Frontdesk/EmployeeController.php | 13 +- .../Controllers/Frontdesk/HostController.php | 12 +- .../Frontdesk/MemberController.php | 9 ++ .../Controllers/Frontdesk/VisitController.php | 12 +- .../components/frontdesk/page-hero.blade.php | 39 ++++++ .../frontdesk/admin/branches/index.blade.php | 66 ++++++---- .../frontdesk/admin/members/index.blade.php | 83 +++++++----- .../views/frontdesk/devices/index.blade.php | 119 ++++++++++-------- .../views/frontdesk/employees/index.blade.php | 117 +++++++++-------- .../views/frontdesk/hosts/index.blade.php | 79 +++++++----- .../views/frontdesk/visits/index.blade.php | 104 ++++++++------- 13 files changed, 439 insertions(+), 235 deletions(-) create mode 100644 resources/views/components/frontdesk/page-hero.blade.php 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) +
+ @foreach ($stats as $stat) +
+

{{ $stat['value'] }}

+

{{ $stat['label'] }}

+
+ @endforeach +
+ @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)

-
-
- Buildings - Edit -
+ +
+ + @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)

+
+
+ Buildings + Edit +
+
+ @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 @@ - -
-

Team members

- Add member -
+ +
+ + + + + Add member + + + -
- - - - - - @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 - - - - - - - @endforeach - -
MemberRoleBranch
{{ $display }}{{ $roles[$member->role] ?? $member->role }}{{ $member->branch?->name ?? 'All branches' }} - @if ($member->user_ref !== auth()->user()->public_id) -
- @csrf @method('DELETE') - -
- @endif -
+
+
+

Team members

+
+ + + + + + @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 + + + + + + + @endforeach + +
MemberRoleBranch
{{ $display }}{{ $roles[$member->role] ?? $member->role }}{{ $member->branch?->name ?? 'All branches' }} + @if ($member->user_ref !== auth()->user()->public_id) +
+ @csrf @method('DELETE') + +
+ @endif +
+
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 + -
- - - - - - - - - - - - - @forelse ($devices as $device) +
+
+

All devices

+
+
NameTypeStatusDesk / branchLast online
+ - - - - - - + + + + + + - @empty - - @endforelse - -
{{ $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 - NameTypeStatusDesk / branchLast online
No devices registered yet.
+ + + @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

+
+ + + + + + + + + + + + @forelse ($employees as $employee) + @php + $presence = $employee->presence; + $status = $presence?->status ?? 'off_site'; + $statusLabel = config('frontdesk.employee_presence_statuses.'.$status, $status); + @endphp + + + + + + + + @empty + + @endforelse + +
NameCodeDepartmentStatus
{{ $employee->full_name }}{{ $employee->employee_code }}{{ $employee->department ?? '—' }} + + {{ $statusLabel }} + + @if ($presence?->destination) + {{ $presence->destination }} + @endif + + Badge + Edit +
No employees yet. Add staff who will sign in at the kiosk.
+ @if ($employees->hasPages()) +
{{ $employees->links() }}
+ @endif
- -
- - - - - - - - - - - - @forelse ($employees as $employee) - @php - $presence = $employee->presence; - $status = $presence?->status ?? 'off_site'; - $statusLabel = config('frontdesk.employee_presence_statuses.'.$status, $status); - @endphp - - - - - - - - @empty - - @endforelse - -
NameCodeDepartmentStatus
{{ $employee->full_name }}{{ $employee->employee_code }}{{ $employee->department ?? '—' }} - - {{ $statusLabel }} - - @if ($presence?->destination) - {{ $presence->destination }} - @endif - - Badge - Edit -
No employees yet. Add staff who will sign in at the kiosk.
-
-
{{ $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 @@ -
-

Host directory

- Add host -
+
+ + + + + Add host + + + -
- - - - - - - - - - - - @forelse ($hosts as $host) +
+
+

All hosts

+
+
NameDepartmentOfficeContact
+ - - - - - + + + + + - @empty - - @endforelse - -
{{ $host->name }}{{ $host->department ?? '—' }}{{ $host->office ?? '—' }}{{ $host->email ?? $host->phone ?? '—' }} - Edit - NameDepartmentOfficeContact
No hosts yet. Add your first host to enable visitor notifications.
+ + + @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 + + + -
- - - -
+
+ + + +
-
- - - - - - - - - - - - @forelse ($visits as $visit) - - - - - - +
+
+

Visit history

+
+
VisitorHostTypeStatusTime
{{ $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 - - @endforelse - -
VisitorHostTypeStatusTime
No visits yet.
+ + + @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() }}