️ Unique name for modal share + new event from parent to children instead of NavigationEnd + all component in one div (avoid moving two divs in the body at the same time)

timeline
Alix JEUDI--LEMOINE 1 week ago
parent 2f11aae5a2
commit db5c7f6514

@ -1,111 +1,113 @@
<!-- Fond assombri -->
<div
class="fixed inset-0 bg-gray-900 bg-opacity-50 w-full h-full transition-opacity duration-300 ease-in-out z-40"
[ngClass]="{
'opacity-0 pointer-events-none': !isShareModalOpen,
'opacity-100': isShareModalOpen
}"
(click)="closeShareModal()"
id="share-modal-background"
></div>
<div id="share-modal-{{pinId}}">
<!-- Fond assombri -->
<div
class="fixed inset-0 bg-gray-900 bg-opacity-50 w-full h-full transition-opacity duration-300 ease-in-out z-40"
[ngClass]="{
'opacity-0 pointer-events-none': !isShareModalOpen,
'opacity-100': isShareModalOpen
}"
(click)="closeShareModal()"
id="share-modal-background-{{pinId}}"
></div>
<!-- Main modal -->
<div
id="share-modal"
tabindex="-1"
aria-hidden="true"
[ngClass]="{
'opacity-0 scale-50 pointer-events-none': !isShareModalOpen,
'opacity-100 scale-100': isShareModalOpen
}"
class="fixed top-0 right-0 left-0 z-50 flex justify-center items-center w-full h-full transition-transform duration-300 ease-in-out overflow-y-auto"
>
<div class="relative p-4 w-full max-w-md max-h-full">
<!-- Modal content -->
<div
class="relative bg-white rounded-lg shadow dark:bg-gray-700 transition-transform duration-300 ease-in-out my-8"
>
<!-- Modal header -->
<!-- Main modal -->
<div
id="share-modal-{{pinId}}"
tabindex="-1"
aria-hidden="true"
[ngClass]="{
'opacity-0 scale-50 pointer-events-none': !isShareModalOpen,
'opacity-100 scale-100': isShareModalOpen
}"
class="fixed top-0 right-0 left-0 z-50 flex justify-center items-center w-full h-full transition-transform duration-300 ease-in-out overflow-y-auto"
>
<div class="relative p-4 w-full max-w-md max-h-full">
<!-- Modal content -->
<div
class="flex items-center justify-between p-4 md:p-5 border-b rounded-t dark:border-gray-600"
class="relative bg-white rounded-lg shadow dark:bg-gray-700 transition-transform duration-300 ease-in-out my-8"
>
<h3 class="text-xl font-semibold text-gray-900 dark:text-white">
Partager ce souvenir
</h3>
<button
type="button"
(click)="closeShareModal()"
class="end-2.5 text-gray-400 bg-transparent hover:bg-gray-200 hover:text-gray-900 rounded-lg text-sm w-8 h-8 ms-auto inline-flex justify-center items-center dark:hover:bg-gray-600 dark:hover:text-white"
<!-- Modal header -->
<div
class="flex items-center justify-between p-4 md:p-5 border-b rounded-t dark:border-gray-600"
>
<svg
class="w-3 h-3"
aria-hidden="true"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 14 14"
<h3 class="text-xl font-semibold text-gray-900 dark:text-white">
Partager ce souvenir
</h3>
<button
type="button"
(click)="closeShareModal()"
class="end-2.5 text-gray-400 bg-transparent hover:bg-gray-200 hover:text-gray-900 rounded-lg text-sm w-8 h-8 ms-auto inline-flex justify-center items-center dark:hover:bg-gray-600 dark:hover:text-white"
>
<path
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="m1 1 6 6m0 0 6 6M7 7l6-6M7 7l-6 6"
/>
</svg>
<span class="sr-only">Fermer la modal</span>
</button>
</div>
<svg
class="w-3 h-3"
aria-hidden="true"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 14 14"
>
<path
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="m1 1 6 6m0 0 6 6M7 7l6-6M7 7l-6 6"
/>
</svg>
<span class="sr-only">Fermer la modal</span>
</button>
</div>
<!-- Modal body -->
<div class="p-4 md:p-5 space-y-4">
<!-- Options de partage -->
<div class="flex flex-col space-y-4">
<div class="p-4">
<input
type="text"
id="search-friends"
class="w-full p-2 mb-2 border rounded-lg dark:bg-gray-700 dark:text-white"
placeholder="Rechercher un ami..."
[(ngModel)]="searchTerm"
(ngModelChange)="onSearchTermChange($event)"
/>
<!-- Modal body -->
<div class="p-4 md:p-5 space-y-4">
<!-- Options de partage -->
<div class="flex flex-col space-y-4">
<div class="p-4">
<input
type="text"
id="search-friends"
class="w-full p-2 mb-2 border rounded-lg dark:bg-gray-700 dark:text-white"
placeholder="Rechercher un ami..."
[(ngModel)]="searchTerm"
(ngModelChange)="onSearchTermChange($event)"
/>
<div *ngIf="listUser" class="text-gray-500 text-sm">
<div
*ngFor="let user of listUser"
class="friend flex items-center justify-between space-x-3 pt-10"
>
<div class="friend flex items-center space-x-3">
<img
class="w-10 h-10 rounded-full"
src="/avatar.png"
alt="Friend 2"
/>
<span class="text-gray-900 dark:text-white">{{
user.username
}}</span>
</div>
<button
(click)="sharePin(user.friend_user_id)"
class="p-2 bg-green-500 text-white rounded-full"
<div *ngIf="listUser" class="text-gray-500 text-sm">
<div
*ngFor="let user of listUser"
class="friend flex items-center justify-between space-x-3 pt-10"
>
<svg
class="w-6 h-6 text-gray-800 dark:text-white"
aria-hidden="true"
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
fill="none"
viewBox="0 0 24 24"
>
<path
stroke="currentColor"
stroke-linecap="round"
stroke-width="2"
d="M7.926 10.898 15 7.727m-7.074 5.39L15 16.29M8 12a2.5 2.5 0 1 1-5 0 2.5 2.5 0 0 1 5 0Zm12 5.5a2.5 2.5 0 1 1-5 0 2.5 2.5 0 0 1 5 0Zm0-11a2.5 2.5 0 1 1-5 0 2.5 2.5 0 0 1 5 0Z"
<div class="friend flex items-center space-x-3">
<img
class="w-10 h-10 rounded-full"
src="/avatar.png"
alt="Friend 2"
/>
</svg>
</button>
<span class="text-gray-900 dark:text-white">{{
user.username
}}</span>
</div>
<button
(click)="sharePin(user.friend_user_id)"
class="p-2 bg-green-500 text-white rounded-full"
>
<svg
class="w-6 h-6 text-gray-800 dark:text-white"
aria-hidden="true"
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
fill="none"
viewBox="0 0 24 24"
>
<path
stroke="currentColor"
stroke-linecap="round"
stroke-width="2"
d="M7.926 10.898 15 7.727m-7.074 5.39L15 16.29M8 12a2.5 2.5 0 1 1-5 0 2.5 2.5 0 0 1 5 0Zm12 5.5a2.5 2.5 0 1 1-5 0 2.5 2.5 0 0 1 5 0Zm0-11a2.5 2.5 0 1 1-5 0 2.5 2.5 0 0 1 5 0Z"
/>
</svg>
</button>
</div>
</div>
</div>
</div>

