From 1ac31ae5a9c574397ee16a8ebd2daaf38b7c1e06 Mon Sep 17 00:00:00 2001 From: Arif Hoque Date: Sat, 21 Feb 2026 13:37:31 +0600 Subject: [PATCH 1/2] error page design update: --- src/Phaseolies/Error/WebErrorRenderer.php | 9 +- .../Error/views/template-headers.odo.php | 63 +- src/Phaseolies/Error/views/template.odo.php | 1202 +++++++++++------ .../Error/views/trace-frames.odo.php | 57 +- 4 files changed, 811 insertions(+), 520 deletions(-) diff --git a/src/Phaseolies/Error/WebErrorRenderer.php b/src/Phaseolies/Error/WebErrorRenderer.php index 7f094b43..a1583aa8 100644 --- a/src/Phaseolies/Error/WebErrorRenderer.php +++ b/src/Phaseolies/Error/WebErrorRenderer.php @@ -9,6 +9,8 @@ use Phaseolies\Http\Controllers\Controller; use Throwable; +use function Tests\Unit\Application\config; + class WebErrorRenderer { /** @@ -47,8 +49,6 @@ public function renderDebug(Throwable $exception): string 'email' => $user->email ?? 'N/A', ] : null; - date_default_timezone_set(config('app.timezone')); - $mdReport = new ExceptionMarkdownReport($exception); // setup the controller to point out to different views location @@ -68,6 +68,7 @@ public function renderDebug(Throwable $exception): string 'php_version' => PHP_VERSION, 'doppar_version' => Application::VERSION, 'request_method' => request()->getMethod(), + 'request_body' => request()->all(), 'request_url' => trim(request()->fullUrl(), '/'), 'timestamp' => now()->toDayDateTimeString(), 'server_software' => $_SERVER['SERVER_SOFTWARE'] ?? 'Unknown', @@ -79,6 +80,10 @@ public function renderDebug(Throwable $exception): string 'exception_class' => class_basename($exception), 'status_code' => $exception->getCode() ?: 500, 'md_content' => $mdReport->generate(), + 'current_middleware' => \Phaseolies\Support\Facades\Route::getCurrentMiddlewareNames(), + 'current_route_name' => \Phaseolies\Support\Facades\Route::currentRouteName(), + 'current_route_action' => \Phaseolies\Support\Facades\Route::currentRouteAction(), + 'current_route_params' => request()->getRouteParams() ]); } diff --git a/src/Phaseolies/Error/views/template-headers.odo.php b/src/Phaseolies/Error/views/template-headers.odo.php index a0bb61b3..85432dad 100644 --- a/src/Phaseolies/Error/views/template-headers.odo.php +++ b/src/Phaseolies/Error/views/template-headers.odo.php @@ -1,38 +1,25 @@ -
-
- - - - -
-
\ No newline at end of file + +
+
+ #foreach ($headers as $header_name => $header_value) +
+ [[ $header_name ]] +
+ [[ $header_value ]] +
+ #endforeach +
+
\ No newline at end of file diff --git a/src/Phaseolies/Error/views/template.odo.php b/src/Phaseolies/Error/views/template.odo.php index bd10d1b4..0d4b7087 100644 --- a/src/Phaseolies/Error/views/template.odo.php +++ b/src/Phaseolies/Error/views/template.odo.php @@ -4,564 +4,870 @@ - Error - [[ $error_message ]] + Error — [[ $error_message ]] + + + + + - loadDarkMode(); - - + - -
-
-
-
-
- - - -
+ .arrow-icon { + transition: transform 0.2s ease; + } -
-
- [[ $exception_class ]] -
-

- [[ $error_message]] -

+ /* ── Clickable rows ── */ + .frame-toggle, + .headers-toggle { + display: flex; + align-items: center; + gap: 12px; + padding: 12px 16px; + cursor: pointer; + user-select: none; + } + + .frame-toggle:hover { + background: rgba(0, 0, 0, .02); + } + + html.dark .frame-toggle:hover { + background: rgba(255, 255, 255, .02); + } + + .headers-toggle:hover { + background: rgba(0, 0, 0, .02); + } + + html.dark .headers-toggle:hover { + background: rgba(255, 255, 255, .02); + } + + /* ── IMPROVED: exception class pill with live dot ── */ + .exception-pill { + display: inline-flex; + align-items: center; + gap: 6px; + padding: 3px 10px 3px 7px; + border-radius: 6px; + font-size: 11px; + font-weight: 600; + letter-spacing: 0.01em; + background: rgba(225, 29, 72, 0.08); + border: 1px solid rgba(225, 29, 72, 0.18); + color: #e11d48; + } + + html.dark .exception-pill { + background: rgba(251, 113, 133, 0.1); + border-color: rgba(251, 113, 133, 0.2); + color: #fb7185; + } + + .exception-pill-dot { + width: 6px; + height: 6px; + border-radius: 50%; + background: currentColor; + animation: pulse-dot 2s ease infinite; + flex-shrink: 0; + } + + @keyframes pulse-dot { + + 0%, + 100% { + opacity: .8; + transform: scale(1); + } + + 50% { + opacity: .3; + transform: scale(.6); + } + } + + /* ── IMPROVED: subtle hero glow ── */ + .hero-glow { + position: absolute; + top: -80px; + right: -80px; + width: 500px; + height: 400px; + border-radius: 50%; + background: radial-gradient(circle, rgba(225, 29, 72, 0.06) 0%, transparent 70%); + pointer-events: none; + } + + html.dark .hero-glow { + background: radial-gradient(circle, rgba(251, 113, 133, 0.07) 0%, transparent 70%); + } + + /* ── IMPROVED: status badge with live dot ── */ + .status-badge { + display: inline-flex; + align-items: center; + gap: 6px; + padding: 4px 10px 4px 7px; + border-radius: 6px; + font-size: 11px; + font-weight: 700; + background: rgba(225, 29, 72, 0.09); + border: 1px solid rgba(225, 29, 72, 0.2); + color: #e11d48; + } + + html.dark .status-badge { + background: rgba(251, 113, 133, 0.09); + border-color: rgba(251, 113, 133, 0.2); + color: #fb7185; + } + + .status-badge-dot { + width: 6px; + height: 6px; + border-radius: 50%; + background: currentColor; + animation: pulse-dot 1.8s ease infinite; + } + + /* ── IMPROVED: code line hover ── */ + .code-line:not(.code-line-error):hover { + background: rgba(0, 0, 0, .025); + } + + html.dark .code-line:not(.code-line-error):hover { + background: rgba(255, 255, 255, .02); + } + + /* ── IMPROVED: param dotted connector ── */ + .param-dot-line { + flex-grow: 1; + border-bottom: 1px dashed rgba(0, 0, 0, .1); + margin: 0 8px 4px; + } + + html.dark .param-dot-line { + border-bottom-color: rgba(255, 255, 255, .07); + } + + /* ── IMPROVED: "Line N" badge in code header ── */ + .line-badge { + display: inline-flex; + align-items: center; + padding: 2px 8px; + border-radius: 5px; + font-size: 10px; + font-weight: 700; + letter-spacing: 0.05em; + background: rgba(225, 29, 72, 0.08); + border: 1px solid rgba(225, 29, 72, 0.18); + color: #e11d48; + } + + html.dark .line-badge { + background: rgba(251, 113, 133, 0.08); + border-color: rgba(251, 113, 133, 0.18); + color: #fb7185; + } + + /* ── IMPROVED: route live indicator ── */ + .route-live-dot { + width: 7px; + height: 7px; + border-radius: 50%; + background: #e11d48; + animation: pulse-dot 1.6s ease infinite; + } + + html.dark .route-live-dot { + background: #fb7185; + } + + /* ── IMPROVED: request bar ── */ + .request-bar { + border-top: 1px solid rgba(0, 0, 0, .06); + border-bottom: 1px solid rgba(0, 0, 0, .06); + background: rgba(255, 255, 255, .4); + backdrop-filter: blur(4px); + } + + html.dark .request-bar { + border-top-color: rgba(255, 255, 255, .05); + border-bottom-color: rgba(255, 255, 255, .05); + background: rgba(255, 255, 255, .02); + } + + /* ── IMPROVED: frame count badge ── */ + .frame-count-badge { + display: inline-flex; + align-items: center; + padding: 2px 8px; + border-radius: 99px; + font-size: 10px; + font-weight: 700; + background: rgba(0, 0, 0, .05); + border: 1px solid rgba(0, 0, 0, .07); + color: #64748b; + } + + html.dark .frame-count-badge { + background: rgba(255, 255, 255, .06); + border-color: rgba(255, 255, 255, .06); + color: #94a3b8; + } + + + + + + +
+
+
+ +
+ + +
+ +
+ + [[ $exception_class ]]
-
-
- - -
-
-
- DOPPAR +
+ + + +
+
+ Doppar [[ $doppar_version ]]
-
- PHP +
+ PHP [[ $php_version ]]
+ + +

+ [[ $error_message ]] +

-
- - [[ $request_method]] - - [[ $request_url ]] -
- - - - [[ $timestamp ]] + +
+
+ [[ $request_method ]] + [[ $request_url ]]
-
-
-
- - - - [[ $error_file ]] + +
+
+
+ +
+ [[ $timestamp ]]
- -
-
[[! $contents !]]
+
+ +
+ + + + [[ $status_code ]] +
- -
-
-

- - - - Stack Trace -

- -
-
- #include('trace-frames', ['traces' => $traces]) -
+
+ +
+ + [[ $request_method ]] +
-
-
- #include('template-headers', ['headers' => $headers])
-
-
-
- - - - -

System

-
-
-
-
Server
-
[[ $server_software ]]
-
-
-
Platform
-
[[ $platform ]]
-
-
-
+ +
-
-
- - - -

Memory

-
-
-
-
Current Usage
-
[[ number_format($memory_usage / 1024 / 1024, 2) ]] MB
-
-
-
Peak Usage
-
[[ number_format($peack_memory_usage / 1024 / 1024, 2) ]] MB
+ +
+
+
+
+
+
+ [[ $error_file ]] + + Line [[ $error_line ]] +
+
+
[[! $contents !]]
-
-
- - - -

User

-
- #if ($user_info) -
-
-
ID
-
[[ $user_info['id'] ]]
-
-
-
Email
-
[[ $user_info['email'] ]]
+ +
+
+
+ + + +

Stack Trace

+ +
+
- #else -
- - - -

// NO USER

-
- #endif -
-
-
-
-
- - - - -

Request Body

+
+ #include('trace-frames', ['traces' => $traces])
- #if (!empty($request_body)) - - #endif
- #if (!empty($request_body)) - - #else -
- - - - -

// EMPTY REQUEST BODY

-
- #endif -
-
-
- - - -

Routing

+ +
+ #include('template-headers', ['headers' => $headers])
-
- #if (!empty($routing['controller'])) -
-
Controller
-
[[ $routing['controller'] ]] + +
+ +
+
+
+ + + +
+ System +
+
+
+ +
[[ $server_software ]]
+
+
+ +
[[ $platform ]]
+
- #endif - #if (!empty($routing['middleware'])) -
-
Middleware
-
- #foreach ($routing['middleware'] as $mw) - [[ $mw ]] - #endforeach + +
+
+
+ + + +
+ Memory +
+
+
+ +
[[ number_format($memory_usage / 1024 / 1024, 2) ]] MB
+
+
+ +
[[ number_format($peack_memory_usage / 1024 / 1024, 2) ]] MB
+
- #endif + + +
+
+
+ + + +
+ User +
+ #if ($user_info) +
+
+ +
[[ $user_info['id'] ]]
+
+
+ +
[[ $user_info['email'] ]]
+
+
+ #else +
+ + + +

No User

+
+ #endif +
-
-
Route Parameters
- #if (!empty($routing['params'])) -
- #foreach ($routing['params'] as $key => $value) -
-
[[ $key ]]
-
[[ $value ]]
+ +
+ +
+
+ + +
- #endforeach + Request Body + #if (!empty($request_body)) + + + + #endif +
+ #if (!empty($request_body)) + #else -
- - - +
+ + -

// NO ROUTE PARAMETERS

+

Empty Request Body

#endif
-
- - - - +
+ + #if(!empty($current_route_action)) +
+ [[ $current_route_action ]] +
+ #else + Closure / No Action + #endif +
+
- + })(); + + \ No newline at end of file diff --git a/src/Phaseolies/Error/views/trace-frames.odo.php b/src/Phaseolies/Error/views/trace-frames.odo.php index a6e698fa..bde91fe0 100644 --- a/src/Phaseolies/Error/views/trace-frames.odo.php +++ b/src/Phaseolies/Error/views/trace-frames.odo.php @@ -1,34 +1,27 @@ -
- #if (empty($traces)) -
No stack trace available
- #else -
- #foreach ($traces as $index => $trace) -
-
- [[ $index + 1 ]] -
-
[[ $trace->getCallSignature() ]]
-
-
[[ $trace->getShortFile() ]]
-
-
- -
- +#if (empty($traces)) +
+

