-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'main' of https://github.com/Potits-chats/frontend into …
…fix-minor-bug
- Loading branch information
Showing
11 changed files
with
297 additions
and
178 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
73 changes: 42 additions & 31 deletions
73
src/app/components/tchat/tchat-message/tchat-message.component.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,46 +1,57 @@ | ||
<div *ngIf="auth.user$ | async as user"> | ||
<div *ngIf="utilisateur"> | ||
<!-- Chat Header --> | ||
<header class="bg-white p-4 text-gray-700 dark:border-t dark:border-orange-900 dark:bg-gray-800 dark:text-white"> | ||
<a href="../../profil?name={{user.name}}"><h1 class="text-2xl font-semibold">{{user.name}}</h1></a> | ||
<h1 *ngIf="!utilisateur!.isAssociation && selectedConversation" class="text-2xl font-semibold text-center flex items-center justify-center space-x-2"> | ||
<a [routerLink]="'/associations/'+selectedConversation!.id" class="hover:text-orange-800"> | ||
{{selectedConversation!.nom}} | ||
</a> | ||
<div *ngIf="!utilisateur!.isAssociation" class="flex items-center justify-center mr-2 hidden sm:flex"> | ||
<img alt="..." [src]="selectedConversation!.photos![0].url" class="w-16 h-16 rounded-full object-cover"> | ||
</div> | ||
</h1> | ||
<h1 *ngIf="utilisateur!.isAssociation && selectedConversation" class="text-2xl font-semibold text-center">{{selectedConversation!.nom}}</h1> | ||
<h1 *ngIf="!selectedConversation" class="text-2xl font-semibold text-center">Sélectionnez une conversation</h1> | ||
</header> | ||
|
||
<!-- Chat Messages --> | ||
<div class="h-screen overflow-y-auto p-4 pb-36 bg-gray-100 dark:bg-gray-700"> | ||
<div *ngIf="messages && messages.length > 0; else noMessages"> | ||
<div *ngFor="let msg of messages"> | ||
<!-- Message entrant --> | ||
<div *ngIf="msg.username !== user.name" class="flex mb-4 cursor-pointer"> | ||
<div class="w-9 h-9 rounded-full flex items-center justify-center mr-2"> | ||
<img alt="..." src="../../../../assets/happy-cat.jpg" class="w-8 h-8 rounded-full"> | ||
</div> | ||
<div class="flex max-w-96 bg-white rounded-lg p-3 gap-3"> | ||
<p class="text-gray-700">{{ msg.message }}</p> | ||
</div> | ||
<!-- Receveur --> | ||
<div *ngIf="!msg.isUserSender && !utilisateur!.isAssociation || msg.isUserSender && utilisateur!.isAssociation" class="flex mb-4 cursor-pointer items-start"> | ||
<div class="flex-shrink-0 mr-2 hidden sm:flex"> | ||
<img alt="..." [src]="selectedConversation?.img || selectedConversation!.photos![0].url" class="w-8 h-8 rounded-full object-cover"> | ||
</div> | ||
<div class="flex flex-col bg-white rounded-lg p-3 gap-3 max-w-full sm:max-w-md md:max-w-lg lg:max-w-xl min-w-0"> | ||
<p class="text-gray-700 break-words">{{ msg.contenu }}</p> | ||
</div> | ||
|
||
<!-- Message sortant --> | ||
<div *ngIf="msg.username === user.name" class="flex justify-end mb-4 cursor-pointer"> | ||
<div class="flex max-w-96 bg-orange-600 text-white rounded-lg p-3 gap-3"> | ||
<p>{{ msg.message }}</p> | ||
</div> | ||
<div class="w-9 h-9 rounded-full flex items-center justify-center ml-2"> | ||
<img alt="..." [src]='user.picture' loading="lazy" decoding="async" referrerpolicy="no-referrer" | ||
class="w-8 h-8 rounded-full"> | ||
</div> | ||
</div> | ||
<!-- L'envoyeur --> | ||
<div *ngIf="msg.isUserSender && !utilisateur!.isAssociation || !msg.isUserSender && utilisateur!.isAssociation" class="flex justify-end mb-4 cursor-pointer items-start"> | ||
<div class="flex flex-col bg-orange-600 text-white rounded-lg p-3 gap-3 max-w-full sm:max-w-md md:max-w-lg lg:max-w-xl min-w-0"> | ||
<p class="break-words">{{ msg.contenu }}</p> | ||
</div> | ||
<!-- <div class="flex-shrink-0 ml-2 hidden sm:flex"> | ||
<img *ngIf="utilisateur!.isAssociation" alt="..." [src]="user.picture" loading="lazy" decoding="async" referrerpolicy="no-referrer" class="w-8 h-8 rounded-full object-cover"> | ||
<img *ngIf="!utilisateur!.isAssociation" alt="..." [src]="user.picture" loading="lazy" decoding="async" referrerpolicy="no-referrer" class="w-8 h-8 rounded-full object-cover"> | ||
</div> --> | ||
</div> | ||
</div> | ||
</div> | ||
<ng-template #noMessages> | ||
<div class="flex items-center justify-center h-full"> | ||
<h1 class="text-center text-4xl font-extrabold leading-none tracking-tight text-gray-900 md:text-5xl lg:text-6xl dark:text-white">Vous pouvez commencer une conversation</h1> | ||
</div> | ||
</ng-template> | ||
</div> | ||
|
||
<!-- Chat Input --> | ||
<footer class="bg-white p-4 absolute bottom-0 w-3/4 dark:bg-gray-800"> | ||
<div class="flex items-center"> | ||
<!-- Utilisez ngModel ici pour lier le champ de saisie au modèle --> | ||
<input type="text" [(ngModel)]="message" (keydown.enter)="submit()" placeholder="Tapez un message..." | ||
class="w-full p-2 rounded-md border border-gray-400 focus:outline-none focus:border-blue-500"> | ||
<button (click)="submit()" class="bg-orange-600 text-white px-4 py-1 rounded-md ml-2 hover:bg-orange-700"> | ||
<span class="material-symbols-outlined"> | ||
send | ||
</span> | ||
</button> | ||
</div> | ||
<footer class="bg-white p-4 absolute bottom-0 w-full dark:bg-gray-800"> | ||
<div class="flex items-center"> | ||
<input type="text" [(ngModel)]="message" (keydown.enter)="submit()" placeholder="Tapez un message..." class="w-full p-2 rounded-md border border-gray-400 focus:outline-none focus:border-blue-500"> | ||
<button (click)="submit()" class="bg-orange-600 text-white px-4 py-1 rounded-md ml-2 hover:bg-orange-700"> | ||
<span class="material-symbols-outlined">send</span> | ||
</button> | ||
</div> | ||
</footer> | ||
</div> |
110 changes: 73 additions & 37 deletions
110
src/app/components/tchat/tchat-message/tchat-message.component.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,60 +1,96 @@ | ||
import { Component } from '@angular/core'; | ||
import { Component, OnInit, Input, OnChanges, SimpleChanges } from '@angular/core'; | ||
import { AppService } from '../../../services/app.service'; | ||
import { AuthService } from '@auth0/auth0-angular'; | ||
import { Message, Utilisateur } from '../../../interfaces/interfaces'; | ||
import { WebSocketService } from '../../../services/web-socket.service'; | ||
import { AppService } from '../../../services/app.service'; | ||
import Pusher from 'pusher-js'; | ||
|
||
import { Message, Utilisateur } from '../../../interfaces/interfaces'; | ||
import { Conversation } from '../../../interfaces/interfaces'; | ||
import { ActivatedRoute } from '@angular/router'; | ||
|
||
@Component({ | ||
selector: 'app-tchat-message', | ||
templateUrl: './tchat-message.component.html', | ||
styleUrls: ['./tchat-message.component.scss'] | ||
styleUrls: ['./tchat-message.component.scss'], | ||
}) | ||
export class TchatMessageComponent implements OnInit, OnChanges { | ||
|
||
@Input() selectedConversation: Conversation | null = null; | ||
@Input() utilisateur: Utilisateur | null = null; | ||
@Input() idFromUrl: number | null = null; | ||
|
||
export class TchatMessageComponent { | ||
username: String = ''; | ||
associationId: number | undefined = undefined; | ||
utilisateurId: number | undefined = undefined; | ||
message = ''; | ||
|
||
|
||
messages: Message[] = [ | ||
// exemple de données initiales | ||
{ username: 'Alice', message: 'Bonjour' }, | ||
{ username: 'Bob', message: 'Comment ça va ?' } | ||
]; | ||
messages: Message[] = []; | ||
|
||
constructor( | ||
public auth: AuthService, | ||
private appService: AppService, | ||
) { | ||
this.auth.user$.subscribe((user) => { | ||
if (user && user.name){ | ||
this.username = user.name; | ||
} | ||
}); | ||
} | ||
private webSocketService: WebSocketService | ||
) {} | ||
|
||
|
||
ngOnInit() { | ||
Pusher.logToConsole = true; | ||
|
||
const pusher = new Pusher('29fdd82357f17b9e1f8e', { | ||
cluster: 'eu' | ||
}); | ||
ngOnInit(): void { | ||
this.messages = []; | ||
if (this.idFromUrl) { | ||
this.associationId = this.idFromUrl; | ||
this.appService.getByIdAsso(this.idFromUrl).subscribe((association) => { | ||
this.selectedConversation = association as unknown as Conversation; | ||
this.associationId = this.selectedConversation!.id; | ||
this.utilisateurId = this.utilisateur!.id; | ||
this.loadMessages(); | ||
}); | ||
}else { | ||
this.calculateIds(); | ||
this.loadMessages(); | ||
} | ||
} | ||
|
||
const channel = pusher.subscribe('chat'); | ||
channel.bind('message', (data: any) => this.messages.push(data)); | ||
ngOnChanges(changes: SimpleChanges): void { | ||
if (changes['selectedConversation'] && this.selectedConversation) { | ||
this.messages = []; | ||
this.calculateIds(); | ||
this.loadMessages(); | ||
} | ||
} | ||
|
||
submit(): void { | ||
this.appService.sendMessage(this.username, this.message).subscribe( | ||
() => this.message = '' | ||
); | ||
calculateIds(): void { | ||
if (this.utilisateur) { | ||
if (this.utilisateur.isAssociation) { | ||
if (this.selectedConversation?.id) { | ||
this.utilisateurId = this.selectedConversation.id; | ||
} | ||
this.associationId = this.utilisateur.associationId; | ||
} else { | ||
this.utilisateurId = this.utilisateur.id; | ||
if (this.selectedConversation?.id) { | ||
this.associationId = this.selectedConversation.id; | ||
} | ||
} | ||
} | ||
} | ||
|
||
handleMessageChange(event: Event): void { | ||
this.message = (event.target as HTMLInputElement).value; | ||
loadMessages(): void { | ||
if (this.utilisateur && this.utilisateurId && this.associationId) { | ||
this.appService.getMessages(this.utilisateurId!, this.associationId).subscribe((messages: Message[]) => { | ||
this.messages = messages; | ||
}); | ||
this.listenForNewMessages(); | ||
} | ||
} | ||
|
||
listenForNewMessages(): void { | ||
this.webSocketService.subscribeToChannel(`association-${this.associationId}-user-${this.utilisateurId}`, 'new-message', (data: Message) => { | ||
if (!this.messages.some(message => message.id === data.id)) { | ||
this.messages.push(data); | ||
} | ||
}) | ||
}; | ||
|
||
|
||
submit(): void { | ||
if (this.utilisateurId && this.associationId) { | ||
this.appService.sendMessage(this.utilisateurId, this.associationId, this.message, !this.utilisateur?.isAssociation).subscribe(() => { | ||
this.message = ''; | ||
}); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,57 +1,54 @@ | ||
<!-- component --> | ||
<div class="flex h-screen overflow-hidden"> | ||
<!-- Sidebar --> | ||
<div class="w-1/4 bg-white border-r border-gray-300 dark:border-gray-600"> | ||
<!-- Sidebar Header --> | ||
<header class="p-4 flex justify-between items-center bg-orange-600 text-white"> | ||
<h1 class="text-2xl font-semibold">Chat Web</h1> | ||
<div class="relative"> | ||
<button id="menuButton" class="focus:outline-none"> | ||
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 text-gray-100" viewBox="0 0 20 20" fill="currentColor"> | ||
<path d="M10 12a2 2 0 100-4 2 2 0 000 4z" /> | ||
<path d="M2 10a2 2 0 012-2h12a2 2 0 012 2 2 2 0 01-2 2H4a2 2 0 01-2-2z" /> | ||
</svg> | ||
</button> | ||
</div> | ||
</header> | ||
|
||
<!-- Contact List --> | ||
<div class="overflow-y-auto h-screen p-3 mb-9 pb-20 dark:bg-gray-700 dark:text-white"> | ||
<div class="flex items-center mb-4 cursor-pointer hover:bg-gray-100 p-2 rounded-md dark:hover:bg-gray-600"> | ||
<div class="w-12 h-12 bg-gray-300 rounded-full mr-3"> | ||
<img src="https://placehold.co/200x/ffa8e4/ffffff.svg?text=ʕ•́ᴥ•̀ʔ&font=Lato" alt="User Avatar" class="w-12 h-12 rounded-full"> | ||
</div> | ||
<div class="flex-1"> | ||
<h2 class="text-lg font-semibold">Alice</h2> | ||
<p class="text-gray-600 dark:text-white">Hoorayy!!</p> | ||
</div> | ||
</div> | ||
|
||
<div class="flex items-center mb-4 cursor-pointer hover:bg-gray-100 p-2 rounded-md dark:hover:bg-gray-600"> | ||
<div class="w-12 h-12 bg-gray-300 rounded-full mr-3"> | ||
<img src="https://placehold.co/200x/ad922e/ffffff.svg?text=ʕ•́ᴥ•̀ʔ&font=Lato" alt="User Avatar" class="w-12 h-12 rounded-full"> | ||
</div> | ||
<div class="flex-1"> | ||
<h2 class="text-lg font-semibold">Martin</h2> | ||
<p class="text-gray-600 dark:text-white">That pizza place was amazing! We should go again sometime. 🍕</p> | ||
</div> | ||
</div> | ||
|
||
<div class="flex items-center mb-4 cursor-pointer hover:bg-gray-100 p-2 rounded-md dark:hover:bg-gray-600"> | ||
<div class="w-12 h-12 bg-gray-300 rounded-full mr-3"> | ||
<img src="https://placehold.co/200x/2e83ad/ffffff.svg?text=ʕ•́ᴥ•̀ʔ&font=Lato" alt="User Avatar" class="w-12 h-12 rounded-full"> | ||
<!-- Sidebar --> | ||
<div class="w-full sm:w-1/4 bg-white border-r border-gray-300 dark:border-gray-600" *ngIf="menuVisible"> | ||
<!-- Sidebar Header --> | ||
<header class="p-4 flex justify-between items-center bg-orange-600 text-white"> | ||
<h1 class="text-2xl font-semibold">Messages</h1> | ||
<div class="relative"> | ||
<button id="menuButton" (click)="toggleMenu()" class="focus:outline-none"> | ||
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 text-gray-100 pointer-events-none" viewBox="0 0 20 20" fill="currentColor"> | ||
<path d="M10 12a2 2 0 100-4 2 2 0 000 4z" /> | ||
<path d="M2 10a2 2 0 012-2h12a2 2 0 012 2 2 2 0 01-2 2H4a2 2 0 01-2-2z" /> | ||
</svg> | ||
</button> | ||
</div> | ||
</header> | ||
|
||
<!-- Contact List --> | ||
<div class="overflow-y-auto h-screen p-3 mb-9 pb-20 dark:bg-gray-700 dark:text-white"> | ||
<div *ngIf="conversations.length > 0; else noConversations"> | ||
<div *ngFor="let conversation of conversations" | ||
(click)="onSelectConversation(conversation)" | ||
class="flex items-center mb-4 cursor-pointer p-2 rounded-md dark:hover:bg-gray-600" | ||
[ngClass]="{ | ||
'bg-gray-100 dark:bg-gray-600': selectedConversation?.id === conversation.id, | ||
'hover:bg-gray-100': selectedConversation?.id !== conversation.id | ||
}"> | ||
<div *ngIf="conversation.img || conversation?.photos" class="w-12 h-12 bg-gray-300 rounded-full mr-3"> | ||
<!-- lazy --> | ||
<img [src]="conversation?.img || conversation!.photos![0].url" alt="User Avatar" class="w-12 h-12 rounded-full" loading="lazy"> | ||
</div> | ||
|
||
<div class="flex-1"> | ||
<h2 class="text-lg font-semibold">Charlie</h2> | ||
<p class="text-gray-600 dark:text-white">Hey, do you have any recommendations for a good movie to watch?</p> | ||
<h3 class="text-lg font-semibold">{{ conversation.nom }}</h3> | ||
<p class="text-gray-600 dark:text-white">{{ conversation.messages[0].contenu || 'No message yet' }}</p> | ||
</div> | ||
</div> | ||
|
||
|
||
</div> | ||
<ng-template #noConversations> | ||
<p class="text-center text-gray-600 dark:text-gray-300">No conversations available.</p> | ||
</ng-template> | ||
</div> | ||
|
||
<div class="flex-1"> | ||
<app-tchat-message></app-tchat-message> | ||
</div> | ||
</div> | ||
</div> | ||
|
||
<!-- Main Content --> | ||
<div class="flex-1 relative"> | ||
<app-tchat-message *ngIf="utilisateur" [selectedConversation]="selectedConversation" [utilisateur]="utilisateur"></app-tchat-message> | ||
<button id="menuButton" (click)="toggleMenu()" class="absolute top-4 left-4 focus:outline-none bg-orange-600 text-white p-2 rounded-md"> | ||
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 pointer-events-none" viewBox="0 0 20 20" fill="currentColor"> | ||
<path d="M10 12a2 2 0 100-4 2 2 0 000 4z" /> | ||
<path d="M2 10a2 2 0 012-2h12a2 2 0 012 2 2 2 0 01-2 2H4a2 2 0 01-2-2z" /> | ||
</svg> | ||
</button> | ||
</div> | ||
</div> |
Oops, something went wrong.