profiles => format clean archi
This commit is contained in:
@@ -1,51 +1,82 @@
|
||||
<div class="w-full text-center">
|
||||
<h3 class="font-ubuntu w-full text-start font-bold text-xl uppercase dark:text-white mb-4">Aperçu du projet </h3>
|
||||
|
||||
<div class="w-40 h-40 rounded-full inline-flex items-center justify-center bg-gray-200 text-gray-400">
|
||||
@if (imagePreviewUrl != null && project != undefined) {
|
||||
<img alt="nouveau-projet" class="object-cover object-center h-full w-full"
|
||||
[src]="imagePreviewUrl" loading="lazy">
|
||||
} @else if (project != undefined) {
|
||||
|
||||
@if (project.fichier) {
|
||||
<img alt="{{project!.nom}}" class="object-cover object-center h-full w-full "
|
||||
src="{{environment.baseUrl}}/api/files/projets/{{project.id}}/{{project.fichier}}" loading="lazy">
|
||||
} @else {
|
||||
<img alt="nouveau-projet" class="object-cover object-center h-full w-full "
|
||||
src="https://api.dicebear.com/9.x/shapes/svg?seed={{project.nom}}" loading="lazy">
|
||||
}
|
||||
}
|
||||
|
||||
@if (project == undefined) {
|
||||
<img alt="nouveau-projet" class="object-cover object-center h-full w-full "
|
||||
src="https://api.dicebear.com/9.x/shapes/svg?seed=nouveau-projet" loading="lazy">
|
||||
}
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<label for="uploadFile1"
|
||||
class="flex bg-gray-800 hover:bg-gray-700 text-white text-base px-5 py-3 outline-none rounded w-max cursor-pointer mx-auto font-[sans-serif]">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="w-4 h-4 mr-2 fill-white inline" viewBox="0 0 32 32">
|
||||
<path
|
||||
d="M23.75 11.044a7.99 7.99 0 0 0-15.5-.009A8 8 0 0 0 9 27h3a1 1 0 0 0 0-2H9a6 6 0 0 1-.035-12 1.038 1.038 0 0 0 1.1-.854 5.991 5.991 0 0 1 11.862 0A1.08 1.08 0 0 0 23 13a6 6 0 0 1 0 12h-3a1 1 0 0 0 0 2h3a8 8 0 0 0 .75-15.956z"
|
||||
data-original="#000000"/>
|
||||
<path
|
||||
d="M20.293 19.707a1 1 0 0 0 1.414-1.414l-5-5a1 1 0 0 0-1.414 0l-5 5a1 1 0 0 0 1.414 1.414L15 16.414V29a1 1 0 0 0 2 0V16.414z"
|
||||
data-original="#000000"/>
|
||||
</svg>
|
||||
<small class="text-xs">Selectionner une image</small>
|
||||
<input type="file" id='uploadFile1' class="hidden"
|
||||
accept="image/*"
|
||||
(change)="onPictureChange($event)"/>
|
||||
</label>
|
||||
|
||||
@if (file != null || imagePreviewUrl != null) {
|
||||
<button type="button" [ngClass]="{'bg-purple-600':file!=null || imagePreviewUrl != null}"
|
||||
class="!mt-2 px-6 py-2 w-full bg-[#333] hover:bg-[#444] text-sm text-white mx-auto block"
|
||||
(click)="onSubmit()">Mettre à jour ma photo de projet
|
||||
</button>
|
||||
}
|
||||
|
||||
<div class="w-full text-center">
|
||||
<h3 class="font-ubuntu w-full text-start font-bold text-xl uppercase dark:text-white mb-4">
|
||||
Aperçu du projet
|
||||
</h3>
|
||||
|
||||
<div
|
||||
class="w-40 h-40 rounded-full inline-flex items-center justify-center bg-gray-200 text-gray-400"
|
||||
>
|
||||
@if (imagePreviewUrl != null && project != undefined) {
|
||||
<img
|
||||
alt="nouveau-projet"
|
||||
class="object-cover object-center h-full w-full"
|
||||
[src]="imagePreviewUrl"
|
||||
loading="lazy"
|
||||
/>
|
||||
} @else if (project != undefined) {
|
||||
@if (project.fichier) {
|
||||
<img
|
||||
alt="{{ project!.nom }}"
|
||||
class="object-cover object-center h-full w-full"
|
||||
src="{{ environment.baseUrl }}/api/files/projets/{{ project.id }}/{{ project.fichier }}"
|
||||
loading="lazy"
|
||||
/>
|
||||
} @else {
|
||||
<img
|
||||
alt="nouveau-projet"
|
||||
class="object-cover object-center h-full w-full"
|
||||
src="https://api.dicebear.com/9.x/shapes/svg?seed={{ project.nom }}"
|
||||
loading="lazy"
|
||||
/>
|
||||
}
|
||||
}
|
||||
|
||||
@if (project == undefined) {
|
||||
<img
|
||||
alt="nouveau-projet"
|
||||
class="object-cover object-center h-full w-full"
|
||||
src="https://api.dicebear.com/9.x/shapes/svg?seed=nouveau-projet"
|
||||
loading="lazy"
|
||||
/>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<label
|
||||
for="uploadFile1"
|
||||
class="flex bg-gray-800 hover:bg-gray-700 text-white text-base px-5 py-3 outline-none rounded w-max cursor-pointer mx-auto font-[sans-serif]"
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="w-4 h-4 mr-2 fill-white inline"
|
||||
viewBox="0 0 32 32"
|
||||
>
|
||||
<path
|
||||
d="M23.75 11.044a7.99 7.99 0 0 0-15.5-.009A8 8 0 0 0 9 27h3a1 1 0 0 0 0-2H9a6 6 0 0 1-.035-12 1.038 1.038 0 0 0 1.1-.854 5.991 5.991 0 0 1 11.862 0A1.08 1.08 0 0 0 23 13a6 6 0 0 1 0 12h-3a1 1 0 0 0 0 2h3a8 8 0 0 0 .75-15.956z"
|
||||
data-original="#000000"
|
||||
/>
|
||||
<path
|
||||
d="M20.293 19.707a1 1 0 0 0 1.414-1.414l-5-5a1 1 0 0 0-1.414 0l-5 5a1 1 0 0 0 1.414 1.414L15 16.414V29a1 1 0 0 0 2 0V16.414z"
|
||||
data-original="#000000"
|
||||
/>
|
||||
</svg>
|
||||
<small class="text-xs">Selectionner une image</small>
|
||||
<input
|
||||
type="file"
|
||||
id="uploadFile1"
|
||||
class="hidden"
|
||||
accept="image/*"
|
||||
(change)="onPictureChange($event)"
|
||||
/>
|
||||
</label>
|
||||
|
||||
@if (file != null || imagePreviewUrl != null) {
|
||||
<button
|
||||
type="button"
|
||||
[ngClass]="{ 'bg-purple-600': file != null || imagePreviewUrl != null }"
|
||||
class="!mt-2 px-6 py-2 w-full bg-[#333] hover:bg-[#444] text-sm text-white mx-auto block"
|
||||
(click)="onSubmit()"
|
||||
>
|
||||
Mettre à jour ma photo de projet
|
||||
</button>
|
||||
}
|
||||
|
||||
@@ -1,51 +1,50 @@
|
||||
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";
|
||||
|
||||
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(),
|
||||
warning: jest.fn(),
|
||||
}
|
||||
mockAuthService = {
|
||||
updateUser: jest.fn()
|
||||
};
|
||||
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [ProjectPictureFormComponent],
|
||||
providers: [
|
||||
provideRouter([]),
|
||||
{ provide: ProjectService, useValue: mockProjectService },
|
||||
{ provide: ToastrService, useValue: mockToastrService },
|
||||
{ provide: AuthService, useValue: mockAuthService }
|
||||
]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(ProjectPictureFormComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
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';
|
||||
|
||||
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(),
|
||||
warning: jest.fn(),
|
||||
};
|
||||
mockAuthService = {
|
||||
updateUser: jest.fn(),
|
||||
};
|
||||
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [ProjectPictureFormComponent],
|
||||
providers: [
|
||||
provideRouter([]),
|
||||
{ provide: ProjectService, useValue: mockProjectService },
|
||||
{ provide: ToastrService, useValue: mockToastrService },
|
||||
{ provide: AuthService, useValue: mockAuthService },
|
||||
],
|
||||
}).compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(ProjectPictureFormComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,74 +1,68 @@
|
||||
import {Component, 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";
|
||||
|
||||
@Component({
|
||||
selector: 'app-project-picture-form',
|
||||
standalone: true,
|
||||
imports: [
|
||||
NgClass
|
||||
],
|
||||
templateUrl: './project-picture-form.component.html',
|
||||
styleUrl: './project-picture-form.component.scss'
|
||||
})
|
||||
export class ProjectPictureFormComponent {
|
||||
@Input({required: true}) project: Project | undefined = undefined;
|
||||
|
||||
onFormSubmitted = output<any>();
|
||||
private readonly projectService = inject(ProjectService);
|
||||
private readonly toastrService = inject(ToastrService);
|
||||
|
||||
private readonly authService = inject(AuthService);
|
||||
|
||||
file: File | null = null; // Variable to store file
|
||||
imagePreviewUrl: string | null = null; // URL for image preview
|
||||
|
||||
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("");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
onPictureChange($event: Event) {
|
||||
const target: HTMLInputElement = $event.target as HTMLInputElement;
|
||||
if (target?.files?.[0]) {
|
||||
this.file = target.files[0];
|
||||
this.readFile(this.file);
|
||||
}
|
||||
}
|
||||
|
||||
private readFile(file: File) {
|
||||
const reader = new FileReader();
|
||||
reader.onload = (e) => {
|
||||
this.imagePreviewUrl = e.target?.result as string;
|
||||
};
|
||||
reader.readAsDataURL(file);
|
||||
}
|
||||
|
||||
protected readonly environment = environment;
|
||||
}
|
||||
import { Component, 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';
|
||||
|
||||
@Component({
|
||||
selector: 'app-project-picture-form',
|
||||
standalone: true,
|
||||
imports: [NgClass],
|
||||
templateUrl: './project-picture-form.component.html',
|
||||
styleUrl: './project-picture-form.component.scss',
|
||||
})
|
||||
export class ProjectPictureFormComponent {
|
||||
@Input({ required: true }) project: Project | undefined = undefined;
|
||||
|
||||
onFormSubmitted = output<any>();
|
||||
private readonly projectService = inject(ProjectService);
|
||||
private readonly toastrService = inject(ToastrService);
|
||||
|
||||
private readonly authService = inject(AuthService);
|
||||
|
||||
file: File | null = null; // Variable to store file
|
||||
imagePreviewUrl: string | null = null; // URL for image preview
|
||||
|
||||
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('');
|
||||
}
|
||||
}
|
||||
|
||||
onPictureChange($event: Event) {
|
||||
const target: HTMLInputElement = $event.target as HTMLInputElement;
|
||||
if (target?.files?.[0]) {
|
||||
this.file = target.files[0];
|
||||
this.readFile(this.file);
|
||||
}
|
||||
}
|
||||
|
||||
private readFile(file: File) {
|
||||
const reader = new FileReader();
|
||||
reader.onload = (e) => {
|
||||
this.imagePreviewUrl = e.target?.result as string;
|
||||
};
|
||||
reader.readAsDataURL(file);
|
||||
}
|
||||
|
||||
protected readonly environment = environment;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user