Refactor code structure for improved readability and maintainability

This commit is contained in:
2025-11-15 12:51:32 +05:30
parent 94f4305615
commit d0025d55ef
117 changed files with 5992 additions and 157 deletions
+31 -20
View File
@@ -1,40 +1,51 @@
<div class="otp-container">
<h2>🔐 Email Verification</h2>
<div class="verify-wrapper">
<div class="verify-card">
<!-- Step 1: Enter Email -->
@if (!isOtpSent()) {
<form [formGroup]="emailForm" (ngSubmit)="sendOtp()">
<h2 class="title">🔐 OTP Verification</h2>
<!-- 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" />
<button type="submit" [disabled]="emailForm.invalid">Send OTP</button>
</form>
}
}
<!-- Step 2: Enter OTP -->
@if (isOtpSent() && !isVerified()) {
<div>
<p>OTP sent to <b>{{ emailForm.value.email }}</b></p>
<!-- Step 2: OTP Input -->
@if (isOtpSent() && !isVerified()) {
<div class="otp-section">
<p class="info-text">
OTP sent to <b>{{ emailForm.value.email }}</b>
</p>
<form [formGroup]="otpForm" (ngSubmit)="verifyOtp()">
<label>Enter 6-digit OTP</label>
<input type="text" maxlength="6" formControlName="otp" placeholder="123456" />
<button type="submit" [disabled]="otpForm.invalid">Verify OTP</button>
<button type="submit" [disabled]="otpForm.invalid">
Verify OTP
</button>
</form>
<button (click)="resendOtp()" [disabled]="countdown() > 0">
Resend OTP @if (countdown() > 0) {
<span>({{ countdown() }}s)</span>
<button class="resend-btn" (click)="resendOtp()" [disabled]="countdown() > 0">
Resend OTP
@if (countdown() > 0) {
<span>({{ countdown() }}s)</span>
}
</button>
</div>
}
}
<!-- Step 3: Success -->
@if (isVerified()) {
<!-- Step 3: Success -->
<!-- @if (isVerified()) {
<div>
<p class="success">✅ Your email has been verified successfully!</p>
<p class="success-msg">{{ message() }}✅</p>
</div>
}
}
<p class="message">{{ message() }}</p>
@if (isError()) {
<p class="error-message">{{ message() }}</p>
} -->
</div>
</div>
+129 -37
View File
@@ -1,47 +1,139 @@
.otp-container {
max-width: 400px;
margin: 60px auto;
padding: 30px;
background: #fff;
border-radius: 16px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
/* Background wrapper */
.verify-wrapper {
width: 100%;
height: 100vh;
background: #0e0e0e;
display: flex;
justify-content: center;
align-items: center;
padding: 20px;
}
/* Card */
.verify-card {
width: 420px;
/* NEW: More contrast from background */
background: var(--bg-gradient-onyx);
border-radius: 18px;
padding: 35px 40px;
/* NEW: Clean gold glow */
box-shadow:
0 0 12px rgba(227, 179, 65, 0.25),
0 10px 35px rgba(0, 0, 0, 0.65);
/* NEW: Gold border highlight */
border: 1px solid rgba(227, 179, 65, 0.15);
/* Slight glass effect */
backdrop-filter: blur(6px);
}
/* Title */
.title {
text-align: center;
color: #fff;
font-size: 24px;
font-weight: 600;
margin-bottom: 30px;
}
/* Labels */
label {
color: #d6d6d6;
font-size: 14px;
margin-bottom: 6px;
display: block;
}
/* Inputs */
input {
width: 100%;
padding: 14px;
background: #111;
border: 1px solid #333;
color: #fff;
border-radius: 10px;
font-size: 15px;
margin-bottom: 18px;
outline: none;
transition: 0.25s;
&:focus {
border-color: #e3b341;
box-shadow: 0 0 5px rgba(227, 179, 65, 0.45);
}
&::placeholder {
color: #777;
}
}
/* Primary buttons */
button {
width: 100%;
padding: 14px;
background: #e3b341;
border: none;
color: #111;
font-size: 16px;
border-radius: 10px;
font-weight: 600;
cursor: pointer;
transition: 0.25s;
text-align: center;
h2 {
margin-bottom: 20px;
&:disabled {
background: #555;
color: #aaa;
cursor: not-allowed;
}
input {
width: 100%;
padding: 10px;
margin: 10px 0;
font-size: 16px;
&:not(:disabled):hover {
background: #f2c85c;
}
}
/* Resend OTP button */
.resend-btn {
margin-top: 12px;
background: transparent !important;
color: #e3b341 !important;
border: 1px solid #e3b341;
font-size: 14px;
&:hover:not(:disabled) {
background: rgba(227, 179, 65, 0.1);
}
button {
width: 100%;
margin-top: 10px;
padding: 10px;
background-color: #007bff;
border: none;
color: white;
font-size: 16px;
border-radius: 8px;
cursor: pointer;
&:disabled {
background: #aaa;
cursor: not-allowed;
}
&:disabled {
border-color: #555;
color: #777;
}
}
.success {
color: green;
font-weight: 600;
}
/* Success message */
.success-msg {
margin-top: 10px;
font-size: 16px;
color: #78ff8c;
text-align: center;
font-weight: 500;
}
.message {
margin-top: 15px;
color: #555;
}
/* Error / general message */
.error-message {
margin-top: 12px;
color: #ff6b6b;
text-align: center;
font-size: 14px;
}
.info-text {
color: #ccc;
font-size: 14px;
margin-bottom: 10px;
}
+25 -9
View File
@@ -1,23 +1,29 @@
import { Component, signal } from '@angular/core';
import { Component, inject, OnInit, signal } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { AuthService } from '../auth.service';
import { ActivatedRoute, Router } from '@angular/router';
@Component({
selector: 'app-otp',
standalone: false,
templateUrl: './otp.component.html',
styleUrls: ['./otp.component.scss']
})
export class OtpComponent {
export class OtpComponent implements OnInit {
emailForm: FormGroup;
otpForm: FormGroup;
isOtpSent = signal(false);
isVerified = signal(false);
isError = signal(false);
message = signal('');
countdown = signal(0);
timer: any;
timer: NodeJS.Timeout | undefined;
returnUrl = '/';
fb: FormBuilder = inject(FormBuilder);
authService: AuthService = inject(AuthService);
router: Router = inject(Router);
route: ActivatedRoute = inject(ActivatedRoute);
constructor(private fb: FormBuilder, private authService: AuthService) {
constructor() {
this.emailForm = this.fb.group({
email: ['', [Validators.required, Validators.email]],
});
@@ -25,6 +31,15 @@ export class OtpComponent {
this.otpForm = this.fb.group({
otp: ['', [Validators.required, Validators.pattern(/^[0-9]{6}$/)]],
});
if(this.authService.isLoggedIn()){
this.router.navigateByUrl('/');
}
}
ngOnInit() {
this.returnUrl = this.route.snapshot.queryParamMap.get('returnUrl') || '/';
}
sendOtp() {
@@ -58,15 +73,16 @@ export class OtpComponent {
const { otp: otpCode } = this.otpForm.value;
this.authService.verifyOtp(userId, otpCode).subscribe({
next: (res) => {
next: () => {
this.isVerified.set(true);
this.message.set(res.message || 'OTP verified successfully ✅');
this.router.navigateByUrl(this.returnUrl); // Navigate to dashboard or desired route after successful verification
},
error: (err) => {
this.isError.set(true);
if (err.status === 401 && err.error?.message) {
this.message.set(err.error.message); // "OTP Expired" or "Invalid OTP"
console.log(err.error.message); // "OTP Expired" or "Invalid OTP"
} else {
this.message.set('Something went wrong. Please try again.');
console.log('Something went wrong. Please try again.');
}
}
});