@ -1,9 +1,8 @@
import { CommonModule } from '@angular/common';
import { Component, OnDestroy, OnInit } from '@angular/core';
import { Component, Input, EventEmitter, OnDestroy, OnInit } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { NavigationEnd, Router } from '@angular/router';
import { Router } from '@angular/router';
import { Subject, Subscription } from 'rxjs';
import { filter } from 'rxjs/operators';
import { FriendsService } from '../../services/friends/friends.service';
import { ModalService } from '../../services/modal/modal.service';
import { PinService } from '../../services/pin/pin.service';
@ -16,9 +15,9 @@ import { PinService } from '../../services/pin/pin.service';
})
export class ShareModalComponent implements OnInit, OnDestroy {
modalId: string = 'share-modal';
isShareModalOpen = false;
private modalSub!: Subscription;
private routerSubscription!: Subscription;
isFriendModalOpen: boolean = false;
hasAcceptedFriends: boolean = false;
hasPendingFriends: boolean = false;
@ -26,41 +25,35 @@ export class ShareModalComponent implements OnInit, OnDestroy {
searchTermChanged = new Subject<string>();
listUser: any[] = [];
listFriend: any[] = [];
pinId: string = '';
@Input() pinId!: string;
@Input() pinOpened!: EventEmitter<void>;
constructor(
private modalService: ModalService,
private friendService: FriendsService,
private pinService: PinService,
private router: Router
) {}
ngOnInit() {
this.modalId = 'share-modal-' + this.pinId;
this.modalSub = this.modalService
.getModalState(this.modalId)
.subscribe((open) => {
this.isShareModalOpen = open;
if (open) {
this.getFriend();
this.pinId = this.modalService.getCurrentPinId();
setTimeout(() => this.moveModalToBody(), 0);
}
});
// S'abonner aux événements de navigation du router
this.routerSubscription = this.router.events
.pipe(filter((event) => event instanceof NavigationEnd))
.subscribe(() => {
// Attendre que le DOM soit mis à jour après la navigation
setTimeout(() => this.moveModalToBody(), 0);
});
this.pinOpened.subscribe(() => {
this.moveModalToBody();
});
}
ngOnDestroy() {
this.modalSub?.unsubscribe();
if (this.routerSubscription) {
this.routerSubscription.unsubscribe();
}
}
openShareModal() {
@ -71,20 +64,11 @@ export class ShareModalComponent implements OnInit, OnDestroy {
this.modalService.closeModal(this.modalId);
}
ngAfterViewInit() {
// Appel initial pour déplacer le modal
this.moveModalToBody();
}
private moveModalToBody(): void {
const modal = document.getElementById('share-modal');
const modal = document.getElementById(this.modalId);
if (modal && modal.parentElement !== document.body) {
document.body.appendChild(modal);
}
const bg = document.getElementById('share-modal-background');
if (bg && bg.parentElement !== document.body) {
document.body.appendChild(bg);
}
}
onSearchTermChange(value: string): void {

Loading…
Cancel
Save