From c464a701c1e72f391264cdec80339a84bea13fd7 Mon Sep 17 00:00:00 2001
From: "thibault.capt" <thibault.capt@etu.hesge.ch>
Date: Tue, 18 Feb 2025 11:32:15 +0100
Subject: [PATCH] (feat): add modal for adding a car

---
 .../garage-ui/src/app/app.component.ts        | 10 +++-
 .../garage-ui/src/app/core/cars/car.store.ts  |  2 -
 .../src/app/features/cars/cars.component.html | 17 ++++++-
 .../src/app/features/cars/cars.component.ts   | 19 +++++++-
 .../components/modal/modal.component.html     | 48 +++++++++++++++++++
 .../cars/components/modal/modal.component.ts  | 27 +++++++++++
 .../garage-ui/src/app/shared/fa-icons.ts      |  4 ++
 .../garage/projects/garage-ui/src/main.ts     |  4 +-
 8 files changed, 122 insertions(+), 9 deletions(-)
 create mode 100644 garage-workspace/garage/projects/garage-ui/src/app/features/cars/components/modal/modal.component.html
 create mode 100644 garage-workspace/garage/projects/garage-ui/src/app/features/cars/components/modal/modal.component.ts
 create mode 100644 garage-workspace/garage/projects/garage-ui/src/app/shared/fa-icons.ts

diff --git a/garage-workspace/garage/projects/garage-ui/src/app/app.component.ts b/garage-workspace/garage/projects/garage-ui/src/app/app.component.ts
index 6a3f56ccb..9ab41086a 100644
--- a/garage-workspace/garage/projects/garage-ui/src/app/app.component.ts
+++ b/garage-workspace/garage/projects/garage-ui/src/app/app.component.ts
@@ -1,5 +1,7 @@
-import { Component } from '@angular/core';
+import { Component, inject } from '@angular/core';
 import { RouterOutlet } from '@angular/router';
+import { FaIconLibrary } from '@fortawesome/angular-fontawesome';
+import { faIcons } from '@shared/fa-icons';
 
 @Component({
   selector: 'app-root',
@@ -7,4 +9,8 @@ import { RouterOutlet } from '@angular/router';
   template: `<router-outlet />`,
   styleUrl: './app.component.scss',
 })
-export class AppComponent {}
+export class AppComponent {
+  constructor() {
+    inject(FaIconLibrary).addIcons(...faIcons);
+  }
+}
diff --git a/garage-workspace/garage/projects/garage-ui/src/app/core/cars/car.store.ts b/garage-workspace/garage/projects/garage-ui/src/app/core/cars/car.store.ts
index 80a9d3eb8..64fbef2c4 100644
--- a/garage-workspace/garage/projects/garage-ui/src/app/core/cars/car.store.ts
+++ b/garage-workspace/garage/projects/garage-ui/src/app/core/cars/car.store.ts
@@ -39,9 +39,7 @@ export const CarStore = signalStore(
   })),
   withHooks((store) => ({
     onInit() {
-      patchState(store, { loading: true });
       store.getCars();
-      patchState(store, { loading: false });
     },
   })),
 );
diff --git a/garage-workspace/garage/projects/garage-ui/src/app/features/cars/cars.component.html b/garage-workspace/garage/projects/garage-ui/src/app/features/cars/cars.component.html
index 555630adf..1b75cded1 100644
--- a/garage-workspace/garage/projects/garage-ui/src/app/features/cars/cars.component.html
+++ b/garage-workspace/garage/projects/garage-ui/src/app/features/cars/cars.component.html
@@ -31,7 +31,19 @@
               <td>{{ car.model }}</td>
               <td>{{ car.year }}</td>
               <td>{{ car.color }}</td>
-              <td>Modify | Delete</td>
+              <td>
+                <div class="tooltip" data-tip="Edit">
+                  <button class="btn btn-square btn-sm mr-1" (click)="onEdit(car.id)">
+                    <fa-icon [icon]="['fas', 'pen-nib']"></fa-icon>
+                  </button>
+                </div>
+
+                <div class="tooltip" data-tip="Delete">
+                  <button class="btn btn-square btn-sm" (click)="onDelete(car.id)">
+                    <fa-icon [icon]="['fas', 'trash']"></fa-icon>
+                  </button>
+                </div>
+              </td>
             </tr>
           }
         }
@@ -41,5 +53,8 @@
         </tr>
       }
     </table>
+    <button (click)="onAdd()" class="btn btn-soft btn-primary mt-2">Add new car</button>
   </div>
 </div>
+
+<app-modal #modal />
\ No newline at end of file
diff --git a/garage-workspace/garage/projects/garage-ui/src/app/features/cars/cars.component.ts b/garage-workspace/garage/projects/garage-ui/src/app/features/cars/cars.component.ts
index 55fed316b..e8cece3f3 100644
--- a/garage-workspace/garage/projects/garage-ui/src/app/features/cars/cars.component.ts
+++ b/garage-workspace/garage/projects/garage-ui/src/app/features/cars/cars.component.ts
@@ -1,13 +1,28 @@
-import { Component, inject } from '@angular/core';
+import { Component, inject, viewChild } from '@angular/core';
 import { CarStore } from '@core/cars/car.store';