No stack trace available

+
+#else +#foreach ($traces as $index => $trace) +
+ - #endif -
\ No newline at end of file +
+
+ [[! $trace->getCodeLinesContent() !]] +
+
+
+#endforeach +#endif \ No newline at end of file From 98763f7e51402e3b58170fad80f106e44d15bb06 Mon Sep 17 00:00:00 2001 From: Arif Hoque Date: Sat, 21 Feb 2026 14:52:17 +0600 Subject: [PATCH 2/2] error page design update: --- src/Phaseolies/Error/views/template.odo.php | 85 +++++++++++---------- 1 file changed, 46 insertions(+), 39 deletions(-) diff --git a/src/Phaseolies/Error/views/template.odo.php b/src/Phaseolies/Error/views/template.odo.php index 0d4b7087..a761081b 100644 --- a/src/Phaseolies/Error/views/template.odo.php +++ b/src/Phaseolies/Error/views/template.odo.php @@ -204,7 +204,6 @@ background: rgba(255, 255, 255, .02); } - /* ── IMPROVED: exception class pill with live dot ── */ .exception-pill { display: inline-flex; align-items: center; @@ -248,7 +247,6 @@ } } - /* ── IMPROVED: subtle hero glow ── */ .hero-glow { position: absolute; top: -80px; @@ -256,15 +254,9 @@ width: 500px; height: 400px; border-radius: 50%; - background: radial-gradient(circle, rgba(225, 29, 72, 0.06) 0%, transparent 70%); pointer-events: none; } - html.dark .hero-glow { - background: radial-gradient(circle, rgba(251, 113, 133, 0.07) 0%, transparent 70%); - } - - /* ── IMPROVED: status badge with live dot ── */ .status-badge { display: inline-flex; align-items: center; @@ -292,7 +284,6 @@ animation: pulse-dot 1.8s ease infinite; } - /* ── IMPROVED: code line hover ── */ .code-line:not(.code-line-error):hover { background: rgba(0, 0, 0, .025); } @@ -301,7 +292,6 @@ background: rgba(255, 255, 255, .02); } - /* ── IMPROVED: param dotted connector ── */ .param-dot-line { flex-grow: 1; border-bottom: 1px dashed rgba(0, 0, 0, .1); @@ -312,7 +302,6 @@ border-bottom-color: rgba(255, 255, 255, .07); } - /* ── IMPROVED: "Line N" badge in code header ── */ .line-badge { display: inline-flex; align-items: center; @@ -332,7 +321,6 @@ color: #fb7185; } - /* ── IMPROVED: route live indicator ── */ .route-live-dot { width: 7px; height: 7px; @@ -345,7 +333,6 @@ background: #fb7185; } - /* ── IMPROVED: request bar ── */ .request-bar { border-top: 1px solid rgba(0, 0, 0, .06); border-bottom: 1px solid rgba(0, 0, 0, .06); @@ -359,7 +346,6 @@ background: rgba(255, 255, 255, .02); } - /* ── IMPROVED: frame count badge ── */ .frame-count-badge { display: inline-flex; align-items: center; @@ -385,13 +371,11 @@
-
+
-
-
[[ $exception_class ]] @@ -429,34 +413,45 @@ class="p-2 rounded-xl hover:bg-black/5 dark:hover:bg-white/8 border border-black
- -

+

[[ $error_message ]]

-
-
- [[ $request_method ]] - [[ $request_url ]] +
+
+
+ [[ $request_method ]] + [[ $request_url ]] + +
-
+
[[ $timestamp ]]
-
+
- [[ $status_code ]] @@ -484,7 +479,6 @@ class="p-2 rounded-xl hover:bg-black/5 dark:hover:bg-white/8 border border-black
[[ $error_file ]] - Line [[ $error_line ]]
@@ -500,7 +494,6 @@ class="p-2 rounded-xl hover:bg-black/5 dark:hover:bg-white/8 border border-black

Stack Trace

-