diff --git a/src/app/app.component.css b/src/app/app.component.css new file mode 100644 index 0000000..948f0ee --- /dev/null +++ b/src/app/app.component.css @@ -0,0 +1,6 @@ +/* Styles du composant racine */ +nav { + display: flex; + gap: 1rem; + margin-bottom: 1rem; +} diff --git a/src/app/app.component.html b/src/app/app.component.html new file mode 100644 index 0000000..e6a0f4b --- /dev/null +++ b/src/app/app.component.html @@ -0,0 +1,12 @@ + + + + + diff --git a/src/app/app.component.ts b/src/app/app.component.ts new file mode 100644 index 0000000..d92765c --- /dev/null +++ b/src/app/app.component.ts @@ -0,0 +1,31 @@ +import { Component, OnInit } from '@angular/core'; +import { RouterLink, RouterOutlet } from '@angular/router'; + +/** + * @Component transforme la classe TypeScript en composant Angular. + * selector: + * - nom de la balise HTML personnalisée utilisée dans index.html (). + * templateUrl: + * - chemin vers le fichier HTML du composant (vue). + * styleUrls: + * - liste de fichiers CSS appliqués uniquement à ce composant (encapsulation). + * standalone: + * - indique que le composant peut être démarré sans NgModule racine. + */ +@Component({ + selector: 'app-root', + standalone: true, + imports: [RouterOutlet, RouterLink], + templateUrl: './app.component.html', + styleUrls: ['./app.component.css'], +}) +export class AppComponent implements OnInit { + /** + * ngOnInit est un hook du cycle de vie Angular. + * Il est appelé une fois, juste après la création du composant. + * C'est l'endroit recommandé pour lancer les initialisations simples. + */ + ngOnInit(): void { + // Aucune initialisation spécifique pour le moment. + } +} diff --git a/src/app/users/crud/crud.component.ts b/src/app/users/crud/crud.component.ts new file mode 100644 index 0000000..f37ec2f --- /dev/null +++ b/src/app/users/crud/crud.component.ts @@ -0,0 +1,45 @@ +import { Component, OnInit } from '@angular/core'; +import { UsersService } from '../services/users.service'; +import { User } from '../model/user.model'; + +/** + * Composant de liste CRUD. + * @Component configure: + * - selector: balise utilisable dans d'autres templates. + * - template: vue HTML inline de ce composant. + */ +@Component({ + selector: 'app-crud', + template: ` +

Liste des utilisateurs

+ + `, +}) +export class CrudComponent implements OnInit { + /** Tableau alimenté avec les données de l'API */ + userList: User[] = []; + + /** + * Injection de dépendances: + * Angular fournit automatiquement une instance de UsersService. + */ + constructor(private usersService: UsersService) {} + + /** + * Hook de cycle de vie exécuté après la création du composant. + * On y déclenche l'initialisation métier (chargement de la liste). + */ + ngOnInit(): void { + this.loadUsers(); + } + + /** + * Récupère les utilisateurs via le service. + * subscribe(...) consomme l'Observable et met à jour l'état local. + */ + private loadUsers(): void { + this.usersService.getUsers().subscribe((users) => { + this.userList = users; + }); + } +} diff --git a/src/app/users/model/user.model.ts b/src/app/users/model/user.model.ts new file mode 100644 index 0000000..7eda6f7 --- /dev/null +++ b/src/app/users/model/user.model.ts @@ -0,0 +1,15 @@ +/** + * Interface décrivant la forme d'un utilisateur. + * Une interface TypeScript permet de typer les données manipulées + * pour éviter des erreurs et faciliter l'autocomplétion. + */ +export interface User { + /** Identifiant unique de l'utilisateur côté API/base de données */ + id: number; + /** Prénom affiché dans l'interface */ + firstName: string; + /** Nom de famille affiché dans l'interface */ + lastName: string; + /** Adresse e-mail utilisée pour contacter ou rechercher l'utilisateur */ + email: string; +} diff --git a/src/app/users/services/users.service.ts b/src/app/users/services/users.service.ts new file mode 100644 index 0000000..c581bc6 --- /dev/null +++ b/src/app/users/services/users.service.ts @@ -0,0 +1,56 @@ +import { Injectable } from '@angular/core'; +import { HttpClient, HttpParams } from '@angular/common/http'; +import { Observable } from 'rxjs'; +import { User } from '../model/user.model'; + +/** + * URL de base de l'API REST des utilisateurs. + * Toutes les opérations CRUD partent de cette route. + */ +const baseUrl = 'http://localhost:8081/api/v1/employees'; + +/** + * @Injectable permet à Angular d'instancier ce service via l'injection + * de dépendances. providedIn: 'root' signifie "singleton global". + */ +@Injectable({ + providedIn: 'root', +}) +export class UsersService { + /** + * HttpClient est injecté automatiquement par Angular. + * Il sert à faire les requêtes HTTP (GET, POST, PUT, DELETE). + */ + constructor(private http: HttpClient) {} + + /** + * Lit tous les utilisateurs. + * Retourne un Observable: + * - un Observable représente un flux asynchrone de données. + * - le composant s'abonne (subscribe) pour recevoir la réponse. + */ + getUsers(): Observable { + return this.http.get(baseUrl); + } + + /** Crée un nouvel utilisateur côté API. */ + create(data: Partial): Observable { + return this.http.post(baseUrl, data); + } + + /** Met à jour un utilisateur existant via son id. */ + update(id: number, data: Partial): Observable { + return this.http.put(`${baseUrl}/${id}`, data); + } + + /** Supprime un utilisateur via son id. */ + delete(id: number): Observable { + return this.http.delete(`${baseUrl}/${id}`); + } + + /** Recherche des utilisateurs par adresse e-mail. */ + findByEmail(email: string): Observable { + const params = new HttpParams().set('email', email); + return this.http.get(baseUrl, { params }); + } +} diff --git a/src/app/users/user-card/user-card.component.ts b/src/app/users/user-card/user-card.component.ts new file mode 100644 index 0000000..1d38bcb --- /dev/null +++ b/src/app/users/user-card/user-card.component.ts @@ -0,0 +1,24 @@ +import { Component, Input } from '@angular/core'; +import { User } from '../model/user.model'; + +/** + * Composant enfant chargé d'afficher un utilisateur. + */ +@Component({ + selector: 'app-user-card', + template: ` +
+

{{ user.firstName }} {{ user.lastName }}

+

{{ user.email }}

+
+ `, +}) +export class UserCardComponent { + /** + * @Input() reçoit des données depuis le composant parent. + * Exemple: + * + * Le parent passe l'objet user au composant enfant. + */ + @Input() user!: User; +} diff --git a/src/app/users/users-routing.module.ts b/src/app/users/users-routing.module.ts new file mode 100644 index 0000000..98d7c90 --- /dev/null +++ b/src/app/users/users-routing.module.ts @@ -0,0 +1,20 @@ +import { NgModule } from '@angular/core'; +import { RouterModule, Routes } from '@angular/router'; +import { CrudComponent } from './crud/crud.component'; + +/** + * Configuration des routes internes au module users. + * - 'all' affiche la liste des utilisateurs. + * - 'create' pourrait afficher un formulaire de création + * (ici, on réutilise CrudComponent pour garder l'exemple simple). + */ +const routes: Routes = [ + { path: 'all', component: CrudComponent }, + { path: 'create', component: CrudComponent }, +]; + +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule], +}) +export class UsersRoutingModule {} diff --git a/src/app/users/users.module.ts b/src/app/users/users.module.ts new file mode 100644 index 0000000..3a955dd --- /dev/null +++ b/src/app/users/users.module.ts @@ -0,0 +1,22 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { HttpClientModule } from '@angular/common/http'; +import { UsersRoutingModule } from './users-routing.module'; +import { CrudComponent } from './crud/crud.component'; +import { UserCardComponent } from './user-card/user-card.component'; + +/** + * @NgModule regroupe les éléments liés à une fonctionnalité. + * imports: + * - modules dont ce module a besoin (directives Angular, HTTP, routing local). + * declarations: + * - composants appartenant à ce module. + * providers: + * - services créés pour ce module (vide ici car UsersService est fourni en root). + */ +@NgModule({ + imports: [CommonModule, HttpClientModule, UsersRoutingModule], + declarations: [CrudComponent, UserCardComponent], + providers: [], +}) +export class UsersModule {} diff --git a/src/index.html b/src/index.html new file mode 100644 index 0000000..61cb123 --- /dev/null +++ b/src/index.html @@ -0,0 +1,17 @@ + + + + + Formation Angular + + + + + + + + diff --git a/src/main.ts b/src/main.ts new file mode 100644 index 0000000..f19eda7 --- /dev/null +++ b/src/main.ts @@ -0,0 +1,31 @@ +import { bootstrapApplication } from '@angular/platform-browser'; +import { provideRouter, Routes } from '@angular/router'; +import { AppComponent } from './app/app.component'; + +/** + * Routes principales de l'application. + * - '' affiche la page racine (AppComponent). + * - 'users' charge le module utilisateurs de façon paresseuse (lazy loading) + * pour éviter de charger tout le code dès le démarrage. + */ +const routes: Routes = [ + { path: '', component: AppComponent }, + { + path: 'users', + loadChildren: () => + import('./app/users/users.module').then((m) => m.UsersModule), + }, +]; + +/** + * Point d'entrée de l'application Angular. + * bootstrapApplication: + * - démarre l'application avec un composant racine standalone. + * providers: + * - enregistre des services globaux de l'application. + * provideRouter(routes): + * - active la navigation Angular et injecte la configuration des routes. + */ +bootstrapApplication(AppComponent, { + providers: [provideRouter(routes)], +}).catch((err) => console.error(err));