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;