feat: add dashboard page with Nuxt UI components and verified middleware
This commit is contained in:
14
app/Http/Controllers/DashboardController.php
Normal file
14
app/Http/Controllers/DashboardController.php
Normal 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');
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -113,9 +113,9 @@ return [
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
'redirects' => [
|
'redirects' => [
|
||||||
'login' => env('AUTH_REDIRECT_LOGIN', '/'),
|
'login' => env('AUTH_REDIRECT_LOGIN', '/dashboard'),
|
||||||
'logout' => env('AUTH_REDIRECT_LOGOUT', '/'),
|
'logout' => env('AUTH_REDIRECT_LOGOUT', '/'),
|
||||||
'register' => env('AUTH_REDIRECT_REGISTER', '/'),
|
'register' => env('AUTH_REDIRECT_REGISTER', '/dashboard'),
|
||||||
],
|
],
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
99
resources/js/Pages/Dashboard.vue
Normal file
99
resources/js/Pages/Dashboard.vue
Normal 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>
|
||||||
@@ -20,6 +20,9 @@ function logout() {
|
|||||||
<div class="min-h-screen flex flex-col bg-gray-100 dark:bg-gray-900">
|
<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">
|
<header class="flex items-center justify-end gap-4 p-4">
|
||||||
<template v-if="isAuthenticated">
|
<template v-if="isAuthenticated">
|
||||||
|
<UButton to="/dashboard" variant="ghost">
|
||||||
|
Dashboard
|
||||||
|
</UButton>
|
||||||
<span class="text-sm text-gray-600 dark:text-gray-400">
|
<span class="text-sm text-gray-600 dark:text-gray-400">
|
||||||
{{ user?.full_name }}
|
{{ user?.full_name }}
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
58
resources/js/layouts/DashboardLayout.vue
Normal file
58
resources/js/layouts/DashboardLayout.vue
Normal 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>
|
||||||
@@ -1,10 +1,20 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
use App\Http\Controllers\DashboardController;
|
||||||
|
use Illuminate\Support\Facades\Auth;
|
||||||
use Illuminate\Support\Facades\Route;
|
use Illuminate\Support\Facades\Route;
|
||||||
use Inertia\Inertia;
|
use Inertia\Inertia;
|
||||||
|
|
||||||
Route::get('/', function () {
|
Route::get('/', function () {
|
||||||
|
if (Auth::check()) {
|
||||||
|
return redirect(config('auth-ui.redirects.login', '/dashboard'));
|
||||||
|
}
|
||||||
|
|
||||||
return Inertia::render('Welcome', [
|
return Inertia::render('Welcome', [
|
||||||
'appName' => config('app.name'),
|
'appName' => config('app.name'),
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Route::middleware(['auth', 'verified'])->group(function () {
|
||||||
|
Route::get('/dashboard', DashboardController::class)->name('dashboard');
|
||||||
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user