refacto les card items et list
This commit is contained in:
@@ -6,7 +6,7 @@ import { ProfileRepository } from '@app/domain/profiles/profile.repository';
|
|||||||
import { PROFILE_REPOSITORY_TOKEN } from '@app/infrastructure/profiles/profile-repository.token';
|
import { PROFILE_REPOSITORY_TOKEN } from '@app/infrastructure/profiles/profile-repository.token';
|
||||||
import { of } from 'rxjs';
|
import { of } from 'rxjs';
|
||||||
import { Profile } from '@app/domain/profiles/profile.model';
|
import { Profile } from '@app/domain/profiles/profile.model';
|
||||||
import {ToastrService} from "ngx-toastr";
|
import { ToastrService } from 'ngx-toastr';
|
||||||
|
|
||||||
describe('MyProfileComponent', () => {
|
describe('MyProfileComponent', () => {
|
||||||
let component: MyProfileComponent;
|
let component: MyProfileComponent;
|
||||||
|
|||||||
@@ -236,19 +236,29 @@
|
|||||||
<div
|
<div
|
||||||
class="bg-white dark:bg-gray-800 rounded-xl shadow-lg p-6 md:p-8 hover:shadow-xl transition-shadow duration-300"
|
class="bg-white dark:bg-gray-800 rounded-xl shadow-lg p-6 md:p-8 hover:shadow-xl transition-shadow duration-300"
|
||||||
>
|
>
|
||||||
<h2
|
<!-- Header -->
|
||||||
class="text-2xl font-bold text-gray-900 dark:text-white mb-6 flex items-center gap-2"
|
<div class="flex items-center gap-3 pb-6 mb-8 border-b-2 border-indigo-500">
|
||||||
|
<div
|
||||||
|
class="w-12 h-12 bg-indigo-100 dark:bg-indigo-900 rounded-lg flex items-center justify-center"
|
||||||
>
|
>
|
||||||
<svg
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
class="h-6 w-6 text-indigo-500"
|
class="w-7 h-7 text-indigo-600 dark:text-indigo-400"
|
||||||
viewBox="0 0 20 20"
|
viewBox="0 0 20 20"
|
||||||
fill="currentColor"
|
fill="currentColor"
|
||||||
>
|
>
|
||||||
<path d="M2 6a2 2 0 012-2h5l2 2h5a2 2 0 012 2v6a2 2 0 01-2 2H4a2 2 0 01-2-2V6z" />
|
<path d="M2 6a2 2 0 012-2h5l2 2h5a2 2 0 012 2v6a2 2 0 01-2 2H4a2 2 0 01-2-2V6z" />
|
||||||
</svg>
|
</svg>
|
||||||
Projets
|
</div>
|
||||||
|
<div class="flex-1">
|
||||||
|
<h2 class="text-2xl font-bold text-gray-900 dark:text-white">
|
||||||
|
Explorer les projets
|
||||||
</h2>
|
</h2>
|
||||||
|
<p class="text-sm text-gray-600 dark:text-gray-400 mt-1">
|
||||||
|
Découvrez les réalisations de la communauté
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<app-project-list [userProjectId]="profile().utilisateur" />
|
<app-project-list [userProjectId]="profile().utilisateur" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,16 +1,42 @@
|
|||||||
<div class="min-h-screen py-4 font-sans">
|
<div class="w-full space-y-6">
|
||||||
<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">
|
<!-- Sélecteur de projet -->
|
||||||
<select
|
<div
|
||||||
[(ngModel)]="projectIdSelected"
|
class="bg-white dark:bg-gray-800 rounded-xl shadow-lg p-6 animate-fade-in animation-delay-100"
|
||||||
class="pr-4 pl-14 py-3 text-sm text-black rounded bg-white border border-gray-400 w-full outline-[#333]"
|
|
||||||
>
|
>
|
||||||
<option [value]="null" disabled>Selectionner le projet à modifier</option>
|
<div class="space-y-3">
|
||||||
|
<label
|
||||||
|
for="project-select"
|
||||||
|
class="block text-sm font-medium text-gray-700 dark:text-gray-300"
|
||||||
|
>
|
||||||
|
Sélectionnez un projet à modifier
|
||||||
|
</label>
|
||||||
|
|
||||||
<option [value]="'add'.toLowerCase()">Ajouter un nouveau projet</option>
|
<div class="relative">
|
||||||
|
<!-- Icône à gauche -->
|
||||||
|
<div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
class="h-5 w-5 text-gray-400"
|
||||||
|
viewBox="0 0 20 20"
|
||||||
|
fill="currentColor"
|
||||||
|
>
|
||||||
|
<path d="M2 6a2 2 0 012-2h5l2 2h5a2 2 0 012 2v6a2 2 0 01-2 2H4a2 2 0 01-2-2V6z" />
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Select -->
|
||||||
|
<select
|
||||||
|
id="project-select"
|
||||||
|
[(ngModel)]="projectIdSelected"
|
||||||
|
class="w-full pl-10 pr-10 py-3 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-indigo-500 focus:border-transparent transition-all appearance-none cursor-pointer"
|
||||||
|
>
|
||||||
|
<option [value]="null" disabled>Sélectionnez un projet</option>
|
||||||
|
|
||||||
|
<!-- Option Ajouter avec style spécial -->
|
||||||
|
<option [value]="'add'.toLowerCase()" class="font-semibold">
|
||||||
|
➕ Ajouter un nouveau projet
|
||||||
|
</option>
|
||||||
|
|
||||||
@for (project of projects(); track project.id) {
|
@for (project of projects(); track project.id) {
|
||||||
<option [value]="project.id">
|
<option [value]="project.id">
|
||||||
@@ -18,16 +44,81 @@
|
|||||||
</option>
|
</option>
|
||||||
}
|
}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
<div class="w-full my-8">
|
<!-- Chevron à droite -->
|
||||||
|
<div class="absolute inset-y-0 right-0 pr-3 flex items-center pointer-events-none">
|
||||||
|
<svg
|
||||||
|
class="h-5 w-5 text-gray-400"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
viewBox="0 0 20 20"
|
||||||
|
fill="currentColor"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill-rule="evenodd"
|
||||||
|
d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z"
|
||||||
|
clip-rule="evenodd"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Info bulle -->
|
||||||
|
<p class="text-xs text-gray-500 dark:text-gray-400 flex items-center gap-1">
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
class="h-4 w-4"
|
||||||
|
viewBox="0 0 20 20"
|
||||||
|
fill="currentColor"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill-rule="evenodd"
|
||||||
|
d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a1 1 0 000 2v3a1 1 0 001 1h1a1 1 0 100-2v-3a1 1 0 00-1-1H9z"
|
||||||
|
clip-rule="evenodd"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
Vous avez {{ projects().length }} projet(s) enregistré(s)
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Formulaire du projet sélectionné -->
|
||||||
@if (projectIdSelected() != null) {
|
@if (projectIdSelected() != null) {
|
||||||
|
<div class="animate-slide-up">
|
||||||
<app-my-profile-update-project-form
|
<app-my-profile-update-project-form
|
||||||
[projectId]="projectIdSelected()"
|
[projectId]="projectIdSelected()"
|
||||||
(formIsUpdated)="onProjectFormSubmitted($event)"
|
(formIsUpdated)="onProjectFormSubmitted($event)"
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
|
} @else {
|
||||||
|
<!-- Message d'invite -->
|
||||||
|
<div
|
||||||
|
class="bg-gradient-to-r from-indigo-50 to-purple-50 dark:from-gray-800 dark:to-gray-700 rounded-xl p-8 text-center animate-fade-in animation-delay-200"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="inline-flex w-16 h-16 bg-white dark:bg-gray-600 rounded-full items-center justify-center mb-4 shadow-lg"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
class="w-8 h-8 text-indigo-600 dark:text-indigo-400"
|
||||||
|
fill="none"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
stroke="currentColor"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
stroke-width="2"
|
||||||
|
d="M9 13h6m-3-3v6m5 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<h3 class="text-lg font-semibold text-gray-900 dark:text-white mb-2">
|
||||||
|
Aucun projet sélectionné
|
||||||
|
</h3>
|
||||||
|
<p class="text-gray-600 dark:text-gray-300">
|
||||||
|
Sélectionnez un projet existant ou créez-en un nouveau pour commencer
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,98 +1,189 @@
|
|||||||
@if (projectId) {
|
@if (projectId) {
|
||||||
|
<div class="space-y-6">
|
||||||
|
<!-- Section Image du projet -->
|
||||||
|
<div class="bg-white dark:bg-gray-800 rounded-xl shadow-lg p-6 animate-fade-in">
|
||||||
|
<div class="flex items-center gap-3 mb-6">
|
||||||
|
<div
|
||||||
|
class="w-10 h-10 bg-indigo-100 dark:bg-indigo-900 rounded-lg flex items-center justify-center"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
class="w-6 h-6 text-indigo-600 dark:text-indigo-400"
|
||||||
|
viewBox="0 0 20 20"
|
||||||
|
fill="currentColor"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill-rule="evenodd"
|
||||||
|
d="M4 3a2 2 0 00-2 2v10a2 2 0 002 2h12a2 2 0 002-2V5a2 2 0 00-2-2H4zm12 12H4l4-8 3 6 2-4 3 6z"
|
||||||
|
clip-rule="evenodd"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<h3 class="text-xl font-bold text-gray-900 dark:text-white">Image du projet</h3>
|
||||||
|
</div>
|
||||||
|
|
||||||
@if (projectId == 'add'.toLowerCase()) {
|
@if (projectId == 'add'.toLowerCase()) {
|
||||||
<app-project-picture-form [project]="undefined" />
|
<app-project-picture-form [project]="undefined" />
|
||||||
} @else {
|
} @else {
|
||||||
<app-project-picture-form [project]="project()" />
|
<app-project-picture-form [project]="project()" />
|
||||||
}
|
}
|
||||||
|
</div>
|
||||||
|
|
||||||
<h3 class="font-ubuntu w-full text-start font-bold text-xl uppercase dark:text-white my-5">
|
<!-- Section Informations du projet -->
|
||||||
Information du projet
|
<div
|
||||||
</h3>
|
class="bg-white dark:bg-gray-800 rounded-xl shadow-lg p-6 animate-fade-in animation-delay-100"
|
||||||
|
>
|
||||||
|
<div class="flex items-center gap-3 mb-6">
|
||||||
|
<div
|
||||||
|
class="w-10 h-10 bg-purple-100 dark:bg-purple-900 rounded-lg flex items-center justify-center"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
class="w-6 h-6 text-purple-600 dark:text-purple-400"
|
||||||
|
viewBox="0 0 20 20"
|
||||||
|
fill="currentColor"
|
||||||
|
>
|
||||||
|
<path d="M9 2a1 1 0 000 2h2a1 1 0 100-2H9z" />
|
||||||
|
<path
|
||||||
|
fill-rule="evenodd"
|
||||||
|
d="M4 5a2 2 0 012-2 3 3 0 003 3h2a3 3 0 003-3 2 2 0 012 2v11a2 2 0 01-2 2H6a2 2 0 01-2-2V5zm3 4a1 1 0 000 2h.01a1 1 0 100-2H7zm3 0a1 1 0 000 2h3a1 1 0 100-2h-3zm-3 4a1 1 0 100 2h.01a1 1 0 100-2H7zm3 0a1 1 0 100 2h3a1 1 0 100-2h-3z"
|
||||||
|
clip-rule="evenodd"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<h3 class="text-xl font-bold text-gray-900 dark:text-white">Informations du projet</h3>
|
||||||
|
</div>
|
||||||
|
|
||||||
@if (loading().isLoading) {
|
@if (loading().isLoading) {
|
||||||
@switch (loading().action) {
|
@switch (loading().action) {
|
||||||
@case (ActionType.NONE || ActionType.CREATE || ActionType.DELETE) {}
|
@case (ActionType.NONE || ActionType.CREATE || ActionType.DELETE) {}
|
||||||
@default {
|
@default {
|
||||||
<p>Chargement...</p>
|
<!-- Loader -->
|
||||||
|
<app-loading message="Chargement du projet..." />
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} @else {
|
} @else {
|
||||||
<form class="mx-8" [formGroup]="projectForm" (ngSubmit)="onSubmit()">
|
<!-- Formulaire -->
|
||||||
<label class="mb-2 text-sm text-black block dark:text-white">Nom</label>
|
<form [formGroup]="projectForm" (ngSubmit)="onSubmit()" class="space-y-6">
|
||||||
<div class="relative flex items-center">
|
<!-- Champ Nom -->
|
||||||
|
<div class="space-y-2">
|
||||||
|
<label for="nom" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
|
||||||
|
Nom du projet
|
||||||
|
</label>
|
||||||
|
<div class="relative">
|
||||||
|
<div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
class="h-5 w-5 text-gray-400"
|
||||||
|
viewBox="0 0 20 20"
|
||||||
|
fill="currentColor"
|
||||||
|
>
|
||||||
|
<path d="M2 6a2 2 0 012-2h5l2 2h5a2 2 0 012 2v6a2 2 0 01-2 2H4a2 2 0 01-2-2V6z" />
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
<input
|
<input
|
||||||
|
id="nom"
|
||||||
type="text"
|
type="text"
|
||||||
placeholder="nom du projet"
|
|
||||||
formControlName="nom"
|
formControlName="nom"
|
||||||
class="pr-4 pl-14 py-3 text-sm text-black rounded bg-white border border-gray-400 w-full outline-[#333]"
|
placeholder="Nom du projet"
|
||||||
|
class="w-full pl-10 pr-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white placeholder-gray-400 focus:ring-2 focus:ring-indigo-500 focus:border-transparent transition-all"
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="absolute left-4">
|
<!-- Champ Lien -->
|
||||||
|
<div class="space-y-2">
|
||||||
|
<label for="lien" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
|
||||||
|
Lien du projet
|
||||||
|
</label>
|
||||||
|
<div class="relative">
|
||||||
|
<div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
|
||||||
<svg
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
width="22px"
|
class="h-5 w-5 text-gray-400"
|
||||||
height="22px"
|
viewBox="0 0 20 20"
|
||||||
fill="#bbb"
|
fill="currentColor"
|
||||||
viewBox="0 0 512 512"
|
|
||||||
>
|
>
|
||||||
<path
|
<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"
|
fill-rule="evenodd"
|
||||||
data-original="#000000"
|
d="M12.586 4.586a2 2 0 112.828 2.828l-3 3a2 2 0 01-2.828 0 1 1 0 00-1.414 1.414 4 4 0 005.656 0l3-3a4 4 0 00-5.656-5.656l-1.5 1.5a1 1 0 101.414 1.414l1.5-1.5zm-5 5a2 2 0 012.828 0 1 1 0 101.414-1.414 4 4 0 00-5.656 0l-3 3a4 4 0 105.656 5.656l1.5-1.5a1 1 0 10-1.414-1.414l-1.5 1.5a2 2 0 11-2.828-2.828l3-3z"
|
||||||
></path>
|
clip-rule="evenodd"
|
||||||
|
/>
|
||||||
</svg>
|
</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
|
<input
|
||||||
type="text"
|
id="lien"
|
||||||
placeholder="lien vers votre projet ex : http://monprojet"
|
type="url"
|
||||||
formControlName="lien"
|
formControlName="lien"
|
||||||
class="pr-4 pl-14 py-3 text-sm text-black rounded bg-white border border-gray-400 w-full outline-[#333]"
|
placeholder="https://monprojet.com"
|
||||||
|
class="w-full pl-10 pr-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white placeholder-gray-400 focus:ring-2 focus:ring-indigo-500 focus:border-transparent transition-all"
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="absolute left-4">
|
<!-- Champ Description -->
|
||||||
<svg
|
<div class="space-y-2">
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
<label
|
||||||
width="22px"
|
for="description"
|
||||||
height="22px"
|
class="block text-sm font-medium text-gray-700 dark:text-gray-300"
|
||||||
fill="#bbb"
|
|
||||||
viewBox="0 0 512 512"
|
|
||||||
>
|
>
|
||||||
<path
|
Description
|
||||||
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"
|
</label>
|
||||||
data-original="#000000"
|
|
||||||
></path>
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<label class="mb-2 text-sm text-black block dark:text-white">description</label>
|
|
||||||
<div class="relative flex items-center">
|
|
||||||
<textarea
|
<textarea
|
||||||
placeholder="Type Message"
|
id="description"
|
||||||
formControlName="description"
|
formControlName="description"
|
||||||
class="p-4 bg-white w-full block text-sm border border-gray-300 outline-[#007bff] rounded"
|
placeholder="Décrivez votre projet..."
|
||||||
rows="4"
|
rows="4"
|
||||||
|
class="w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white placeholder-gray-400 focus:ring-2 focus:ring-indigo-500 focus:border-transparent transition-all resize-none"
|
||||||
></textarea>
|
></textarea>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Boutons d'action -->
|
||||||
|
<div class="flex flex-col sm:flex-row gap-3 pt-4">
|
||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
[ngClass]="{ 'bg-purple-600': projectForm.valid }"
|
[disabled]="projectForm.invalid"
|
||||||
class="!mt-8 px-6 py-2 w-full bg-[#333] hover:bg-[#444] text-sm text-white mx-auto block"
|
class="flex-1 py-3 px-4 bg-gradient-to-r from-indigo-600 to-purple-600 hover:from-indigo-700 hover:to-purple-700 text-white font-medium rounded-lg shadow-lg hover:shadow-xl transform hover:-translate-y-0.5 transition-all duration-200 disabled:opacity-50 disabled:cursor-not-allowed disabled:transform-none"
|
||||||
>
|
>
|
||||||
|
<span class="flex items-center justify-center gap-2">
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
class="h-5 w-5"
|
||||||
|
viewBox="0 0 20 20"
|
||||||
|
fill="currentColor"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M7.707 10.293a1 1 0 10-1.414 1.414l3 3a1 1 0 001.414 0l3-3a1 1 0 00-1.414-1.414L11 11.586V6h5a2 2 0 012 2v7a2 2 0 01-2 2H4a2 2 0 01-2-2V8a2 2 0 012-2h5v5.586l-1.293-1.293zM9 4a1 1 0 012 0v2H9V4z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
Sauvegarder
|
Sauvegarder
|
||||||
|
</span>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
(click)="formIsUpdated.emit(null)"
|
(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"
|
class="flex-1 sm:flex-initial py-3 px-6 bg-gray-200 dark:bg-gray-700 hover:bg-gray-300 dark:hover:bg-gray-600 text-gray-900 dark:text-white font-medium rounded-lg transition-all duration-200"
|
||||||
>
|
>
|
||||||
|
<span class="flex items-center justify-center gap-2">
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
class="h-5 w-5"
|
||||||
|
viewBox="0 0 20 20"
|
||||||
|
fill="currentColor"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill-rule="evenodd"
|
||||||
|
d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z"
|
||||||
|
clip-rule="evenodd"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
Annuler
|
Annuler
|
||||||
|
</span>
|
||||||
</button>
|
</button>
|
||||||
|
</div>
|
||||||
</form>
|
</form>
|
||||||
}
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
@keyframes fadeIn {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(20px);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.animate-fade-in {
|
||||||
|
animation: fadeIn 0.6s ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.animation-delay-100 {
|
||||||
|
animation-delay: 0.1s;
|
||||||
|
opacity: 0;
|
||||||
|
animation-fill-mode: forwards;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-reduced-motion: reduce) {
|
||||||
|
*,
|
||||||
|
*::before,
|
||||||
|
*::after {
|
||||||
|
animation-duration: 0.01ms !important;
|
||||||
|
animation-iteration-count: 1 !important;
|
||||||
|
transition-duration: 0.01ms !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -17,11 +17,18 @@ import { AuthService } from '@app/core/services/authentication/auth.service';
|
|||||||
import { ProjectFacade } from '@app/ui/projects/project.facade';
|
import { ProjectFacade } from '@app/ui/projects/project.facade';
|
||||||
import { CreateProjectDto } from '@app/domain/projects/dto/create-project.dto';
|
import { CreateProjectDto } from '@app/domain/projects/dto/create-project.dto';
|
||||||
import { ActionType } from '@app/domain/action-type.util';
|
import { ActionType } from '@app/domain/action-type.util';
|
||||||
|
import { LoadingComponent } from '@app/shared/components/loading/loading.component';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-my-profile-update-project-form',
|
selector: 'app-my-profile-update-project-form',
|
||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [PaginatorModule, ReactiveFormsModule, NgClass, ProjectPictureFormComponent],
|
imports: [
|
||||||
|
PaginatorModule,
|
||||||
|
ReactiveFormsModule,
|
||||||
|
NgClass,
|
||||||
|
ProjectPictureFormComponent,
|
||||||
|
LoadingComponent,
|
||||||
|
],
|
||||||
templateUrl: './my-profile-update-project-form.component.html',
|
templateUrl: './my-profile-update-project-form.component.html',
|
||||||
styleUrl: './my-profile-update-project-form.component.scss',
|
styleUrl: './my-profile-update-project-form.component.scss',
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,32 +1,56 @@
|
|||||||
@if (project) {
|
@if (project) {
|
||||||
<div class="bg-white rounded-2xl border p-6">
|
<div
|
||||||
|
class="group bg-white dark:bg-gray-800 rounded-xl shadow-lg overflow-hidden transition-all duration-300 hover:shadow-2xl hover:-translate-y-2 animate-fade-in"
|
||||||
|
>
|
||||||
|
<!-- Image du projet -->
|
||||||
|
<div class="relative h-48 overflow-hidden bg-gray-100 dark:bg-gray-700">
|
||||||
@if (project.fichier) {
|
@if (project.fichier) {
|
||||||
<img
|
<img
|
||||||
alt="{{ project.nom }}"
|
alt="{{ project.nom }}"
|
||||||
class="object-cover object-center h-full w-full"
|
class="w-full h-full object-cover object-center transition-transform duration-500 group-hover:scale-110"
|
||||||
src="{{ environment.baseUrl }}/api/files/projets/{{ project.id }}/{{ project.fichier }}"
|
src="{{ environment.baseUrl }}/api/files/projets/{{ project.id }}/{{ project.fichier }}"
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
/>
|
/>
|
||||||
} @else {
|
} @else {
|
||||||
<img
|
<img
|
||||||
alt="nouveau-projet"
|
alt="{{ project.nom }}"
|
||||||
class="object-cover object-center h-full w-full"
|
class="w-full h-full object-cover object-center transition-transform duration-500 group-hover:scale-110 opacity-60"
|
||||||
src="https://api.dicebear.com/9.x/shapes/svg?seed={{ project.nom }}"
|
src="https://api.dicebear.com/9.x/shapes/svg?seed={{ project.nom }}"
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
|
|
||||||
<div class="mt-6">
|
<!-- Overlay gradient au hover -->
|
||||||
<h3 class="text-lg font-bold text-gray-800 mb-3">{{ project.nom }}</h3>
|
<div
|
||||||
<p class="text-gray-800 text-sm">{{ project.description }}</p>
|
class="absolute inset-0 bg-gradient-to-t from-black/60 via-transparent to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300"
|
||||||
<div class="mt-6">
|
></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Contenu -->
|
||||||
|
<div class="p-6 space-y-4">
|
||||||
|
<!-- Titre -->
|
||||||
|
<h3
|
||||||
|
class="text-xl font-bold text-gray-900 dark:text-white line-clamp-2 group-hover:text-indigo-600 dark:group-hover:text-indigo-400 transition-colors"
|
||||||
|
>
|
||||||
|
{{ project.nom }}
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
<!-- Description -->
|
||||||
|
<p class="text-sm text-gray-600 dark:text-gray-300 line-clamp-3">
|
||||||
|
{{ project.description || 'Aucune description disponible.' }}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<!-- Lien vers le projet -->
|
||||||
|
@if (project.lien) {
|
||||||
<a
|
<a
|
||||||
class="text-indigo-500 inline-flex items-center md:mb-2 lg:mb-0"
|
[href]="project.lien"
|
||||||
href="{{ project.lien }}"
|
|
||||||
target="_blank"
|
target="_blank"
|
||||||
>Explore
|
rel="noopener noreferrer"
|
||||||
|
class="inline-flex items-center gap-2 text-indigo-600 dark:text-indigo-400 hover:text-indigo-700 dark:hover:text-indigo-300 font-medium text-sm transition-all duration-200 group/link"
|
||||||
|
>
|
||||||
|
<span>Explorer le projet</span>
|
||||||
<svg
|
<svg
|
||||||
class="w-4 h-4 ml-2"
|
class="w-4 h-4 transition-transform duration-200 group-hover/link:translate-x-1"
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
stroke="currentColor"
|
stroke="currentColor"
|
||||||
stroke-width="2"
|
stroke-width="2"
|
||||||
@@ -38,7 +62,12 @@
|
|||||||
<path d="M12 5l7 7-7 7"></path>
|
<path d="M12 5l7 7-7 7"></path>
|
||||||
</svg>
|
</svg>
|
||||||
</a>
|
</a>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
<!-- Bordure animée au hover -->
|
||||||
|
<div
|
||||||
|
class="absolute inset-0 border-2 border-transparent group-hover:border-indigo-500 rounded-xl transition-all duration-300 pointer-events-none"
|
||||||
|
></div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,39 @@
|
|||||||
|
@keyframes fadeIn {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(20px);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.animate-fade-in {
|
||||||
|
animation: fadeIn 0.6s ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Line clamp pour limiter le texte */
|
||||||
|
.line-clamp-2 {
|
||||||
|
display: -webkit-box;
|
||||||
|
-webkit-line-clamp: 2;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.line-clamp-3 {
|
||||||
|
display: -webkit-box;
|
||||||
|
-webkit-line-clamp: 3;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-reduced-motion: reduce) {
|
||||||
|
*,
|
||||||
|
*::before,
|
||||||
|
*::after {
|
||||||
|
animation-duration: 0.01ms !important;
|
||||||
|
animation-iteration-count: 1 !important;
|
||||||
|
transition-duration: 0.01ms !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,12 +1,41 @@
|
|||||||
<div class="min-h-screen py-4 font-sans">
|
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
<div class="max-w-4xl max-lg:max-w-2xl max-sm:max-w-sm mx-auto">
|
<!-- Grid des projets -->
|
||||||
<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-6">
|
||||||
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4">
|
@for (project of projects(); track project.id) {
|
||||||
@for (project of projects(); track project) {
|
|
||||||
<app-project-item [project]="project" />
|
<app-project-item [project]="project" />
|
||||||
} @empty {
|
} @empty {
|
||||||
<p>Aucun projet</p>
|
<!-- Message si aucun projet -->
|
||||||
|
<div class="col-span-full">
|
||||||
|
<div
|
||||||
|
class="bg-gradient-to-r from-gray-50 to-gray-100 dark:from-gray-800 dark:to-gray-700 rounded-xl p-12 text-center"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="inline-flex w-20 h-20 bg-white dark:bg-gray-600 rounded-full items-center justify-center mb-6 shadow-lg"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
class="w-10 h-10 text-gray-400 dark:text-gray-500"
|
||||||
|
fill="none"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
stroke="currentColor"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
stroke-width="2"
|
||||||
|
d="M3 7v10a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-6l-2-2H5a2 2 0 00-2 2z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-3">
|
||||||
|
Aucun projet disponible
|
||||||
|
</h3>
|
||||||
|
<p class="text-gray-600 dark:text-gray-300 max-w-md mx-auto">
|
||||||
|
Il n'y a pas encore de projets à explorer. Revenez plus tard pour découvrir de nouvelles
|
||||||
|
réalisations !
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
@keyframes fadeIn {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(20px);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.animate-fade-in {
|
||||||
|
animation: fadeIn 0.6s ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-reduced-motion: reduce) {
|
||||||
|
*,
|
||||||
|
*::before,
|
||||||
|
*::after {
|
||||||
|
animation-duration: 0.01ms !important;
|
||||||
|
animation-iteration-count: 1 !important;
|
||||||
|
transition-duration: 0.01ms !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,35 +1,107 @@
|
|||||||
<form
|
<form
|
||||||
class="space-y-6 px-4 max-w-sm mx-auto font-[sans-serif]"
|
|
||||||
[formGroup]="userForm"
|
[formGroup]="userForm"
|
||||||
(ngSubmit)="onUserFormSubmit()"
|
(ngSubmit)="onUserFormSubmit()"
|
||||||
|
class="w-full space-y-6 animate-fade-in"
|
||||||
>
|
>
|
||||||
<h3 class="font-ubuntu font-bold text-xl uppercase dark:text-white mb-4">Mon Identité</h3>
|
<!-- Titre -->
|
||||||
|
<div class="flex items-center gap-3 pb-4 border-b border-gray-200 dark:border-gray-700">
|
||||||
|
<div
|
||||||
|
class="w-10 h-10 bg-indigo-100 dark:bg-indigo-900 rounded-lg flex items-center justify-center"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
class="w-6 h-6 text-indigo-600 dark:text-indigo-400"
|
||||||
|
viewBox="0 0 20 20"
|
||||||
|
fill="currentColor"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill-rule="evenodd"
|
||||||
|
d="M10 9a3 3 0 100-6 3 3 0 000 6zm-7 9a7 7 0 1114 0H3z"
|
||||||
|
clip-rule="evenodd"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<h3 class="text-xl font-bold text-gray-900 dark:text-white">Mon identité</h3>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="flex items-center">
|
<!-- Champ Nom -->
|
||||||
<label class="text-gray-400 w-36 text-xs">Nom</label>
|
<div class="space-y-2">
|
||||||
|
<label for="name" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
|
||||||
|
Nom
|
||||||
|
</label>
|
||||||
|
<div class="relative">
|
||||||
|
<div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
class="h-5 w-5 text-gray-400"
|
||||||
|
viewBox="0 0 20 20"
|
||||||
|
fill="currentColor"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill-rule="evenodd"
|
||||||
|
d="M10 9a3 3 0 100-6 3 3 0 000 6zm-7 9a7 7 0 1114 0H3z"
|
||||||
|
clip-rule="evenodd"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
<input
|
<input
|
||||||
|
id="name"
|
||||||
type="text"
|
type="text"
|
||||||
placeholder="Enter your name"
|
|
||||||
formControlName="name"
|
formControlName="name"
|
||||||
class="px-4 py-3 bg-gray-100 focus:bg-transparent w-full text-xs outline-[#333] rounded-sm transition-all"
|
placeholder="Votre nom"
|
||||||
|
class="w-full pl-10 pr-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white placeholder-gray-400 focus:ring-2 focus:ring-indigo-500 focus:border-transparent transition-all"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="flex items-center">
|
<!-- Champ Prénom -->
|
||||||
<label class="text-gray-400 w-36 text-xs">Prénom</label>
|
<div class="space-y-2">
|
||||||
|
<label for="firstname" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
|
||||||
|
Prénom
|
||||||
|
</label>
|
||||||
|
<div class="relative">
|
||||||
|
<div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
class="h-5 w-5 text-gray-400"
|
||||||
|
viewBox="0 0 20 20"
|
||||||
|
fill="currentColor"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill-rule="evenodd"
|
||||||
|
d="M10 9a3 3 0 100-6 3 3 0 000 6zm-7 9a7 7 0 1114 0H3z"
|
||||||
|
clip-rule="evenodd"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
<input
|
<input
|
||||||
|
id="firstname"
|
||||||
type="text"
|
type="text"
|
||||||
placeholder="entre votre prénom"
|
|
||||||
formControlName="firstname"
|
formControlName="firstname"
|
||||||
class="px-4 py-3 bg-gray-100 focus:bg-transparent w-full text-xs outline-[#333] rounded-sm transition-all"
|
placeholder="Votre prénom"
|
||||||
|
class="w-full pl-10 pr-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white placeholder-gray-400 focus:ring-2 focus:ring-indigo-500 focus:border-transparent transition-all"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Bouton de soumission -->
|
||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
[ngClass]="{ 'bg-purple-600': userForm.valid }"
|
[disabled]="userForm.invalid"
|
||||||
class="!mt-4 px-6 py-2 w-full bg-[#333] hover:bg-[#444] text-sm text-white mx-auto block"
|
class="w-full py-3 px-4 bg-gradient-to-r from-indigo-600 to-purple-600 hover:from-indigo-700 hover:to-purple-700 text-white font-medium rounded-lg shadow-lg hover:shadow-xl transform hover:-translate-y-0.5 transition-all duration-200 disabled:opacity-50 disabled:cursor-not-allowed disabled:transform-none"
|
||||||
>
|
>
|
||||||
|
<span class="flex items-center justify-center gap-2">
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
class="h-5 w-5"
|
||||||
|
viewBox="0 0 20 20"
|
||||||
|
fill="currentColor"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M7.707 10.293a1 1 0 10-1.414 1.414l3 3a1 1 0 001.414 0l3-3a1 1 0 00-1.414-1.414L11 11.586V6h5a2 2 0 012 2v7a2 2 0 01-2 2H4a2 2 0 01-2-2V8a2 2 0 012-2h5v5.586l-1.293-1.293zM9 4a1 1 0 012 0v2H9V4z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
Modifier mon identité
|
Modifier mon identité
|
||||||
|
</span>
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
@keyframes fadeIn {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(20px);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.animate-fade-in {
|
||||||
|
animation: fadeIn 0.6s ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-reduced-motion: reduce) {
|
||||||
|
*,
|
||||||
|
*::before,
|
||||||
|
*::after {
|
||||||
|
animation-duration: 0.01ms !important;
|
||||||
|
animation-iteration-count: 1 !important;
|
||||||
|
transition-duration: 0.01ms !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,15 +2,21 @@
|
|||||||
<a
|
<a
|
||||||
[routerLink]="[user.username ? user.username : user.id]"
|
[routerLink]="[user.username ? user.username : user.id]"
|
||||||
[state]="{ user, profile }"
|
[state]="{ user, profile }"
|
||||||
class="cursor-pointer"
|
class="block group"
|
||||||
>
|
>
|
||||||
<div class="group text-center text-gray-500 dark:text-gray-400">
|
<!-- Card du profil -->
|
||||||
|
<div
|
||||||
|
class="relative bg-white dark:bg-gray-800 rounded-xl shadow-lg overflow-hidden transition-all duration-300 hover:shadow-2xl hover:-translate-y-2"
|
||||||
|
>
|
||||||
|
<!-- Badge vérifié (position absolue en haut à droite) -->
|
||||||
@if (profile.estVerifier) {
|
@if (profile.estVerifier) {
|
||||||
|
<div class="absolute top-3 right-3 z-10 animate-pulse-slow">
|
||||||
|
<div class="bg-purple-500/20 backdrop-blur-md p-2 rounded-full">
|
||||||
<svg
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
fill="currentColor"
|
fill="currentColor"
|
||||||
class="size-6 text-purple-800"
|
class="w-6 h-6 text-purple-500"
|
||||||
>
|
>
|
||||||
<path
|
<path
|
||||||
fill-rule="evenodd"
|
fill-rule="evenodd"
|
||||||
@@ -18,43 +24,75 @@
|
|||||||
clip-rule="evenodd"
|
clip-rule="evenodd"
|
||||||
/>
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
<!-- Partie supérieure avec avatar -->
|
||||||
|
<div class="p-6 text-center">
|
||||||
|
<!-- Avatar avec bordure gradient -->
|
||||||
|
<div class="relative inline-block mb-4">
|
||||||
|
<div class="w-32 h-32 rounded-full bg-gradient-to-br from-indigo-500 to-purple-600 p-1">
|
||||||
@if (user.avatar) {
|
@if (user.avatar) {
|
||||||
<img
|
<img
|
||||||
class="mx-auto mb-4 w-36 h-36 rounded-full grayscale object-cover object-top ransition duration-500 group-hover:scale-105 group-hover:grayscale-0"
|
class="w-full h-full rounded-full object-cover grayscale group-hover:grayscale-0 transition-all duration-500 group-hover:scale-105"
|
||||||
src="{{ environment.baseUrl }}/api/files/users/{{ user.id }}/{{ user.avatar }}"
|
src="{{ environment.baseUrl }}/api/files/users/{{ user.id }}/{{ user.avatar }}"
|
||||||
alt="{{ user.username }}"
|
alt="{{ user.username }}"
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
/>
|
/>
|
||||||
} @else {
|
} @else {
|
||||||
<img
|
<img
|
||||||
class="mx-auto mb-4 w-36 h-36 rounded-full grayscale object-cover object-top ransition duration-500 group-hover:scale-105 group-hover:grayscale-0"
|
class="w-full h-full rounded-full object-cover grayscale group-hover:grayscale-0 transition-all duration-500 group-hover:scale-105"
|
||||||
src="https://api.dicebear.com/9.x/adventurer/svg?seed={{ user.username }}"
|
src="https://api.dicebear.com/9.x/adventurer/svg?seed={{ user.username }}"
|
||||||
alt="{{ user.username }}"
|
alt="{{ user.username }}"
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div
|
<!-- Nom -->
|
||||||
class="translate-y-2 transition duration-300 ease-in-out group-hover:translate-y-0 flex flex-col items-center space-y-2"
|
|
||||||
>
|
|
||||||
@if (user.name) {
|
@if (user.name) {
|
||||||
<h3 class="mb-1 text-2xl font-bold tracking-tight text-gray-900 dark:text-white">
|
<h3
|
||||||
|
class="text-lg font-bold text-gray-900 dark:text-white mb-2 group-hover:text-indigo-600 dark:group-hover:text-indigo-400 transition-colors"
|
||||||
|
>
|
||||||
{{ user.name }}
|
{{ user.name }}
|
||||||
</h3>
|
</h3>
|
||||||
} @else if (user.username) {
|
} @else if (user.username) {
|
||||||
<h3 class="mb-1 text-2xl font-bold tracking-tight text-gray-900 dark:text-white">
|
<h3
|
||||||
|
class="text-lg font-bold text-gray-900 dark:text-white mb-2 group-hover:text-indigo-600 dark:group-hover:text-indigo-400 transition-colors"
|
||||||
|
>
|
||||||
{{ user.username }}
|
{{ user.username }}
|
||||||
</h3>
|
</h3>
|
||||||
} @else {
|
} @else {
|
||||||
<h3 class="text-xl font-bold tracking-tight text-gray-900 dark:text-white">
|
<h3 class="text-lg font-bold text-gray-500 dark:text-gray-400 mb-2">Non mentionné</h3>
|
||||||
Non mentionné
|
|
||||||
</h3>
|
|
||||||
}
|
}
|
||||||
<p class="font-semibold">{{ profile.profession }}</p>
|
|
||||||
|
<!-- Profession -->
|
||||||
|
<p class="text-sm font-semibold text-gray-600 dark:text-gray-300 mb-4">
|
||||||
|
{{ profile.profession || 'Profession non renseignée' }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Partie inférieure avec infos -->
|
||||||
|
<div class="px-6 pb-6 space-y-3 border-t border-gray-100 dark:border-gray-700 pt-4">
|
||||||
|
<!-- Secteur -->
|
||||||
|
<div class="flex justify-center">
|
||||||
<app-chips [sectorId]="profile.secteur" />
|
<app-chips [sectorId]="profile.secteur" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Réseaux sociaux -->
|
||||||
|
@if (profile.reseaux) {
|
||||||
|
<div class="flex justify-center">
|
||||||
<app-reseaux [reseaux]="profile.reseaux" />
|
<app-reseaux [reseaux]="profile.reseaux" />
|
||||||
</div>
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Indicateur de hover (bordure animée) -->
|
||||||
|
<div
|
||||||
|
class="absolute inset-0 border-2 border-transparent group-hover:border-indigo-500 rounded-xl transition-all duration-300 pointer-events-none"
|
||||||
|
></div>
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
@keyframes pulseSlow {
|
||||||
|
0%,
|
||||||
|
100% {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.animate-pulse-slow {
|
||||||
|
animation: pulseSlow 3s ease-in-out infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-reduced-motion: reduce) {
|
||||||
|
*,
|
||||||
|
*::before,
|
||||||
|
*::after {
|
||||||
|
animation-duration: 0.01ms !important;
|
||||||
|
animation-iteration-count: 1 !important;
|
||||||
|
transition-duration: 0.01ms !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,10 +1,41 @@
|
|||||||
<section class="bg-white dark:bg-gray-900">
|
<section class="w-full animate-fade-in">
|
||||||
<div class="py-8 px-4 mx-auto max-w-screen-xl text-center lg:py-16 lg:px-6">
|
<div class="py-8 px-4 mx-auto max-w-screen-xl">
|
||||||
<div class="grid gap-8 lg:gap-16 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4">
|
<!-- Grid des profils -->
|
||||||
|
<div class="grid gap-6 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4">
|
||||||
@for (profile of profiles; track profile.id) {
|
@for (profile of profiles; track profile.id) {
|
||||||
<app-vertical-profile-item [profile]="profile" />
|
<app-vertical-profile-item [profile]="profile" />
|
||||||
} @empty {
|
} @empty {
|
||||||
<p>Aucun profile trouvée</p>
|
<!-- Message si aucun profil -->
|
||||||
|
<div class="col-span-full">
|
||||||
|
<div
|
||||||
|
class="bg-gradient-to-r from-gray-50 to-gray-100 dark:from-gray-800 dark:to-gray-700 rounded-xl p-12 text-center"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="inline-flex w-20 h-20 bg-white dark:bg-gray-600 rounded-full items-center justify-center mb-6 shadow-lg"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
class="w-10 h-10 text-gray-400 dark:text-gray-500"
|
||||||
|
fill="none"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
stroke="currentColor"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
stroke-width="2"
|
||||||
|
d="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0zm6 3a2 2 0 11-4 0 2 2 0 014 0zM7 10a2 2 0 11-4 0 2 2 0 014 0z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-3">
|
||||||
|
Aucun profil trouvé
|
||||||
|
</h3>
|
||||||
|
<p class="text-gray-600 dark:text-gray-300 max-w-md mx-auto">
|
||||||
|
Aucun profil ne correspond à votre recherche. Essayez de modifier vos critères.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
@keyframes fadeIn {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(20px);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.animate-fade-in {
|
||||||
|
animation: fadeIn 0.6s ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-reduced-motion: reduce) {
|
||||||
|
*,
|
||||||
|
*::before,
|
||||||
|
*::after {
|
||||||
|
animation-duration: 0.01ms !important;
|
||||||
|
animation-iteration-count: 1 !important;
|
||||||
|
transition-duration: 0.01ms !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,4 +1,57 @@
|
|||||||
@if (cv_link()) {
|
@if (cv_link()) {
|
||||||
|
<!-- Container du PDF viewer -->
|
||||||
|
<div class="bg-white dark:bg-gray-800 rounded-xl shadow-lg overflow-hidden animate-fade-in">
|
||||||
|
<!-- Header -->
|
||||||
|
<div
|
||||||
|
class="bg-gradient-to-r from-indigo-600 to-purple-600 px-6 py-4 flex items-center justify-between"
|
||||||
|
>
|
||||||
|
<div class="flex items-center gap-3">
|
||||||
|
<div
|
||||||
|
class="w-10 h-10 bg-white/20 backdrop-blur-md rounded-lg flex items-center justify-center"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
class="w-6 h-6 text-white"
|
||||||
|
fill="none"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
stroke="currentColor"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
stroke-width="2"
|
||||||
|
d="M7 21h10a2 2 0 002-2V9.414a1 1 0 00-.293-.707l-5.414-5.414A1 1 0 0012.586 3H7a2 2 0 00-2 2v14a2 2 0 002 2z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<h3 class="text-lg font-bold text-white">Mon CV</h3>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Bouton télécharger -->
|
||||||
|
<a
|
||||||
|
[href]="cv_link()"
|
||||||
|
download
|
||||||
|
target="_blank"
|
||||||
|
class="flex items-center gap-2 px-4 py-2 bg-white/20 hover:bg-white/30 backdrop-blur-md rounded-lg text-white text-sm font-medium transition-all duration-200 hover:scale-105"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
class="h-5 w-5"
|
||||||
|
viewBox="0 0 20 20"
|
||||||
|
fill="currentColor"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill-rule="evenodd"
|
||||||
|
d="M3 17a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1zm3.293-7.707a1 1 0 011.414 0L9 10.586V3a1 1 0 112 0v7.586l1.293-1.293a1 1 0 111.414 1.414l-3 3a1 1 0 01-1.414 0l-3-3a1 1 0 010-1.414z"
|
||||||
|
clip-rule="evenodd"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
<span class="hidden sm:inline">Télécharger</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- PDF Viewer -->
|
||||||
|
<div class="p-4 bg-gray-100 dark:bg-gray-900">
|
||||||
<pdf-viewer
|
<pdf-viewer
|
||||||
[src]="cv_link()"
|
[src]="cv_link()"
|
||||||
[zoom]="1"
|
[zoom]="1"
|
||||||
@@ -11,8 +64,38 @@
|
|||||||
[render-text]="true"
|
[render-text]="true"
|
||||||
[external-link-target]="'blank'"
|
[external-link-target]="'blank'"
|
||||||
[autoresize]="true"
|
[autoresize]="true"
|
||||||
[show-borders]="false"
|
[show-borders]="true"
|
||||||
|
class="rounded-lg overflow-hidden shadow-inner"
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
} @else {
|
} @else {
|
||||||
<p>Aucun curriculum vitae (CV) n'a été rajouté.</p>
|
<!-- Message si aucun CV -->
|
||||||
|
<div
|
||||||
|
class="bg-gradient-to-r from-gray-50 to-gray-100 dark:from-gray-800 dark:to-gray-700 rounded-xl p-12 text-center animate-fade-in"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="inline-flex w-20 h-20 bg-white dark:bg-gray-600 rounded-full items-center justify-center mb-6 shadow-lg"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
class="w-10 h-10 text-gray-400 dark:text-gray-500"
|
||||||
|
fill="none"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
stroke="currentColor"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
stroke-width="2"
|
||||||
|
d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-3">Aucun CV disponible</h3>
|
||||||
|
<p class="text-gray-600 dark:text-gray-300 max-w-md mx-auto">
|
||||||
|
Aucun curriculum vitae n'a été ajouté pour le moment. Veuillez télécharger votre CV pour le
|
||||||
|
visualiser ici.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,25 +28,6 @@
|
|||||||
<div
|
<div
|
||||||
class="bg-white dark:bg-gray-800 rounded-xl shadow-lg p-6 animate-fade-in animation-delay-100"
|
class="bg-white dark:bg-gray-800 rounded-xl shadow-lg p-6 animate-fade-in animation-delay-100"
|
||||||
>
|
>
|
||||||
<div class="flex items-center gap-3 mb-6">
|
|
||||||
<div
|
|
||||||
class="w-10 h-10 bg-purple-100 dark:bg-purple-900 rounded-lg flex items-center justify-center"
|
|
||||||
>
|
|
||||||
<svg
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
class="w-6 h-6 text-purple-600 dark:text-purple-400"
|
|
||||||
viewBox="0 0 20 20"
|
|
||||||
fill="currentColor"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
fill-rule="evenodd"
|
|
||||||
d="M10 9a3 3 0 100-6 3 3 0 000 6zm-7 9a7 7 0 1114 0H3z"
|
|
||||||
clip-rule="evenodd"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white">Informations personnelles</h3>
|
|
||||||
</div>
|
|
||||||
<app-user-form [user]="user" />
|
<app-user-form [user]="user" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user