import { Component, OnInit } from '@angular/core'; import { Router, ActivatedRoute, RouterLink } from '@angular/router'; import { FormBuilder, ReactiveFormsModule, Validators } from '@angular/forms'; import { NgIf } from '@angular/common'; 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'; type PageState = 'check-email' | 'verifying' | 'verified' | 'set-password' | 'error'; @Component({ selector: 'app-verify-email', standalone: true, imports: [ RouterLink, ReactiveFormsModule, NgIf, MatCardModule, MatFormFieldModule, MatInputModule, MatButtonModule, MatProgressSpinnerModule, ], template: `

Indie

📧

Check your email

We sent a verification link to {{ email }}

The link expires in 24 hours.

{{ resendMessage }}
{{ resendError }}
Back to login

Verifying your email...

Email verified!

Your email has been verified. Now set your password to activate your account.

Set your password

New Password Password is required At least 8 characters Confirm Password Please confirm your password Passwords do not match
{{ passwordError }}

{{ errorTitle }}

{{ errorMessage }}

Create a new account Back to login
`, }) export class VerifyEmailComponent implements OnInit { state: PageState = 'check-email'; email = ''; errorTitle = ''; errorMessage = ''; showResend = false; resendMessage = ''; resendError = ''; resending = false; private setupToken = ''; passwordLoading = false; passwordError = ''; passwordForm = this.fb.group({ password: ['', [Validators.required, Validators.minLength(8)]], confirmPassword: ['', Validators.required], }, { validators: this.passwordsMatch }); constructor( private route: ActivatedRoute, private router: Router, private authService: AuthService, private fb: FormBuilder, ) {} ngOnInit(): void { this.route.queryParams.subscribe(params => { const token = params['token']; const email = params['email']; if (token) { this.verify(token); } else if (email) { this.email = email; this.state = 'check-email'; } else { this.state = 'check-email'; } }); } private verify(token: string): void { this.state = 'verifying'; this.authService.verifyEmail(token).subscribe({ next: (res) => { if (res.setupToken) { this.setupToken = res.setupToken; this.state = 'verified'; } else { this.state = 'verified'; } }, error: (err) => { const msg = err.error?.detail || err.error?.message || 'Verification failed'; if (msg.toLowerCase().includes('expired')) { this.errorTitle = 'Link expired'; this.errorMessage = 'This verification link has expired. Request a new one.'; this.showResend = true; } else if (msg.toLowerCase().includes('already been used')) { this.errorTitle = 'Already verified'; this.errorMessage = 'This link has already been used. Your email may already be verified. Try logging in.'; this.showResend = false; } else { this.errorTitle = 'Verification failed'; this.errorMessage = msg; this.showResend = true; } this.state = 'error'; }, }); } resend(): void { if (!this.email) { const token = this.route.snapshot.queryParams['token']; this.authService.verifyEmail(token).subscribe({ next: () => {}, error: (err) => { this.email = err.error?.email || ''; }, }); return; } this.resending = true; this.resendMessage = ''; this.resendError = ''; this.authService.resendVerification(this.email).subscribe({ next: () => { this.resendMessage = 'Verification email resent. Please check your inbox.'; this.resending = false; this.state = 'check-email'; }, error: () => { this.resendError = 'Failed to resend. Please try again later.'; this.resending = false; }, }); } onSetPassword(): void { if (this.passwordForm.invalid) return; this.passwordLoading = true; this.passwordError = ''; this.authService.setPassword(this.setupToken, this.passwordForm.value.password!).subscribe({ next: () => { this.router.navigate(['/login'], { queryParams: { verified: 'true' } }); }, error: (err) => { this.passwordError = err.error?.detail || err.error?.message || 'Failed to set password'; this.passwordLoading = false; }, }); } private passwordsMatch(group: any): { mismatch: boolean } | null { const password = group.get('password')?.value; const confirm = group.get('confirmPassword')?.value; return password === confirm ? null : { mismatch: true }; } }