From 0e4cfa5bb567a9c28f3af6997ac858448059a171 Mon Sep 17 00:00:00 2001 From: Carlos Santos <4a.santos@gmail.com> Date: Tue, 15 Jul 2025 16:58:42 +0200 Subject: [PATCH] frontend: redesign error page with enhanced layout, responsive design, and improved error handling --- .../src/lib/pages/error/error.component.html | 39 ++- .../src/lib/pages/error/error.component.scss | 239 ++++++++++++++++-- .../src/lib/pages/error/error.component.ts | 16 +- 3 files changed, 256 insertions(+), 38 deletions(-) diff --git a/frontend/projects/shared-meet-components/src/lib/pages/error/error.component.html b/frontend/projects/shared-meet-components/src/lib/pages/error/error.component.html index 7204206..e7daca9 100644 --- a/frontend/projects/shared-meet-components/src/lib/pages/error/error.component.html +++ b/frontend/projects/shared-meet-components/src/lib/pages/error/error.component.html @@ -1,10 +1,31 @@ -
- - - {{ errorName }} - - -

{{ message }}

-
-
+
+
+
+
+ error_outline +
+ +
+

{{ errorName }}

+

{{ message }}

+
+ +
+ +
+
+ +
+
+ cloud_off +
+ Oops! + Something went wrong +
+
+
+
diff --git a/frontend/projects/shared-meet-components/src/lib/pages/error/error.component.scss b/frontend/projects/shared-meet-components/src/lib/pages/error/error.component.scss index 2eb04f0..a637a5e 100644 --- a/frontend/projects/shared-meet-components/src/lib/pages/error/error.component.scss +++ b/frontend/projects/shared-meet-components/src/lib/pages/error/error.component.scss @@ -1,33 +1,220 @@ -.container { - display: flex; - justify-content: center; - align-items: center; - height: 100vh; - background-color: var(--ov-background-color); +@import '../../../../../../src/assets/styles/design-tokens'; + +.error-page { + @include ov-theme-transition; + @include ov-flex-center; + min-height: 100vh; + background: var(--ov-meet-background-color); + padding: var(--ov-meet-spacing-lg); + + .error-container { + @include ov-theme-transition; + display: flex; + flex-direction: row; + align-items: center; + gap: var(--ov-meet-spacing-xxl); + max-width: 800px; + width: 100%; + + @include ov-tablet-down { + flex-direction: column; + gap: var(--ov-meet-spacing-xl); + text-align: center; + } + + .error-content { + flex: 1; + display: flex; + flex-direction: column; + gap: var(--ov-meet-spacing-lg); + + .error-icon-section { + @include ov-flex-center; + justify-content: flex-start; + + @include ov-tablet-down { + justify-content: center; + } + + .error-main-icon { + @include ov-icon(xl); + color: var(--ov-meet-color-error); + background: rgba(var(--ov-meet-color-error), 0.1); + border-radius: var(--ov-meet-radius-circle); + padding: var(--ov-meet-spacing-md); + width: 64px; + height: 64px; + font-size: 32px; + } + } + + .error-details { + .error-title { + margin: 0 0 var(--ov-meet-spacing-sm) 0; + font-size: var(--ov-meet-font-size-xxl); + font-weight: var(--ov-meet-font-weight-semibold); + color: var(--ov-meet-text-primary); + line-height: var(--ov-meet-line-height-tight); + + @include ov-mobile-down { + font-size: var(--ov-meet-font-size-xl); + } + } + + .error-message { + margin: 0; + font-size: var(--ov-meet-font-size-md); + color: var(--ov-meet-text-secondary); + line-height: var(--ov-meet-line-height-normal); + max-width: 400px; + + @include ov-tablet-down { + max-width: none; + } + + @include ov-mobile-down { + font-size: var(--ov-meet-font-size-sm); + } + } + } + + .error-actions { + display: flex; + gap: var(--ov-meet-spacing-md); + margin-top: var(--ov-meet-spacing-md); + + @include ov-tablet-down { + justify-content: center; + } + + @include ov-mobile-down { + flex-direction: column; + align-items: center; + } + + .action-button { + @include ov-button-base; + @include ov-flex-center; + gap: var(--ov-meet-spacing-xs); + min-width: 120px; + + &.secondary { + color: var(--ov-meet-text-secondary); + border-color: var(--ov-meet-border-color); + + &:hover { + color: var(--ov-meet-text-primary); + border-color: var(--ov-meet-text-primary); + background: var(--ov-meet-surface-hover); + } + } + + mat-icon { + @include ov-icon(sm); + } + + @include ov-mobile-down { + min-width: 200px; + } + } + } + } + + .error-illustration { + flex: 1; + @include ov-flex-center; + + @include ov-tablet-down { + order: -1; + } + + .illustration-container { + @include ov-flex-center; + flex-direction: column; + gap: var(--ov-meet-spacing-lg); + opacity: 0.6; + + .illustration-icon { + font-size: 120px; + width: 120px; + height: 120px; + color: var(--ov-meet-text-hint); + + @include ov-mobile-down { + font-size: 80px; + width: 80px; + height: 80px; + } + } + + .illustration-text { + display: flex; + flex-direction: column; + gap: var(--ov-meet-spacing-xs); + text-align: center; + + .illustration-title { + font-size: var(--ov-meet-font-size-xl); + font-weight: var(--ov-meet-font-weight-bold); + color: var(--ov-meet-text-secondary); + + @include ov-mobile-down { + font-size: var(--ov-meet-font-size-lg); + } + } + + .illustration-subtitle { + font-size: var(--ov-meet-font-size-sm); + color: var(--ov-meet-text-hint); + } + } + } + } + } } -.card { - width: 400px; - padding: 20px; - text-align: center; - background-color: var(--ov-surface-color); - border-radius: var(--ov-surface-radius); +// Animation states +.fade-in { + animation: fadeIn 0.6s ease-out forwards; } -mat-card-header { - justify-content: center; - align-items: center; +// Enhanced responsive design +@include ov-mobile-down { + .error-page { + padding: var(--ov-meet-spacing-md); + + .error-container { + .error-content { + .error-details { + .error-title { + margin-bottom: var(--ov-meet-spacing-md); + } + } + + .error-actions { + margin-top: var(--ov-meet-spacing-lg); + + .action-button { + padding: var(--ov-meet-spacing-md) var(--ov-meet-spacing-lg); + font-size: var(--ov-meet-font-size-md); + } + } + } + } + } } -mat-card-title { - font-size: 1.5em; -} - -mat-card-content p { - font-size: 1em; - color: #555; -} - -mat-card-actions { - margin-top: 20px; +// Dark theme enhancements +[data-theme='dark'] { + .error-page { + .error-container { + .error-content { + .error-icon-section { + .error-main-icon { + background: rgba(var(--ov-meet-color-error), 0.15); + } + } + } + } + } } diff --git a/frontend/projects/shared-meet-components/src/lib/pages/error/error.component.ts b/frontend/projects/shared-meet-components/src/lib/pages/error/error.component.ts index 619576e..9cb8857 100644 --- a/frontend/projects/shared-meet-components/src/lib/pages/error/error.component.ts +++ b/frontend/projects/shared-meet-components/src/lib/pages/error/error.component.ts @@ -1,12 +1,15 @@ import { Component, OnInit } from '@angular/core'; +import { MatButtonModule } from '@angular/material/button'; import { MatCardModule } from '@angular/material/card'; -import { ActivatedRoute } from '@angular/router'; +import { MatIconModule } from '@angular/material/icon'; +import { ActivatedRoute, Router } from '@angular/router'; +import { Location } from '@angular/common'; import { ErrorReason } from '@lib/models'; @Component({ selector: 'ov-error', standalone: true, - imports: [MatCardModule], + imports: [MatCardModule, MatIconModule, MatButtonModule], templateUrl: './error.component.html', styleUrl: './error.component.scss' }) @@ -14,7 +17,10 @@ export class ErrorComponent implements OnInit { errorName = 'Error'; message = ''; - constructor(private route: ActivatedRoute) {} + constructor( + private route: ActivatedRoute, + private location: Location + ) {} ngOnInit(): void { this.route.queryParams.subscribe((params) => { @@ -64,4 +70,8 @@ export class ErrorComponent implements OnInit { } }); } + + goBack(): void { + this.location.back(); + } }