From dbcceed912d11fc6b4ebe9cb532fb23e26bff01c Mon Sep 17 00:00:00 2001
From: Hugo <hugo.cubino@estudiantes.uva.es>
Date: Wed, 27 Nov 2024 09:39:33 +0100
Subject: [PATCH] Implementacion de formulario con datos de usuario

---
 angular/RestClient/src/app/app.routes.ts      |  5 +
 .../user/user-form/user-form.component.css    | 68 ++++++++++++++
 .../user/user-form/user-form.component.html   | 79 ++++++++++++++++
 .../user-form/user-form.component.spec.ts     | 91 +++++++++++++++++++
 .../user/user-form/user-form.component.ts     | 61 +++++++++++++
 .../src/app/shared/user-client.service.ts     | 29 ++++++
 6 files changed, 333 insertions(+)
 create mode 100644 angular/RestClient/src/app/core/features/user/user-form/user-form.component.css
 create mode 100644 angular/RestClient/src/app/core/features/user/user-form/user-form.component.html
 create mode 100644 angular/RestClient/src/app/core/features/user/user-form/user-form.component.spec.ts
 create mode 100644 angular/RestClient/src/app/core/features/user/user-form/user-form.component.ts

diff --git a/angular/RestClient/src/app/app.routes.ts b/angular/RestClient/src/app/app.routes.ts
index b8ee77b..1ce26ae 100644
--- a/angular/RestClient/src/app/app.routes.ts
+++ b/angular/RestClient/src/app/app.routes.ts
@@ -5,6 +5,7 @@ import { HotelRegisterComponent } from './core/features/hotel/hotel-register/hot
 import { MainPageComponent } from './core/features/user/main-page/main-page.component';
 import { BookingListComponent } from './core/features/bookings/booking-list/booking-list.component';
 import { UserBookingListComponent } from './core/features/user/user-booking-list/user-booking-list.component';
