Preview:
//TS
import { CommonModule } from '@angular/common';
import { HttpClientModule } from '@angular/common/http';
import { Component } from '@angular/core';
import { FormBuilder, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms';
import { Router, RouterLink } from '@angular/router';
import { BackendService } from '../services/backend.service';
import { MaterialModule } from '../shared/material.module';
import { FlexLayoutModule } from '@angular/flex-layout';
import { MatSnackBar } from '@angular/material/snack-bar';

@Component({
  selector: 'app-login',
  standalone: true,
  imports: [
    MaterialModule,
    ReactiveFormsModule,
    RouterLink,
    CommonModule,
    HttpClientModule, 
    FlexLayoutModule
],
  templateUrl: './login.component.html',
  styleUrl: './login.component.scss'
})
export class LoginComponent {
  loginFormGroup: FormGroup;
  isLoading: boolean = false;

  constructor(
    private router: Router,
    private backendService: BackendService,
    private fb: FormBuilder,
    private snackBar: MatSnackBar
  ) {
    this.loginFormGroup = this.fb.group({
      email: ['', [Validators.required, Validators.email]],
      password: ['', [Validators.required, Validators.minLength(8), Validators.maxLength(16)]]
    });
  }

  ngOnInit(): void {}

  LoginUser() {
    if (this.loginFormGroup.valid) {
      this.isLoading = true;

      this.backendService.LoginUser(this.loginFormGroup.value).subscribe({
        next: (result) => {
          localStorage.setItem('User', JSON.stringify(result));
          this.loginFormGroup.reset();
          this.router.navigateByUrl('product-listing');
          this.snackBar.open('Login successful', 'X', { duration: 2000 });
          this.isLoading = false;
        },
        error: (err) => {
          let errorMessage = 'Login failed. Please try again.';
          if (err.status === 401) {
            errorMessage = 'Invalid email or password.';
          } else if (err.status === 500) {
            errorMessage = 'Internal server error. Please contact support.';
          }
          this.snackBar.open(errorMessage, 'X', { duration: 3000 });
          this.isLoading = false;
        }
      });
    } else {
      this.snackBar.open('Please fill out the form correctly.', 'X', { duration: 3000 });
    }
  }
}
//Memo
export class LoginComponent implements OnInit {

  loginFormGroup: FormGroup = this.fb.group({
    emailaddress: ['', [Validators.required, Validators.email]],
    password: ['', Validators.required],
  })

  isLoading:boolean = false

  constructor(private router: Router, private apiService: APIService, private fb: FormBuilder, private snackBar: MatSnackBar) { }

  ngOnInit(): void {}

  async LoginUser(){
    if(this.loginFormGroup.valid)
    {
      this.isLoading = true

      await this.apiService.LoginUser(this.loginFormGroup.value).subscribe(result => {
        localStorage.setItem('User', JSON.stringify(result))
        this.loginFormGroup.reset();
        this.router.navigateByUrl('productListing');
      })
    }
  }
}
//Logout
ngOnInit(): void {
    this.isLoggedIn = localStorage.getItem('User') ? true : false;
  }
logout(): void {
    localStorage.removeItem('User');
    this.router.navigateByUrl('login');
    this.snackBar.open('You have been successfully logged out.', 'X', {duration: 3000});
  }
//OR
logout(){
    if(localStorage.getItem('User'))
    {
      localStorage.removeItem('User')
      this.router.navigateByUrl('login');
    }
  }
//HTML
<div class="login-wrapper" fxLayout="row" fxLayoutAlign="center center">
  <mat-card class="box" *ngIf="!isLoading">
    <mat-card-header>
      <mat-card-title>Log in</mat-card-title>
    </mat-card-header>
    <form class="form" [formGroup]="loginFormGroup" (ngSubmit)="LoginUser()">
      <mat-card-content>
        <mat-form-field class="full-width">
          <mat-label>Email Address</mat-label>
          <input matInput placeholder="e.g., user@example.com" formControlName="email">
          <mat-error *ngIf="loginFormGroup.controls['email'].hasError('required')">Email is required</mat-error>
          <mat-error *ngIf="loginFormGroup.controls['email'].hasError('email')">Enter a valid email</mat-error>
        </mat-form-field>
        <mat-form-field class="full-width">
          <mat-label>Password</mat-label>
          <input type="password" matInput placeholder="e.g., 8-16 characters" formControlName="password">
          <mat-error *ngIf="loginFormGroup.controls['password'].hasError('required')">Password is required</mat-error>
          <mat-error *ngIf="loginFormGroup.controls['password'].hasError('minlength')">Minimum 8 characters required</mat-error>
          <mat-error *ngIf="loginFormGroup.controls['password'].hasError('maxlength')">Maximum 16 characters allowed</mat-error>
        </mat-form-field>
      </mat-card-content>
      <mat-card-actions>
        <button mat-stroked-button color="primary" class="btn-block" type="submit">Log in</button>
      </mat-card-actions>
      <div style="text-align: center;">Don't have an account? <a [routerLink]="['../register']">Register</a></div>
    </form>
  </mat-card>
  <mat-progress-spinner mode="indeterminate" *ngIf="isLoading"></mat-progress-spinner>
</div>
downloadDownload PNG downloadDownload JPEG downloadDownload SVG

Tip: You can change the style, width & colours of the snippet with the inspect tool before clicking Download!

Click to optimize width for Twitter