diff --git a/web/src/app/features/auth/login.component.ts b/web/src/app/features/auth/login.component.ts index 9310134..05c69fb 100644 --- a/web/src/app/features/auth/login.component.ts +++ b/web/src/app/features/auth/login.component.ts @@ -1,5 +1,5 @@ import { CommonModule } from '@angular/common'; -import { Component, inject, signal } from '@angular/core'; +import { Component, computed, inject, signal } from '@angular/core'; import { FormBuilder, ReactiveFormsModule, Validators } from '@angular/forms'; import { Router } from '@angular/router'; import { AppSettingsService } from '../../core/services/app-settings.service'; @@ -24,50 +24,26 @@ import { UiService } from '../../core/services/ui.service';
{{ mode() === 'login' ? loginSubtitle() : registerSubtitle() }}
-
- +
+ - +
@@ -89,16 +65,26 @@ import { UiService } from '../../core/services/ui.service'; + @if (errorMessage()) { +
{{ errorMessage() }}
+ } + + + @if (appSettings.registrationEnabled()) { @@ -121,6 +107,8 @@ export class LoginComponent { readonly loading = signal(false); readonly mode = signal<'login' | 'register'>('login'); + readonly errorMessage = signal(null); + readonly currentLanguageLabel = computed(() => this.ui.language() === 'pl' ? 'Polski' : 'English'); readonly form = this.fb.nonNullable.group({ email: ['', [Validators.required, Validators.email]], @@ -134,6 +122,7 @@ export class LoginComponent { submit() { if (this.form.invalid) return; + this.errorMessage.set(null); this.loading.set(true); const raw = this.form.getRawValue(); @@ -144,8 +133,10 @@ export class LoginComponent { this.router.navigate(['/']); }, error: (error) => { + const message = error.error?.message ?? 'Nie udało się zalogować.'; this.loading.set(false); - this.toast.error(error.error?.message ?? 'Nie udało się zalogować.'); + this.errorMessage.set(message); + this.toast.error(message); } }); return; @@ -154,16 +145,28 @@ export class LoginComponent { this.auth.register({ email: raw.email, password: raw.password, fullName: raw.fullName || raw.email }).subscribe({ next: () => { this.loading.set(false); + this.errorMessage.set(null); this.toast.success('Konto zostało utworzone.'); this.mode.set('login'); }, error: (error) => { + const message = error.error?.message ?? 'Nie udało się utworzyć konta.'; this.loading.set(false); - this.toast.error(error.error?.message ?? 'Nie udało się utworzyć konta.'); + this.errorMessage.set(message); + this.toast.error(message); } }); } + toggleLanguage() { + this.ui.setLanguage(this.ui.language() === 'pl' ? 'en' : 'pl'); + } + + switchMode() { + this.errorMessage.set(null); + this.mode.set(this.mode() === 'login' ? 'register' : 'login'); + } + loginSubtitle() { return this.ui.language() === 'pl' ? 'Zaloguj się, aby zarządzać wydatkami, kontrahentami i raportami.' diff --git a/web/src/styles.scss b/web/src/styles.scss index 2e2b5f9..760e988 100644 --- a/web/src/styles.scss +++ b/web/src/styles.scss @@ -3,16 +3,18 @@ :root { --tblr-primary: #111827; --tblr-primary-rgb: 17, 24, 39; - --tblr-border-radius: 0.75rem; - --tblr-border-radius-lg: 0.9rem; - --tblr-border-radius-sm: 0.45rem; - --tblr-card-border-radius: 0.9rem; + --tblr-border-radius: 1rem; + --tblr-border-radius-lg: 1rem; + --tblr-border-radius-sm: 0.75rem; + --tblr-card-border-radius: 1rem; --tblr-body-bg: #f4f6f8; --ec-shell-bg: #f4f6f8; --ec-card-shadow: 0 2px 8px rgba(15, 23, 42, 0.05); --ec-card-border: rgba(15, 23, 42, 0.08); --ec-navbar-bg: rgba(255, 255, 255, 0.95); --ec-subnav-bg: rgba(255, 255, 255, 0.9); + --ec-light-radius-sm: 0.75rem; + --ec-light-radius-md: 1rem; } html, @@ -24,6 +26,41 @@ body { background: var(--ec-shell-bg); } +[data-bs-theme="light"] { + --tblr-border-radius: var(--ec-light-radius-md); + --tblr-border-radius-lg: var(--ec-light-radius-md); + --tblr-border-radius-sm: var(--ec-light-radius-sm); + --tblr-card-border-radius: var(--ec-light-radius-md); +} + +[data-bs-theme="light"] .card, +[data-bs-theme="light"] .pv-card, +[data-bs-theme="light"] .login-card, +[data-bs-theme="light"] .modal-content, +[data-bs-theme="light"] .alert, +[data-bs-theme="light"] .toast, +[data-bs-theme="light"] .dropdown-menu, +[data-bs-theme="light"] .table-responsive, +[data-bs-theme="light"] .form-control, +[data-bs-theme="light"] .form-select, +[data-bs-theme="light"] .form-check-input, +[data-bs-theme="light"] .input-group-text, +[data-bs-theme="light"] .btn, +[data-bs-theme="light"] .nav-segmented, +[data-bs-theme="light"] .nav-pills .nav-link, +[data-bs-theme="light"] .nav-tabs .nav-link, +[data-bs-theme="light"] .page-link { + border-radius: var(--ec-light-radius-md); +} + +[data-bs-theme="light"] .rounded-3 { + border-radius: var(--ec-light-radius-md) !important; +} + +[data-bs-theme="light"] .rounded-2 { + border-radius: var(--ec-light-radius-sm) !important; +} + [data-bs-theme="dark"] { --tblr-primary: #0f172a; --tblr-primary-rgb: 15, 23, 42; @@ -158,7 +195,21 @@ body { } .login-card-enhanced { + position: relative; overflow: hidden; + border-width: 1px; +} + +.login-card-enhanced::before { + content: ""; + position: absolute; + inset: 0 0 auto 0; + height: 5px; + background: linear-gradient(90deg, rgba(32, 107, 196, 0.95), rgba(47, 179, 68, 0.9)); +} + +.login-card-enhanced .card-body { + position: relative; } .login-input-stack { @@ -175,6 +226,8 @@ body { .login-footer-note { margin-top: 1rem; + padding-top: 1rem; + border-top: 1px solid rgba(148, 163, 184, 0.18); color: var(--tblr-secondary); font-size: 0.875rem; }