- V1__init.sql: синхронизированы таблицы с Java моделями (users, folders, messages, contacts) - docker-compose.yml: обновлён контекст сборки, переменные R2DBC/Flyway, порты (5433, 3026, 1443) - backend/Dockerfile: обновлены пути COPY для нового контекста сборки - settings.gradle: удалён frontend проект из Gradle - contacts.component.html: исправлен ternary оператор с HTML на Angular @if/@else - Фронтенд компоненты: обновления compose, inbox, layout, login, message-detail, register - index.html, styles.css: обновления стилей и мета-данных Co-authored-by: Junie <junie@jetbrains.com>
99 lines
4.0 KiB
TypeScript
99 lines
4.0 KiB
TypeScript
import { Component, inject } from '@angular/core';
|
|
import { RouterLink } from '@angular/router';
|
|
import { FormsModule } from '@angular/forms';
|
|
import { AuthService } from '../../services/auth.service';
|
|
import { Router } from '@angular/router';
|
|
|
|
@Component({
|
|
selector: 'app-login',
|
|
standalone: true,
|
|
imports: [RouterLink, FormsModule],
|
|
template: `
|
|
<div class="min-h-screen relative flex items-center justify-center theme-cyber-magenta">
|
|
<!-- Synthwave анимированный фон -->
|
|
<div class="synth-stage" aria-hidden="true">
|
|
<div class="synth-sun"></div>
|
|
<div class="synth-mountains"></div>
|
|
<div class="grid-container">
|
|
<div class="grid-plane"></div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Форма логина -->
|
|
<div class="relative z-10 w-full max-w-md px-4">
|
|
<div class="glass-panel p-8 border-2 border-cyan-400 shadow-[0_0_50px_rgba(0,240,255,0.4)]">
|
|
<div class="text-center mb-8">
|
|
<div class="w-16 h-16 mx-auto rounded-xl bg-gradient-to-br from-pink-500 to-cyan-400 flex items-center justify-center text-slate-950 font-black text-2xl font-orbitron shadow-[0_0_20px_rgba(255,0,127,0.8)] mb-4">
|
|
M
|
|
</div>
|
|
<h1 class="text-3xl font-extrabold font-orbitron tracking-wider neon-text-primary mb-2">
|
|
MAIL<span class="text-cyan-400 font-normal">SERVER</span>
|
|
</h1>
|
|
<p class="text-sm text-cyan-300/70 font-mono tracking-widest uppercase">Synthwave Edition</p>
|
|
</div>
|
|
|
|
@if (error) {
|
|
<div class="mb-4 p-3 rounded-lg bg-pink-500/20 border border-pink-500/40 text-pink-400 text-sm font-mono">
|
|
{{ error }}
|
|
</div>
|
|
}
|
|
|
|
<form (ngSubmit)="onLogin()" class="space-y-4">
|
|
<div>
|
|
<label for="email" class="block text-xs font-mono text-pink-400 mb-1">EMAIL</label>
|
|
<input id="email" type="email" [(ngModel)]="email" name="email" required
|
|
class="w-full bg-slate-950/80 border border-cyan-500/40 rounded-xl px-4 py-3 text-sm text-slate-200 font-mono focus:outline-none focus:ring-2 focus:ring-pink-500 focus:border-cyan-400 transition-all"
|
|
placeholder="user@example.com">
|
|
</div>
|
|
|
|
<div>
|
|
<label for="password" class="block text-xs font-mono text-pink-400 mb-1">PASSWORD</label>
|
|
<input id="password" type="password" [(ngModel)]="password" name="password" required
|
|
class="w-full bg-slate-950/80 border border-cyan-500/40 rounded-xl px-4 py-3 text-sm text-slate-200 font-mono focus:outline-none focus:ring-2 focus:ring-pink-500 focus:border-cyan-400 transition-all"
|
|
placeholder="••••••••">
|
|
</div>
|
|
|
|
<button type="submit" [disabled]="loading"
|
|
class="cyber-btn w-full py-3 rounded-xl text-sm font-bold mt-6">
|
|
@if (loading) {
|
|
<i class="fa-solid fa-spinner fa-spin mr-1"></i> CONNECTING...
|
|
} @else {
|
|
<i class="fa-solid fa-bolt mr-1"></i> LOGIN
|
|
}
|
|
</button>
|
|
</form>
|
|
|
|
<p class="text-center text-sm text-slate-400 mt-6 font-rajdhani">
|
|
No account?
|
|
<a routerLink="/register" class="text-cyan-400 hover:text-pink-400 font-mono transition-colors">
|
|
Register here
|
|
</a>
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
`,
|
|
styles: ``
|
|
})
|
|
export default class LoginComponent {
|
|
private authService = inject(AuthService);
|
|
private router = inject(Router);
|
|
|
|
email = '';
|
|
password = '';
|
|
error = '' as string | null;
|
|
loading = false as boolean;
|
|
|
|
onLogin(): void {
|
|
this.loading = true;
|
|
this.error = null;
|
|
this.authService.login({ email: this.email, password: this.password }).subscribe({
|
|
next: () => this.router.navigate(['/inbox']),
|
|
error: (err) => {
|
|
this.error = 'Invalid email or password';
|
|
this.loading = false;
|
|
}
|
|
});
|
|
}
|
|
}
|