+import { FaIconComponent } from '@fortawesome/angular-fontawesome';
+import { ModalComponent } from '@features/cars/components/modal/modal.component';
 
 @Component({
   selector: 'app-cars',
-  imports: [],
+  imports: [FaIconComponent, ModalComponent],
   templateUrl: './cars.component.html',
   styleUrl: './cars.component.scss',
   providers: [CarStore],
 })
 export default class CarsComponent {
   readonly store = inject(CarStore);
+  modal = viewChild<ModalComponent>('modal');
+
+  onEdit(id: number) {
+    alert(`Edit car with id: ${id}`);
+  }
+
+  onDelete(id: number) {
+    alert(`Delete car with id: ${id}`);
+  }
+
+  onAdd() {
+    this.modal()!.open();
+  }
 }
diff --git a/garage-workspace/garage/projects/garage-ui/src/app/features/cars/components/modal/modal.component.html b/garage-workspace/garage/projects/garage-ui/src/app/features/cars/components/modal/modal.component.html
new file mode 100644
index 000000000..30b39eb15
--- /dev/null
+++ b/garage-workspace/garage/projects/garage-ui/src/app/features/cars/components/modal/modal.component.html
@@ -0,0 +1,48 @@
+@if (isOpen()) {
+<div class="modal modal-open">
+  <div class="modal-box">
+    <button (click)="close()" class="btn btn-sm btn-circle btn-ghost absolute right-2 top-2">✕</button>
+    <h3 class="text-lg font-bold">Adding a new car!</h3>
+
+    <form (ngSubmit)="onSubmit()" class="mt-4 mb-4">
+      <!-- Brand -->
+      <div class="mb-4">
+        <label class="floating-label" for="brand">
+          <span>Brand</span>
+          <input id="brand" name="brand" type="text" placeholder="Brand" class="input input-bordered" required>
+        </label>
+      </div>
+
+      <!-- Model -->
+      <div class="mb-4">
+        <label class="floating-label" for="model">
+          <span>Model</span>
+          <input id="model" name="model" type="text" placeholder="Model" class="input input-bordered" required>
+        </label>
+      </div>
+
+      <!-- Year -->
+      <div class="mb-4">
+        <label class="floating-label" for="year">
+          <span>Year</span>
+          <input id="year" name="year" type="number" min="1900" max="2025" placeholder="Year" class="input input-bordered" required>
+        </label>
+      </div>
+
+      <!-- Color -->
+      <div class="mb-4">
+        <label class="floating-label" for="brand">
+          <span>Color</span>
+          <input id="color" name="color" type="text" placeholder="Color" class="input input-bordered" required>
+        </label>
+      </div>
+
+      <!-- Actions du modal -->
+      <div class="modal-action">
+        <button type="button" class="btn" (click)="close()">Cancel</button>
+        <button type="submit" class="btn btn-primary">Save</button>
+      </div>
+    </form>
+  </div>
+</div>
+}
\ No newline at end of file
diff --git a/garage-workspace/garage/projects/garage-ui/src/app/features/cars/components/modal/modal.component.ts b/garage-workspace/garage/projects/garage-ui/src/app/features/cars/components/modal/modal.component.ts
new file mode 100644
index 000000000..fcdd0e0b0
--- /dev/null
+++ b/garage-workspace/garage/projects/garage-ui/src/app/features/cars/components/modal/modal.component.ts
@@ -0,0 +1,27 @@
+import { Component, input, signal } from '@angular/core';
+import { Car } from '@core/cars/models/car.model';
+import { FormsModule } from '@angular/forms';
+
+@Component({
+  selector: 'app-modal',
+  imports: [FormsModule],
+  templateUrl: './modal.component.html',
+})
+export class ModalComponent {
+  isOpen = signal(false);
+  newCar = input.required<Car>();
+
+  open(): void {
+    this.isOpen.set(true);
+  }
+
+  close(): void {
+    this.isOpen.set(false);
+  }
+
+  onSubmit() {
+    alert('Submitted');
+  }
+
+  // TODO: continuer le add car
+}
diff --git a/garage-workspace/garage/projects/garage-ui/src/app/shared/fa-icons.ts b/garage-workspace/garage/projects/garage-ui/src/app/shared/fa-icons.ts
new file mode 100644
index 000000000..209e7b4ea
--- /dev/null
+++ b/garage-workspace/garage/projects/garage-ui/src/app/shared/fa-icons.ts
@@ -0,0 +1,4 @@
+import { IconDefinition } from '@fortawesome/angular-fontawesome';
+import { faPenNib, faTrash } from '@fortawesome/free-solid-svg-icons';
+
+export const faIcons: IconDefinition[] = [faPenNib, faTrash];
diff --git a/garage-workspace/garage/projects/garage-ui/src/main.ts b/garage-workspace/garage/projects/garage-ui/src/main.ts
index f3a7223da..bb8ead67f 100644
--- a/garage-workspace/garage/projects/garage-ui/src/main.ts
+++ b/garage-workspace/garage/projects/garage-ui/src/main.ts
@@ -1,6 +1,6 @@
 import { bootstrapApplication } from '@angular/platform-browser';
-import { AppComponent } from './app/app.component';
-import { appConfig } from './app/app.config';
+import { AppComponent } from '@app/app.component';
+import { appConfig } from '@app/app.config';
 
 bootstrapApplication(AppComponent, appConfig).catch((err) =>
   console.error(err),
-- 
GitLab