Skip to content

Commit

Permalink
Merge branch 'main' of https://github.com/Potits-chats/frontend into …
Browse files Browse the repository at this point in the history
…fix-minor-bug
  • Loading branch information
FazCodeFR committed Jul 18, 2024
2 parents fb417d5 + fbb689f commit 046f8b3
Show file tree
Hide file tree
Showing 11 changed files with 297 additions and 178 deletions.
6 changes: 6 additions & 0 deletions src/app/app-routing.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,15 @@ const routes: Routes = [
path: 'mentions-legales',
component: CguComponent,
},
{
path: 'tchat/:id',
component: TchatComponent,
canActivate: [AuthGuard],
},
{
path: 'tchat',
component: TchatComponent,
canActivate: [AuthGuard],
},
{
path : 'callback',
Expand Down
9 changes: 9 additions & 0 deletions src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,15 @@ import { PaginatorModule } from 'primeng/paginator';
uri: `${environment.urlAPI}/*`,
httpMethod: HttpMethod.Patch,
},
// Protéger la route GET messages
{
uri: `${environment.urlAPI}/users/infos`,
httpMethod: HttpMethod.Get,
},
{
uri: `${environment.urlAPI}/messages/*`,
httpMethod: HttpMethod.Get,
}
],
},
}),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,8 +142,9 @@ <h1 class="max-w-lg mb-6 font-sans text-2xl font-bold leading-none tracking-tigh
</button>

<button *ngIf="!isEditMode"
class="flex mx-auto mt-16 text-white bg-indigo-500 border-0 py-2 px-8 focus:outline-none hover:bg-indigo-600 rounded text-lg">
Contacter {{asso.nom }}
class="flex mx-auto mt-16 text-white bg-indigo-500 border-0 py-2 px-8 focus:outline-none hover:bg-indigo-600 rounded text-lg"
[routerLink]="['/tchat', asso.id]">
Contacter {{asso.nom }}
</button>

</div>
73 changes: 42 additions & 31 deletions src/app/components/tchat/tchat-message/tchat-message.component.html
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 src/app/components/tchat/tchat-message/tchat-message.component.ts
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 = '';
});
}
}
}
97 changes: 47 additions & 50 deletions src/app/components/tchat/tchat.component.html
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>
Loading

0 comments on commit 046f8b3

Please sign in to comment.