feat: enhance application structure and improve accessibility
- Refactor various components for better readability and maintainability. - Update HTML templates to include `alt` attributes for images and `for` attributes for labels. - Implement reactive forms in OTP component and improve token management in AuthService. - Adjust routing to redirect to 'admin/about' by default. - Remove deprecated interceptor implementation and streamline authentication logic. - Add console logs for better debugging during initialization.
This commit is contained in:
@@ -1,23 +1,13 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { OtpComponent } from './otp/otp.component';
|
||||
import { ReactiveFormsModule } from '@angular/forms';
|
||||
import { AuthInterceptor } from '../interceptors/auth-interceptor';
|
||||
|
||||
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
OtpComponent
|
||||
],
|
||||
imports: [
|
||||
CommonModule,
|
||||
BrowserModule,
|
||||
ReactiveFormsModule
|
||||
],
|
||||
providers:[
|
||||
AuthInterceptor
|
||||
]
|
||||
})
|
||||
export class AuthModule { }
|
||||
|
||||
@@ -20,41 +20,50 @@ export class AuthService {
|
||||
private readonly baseUrl = (environment.apiUrl ?? '').replace(/\/+$/, '');
|
||||
private accessToken: string | null = null;
|
||||
private platformId = inject(PLATFORM_ID);
|
||||
private accessTokenSub = new BehaviorSubject<string | null>(null);
|
||||
tokenReady$ = new BehaviorSubject<boolean>(false);
|
||||
public accessTokenSub = new BehaviorSubject<string | null>(null);
|
||||
http = inject(HttpClient);
|
||||
router = inject(Router);
|
||||
|
||||
private readonly storageKey = 'accessToken';
|
||||
|
||||
constructor() {
|
||||
console.log('🔥 AuthService constructor started');
|
||||
this.accessToken = this.safeGetToken();
|
||||
console.log('🔥 AuthService constructor finished', { accessToken: !!this.accessToken });
|
||||
}
|
||||
|
||||
private api(path: string) {
|
||||
return `${this.baseUrl}${path.startsWith('/') ? '' : '/'}${path}`;
|
||||
}
|
||||
|
||||
// Call on app start, or from guard
|
||||
async ensureTokenReady(): Promise<void>{
|
||||
if(this.tokenReady$.value) return;
|
||||
// // Call on app start, or from guard
|
||||
// async ensureTokenReady(): Promise<void>{
|
||||
// if(this.tokenReady$.value) return;
|
||||
|
||||
const stored = this.safeGetToken();
|
||||
// const stored = this.safeGetToken();
|
||||
|
||||
// try to restore from storage
|
||||
if(stored){
|
||||
this.accessTokenSub.next(stored);
|
||||
this.tokenReady$.next(true);
|
||||
return;
|
||||
}
|
||||
// // try to restore from storage
|
||||
// if(stored){
|
||||
// this.accessTokenSub.next(stored);
|
||||
// this.tokenReady$.next(true);
|
||||
// return;
|
||||
// }
|
||||
|
||||
// // Optionally: try a silent refresh on startup to restore session using HttpOnly cookie
|
||||
// try {
|
||||
// const res = await firstValueFrom(this.refreshToken());
|
||||
// this.safeSetToken(res.accessToken);
|
||||
// }
|
||||
// catch{
|
||||
// console.warn('Silent token refresh failed on startup');
|
||||
// }
|
||||
// finally{
|
||||
// this.tokenReady$.next(true);
|
||||
// }
|
||||
// // // Optionally: try a silent refresh on startup to restore session using HttpOnly cookie
|
||||
// // try {
|
||||
// // const res = await firstValueFrom(this.refreshToken());
|
||||
// // this.safeSetToken(res.accessToken);
|
||||
// // }
|
||||
// // catch{
|
||||
// // console.warn('Silent token refresh failed on startup');
|
||||
// // }
|
||||
// // finally{
|
||||
// // this.tokenReady$.next(true);
|
||||
// // }
|
||||
// }
|
||||
|
||||
get currentToken(): string | null {
|
||||
return this.safeGetToken();
|
||||
}
|
||||
|
||||
safeSetToken(token: string) {
|
||||
@@ -62,12 +71,19 @@ export class AuthService {
|
||||
|
||||
if (isPlatformBrowser(this.platformId)) {
|
||||
localStorage.setItem(this.storageKey, token);
|
||||
this.accessTokenSub.next(token);
|
||||
}
|
||||
}
|
||||
|
||||
private safeGetToken(): string | null {
|
||||
if (isPlatformBrowser(this.platformId)) {
|
||||
return localStorage.getItem(this.storageKey);
|
||||
try {
|
||||
if (isPlatformBrowser(this.platformId)) {
|
||||
const token = localStorage.getItem(this.storageKey);
|
||||
this.accessTokenSub.next(token);
|
||||
return token;
|
||||
}
|
||||
} catch (e) {
|
||||
console.warn('Failed to read from localStorage:', e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -77,6 +93,7 @@ export class AuthService {
|
||||
|
||||
if (isPlatformBrowser(this.platformId)) {
|
||||
localStorage.removeItem(this.storageKey);
|
||||
this.accessTokenSub.next(null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,7 +117,7 @@ export class AuthService {
|
||||
}
|
||||
|
||||
getAccessToken(): string | null {
|
||||
return this.accessToken ?? this.safeGetToken();
|
||||
return this.accessToken;
|
||||
}
|
||||
|
||||
logout(): Observable<void> {
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
<!-- Step 1: Enter Email -->
|
||||
@if (!isOtpSent()) {
|
||||
<form [formGroup]="emailForm" (ngSubmit)="sendOtp()" class="form-section">
|
||||
<label>Email Address</label>
|
||||
<input type="email" formControlName="email" placeholder="Enter your email" />
|
||||
<label for="email">Email Address</label>
|
||||
<input id="email" type="email" formControlName="email" placeholder="Enter your email" />
|
||||
<button type="submit" [disabled]="emailForm.invalid">Send OTP</button>
|
||||
</form>
|
||||
}
|
||||
@@ -20,8 +20,8 @@
|
||||
</p>
|
||||
|
||||
<form [formGroup]="otpForm" (ngSubmit)="verifyOtp()">
|
||||
<label>Enter 6-digit OTP</label>
|
||||
<input type="text" maxlength="6" formControlName="otp" placeholder="123456" />
|
||||
<label for="otp">Enter 6-digit OTP</label>
|
||||
<input id="otp" type="text" maxlength="6" formControlName="otp" placeholder="123456" />
|
||||
<button type="submit" [disabled]="otpForm.invalid">
|
||||
Verify OTP
|
||||
</button>
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
import { Component, inject, OnInit, signal } from '@angular/core';
|
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
import { FormBuilder, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms';
|
||||
import { AuthService } from '../auth.service';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
@Component({
|
||||
selector: 'app-otp',
|
||||
templateUrl: './otp.component.html',
|
||||
styleUrls: ['./otp.component.scss']
|
||||
styleUrls: ['./otp.component.scss'],
|
||||
imports: [ReactiveFormsModule, CommonModule]
|
||||
})
|
||||
export class OtpComponent implements OnInit {
|
||||
emailForm: FormGroup;
|
||||
|
||||
Reference in New Issue
Block a user