project refactoring en clean archi
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
@if (project) {
|
||||
@if (project()) {
|
||||
<div class="bg-white rounded-2xl border p-6 max-w-sm">
|
||||
<div class="">
|
||||
<h3 class="text-lg font-bold text-gray-800 mb-3">{{ project.nom }}</h3>
|
||||
<p class="text-gray-800 text-sm">{{ project.description }}</p>
|
||||
<h3 class="text-lg font-bold text-gray-800 mb-3">{{ project().nom }}</h3>
|
||||
<p class="text-gray-800 text-sm">{{ project().description }}</p>
|
||||
<div class="mt-6">
|
||||
<a
|
||||
[routerLink]="[]"
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
import { Component, inject, Input, OnInit } from '@angular/core';
|
||||
import { AuthService } from '@app/core/services/authentication/auth.service';
|
||||
import { ProjectService } from '@app/core/services/project/project.service';
|
||||
import { Project } from '@app/shared/models/project';
|
||||
import { environment } from '@env/environment';
|
||||
import { RouterLink } from '@angular/router';
|
||||
import { ProjectFacade } from '@app/ui/projects/project.facade';
|
||||
|
||||
@Component({
|
||||
selector: 'app-my-profile-project-item',
|
||||
@@ -17,11 +16,10 @@ export class MyProfileProjectItemComponent implements OnInit {
|
||||
@Input({ required: true }) projectId = '';
|
||||
protected authService = inject(AuthService);
|
||||
|
||||
protected projectService = inject(ProjectService);
|
||||
|
||||
protected project: Project | undefined = undefined;
|
||||
private readonly projectFacade = new ProjectFacade();
|
||||
protected project = this.projectFacade.project;
|
||||
|
||||
ngOnInit(): void {
|
||||
this.projectService.getProjectById(this.projectId).subscribe((value) => (this.project = value));
|
||||
this.projectFacade.loadOne(this.projectId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<div class="max-w-4xl max-lg:max-w-2xl max-sm:max-w-sm mx-auto">
|
||||
<h2 class="text-2xl font-bold text-gray-800 mb-8">Mes projets</h2>
|
||||
|
||||
@if (projects) {
|
||||
@if (projects()) {
|
||||
<div class="relative flex items-center">
|
||||
<select
|
||||
[(ngModel)]="projectIdSelected"
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
<option [value]="'add'.toLowerCase()">Ajouter un nouveau projet</option>
|
||||
|
||||
@for (project of projects; track project.id) {
|
||||
@for (project of projects(); track project.id) {
|
||||
<option [value]="project.id">
|
||||
{{ project.nom }}
|
||||
</option>
|
||||
|
||||
@@ -1,24 +1,14 @@
|
||||
import { Component, inject, Input, OnInit, signal } from '@angular/core';
|
||||
import { MyProfileProjectItemComponent } from '@app/shared/components/my-profile-project-item/my-profile-project-item.component';
|
||||
import { Component, Input, OnInit, signal } from '@angular/core';
|
||||
import { PaginatorModule } from 'primeng/paginator';
|
||||
import { ReactiveFormsModule } from '@angular/forms';
|
||||
import { ProjectService } from '@app/core/services/project/project.service';
|
||||
import { AsyncPipe, JsonPipe } from '@angular/common';
|
||||
import { Project } from '@app/shared/models/project';
|
||||
import { UntilDestroy } from '@ngneat/until-destroy';
|
||||
import { MyProfileUpdateProjectFormComponent } from '@app/shared/components/my-profile-update-project-form/my-profile-update-project-form.component';
|
||||
import { ProjectFacade } from '@app/ui/projects/project.facade';
|
||||
|
||||
@Component({
|
||||
selector: 'app-my-profile-project-list',
|
||||
standalone: true,
|
||||
imports: [
|
||||
MyProfileProjectItemComponent,
|
||||
PaginatorModule,
|
||||
ReactiveFormsModule,
|
||||
AsyncPipe,
|
||||
JsonPipe,
|
||||
MyProfileUpdateProjectFormComponent,
|
||||
],
|
||||
imports: [PaginatorModule, ReactiveFormsModule, MyProfileUpdateProjectFormComponent],
|
||||
templateUrl: './my-profile-project-list.component.html',
|
||||
styleUrl: './my-profile-project-list.component.scss',
|
||||
})
|
||||
@@ -26,15 +16,14 @@ import { MyProfileUpdateProjectFormComponent } from '@app/shared/components/my-p
|
||||
export class MyProfileProjectListComponent implements OnInit {
|
||||
@Input({ required: true }) projectIds: string[] = [];
|
||||
@Input({ required: true }) userId = '';
|
||||
protected projectService = inject(ProjectService);
|
||||
|
||||
protected projectIdSelected = signal<string | null>(null);
|
||||
|
||||
protected projects: Project[] = [];
|
||||
private readonly projectFacade = new ProjectFacade();
|
||||
protected projects = this.projectFacade.projects;
|
||||
|
||||
ngOnInit(): void {
|
||||
this.projectService
|
||||
.getProjectByUserId(this.userId)
|
||||
.subscribe((value) => (this.projects = value));
|
||||
this.projectFacade.load(this.userId);
|
||||
}
|
||||
|
||||
onProjectFormSubmitted($event: string | null) {
|
||||
|
||||
@@ -2,88 +2,97 @@
|
||||
@if (projectId == 'add'.toLowerCase()) {
|
||||
<app-project-picture-form [project]="undefined" />
|
||||
} @else {
|
||||
<app-project-picture-form [project]="project" />
|
||||
<app-project-picture-form [project]="project()" />
|
||||
}
|
||||
|
||||
<h3 class="font-ubuntu w-full text-start font-bold text-xl uppercase dark:text-white my-5">
|
||||
Information du projet
|
||||
</h3>
|
||||
|
||||
<form class="mx-8" [formGroup]="projectForm" (ngSubmit)="onSubmit()">
|
||||
<label class="mb-2 text-sm text-black block dark:text-white">Nom</label>
|
||||
<div class="relative flex items-center">
|
||||
<input
|
||||
type="text"
|
||||
placeholder="nom du projet"
|
||||
formControlName="nom"
|
||||
class="pr-4 pl-14 py-3 text-sm text-black rounded bg-white border border-gray-400 w-full outline-[#333]"
|
||||
/>
|
||||
@if (loading().isLoading) {
|
||||
@switch (loading().action) {
|
||||
@case (ActionType.NONE || ActionType.CREATE || ActionType.DELETE) {}
|
||||
@default {
|
||||
<p>Chargement...</p>
|
||||
}
|
||||
}
|
||||
} @else {
|
||||
<form class="mx-8" [formGroup]="projectForm" (ngSubmit)="onSubmit()">
|
||||
<label class="mb-2 text-sm text-black block dark:text-white">Nom</label>
|
||||
<div class="relative flex items-center">
|
||||
<input
|
||||
type="text"
|
||||
placeholder="nom du projet"
|
||||
formControlName="nom"
|
||||
class="pr-4 pl-14 py-3 text-sm text-black rounded bg-white border border-gray-400 w-full outline-[#333]"
|
||||
/>
|
||||
|
||||
<div class="absolute left-4">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="22px"
|
||||
height="22px"
|
||||
fill="#bbb"
|
||||
viewBox="0 0 512 512"
|
||||
>
|
||||
<path
|
||||
d="M437.02 74.981C388.667 26.629 324.38 0 256 0S123.333 26.629 74.98 74.981C26.629 123.333 0 187.62 0 256s26.629 132.667 74.98 181.019C123.333 485.371 187.62 512 256 512s132.667-26.629 181.02-74.981C485.371 388.667 512 324.38 512 256s-26.629-132.667-74.98-181.019zM256 482c-66.869 0-127.037-29.202-168.452-75.511C113.223 338.422 178.948 290 256 290c-49.706 0-90-40.294-90-90s40.294-90 90-90 90 40.294 90 90-40.294 90-90 90c77.052 0 142.777 48.422 168.452 116.489C383.037 452.798 322.869 482 256 482z"
|
||||
data-original="#000000"
|
||||
></path>
|
||||
</svg>
|
||||
<div class="absolute left-4">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="22px"
|
||||
height="22px"
|
||||
fill="#bbb"
|
||||
viewBox="0 0 512 512"
|
||||
>
|
||||
<path
|
||||
d="M437.02 74.981C388.667 26.629 324.38 0 256 0S123.333 26.629 74.98 74.981C26.629 123.333 0 187.62 0 256s26.629 132.667 74.98 181.019C123.333 485.371 187.62 512 256 512s132.667-26.629 181.02-74.981C485.371 388.667 512 324.38 512 256s-26.629-132.667-74.98-181.019zM256 482c-66.869 0-127.037-29.202-168.452-75.511C113.223 338.422 178.948 290 256 290c-49.706 0-90-40.294-90-90s40.294-90 90-90 90 40.294 90 90-40.294 90-90 90c77.052 0 142.777 48.422 168.452 116.489C383.037 452.798 322.869 482 256 482z"
|
||||
data-original="#000000"
|
||||
></path>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<label class="mb-2 text-sm text-black block dark:text-white">Lien</label>
|
||||
<div class="relative flex items-center">
|
||||
<input
|
||||
type="text"
|
||||
placeholder="lien vers votre projet ex : http://monprojet"
|
||||
formControlName="lien"
|
||||
class="pr-4 pl-14 py-3 text-sm text-black rounded bg-white border border-gray-400 w-full outline-[#333]"
|
||||
/>
|
||||
<label class="mb-2 text-sm text-black block dark:text-white">Lien</label>
|
||||
<div class="relative flex items-center">
|
||||
<input
|
||||
type="text"
|
||||
placeholder="lien vers votre projet ex : http://monprojet"
|
||||
formControlName="lien"
|
||||
class="pr-4 pl-14 py-3 text-sm text-black rounded bg-white border border-gray-400 w-full outline-[#333]"
|
||||
/>
|
||||
|
||||
<div class="absolute left-4">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="22px"
|
||||
height="22px"
|
||||
fill="#bbb"
|
||||
viewBox="0 0 512 512"
|
||||
>
|
||||
<path
|
||||
d="M437.02 74.981C388.667 26.629 324.38 0 256 0S123.333 26.629 74.98 74.981C26.629 123.333 0 187.62 0 256s26.629 132.667 74.98 181.019C123.333 485.371 187.62 512 256 512s132.667-26.629 181.02-74.981C485.371 388.667 512 324.38 512 256s-26.629-132.667-74.98-181.019zM256 482c-66.869 0-127.037-29.202-168.452-75.511C113.223 338.422 178.948 290 256 290c-49.706 0-90-40.294-90-90s40.294-90 90-90 90 40.294 90 90-40.294 90-90 90c77.052 0 142.777 48.422 168.452 116.489C383.037 452.798 322.869 482 256 482z"
|
||||
data-original="#000000"
|
||||
></path>
|
||||
</svg>
|
||||
<div class="absolute left-4">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="22px"
|
||||
height="22px"
|
||||
fill="#bbb"
|
||||
viewBox="0 0 512 512"
|
||||
>
|
||||
<path
|
||||
d="M437.02 74.981C388.667 26.629 324.38 0 256 0S123.333 26.629 74.98 74.981C26.629 123.333 0 187.62 0 256s26.629 132.667 74.98 181.019C123.333 485.371 187.62 512 256 512s132.667-26.629 181.02-74.981C485.371 388.667 512 324.38 512 256s-26.629-132.667-74.98-181.019zM256 482c-66.869 0-127.037-29.202-168.452-75.511C113.223 338.422 178.948 290 256 290c-49.706 0-90-40.294-90-90s40.294-90 90-90 90 40.294 90 90-40.294 90-90 90c77.052 0 142.777 48.422 168.452 116.489C383.037 452.798 322.869 482 256 482z"
|
||||
data-original="#000000"
|
||||
></path>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<label class="mb-2 text-sm text-black block dark:text-white">description</label>
|
||||
<div class="relative flex items-center">
|
||||
<textarea
|
||||
placeholder="Type Message"
|
||||
formControlName="description"
|
||||
class="p-4 bg-white w-full block text-sm border border-gray-300 outline-[#007bff] rounded"
|
||||
rows="4"
|
||||
></textarea>
|
||||
</div>
|
||||
<label class="mb-2 text-sm text-black block dark:text-white">description</label>
|
||||
<div class="relative flex items-center">
|
||||
<textarea
|
||||
placeholder="Type Message"
|
||||
formControlName="description"
|
||||
class="p-4 bg-white w-full block text-sm border border-gray-300 outline-[#007bff] rounded"
|
||||
rows="4"
|
||||
></textarea>
|
||||
</div>
|
||||
|
||||
<button
|
||||
type="submit"
|
||||
[ngClass]="{ 'bg-purple-600': projectForm.valid }"
|
||||
class="!mt-8 px-6 py-2 w-full bg-[#333] hover:bg-[#444] text-sm text-white mx-auto block"
|
||||
>
|
||||
Sauvegarder
|
||||
</button>
|
||||
<button
|
||||
type="submit"
|
||||
[ngClass]="{ 'bg-purple-600': projectForm.valid }"
|
||||
class="!mt-8 px-6 py-2 w-full bg-[#333] hover:bg-[#444] text-sm text-white mx-auto block"
|
||||
>
|
||||
Sauvegarder
|
||||
</button>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
(click)="formIsUpdated.emit(null)"
|
||||
class="!mt-8 px-6 py-2 w-full bg-[#333] hover:bg-[#444] text-sm text-white mx-auto block"
|
||||
>
|
||||
Annuler
|
||||
</button>
|
||||
</form>
|
||||
<button
|
||||
type="button"
|
||||
(click)="formIsUpdated.emit(null)"
|
||||
class="!mt-8 px-6 py-2 w-full bg-[#333] hover:bg-[#444] text-sm text-white mx-auto block"
|
||||
>
|
||||
Annuler
|
||||
</button>
|
||||
</form>
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { MyProfileUpdateProjectFormComponent } from './my-profile-update-project-form.component';
|
||||
import { AuthService } from '@app/core/services/authentication/auth.service';
|
||||
import { ToastrService } from 'ngx-toastr';
|
||||
import { ProjectService } from '@app/core/services/project/project.service';
|
||||
import { provideRouter } from '@angular/router';
|
||||
import { signal } from '@angular/core';
|
||||
import { Auth } from '@app/shared/models/auth';
|
||||
@@ -12,7 +11,6 @@ describe('MyProfileUpdateProjectFormComponent', () => {
|
||||
let component: MyProfileUpdateProjectFormComponent;
|
||||
let fixture: ComponentFixture<MyProfileUpdateProjectFormComponent>;
|
||||
|
||||
let mockProjectService: Partial<ProjectService>;
|
||||
let mockAuthService: Partial<AuthService>;
|
||||
let mockToastrService: Partial<ToastrService>;
|
||||
|
||||
@@ -27,15 +25,12 @@ describe('MyProfileUpdateProjectFormComponent', () => {
|
||||
user: signal<Auth | undefined>(undefined),
|
||||
};
|
||||
|
||||
mockProjectService = {};
|
||||
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [MyProfileUpdateProjectFormComponent],
|
||||
providers: [
|
||||
provideRouter([]),
|
||||
{ provide: AuthService, useValue: mockAuthService },
|
||||
{ provide: ToastrService, useValue: mockToastrService },
|
||||
{ provide: ProjectService, useValue: mockProjectService },
|
||||
],
|
||||
}).compileComponents();
|
||||
|
||||
|
||||
@@ -1,13 +1,22 @@
|
||||
import { Component, inject, Input, OnChanges, OnInit, output, SimpleChanges } from '@angular/core';
|
||||
import {
|
||||
Component,
|
||||
effect,
|
||||
inject,
|
||||
Input,
|
||||
OnChanges,
|
||||
OnInit,
|
||||
output,
|
||||
SimpleChanges,
|
||||
} from '@angular/core';
|
||||
import { FormBuilder, FormControl, ReactiveFormsModule, Validators } from '@angular/forms';
|
||||
import { ProjectService } from '@app/core/services/project/project.service';
|
||||
import { Project } from '@app/shared/models/project';
|
||||
import { NgClass } from '@angular/common';
|
||||
import { PaginatorModule } from 'primeng/paginator';
|
||||
import { ProjectPictureFormComponent } from '@app/shared/components/project-picture-form/project-picture-form.component';
|
||||
import { ToastrService } from 'ngx-toastr';
|
||||
import { AuthService } from '@app/core/services/authentication/auth.service';
|
||||
import { ProjectDto } from '@app/shared/models/project-dto';
|
||||
import { ProjectFacade } from '@app/ui/projects/project.facade';
|
||||
import { CreateProjectDto } from '@app/domain/projects/dto/create-project.dto';
|
||||
import { ActionType } from '@app/domain/action-type.util';
|
||||
|
||||
@Component({
|
||||
selector: 'app-my-profile-update-project-form',
|
||||
@@ -19,11 +28,15 @@ import { ProjectDto } from '@app/shared/models/project-dto';
|
||||
export class MyProfileUpdateProjectFormComponent implements OnInit, OnChanges {
|
||||
@Input({ required: true }) projectId: string | null = null;
|
||||
|
||||
protected project: Project | undefined = undefined;
|
||||
private readonly toastrService = inject(ToastrService);
|
||||
private readonly authService = inject(AuthService);
|
||||
|
||||
protected readonly projectService = inject(ProjectService);
|
||||
private readonly projectFacade = new ProjectFacade();
|
||||
protected readonly ActionType = ActionType;
|
||||
protected readonly project = this.projectFacade.project;
|
||||
protected readonly loading = this.projectFacade.loading;
|
||||
protected readonly error = this.projectFacade.error;
|
||||
|
||||
private readonly formBuilder = inject(FormBuilder);
|
||||
|
||||
protected projectForm = this.formBuilder.group({
|
||||
@@ -34,6 +47,32 @@ export class MyProfileUpdateProjectFormComponent implements OnInit, OnChanges {
|
||||
|
||||
formIsUpdated = output<string | null>();
|
||||
|
||||
constructor() {
|
||||
let message = '';
|
||||
effect(() => {
|
||||
if (!this.loading().isLoading) {
|
||||
switch (this.loading().action) {
|
||||
case ActionType.CREATE:
|
||||
message = `Le projet ${this.projectForm.getRawValue().nom} a bien été créer !`;
|
||||
this.customToast(ActionType.CREATE, message);
|
||||
break;
|
||||
case ActionType.UPDATE:
|
||||
message = `Les informations du projet ${this.projectForm.getRawValue().nom} ont bien été modifier !`;
|
||||
this.customToast(ActionType.UPDATE, message);
|
||||
break;
|
||||
}
|
||||
|
||||
if (this.project() !== undefined) {
|
||||
this.projectForm.setValue({
|
||||
nom: this.project()!.nom,
|
||||
description: this.project()!.description,
|
||||
lien: this.project()!.lien,
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
if (this.projectId == 'add'.toLowerCase()) {
|
||||
this.projectForm.setValue({
|
||||
@@ -44,14 +83,7 @@ export class MyProfileUpdateProjectFormComponent implements OnInit, OnChanges {
|
||||
}
|
||||
|
||||
if (this.projectId != null && this.projectId != 'add'.toLowerCase()) {
|
||||
this.projectService.getProjectById(this.projectId).subscribe((value) => {
|
||||
this.project = value;
|
||||
this.projectForm.setValue({
|
||||
nom: value.nom,
|
||||
description: value.description,
|
||||
lien: value.lien,
|
||||
});
|
||||
});
|
||||
this.projectFacade.loadOne(this.projectId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,39 +94,15 @@ export class MyProfileUpdateProjectFormComponent implements OnInit, OnChanges {
|
||||
|
||||
if (this.projectId != null && this.projectId != 'add'.toLowerCase()) {
|
||||
// Update
|
||||
|
||||
this.projectService
|
||||
.updateProject(this.project!.id, this.projectForm.getRawValue())
|
||||
.subscribe((value) => {
|
||||
this.formIsUpdated.emit(value.id);
|
||||
|
||||
this.toastrService.success(
|
||||
`Les informations du projet ${value.nom} ont bien été modifier !`,
|
||||
`Mise à jour`,
|
||||
{
|
||||
closeButton: true,
|
||||
progressAnimation: 'decreasing',
|
||||
progressBar: true,
|
||||
}
|
||||
);
|
||||
});
|
||||
this.projectFacade.update(this.project()!.id, this.projectForm.getRawValue());
|
||||
} else {
|
||||
// Create
|
||||
|
||||
const projectDto: ProjectDto = {
|
||||
const projectDto: CreateProjectDto = {
|
||||
...this.projectForm.getRawValue(),
|
||||
utilisateur: this.authService.user()!.record!.id,
|
||||
} as ProjectDto;
|
||||
} as CreateProjectDto;
|
||||
|
||||
this.projectService.createProject(projectDto).subscribe((value) => {
|
||||
this.formIsUpdated.emit(value.id);
|
||||
|
||||
this.toastrService.success(`Le projet ${value.nom} a bien été créer !`, `Nouveau projet`, {
|
||||
closeButton: true,
|
||||
progressAnimation: 'decreasing',
|
||||
progressBar: true,
|
||||
});
|
||||
});
|
||||
this.projectFacade.create(projectDto);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,4 +110,30 @@ export class MyProfileUpdateProjectFormComponent implements OnInit, OnChanges {
|
||||
this.projectId = changes['projectId'].currentValue;
|
||||
this.ngOnInit();
|
||||
}
|
||||
|
||||
private customToast(action: ActionType, message: string): void {
|
||||
if (this.error().hasError) {
|
||||
this.toastrService.error(
|
||||
`Une erreur s'est produite, veuillez réessayer ulterieurement`,
|
||||
`Erreur`,
|
||||
{
|
||||
closeButton: true,
|
||||
progressAnimation: 'decreasing',
|
||||
progressBar: true,
|
||||
}
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
this.formIsUpdated.emit(this.project()!.id);
|
||||
this.toastrService.success(
|
||||
`${message}`,
|
||||
`${action === ActionType.UPDATE ? 'Mise à jour' : 'Nouveau projet'}`,
|
||||
{
|
||||
closeButton: true,
|
||||
progressAnimation: 'decreasing',
|
||||
progressBar: true,
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +1,16 @@
|
||||
import { Component, Input } from '@angular/core';
|
||||
import { Project } from '@app/shared/models/project';
|
||||
import { JsonPipe } from '@angular/common';
|
||||
import { environment } from '@env/environment';
|
||||
import { RouterLink } from '@angular/router';
|
||||
import { ProjectViewModel } from '@app/ui/projects/project.presenter.model';
|
||||
|
||||
@Component({
|
||||
selector: 'app-project-item',
|
||||
standalone: true,
|
||||
imports: [JsonPipe, RouterLink],
|
||||
imports: [],
|
||||
templateUrl: './project-item.component.html',
|
||||
styleUrl: './project-item.component.scss',
|
||||
})
|
||||
export class ProjectItemComponent {
|
||||
protected readonly environment = environment;
|
||||
|
||||
@Input({ required: true }) project: Project | undefined = undefined;
|
||||
@Input({ required: true }) project: ProjectViewModel | undefined = undefined;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<div class="max-w-4xl max-lg:max-w-2xl max-sm:max-w-sm mx-auto">
|
||||
<h2 class="text-2xl font-bold text-gray-800 mb-8">Explorer les projets</h2>
|
||||
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4">
|
||||
@for (project of projects; track project) {
|
||||
@for (project of projects(); track project) {
|
||||
<app-project-item [project]="project" />
|
||||
} @empty {
|
||||
<p>Aucun projet</p>
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
import { Component, inject, Input, OnInit } from '@angular/core';
|
||||
import { Component, Input, OnInit } from '@angular/core';
|
||||
import { UntilDestroy } from '@ngneat/until-destroy';
|
||||
import { ProjectItemComponent } from '@app/shared/components/project-item/project-item.component';
|
||||
import { JsonPipe } from '@angular/common';
|
||||
import { ProjectService } from '@app/core/services/project/project.service';
|
||||
import { Project } from '@app/shared/models/project';
|
||||
import { ProjectFacade } from '@app/ui/projects/project.facade';
|
||||
|
||||
@Component({
|
||||
selector: 'app-project-list',
|
||||
standalone: true,
|
||||
imports: [ProjectItemComponent, JsonPipe],
|
||||
imports: [ProjectItemComponent],
|
||||
templateUrl: './project-list.component.html',
|
||||
styleUrl: './project-list.component.scss',
|
||||
})
|
||||
@@ -16,13 +14,11 @@ import { Project } from '@app/shared/models/project';
|
||||
export class ProjectListComponent implements OnInit {
|
||||
@Input({ required: true }) userProjectId = '';
|
||||
|
||||
protected readonly projectService = inject(ProjectService);
|
||||
private readonly projectFacade = new ProjectFacade();
|
||||
|
||||
protected projects: Project[] = [];
|
||||
protected projects = this.projectFacade.projects;
|
||||
|
||||
ngOnInit(): void {
|
||||
this.projectService
|
||||
.getProjectByUserId(this.userProjectId)
|
||||
.subscribe((value) => (this.projects = value));
|
||||
this.projectFacade.load(this.userProjectId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { ProjectPictureFormComponent } from './project-picture-form.component';
|
||||
import { provideRouter } from '@angular/router';
|
||||
import { ProjectService } from '@app/core/services/project/project.service';
|
||||
import { ToastrService } from 'ngx-toastr';
|
||||
import { AuthService } from '@app/core/services/authentication/auth.service';
|
||||
|
||||
@@ -10,16 +9,10 @@ describe('ProjectPictureFormComponent', () => {
|
||||
let component: ProjectPictureFormComponent;
|
||||
let fixture: ComponentFixture<ProjectPictureFormComponent>;
|
||||
|
||||
let mockProjectService: Partial<ProjectService>;
|
||||
let mockToastrService: Partial<ToastrService>;
|
||||
let mockAuthService: Partial<AuthService>;
|
||||
|
||||
beforeEach(async () => {
|
||||
mockProjectService = {
|
||||
updateProject: jest.fn().mockReturnValue({
|
||||
subscribe: jest.fn(),
|
||||
}),
|
||||
};
|
||||
mockToastrService = {
|
||||
success: jest.fn(),
|
||||
error: jest.fn(),
|
||||
@@ -33,7 +26,6 @@ describe('ProjectPictureFormComponent', () => {
|
||||
imports: [ProjectPictureFormComponent],
|
||||
providers: [
|
||||
provideRouter([]),
|
||||
{ provide: ProjectService, useValue: mockProjectService },
|
||||
{ provide: ToastrService, useValue: mockToastrService },
|
||||
{ provide: AuthService, useValue: mockAuthService },
|
||||
],
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import { Component, inject, Input, output } from '@angular/core';
|
||||
import { Component, effect, inject, Input, output } from '@angular/core';
|
||||
import { AuthService } from '@app/core/services/authentication/auth.service';
|
||||
import { Project } from '@app/shared/models/project';
|
||||
import { ProjectService } from '@app/core/services/project/project.service';
|
||||
import { NgClass } from '@angular/common';
|
||||
import { environment } from '@env/environment';
|
||||
import { ToastrService } from 'ngx-toastr';
|
||||
import { ProjectViewModel } from '@app/ui/projects/project.presenter.model';
|
||||
import { ProjectFacade } from '@app/ui/projects/project.facade';
|
||||
import { ActionType } from '@app/domain/action-type.util';
|
||||
|
||||
@Component({
|
||||
selector: 'app-project-picture-form',
|
||||
@@ -14,37 +15,50 @@ import { ToastrService } from 'ngx-toastr';
|
||||
styleUrl: './project-picture-form.component.scss',
|
||||
})
|
||||
export class ProjectPictureFormComponent {
|
||||
@Input({ required: true }) project: Project | undefined = undefined;
|
||||
@Input({ required: true }) project: ProjectViewModel | undefined = undefined;
|
||||
|
||||
onFormSubmitted = output<any>();
|
||||
private readonly projectService = inject(ProjectService);
|
||||
private readonly toastrService = inject(ToastrService);
|
||||
|
||||
private readonly projectFacade = new ProjectFacade();
|
||||
protected readonly loading = this.projectFacade.loading;
|
||||
protected readonly error = this.projectFacade.error;
|
||||
|
||||
private readonly authService = inject(AuthService);
|
||||
|
||||
file: File | null = null; // Variable to store file
|
||||
imagePreviewUrl: string | null = null; // URL for image preview
|
||||
|
||||
constructor() {
|
||||
effect(() => {
|
||||
if (!this.loading().isLoading) {
|
||||
switch (this.loading().action) {
|
||||
case ActionType.UPDATE:
|
||||
this.authService.updateUser();
|
||||
|
||||
this.toastrService.success(
|
||||
`L'aperçu du projet ${this.project!.nom} ont bien été modifier !`,
|
||||
`Mise à jour`,
|
||||
{
|
||||
closeButton: true,
|
||||
progressAnimation: 'decreasing',
|
||||
progressBar: true,
|
||||
}
|
||||
);
|
||||
|
||||
this.onFormSubmitted.emit('');
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
onSubmit() {
|
||||
if (this.file != null) {
|
||||
const formData = new FormData();
|
||||
formData.append('fichier', this.file); // "fichier" est le nom du champ dans PocketBase
|
||||
|
||||
this.projectService.updateProject(this.project?.id!, formData).subscribe((value) => {
|
||||
this.authService.updateUser();
|
||||
|
||||
this.toastrService.success(
|
||||
`L'aperçu du projet ${value.nom} ont bien été modifier !`,
|
||||
`Mise à jour`,
|
||||
{
|
||||
closeButton: true,
|
||||
progressAnimation: 'decreasing',
|
||||
progressBar: true,
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
this.onFormSubmitted.emit('');
|
||||
this.projectFacade.update(this.project?.id!, formData);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user