1
\$\begingroup\$

Let me give a brief explanation of the mini-application I've designed using Angular : A simple login page that requires user email and password as credentials. Once logged in, the user is moved to a page where a list of tasks is displayed in the form of individual boxes.

This code review is not focused on CSS, but on functionality, so please can you focus on providing feedback on the following:

  1. authenticate() method (return value and code logic)
  2. login() method (code logic and debugging)
  3. task service (Correctness of object used and correctness of logic and best practices)

login component.html:


<form [formGroup]="loginForm" (ngSubmit)="login()">
   <label>Email:</label>
   <input type="email" formControlName="email">
   <label>Password:</label>
   <input type="text" formControlName="password">
   <button>Login</button>
</form>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz" crossorigin="anonymous"></script>

authentication.service:

    // src/app/auth.service.ts

import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders, HttpRequest, HttpResponse } from '@angular/common/http';
import { Observable } from 'rxjs';


@Injectable({
  providedIn: 'root'
})
export class AuthenticationService {

  private  baseUrl= 'http://localhost:8080/api/v1/auth';

  constructor(private http: HttpClient) {}

  authenticate(credentials: {email: string, password: string}) : Observable<HttpResponse<any>> {
    const apiUrl = `${this.baseUrl}/authenticate` ;
    return this.http.post<any>(apiUrl, credentials, {observe: 'response'}) ;

  }

  
}

login.component.ts :


  
    
  // src/app/login/login.component.ts

import { Component } from '@angular/core';
import { AuthenticationService } from '../authentication/authentication.service';
import { FormControl, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms';
import { FormsModule } from '@angular/forms';
import { HttpResponse } from '@angular/common/http';
import { Router } from '@angular/router';
import { RouterOutlet } from '@angular/router';
@Component({
  selector: 'app-login',
  templateUrl: './login.component.html',
  styleUrls: ['./login.component.css', '../bootstrap-5.3.3-dist/css/bootstrap-grid.css'],
  imports: [FormsModule, ReactiveFormsModule, RouterOutlet],
  standalone: true
})
export class LoginComponent {
  loginForm = new FormGroup ({
    email: new FormControl<string>('', [Validators.required, Validators.email]),
    password: new FormControl<string>('', Validators.required)
  })

  constructor(private authenticationService: AuthenticationService, private router: Router) {}

  getEmail(): string {
    return this.loginForm.get('email')?.value || '' ;
  }

  getPassword(){
    return this.loginForm.get('password')?.value || '' ;
  }

  login() {

    if (this.loginForm.invalid) {
      return ;
    }
    const email: string = this.getEmail();
    const password: string = this.getPassword();

    this.authenticationService.authenticate({ email, password }).subscribe(
      (response: HttpResponse<any>) => {
        console.log('Response:', response);
        if (response.status === 200) {
          console.log('Navigation triggered');
          const token = response.body.token ; 
          localStorage.setItem('token', token);
          this.router.navigate(['/tasksForm']).then(
            success => {
              console.log(success);
              
              if (!success) {
                console.error('Navigation failed');
              }
            }
          );
        } else {
          console.error('Error:', response.body);
        }
      },
      error => {
        console.error("Err:", error) ;
      }
    );
  }
  // login() { 
  //   this.router.navigate(['/tasksForm']); 
  // }

tasks.component.html


    <div class="task-container">
    @for(task of tasks ; track task) {
    <div class="task-box">
      <h3>{{ task.description }}</h3>
      <p><strong>ID:</strong> {{ task.ID }}</p>
      <p><strong>Executor ID:</strong> {{ task.executorID }}</p>
      <p><strong>Completed:</strong> {{ task.completed ? 'Yes' : 'No' }}</p>
      <p><strong>Deadline:</strong> {{ task.deadline | date }}</p>
    </div>
}
</div>

task.service.ts


    import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Task } from '../models/Models.model';
import { Observable } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class TaskService {
  baseUrl : string  = "http://localhost:8080/Task"
  constructor(private http : HttpClient) { }

  get getTasks() : Observable<Task[]> {
    const apiUrl = this.baseUrl ;
    const token = localStorage.getItem('token');
    const headers = {
      'Authorization' : `Bearer ${token}`,
      'cors':'no-cors'
    }
    return this.http.get<Task[]>(apiUrl, {headers})
  }

  
  

}

app.routes.ts :


    import { Routes } from '@angular/router';
import { LoginComponent } from './login/login.component';
import { TasksComponent } from './tasks/tasks.component';

export const routes: Routes = [
    {path: '', component: LoginComponent },
    {path: 'tasksForm', component: TasksComponent},
    {path: '**', redirectTo: '' }

];

models :


    export interface Task {
    ID: Number ;
    description : string ;
    completed : boolean ;
    executorID : Number ;
    deadline : Date ; 
}
export interface User {
    firstname : string ;
    lastname : string ;
    email : string ;
    password : string ;
}
\$\endgroup\$
1
  • \$\begingroup\$ Welcome to Code Review! The current question title, which states your concerns about the code, is too general to be useful here. Please edit to the site standard, which is for the title to simply state the task accomplished by the code. Please see How to get the best value out of Code Review: Asking Questions for guidance on writing good question titles. \$\endgroup\$ Commented Aug 8 at 13:59

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.