+import { UserFormComponent} from './core/features/user/user-form/user-form.component';
 
 export const routes: Routes = [
   {
@@ -35,6 +36,10 @@ export const routes: Routes = [
     path: 'hotels/:id',
     component: HotelRegisterComponent,
   },
+  {
+    path: 'users/:id',
+    component: UserFormComponent,
+  },
   {
     path: '**',
     redirectTo: '',
diff --git a/angular/RestClient/src/app/core/features/user/user-form/user-form.component.css b/angular/RestClient/src/app/core/features/user/user-form/user-form.component.css
new file mode 100644
index 0000000..66cd833
--- /dev/null
+++ b/angular/RestClient/src/app/core/features/user/user-form/user-form.component.css
@@ -0,0 +1,68 @@
+.form-container {
+    width: 100%;
+    max-width: 500px;
+    margin: 0 auto;
+    padding: 20px;
+    background: #f9f9f9;
+    border: 1px solid #ddd;
+    border-radius: 8px;
+  }
+  
+  h2 {
+    text-align: center;
+    margin-bottom: 20px;
+  }
+  
+  .form-group {
+    margin-bottom: 15px;
+  }
+  
+  label {
+    display: block;
+    font-weight: bold;
+    margin-bottom: 5px;
+  }
+  
+  input {
+    width: 100%;
+    padding: 10px;
+    font-size: 16px;
+    border: 1px solid #ccc;
+    border-radius: 4px;
+    box-sizing: border-box;
+  }
+  
+  input[readonly] {
+    background-color: #f5f5f5;
+    cursor: not-allowed;
+  }
+  
+  .button-group {
+    display: flex;
+    gap: 10px;
+    justify-content: center;
+  }
+  
+  button {
+    padding: 10px 20px;
+    font-size: 16px;
+    border-radius: 4px;
+    border: none;
+    cursor: pointer;
+  }
+  
+  .btn-primary {
+    background-color: #007bff;
+    color: #fff;
+  }
+  
+  .btn-secondary {
+    background-color: #6c757d;
+    color: #fff;
+  }
+  
+  .btn-success {
+    background-color: #28a745;
+    color: #fff;
+  }
+  
\ No newline at end of file
diff --git a/angular/RestClient/src/app/core/features/user/user-form/user-form.component.html b/angular/RestClient/src/app/core/features/user/user-form/user-form.component.html
new file mode 100644
index 0000000..0a6e33f
--- /dev/null
+++ b/angular/RestClient/src/app/core/features/user/user-form/user-form.component.html
@@ -0,0 +1,79 @@
+<div class="form-container">
+    <h2>Perfil de Usuario</h2>
+    <form [formGroup]="userForm">
+      <div class="form-group">
+        <label for="name">Nombre:</label>
+        <input
+          id="name"
+          type="text"
+          class="form-control"
+          formControlName="name"
+          [readonly]="!isEditing"
+        />
+      </div>
+  
+      <div class="form-group">
+        <label for="email">Email:</label>
+        <input
+          id="email"
+          type="email"
+          class="form-control"
+          formControlName="email"
+          [readonly]="!isEditing"
+        />
+      </div>
+  
+      <div class="form-group" *ngIf="isEditing">
+        <label for="currentPassword">Contraseña actual:</label>
+        <input
+          id="currentPassword"
+          type="password"
+          class="form-control"
+          formControlName="currentPassword"
+          placeholder="Introduce tu contraseña actual"
+        />
+      </div>
+  
+      <div class="form-group" *ngIf="isEditing">
+        <label for="newPassword">Nueva contraseña:</label>
+        <input
+          id="newPassword"
+          type="password"
+          class="form-control"
+          formControlName="newPassword"
+          placeholder="Introduce tu nueva contraseña"
+        />
+      </div>
+  
+      <div class="button-group">
+        <button
+          *ngIf="!isEditing"
+          type="button"
+          class="btn btn-primary"
+          (click)="toggleEdit()"
+        >
+          Editar
+        </button>
+  
+        <button
+          *ngIf="isEditing"
+          type="button"
+          class="btn btn-secondary"
+          (click)="cancelEdit()"
+        >
+          Cancelar
+        </button>
+  
+        <button
+          *ngIf="isEditing"
+          type="submit"
+          class="btn btn-success"
+          (click)="saveChanges()"
+          [disabled]="!userForm.valid"
+        >
+          Guardar
+        </button>
+      </div>
+    </form>
+  </div>
+  
\ No newline at end of file
diff --git a/angular/RestClient/src/app/core/features/user/user-form/user-form.component.spec.ts b/angular/RestClient/src/app/core/features/user/user-form/user-form.component.spec.ts
new file mode 100644
index 0000000..292f234
--- /dev/null
+++ b/angular/RestClient/src/app/core/features/user/user-form/user-form.component.spec.ts
@@ -0,0 +1,91 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { FormsModule, ReactiveFormsModule } from '@angular/forms';
+import { HttpResponse } from '@angular/common/http';
+import { UserFormComponent } from './user-form.component';
+import { UserClientService } from '../../../../shared/user-client.service';
+import { of } from 'rxjs';
+
+describe('UserFormComponent', () => {
+  let component: UserFormComponent;
+  let fixture: ComponentFixture<UserFormComponent>;
+  let userService: UserClientService;
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      imports: [ReactiveFormsModule, FormsModule],
+      declarations: [UserFormComponent],
+      providers: [UserClientService],
+    }).compileComponents();
+
+    fixture = TestBed.createComponent(UserFormComponent);
+    component = fixture.componentInstance;
+    userService = TestBed.inject(UserClientService);
+
+    spyOn(userService, 'getCurrentUser').and.returnValue(
+      of({
+        id: 1,
+        name: 'John Doe',
+        email: 'johndoe@example.com',
+        rol: 'CONSUMER',
+        status: 'WITH_ACTIVE_BOOKINGS',
+      })
+    );
+
+    spyOn(userService, 'updateUser').and.returnValue(of(new HttpResponse({ body: 'User updated successfully' })));
+    spyOn(userService, 'updatePassword').and.returnValue(of(new HttpResponse({ body: 'Password updated successfully' })));
+
+    fixture.detectChanges();
+  });
+
+  it('should create the component', () => {
+    expect(component).toBeTruthy();
+  });
+
+  it('should load user data on initialization', () => {
+    expect(component.userForm.value).toEqual({
+      name: 'John Doe',
+      email: 'johndoe@example.com',
+      password: '',
+      confirmPassword: '',
+    });
+  });
+
+  it('should call updateUser when saving valid user data', () => {
+    component.userForm.patchValue({
+      name: 'Jane Doe',
+      email: 'janedoe@example.com',
+    });
+
+    component.saveChanges();
+
+    expect(userService.updateUser).toHaveBeenCalledWith({
+      name: 'Jane Doe',
+      email: 'janedoe@example.com',
+    });
+  });
+
+  it('should call updatePassword when password is updated and matches confirmPassword', () => {
+    component.userForm.patchValue({
+      password: 'newpassword123',
+      confirmPassword: 'newpassword123',
+    });
+
+    component.saveChanges();
+
+    expect(userService.updatePassword).toHaveBeenCalledWith(
+      '',
+      'newpassword123'
+    );
+  });
+
+  it('should not call updatePassword if password and confirmPassword do not match', () => {
+    component.userForm.patchValue({
+      password: 'newpassword123',
+      confirmPassword: 'differentpassword',
+    });
+
+    component.saveChanges();
+
+    expect(userService.updatePassword).not.toHaveBeenCalled();
+  });
+});
diff --git a/angular/RestClient/src/app/core/features/user/user-form/user-form.component.ts b/angular/RestClient/src/app/core/features/user/user-form/user-form.component.ts
new file mode 100644
index 0000000..238d811
--- /dev/null
+++ b/angular/RestClient/src/app/core/features/user/user-form/user-form.component.ts
@@ -0,0 +1,61 @@
+import { Component, OnInit } from '@angular/core';
+import { FormBuilder, FormGroup, Validators } from '@angular/forms';
+import { UserClientService } from '../../../../shared/user-client.service';
+
+@Component({
+  selector: 'app-user-form',
+  templateUrl: './user-form.component.html',
+  styleUrls: ['./user-form.component.css'],
+})
+export class UserFormComponent implements OnInit {
+  userForm!: FormGroup;
+  isEditing = false;
+
+  constructor(private fb: FormBuilder, private userService: UserClientService) {}
+
+  ngOnInit(): void {
+    this.initializeForm();
+    this.loadUserData();
+  }
+
+  private initializeForm(): void {
+    this.userForm = this.fb.group({
+      name: [{ value: '', disabled: true }, Validators.required],
+      email: [{ value: '', disabled: true }, [Validators.required, Validators.email]],
+      currentPassword: [''], // Solo habilitado en modo edición
+      newPassword: [''], // Solo habilitado en modo edición
+    });
+  }
+
+  private loadUserData(): void {
+    this.userService.getCurrentUser().subscribe((user) => {
+      this.userForm.patchValue({
+        name: user.name,
+        email: user.email,
+      });
+    });
+  }
+
+  toggleEdit(): void {
+    this.isEditing = true;
+    this.userForm.get('name')?.enable();
+    this.userForm.get('email')?.enable();
+  }
+
+  cancelEdit(): void {
+    this.isEditing = false;
+    this.loadUserData(); // Volver a cargar los datos originales
+    this.userForm.get('name')?.disable();
+    this.userForm.get('email')?.disable();
+  }
+
+  saveChanges(): void {
+    if (this.userForm.valid) {
+      const updatedData = this.userForm.value;
+      this.userService.updateUser(updatedData).subscribe(() => {
+        this.isEditing = false;
+        this.loadUserData();
+      });
+    }
+  }
+}
diff --git a/angular/RestClient/src/app/shared/user-client.service.ts b/angular/RestClient/src/app/shared/user-client.service.ts
index 2a09c6d..3e42700 100644
--- a/angular/RestClient/src/app/shared/user-client.service.ts
+++ b/angular/RestClient/src/app/shared/user-client.service.ts
@@ -8,18 +8,22 @@ import { User, UserState } from '../../types';
 })
 export class UserClientService {
   private readonly URI = environment.userAPI;
+
   constructor(private http: HttpClient) {}
 
+  // Obtener un usuario por ID
   getUser(userId: number) {
     return this.http.get<User>(`${this.URI}/${userId}`);
   }
 
+  // Obtener todos los usuarios
   getAllUsers() {
     return this.http.get<User[]>(this.URI, {
       observe: 'body',
     });
   }
 
+  // Cambiar estado de un usuario
   alterUserStatus(userId: number, status: UserState) {
     return this.http.patch(
       `${this.URI}/${userId}`,
@@ -32,4 +36,29 @@ export class UserClientService {
       }
     );
   }
+
+  // Obtener el usuario actual (autenticado)
+  getCurrentUser() {
+    return this.http.get<User>(`${this.URI}/me`);
+  }
+
+  // Actualizar los datos del usuario
+  updateUser(user: Partial<User>) {
+    return this.http.patch(`${this.URI}/me`, user, {
+      observe: 'response',
+      responseType: 'text',
+    });
+  }
+
+  // Cambiar la contraseña del usuario
+  updatePassword(currentPassword: string, newPassword: string) {
+    return this.http.patch(
+      `${this.URI}/me/password`,
+      { currentPassword, newPassword },
+      {
+        observe: 'response',
+        responseType: 'text',
+      }
+    );
+  }
 }
-- 
GitLab