129 lines
4.8 KiB
TypeScript
129 lines
4.8 KiB
TypeScript
import { Component, OnInit } from '@angular/core';
|
|
import { Router, ActivatedRoute, RouterLink } from '@angular/router';
|
|
import { FormBuilder, ReactiveFormsModule, Validators } from '@angular/forms';
|
|
import { MatCardModule } from '@angular/material/card';
|
|
import { MatFormFieldModule } from '@angular/material/form-field';
|
|
import { MatInputModule } from '@angular/material/input';
|
|
import { MatButtonModule } from '@angular/material/button';
|
|
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
|
import { AuthService } from '../../core/services/auth.service';
|
|
import { NgIf } from '@angular/common';
|
|
|
|
@Component({
|
|
selector: 'app-login',
|
|
standalone: true,
|
|
imports: [
|
|
RouterLink, ReactiveFormsModule, NgIf,
|
|
MatCardModule, MatFormFieldModule, MatInputModule, MatButtonModule,
|
|
MatProgressSpinnerModule,
|
|
],
|
|
template: `
|
|
<div class="min-h-screen flex items-center justify-center bg-gray-50 px-4">
|
|
<mat-card class="w-full max-w-md p-8">
|
|
<div class="text-center mb-8">
|
|
<h1 class="text-3xl font-bold text-indigo-600">Indie</h1>
|
|
<p class="text-gray-500 mt-1">Sign in to your account</p>
|
|
</div>
|
|
|
|
<div *ngIf="showVerifiedMessage" class="bg-green-50 border border-green-200 text-green-700 text-sm rounded-lg p-3 mb-4">
|
|
Your account is ready. Please sign in.
|
|
</div>
|
|
|
|
<form [formGroup]="loginForm" (ngSubmit)="onSubmit()" class="flex flex-col gap-4">
|
|
<mat-form-field appearance="outline" class="w-full">
|
|
<mat-label>Email</mat-label>
|
|
<input matInput type="email" formControlName="email" placeholder="you@example.com" />
|
|
<mat-error *ngIf="loginForm.get('email')?.hasError('required')">Email is required</mat-error>
|
|
<mat-error *ngIf="loginForm.get('email')?.hasError('email')">Invalid email format</mat-error>
|
|
</mat-form-field>
|
|
|
|
<mat-form-field appearance="outline" class="w-full">
|
|
<mat-label>Password</mat-label>
|
|
<input matInput type="password" formControlName="password" />
|
|
<mat-error *ngIf="loginForm.get('password')?.hasError('required')">Password is required</mat-error>
|
|
</mat-form-field>
|
|
|
|
<div *ngIf="error" class="text-red-600 text-sm">{{ error }}</div>
|
|
|
|
<div *ngIf="showResendLink" class="text-sm text-center">
|
|
<a (click)="resendVerification()" class="text-indigo-600 font-medium hover:underline cursor-pointer">
|
|
Resend verification email
|
|
</a>
|
|
<div *ngIf="resendMessage" class="text-green-600 mt-1">{{ resendMessage }}</div>
|
|
</div>
|
|
|
|
<button mat-flat-button color="primary" type="submit" [disabled]="loading" class="w-full py-2">
|
|
<mat-spinner *ngIf="loading" diameter="20" class="inline-block mr-2"></mat-spinner>
|
|
{{ loading ? 'Signing in...' : 'Sign In' }}
|
|
</button>
|
|
</form>
|
|
|
|
<p class="text-center mt-6 text-sm text-gray-500">
|
|
Don't have an account?
|
|
<a routerLink="/register" class="text-indigo-600 font-medium hover:underline">Register</a>
|
|
</p>
|
|
</mat-card>
|
|
</div>
|
|
`,
|
|
})
|
|
export class LoginComponent implements OnInit {
|
|
loginForm = this.fb.group({
|
|
email: ['', [Validators.required, Validators.email]],
|
|
password: ['', Validators.required],
|
|
});
|
|
loading = false;
|
|
error = '';
|
|
showResendLink = false;
|
|
resendMessage = '';
|
|
showVerifiedMessage = false;
|
|
private unverifiedEmail = '';
|
|
|
|
constructor(
|
|
private fb: FormBuilder,
|
|
private authService: AuthService,
|
|
private router: Router,
|
|
private route: ActivatedRoute,
|
|
) {}
|
|
|
|
ngOnInit(): void {
|
|
if (this.route.snapshot.queryParams['verified'] === 'true') {
|
|
this.showVerifiedMessage = true;
|
|
}
|
|
}
|
|
|
|
onSubmit(): void {
|
|
if (this.loginForm.invalid) return;
|
|
this.loading = true;
|
|
this.error = '';
|
|
this.showResendLink = false;
|
|
this.resendMessage = '';
|
|
const { email, password } = this.loginForm.value;
|
|
this.authService.login(email!, password!).subscribe({
|
|
next: () => this.router.navigate(['/dashboard']),
|
|
error: (err) => {
|
|
const msg = err.error?.detail || err.error?.message || 'Invalid email or password';
|
|
if (msg.toLowerCase().includes('verify your email')) {
|
|
this.error = 'Please verify your email address before logging in.';
|
|
this.showResendLink = true;
|
|
this.unverifiedEmail = email!;
|
|
} else {
|
|
this.error = msg;
|
|
}
|
|
this.loading = false;
|
|
},
|
|
});
|
|
}
|
|
|
|
resendVerification(): void {
|
|
if (!this.unverifiedEmail) return;
|
|
this.authService.resendVerification(this.unverifiedEmail).subscribe({
|
|
next: () => {
|
|
this.resendMessage = 'Verification email resent.';
|
|
},
|
|
error: () => {
|
|
this.resendMessage = 'Failed to resend. Please try again later.';
|
|
},
|
|
});
|
|
}
|
|
}
|