feat: add dashboard page with Nuxt UI components and verified middleware

This commit is contained in:
2026-03-19 23:15:23 +01:00
parent a096704b0b
commit 4ea87c0cf7
6 changed files with 186 additions and 2 deletions

View File

@@ -0,0 +1,14 @@
<?php
namespace App\Http\Controllers;
use Inertia\Inertia;
use Inertia\Response;
class DashboardController extends Controller
{
public function __invoke(): Response
{
return Inertia::render('Dashboard');
}
}

View File

@@ -113,9 +113,9 @@ return [
*/
'redirects' => [
'login' => env('AUTH_REDIRECT_LOGIN', '/'),
'login' => env('AUTH_REDIRECT_LOGIN', '/dashboard'),
'logout' => env('AUTH_REDIRECT_LOGOUT', '/'),
'register' => env('AUTH_REDIRECT_REGISTER', '/'),
'register' => env('AUTH_REDIRECT_REGISTER', '/dashboard'),
],
/*

View File

@@ -0,0 +1,99 @@
<script setup lang="ts">
import { useAuth } from '@/composables/useAuth'
import DashboardLayout from '@/layouts/DashboardLayout.vue'
defineOptions({
layout: DashboardLayout,
})
const { user } = useAuth()
</script>
<template>
<UDashboardPanel>
<template #header>
<UDashboardNavbar title="Dashboard" />
</template>
<template #body>
<div class="flex flex-col gap-6">
<UCard>
<div class="flex items-center gap-4">
<UIcon name="i-lucide-shield-check" class="text-primary size-8" />
<div>
<h2 class="text-lg font-medium">
Welcome back, {{ user?.first_name }}!
</h2>
<p class="text-muted text-sm">
Your email is verified and you have access to this protected page.
</p>
</div>
</div>
</UCard>
<div class="grid grid-cols-1 md:grid-cols-3 gap-4">
<UCard>
<div class="flex items-center gap-3">
<UIcon name="i-lucide-lock" class="text-primary size-5" />
<div>
<p class="text-sm font-medium">
Auth Middleware
</p>
<p class="text-muted text-xs">
Route requires authentication
</p>
</div>
</div>
</UCard>
<UCard>
<div class="flex items-center gap-3">
<UIcon name="i-lucide-mail-check" class="text-primary size-5" />
<div>
<p class="text-sm font-medium">
Verified Middleware
</p>
<p class="text-muted text-xs">
Route requires email verification
</p>
</div>
</div>
</UCard>
<UCard>
<div class="flex items-center gap-3">
<UIcon name="i-lucide-layout-dashboard" class="text-primary size-5" />
<div>
<p class="text-sm font-medium">
Nuxt UI Dashboard
</p>
<p class="text-muted text-xs">
Built with dashboard components
</p>
</div>
</div>
</UCard>
</div>
<UCard>
<template #header>
<h3 class="font-medium">
Route Protection
</h3>
</template>
<div class="text-sm space-y-2">
<p class="text-muted">
This page is protected with both <code class="bg-gray-100 dark:bg-gray-800 px-1.5 py-0.5 rounded text-xs">auth</code> and <code class="bg-gray-100 dark:bg-gray-800 px-1.5 py-0.5 rounded text-xs">verified</code> middleware. Unauthenticated users are redirected to login, and unverified users are redirected to the email verification page.
</p>
<UAlert
icon="i-lucide-info"
color="info"
variant="subtle"
title="Enable email verification by setting AUTH_ENABLE_EMAIL_VERIFICATION=true in your .env file."
/>
</div>
</UCard>
</div>
</template>
</UDashboardPanel>
</template>

View File

@@ -20,6 +20,9 @@ function logout() {
<div class="min-h-screen flex flex-col bg-gray-100 dark:bg-gray-900">
<header class="flex items-center justify-end gap-4 p-4">
<template v-if="isAuthenticated">
<UButton to="/dashboard" variant="ghost">
Dashboard
</UButton>
<span class="text-sm text-gray-600 dark:text-gray-400">
{{ user?.full_name }}
</span>

View File

@@ -0,0 +1,58 @@
<script setup lang="ts">
import { useForm } from '@inertiajs/vue3'
import Logo from '@/components/common/Logo.vue'
import { useAuth } from '@/composables/useAuth'
const { user } = useAuth()
const logoutForm = useForm({})
function logout() {
logoutForm.post('/logout')
}
const sidebarLinks = [
{
label: 'Dashboard',
icon: 'i-lucide-house',
to: '/dashboard',
},
]
</script>
<template>
<UApp>
<UDashboardGroup>
<UDashboardSidebar collapsible>
<template #header>
<Logo :link-to-home="false" size="sm" />
</template>
<UNavigationMenu :items="sidebarLinks" />
<template #footer>
<div class="flex items-center gap-2 px-2">
<UAvatar :alt="user?.full_name" size="sm" />
<div class="flex-1 truncate text-sm">
<p class="font-medium truncate">
{{ user?.full_name }}
</p>
<p class="text-muted truncate text-xs">
{{ user?.email }}
</p>
</div>
<UButton
icon="i-lucide-log-out"
variant="ghost"
size="sm"
:loading="logoutForm.processing"
@click="logout"
/>
</div>
</template>
</UDashboardSidebar>
<slot />
</UDashboardGroup>
</UApp>
</template>

View File

@@ -1,10 +1,20 @@
<?php
use App\Http\Controllers\DashboardController;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Route;
use Inertia\Inertia;
Route::get('/', function () {
if (Auth::check()) {
return redirect(config('auth-ui.redirects.login', '/dashboard'));
}
return Inertia::render('Welcome', [
'appName' => config('app.name'),
]);
});
Route::middleware(['auth', 'verified'])->group(function () {
Route::get('/dashboard', DashboardController::class)->name('dashboard');
});