From eb13532b0b4720f755542737cb7148e4b201d205 Mon Sep 17 00:00:00 2001 From: Yoga Pangestu Date: Thu, 30 Apr 2026 15:27:07 +0700 Subject: [PATCH] feat: add custom error page handler and improve permission check safety in sidebar navigation --- bootstrap/app.php | 11 ++- resources/js/app.tsx | 2 +- resources/js/components/app-sidebar.tsx | 2 +- resources/js/pages/error.tsx | 89 +++++++++++++++++++++++++ 4 files changed, 101 insertions(+), 3 deletions(-) create mode 100644 resources/js/pages/error.tsx diff --git a/bootstrap/app.php b/bootstrap/app.php index aa3b6de..a387750 100644 --- a/bootstrap/app.php +++ b/bootstrap/app.php @@ -7,6 +7,7 @@ use Illuminate\Foundation\Configuration\Exceptions; use Illuminate\Foundation\Configuration\Middleware; use Illuminate\Http\Middleware\AddLinkHeadersForPreloadedAssets; +use Inertia\Inertia; return Application::configure(basePath: dirname(__DIR__)) ->withRouting( @@ -27,5 +28,13 @@ $schedule->command('payroll:generate')->monthlyOn(1, '00:00'); }) ->withExceptions(function (Exceptions $exceptions): void { - // + $exceptions->respond(function ($response) { + if (in_array($response->getStatusCode(), [500, 503, 404, 403])) { + return Inertia::render('error', ['status' => $response->getStatusCode()]) + ->toResponse(request()) + ->setStatusCode($response->getStatusCode()); + } + + return $response; + }); })->create(); diff --git a/resources/js/app.tsx b/resources/js/app.tsx index 8bb1ba8..695119c 100644 --- a/resources/js/app.tsx +++ b/resources/js/app.tsx @@ -14,7 +14,7 @@ createInertiaApp({ title: (title) => (title ? `${title} - ${appName}` : appName), layout: (name) => { switch (true) { - case name === 'welcome' || name === 'homepage': + case name === 'welcome' || name === 'homepage' || name === 'error': return null; case name.startsWith('auth/'): return AuthLayout; diff --git a/resources/js/components/app-sidebar.tsx b/resources/js/components/app-sidebar.tsx index df9c99e..d8e65df 100644 --- a/resources/js/components/app-sidebar.tsx +++ b/resources/js/components/app-sidebar.tsx @@ -137,7 +137,7 @@ export function AppSidebar() { const filterNavItems = (items: NavItem[]) => { return items.filter((item) => { if (!item.permission) return true; - return auth.permissions.includes(item.permission); + return auth?.permissions?.includes(item.permission) ?? false; }); }; diff --git a/resources/js/pages/error.tsx b/resources/js/pages/error.tsx new file mode 100644 index 0000000..6e2134e --- /dev/null +++ b/resources/js/pages/error.tsx @@ -0,0 +1,89 @@ +import { Button } from '@/components/ui/button'; +import { homepage } from '@/routes'; +import { Head, Link } from '@inertiajs/react'; +import { AlertCircle, ArrowLeft, Home, Search } from 'lucide-react'; + +export default function ErrorPage({ status }: { status: number }) { + const title = + { + 503: '503: Service Unavailable', + 500: '500: Server Error', + 404: '404: Page Not Found', + 403: '403: Forbidden', + }[status] || 'Error'; + + const description = + { + 503: 'Maaf, kami sedang melakukan pemeliharaan rutin untuk meningkatkan layanan. Silakan kembali lagi nanti.', + 500: 'Ups, terjadi kesalahan sistem yang tidak terduga. Tim teknis kami telah diberitahu.', + 404: 'Halaman yang Anda cari tidak dapat ditemukan atau telah dipindahkan ke alamat lain.', + 403: 'Maaf, Anda tidak memiliki akses untuk melihat konten di halaman ini.', + }[status] || 'Terjadi kesalahan pada aplikasi.'; + + return ( + <> + +
+ {/* Abstract Background Elements */} +
+
+ +
+ {/* Big Error Number with Gradient */} +
+

+ {status} +

+
+ + {/* Content Card */} +
+
+
+
+ {status === 404 ? ( + + ) : ( + + )} +
+
+ +
+

+ {title} +

+

+ {description} +

+
+ +
+ + +
+
+
+
+ + ); +} + +ErrorPage.layout = null;