Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 78 additions & 0 deletions resources/views/admin/dashboard.blade.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
@php
$toolbarItems = [
[
'label' => 'Ideas',
'href' => route('home'),
'icon' => 'heroicon-o-light-bulb',
],
[
'label' => 'Planning',
'href' => '#planning',
'icon' => 'heroicon-o-clipboard-document-list',
],
[
'label' => 'Development',
'href' => '#development',
'icon' => 'heroicon-o-code-bracket-square',
],
[
'label' => 'Testing',
'href' => '#testing',
'icon' => 'heroicon-o-beaker',
],
[
'label' => 'Security',
'href' => '#security',
'icon' => 'heroicon-o-shield-check',
],
[
'label' => 'Ops',
'href' => '#ops',
'icon' => 'heroicon-o-command-line',
],
];

$contextItems = [
[
'label' => 'Dashboard',
'href' => route('admin.dashboard'),
'current' => true,
'icon' => 'heroicon-o-squares-2x2',
],
[
'label' => 'Users',
'href' => '#users',
'icon' => 'heroicon-o-users',
],
[
'label' => 'Roles',
'href' => '#roles',
'icon' => 'heroicon-o-shield-check',
],
];
@endphp

<x-layouts.app-shell
title="Admin"
:toolbar-items="$toolbarItems"
:context-items="$contextItems"
:show-admin-entry="true"
>
<div class="mx-auto max-w-5xl space-y-8">
<x-ui.page-header
eyebrow="Admin"
title="Control center"
description="This area is reserved for administrative work and future user management."
/>

<x-ui.panel
title="Protected area"
subtitle="Access here is restricted to users with the admin role."
>
<p class="text-sm leading-7 text-muted">
This dashboard is the first admin-only landing surface. It uses the same shell and shared components as the rest of the app,
but it stays behind the authorization gate and will grow into user, role, and system management from here.
</p>
</x-ui.panel>
</div>
</x-layouts.app-shell>
10 changes: 10 additions & 0 deletions resources/views/components/layouts/app-shell.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
'title' => config('app.name', 'Replicator'),
'toolbarItems' => [],
'contextItems' => [],
'showAdminEntry' => false,
])

@php
Expand Down Expand Up @@ -90,6 +91,15 @@ class="flex size-10 items-center justify-center rounded-lg bg-white/10 text-whit
:current="$item['current'] ?? false"
/>
@endforeach

@if ($showAdminEntry && auth()->user()?->isAn('admin'))
<x-app.toolbar-item
href="{{ route('admin.dashboard') }}"
label="Admin"
icon="heroicon-o-shield-check"
:current="request()->routeIs('admin.*')"
/>
Comment on lines +95 to +101
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The admin toolbar entry visibility duplicates the authorization logic by checking auth()->user()?->isAn('admin') directly. Since the route is protected with can:access-admin (and the Gate is defined), consider switching this to @can('access-admin') / auth()->user()?->can('access-admin') so UI visibility stays consistent with the actual authorization rules if they change later.

Copilot uses AI. Check for mistakes.
@endif
</nav>
</aside>

Expand Down
12 changes: 6 additions & 6 deletions resources/views/home.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,6 @@
'href' => '#ops',
'icon' => 'heroicon-o-command-line',
],
[
'label' => 'Admin',
'href' => '#admin',
'icon' => 'heroicon-o-cog-6-tooth',
],
];

$contextItems = [
Expand Down Expand Up @@ -63,7 +58,12 @@
];
@endphp

<x-layouts.app-shell :title="config('app.name', 'Replicator')" :toolbar-items="$toolbarItems" :context-items="$contextItems">
<x-layouts.app-shell
:title="config('app.name', 'Replicator')"
:toolbar-items="$toolbarItems"
:context-items="$contextItems"
:show-admin-entry="true"
>
<div class="mx-auto max-w-5xl space-y-8">
<x-ui.page-header
eyebrow="Workspace"
Expand Down
2 changes: 1 addition & 1 deletion routes/web.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@
})->name('home');

Route::get('/admin', function () {
return view('home');
return view('admin.dashboard');
})->middleware(['auth', 'can:access-admin'])->name('admin.dashboard');
17 changes: 17 additions & 0 deletions tests/Feature/Auth/RbacTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,20 @@
->get(route('admin.dashboard'))
->assertSuccessful();
});

it('shows the admin toolbar entry only to admins', function (): void {
$user = User::factory()->create();

$this->actingAs($user)
->get(route('home'))
->assertSuccessful()
->assertDontSee('href="'.route('admin.dashboard').'"', false);

$admin = User::factory()->create();
$admin->assign('admin');

$this->actingAs($admin)
->get(route('home'))
->assertSuccessful()
->assertSee('href="'.route('admin.dashboard').'"', false);
});
Loading