Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lmst2 69 study hebergeurs #74

Merged
merged 4 commits into from
Jul 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -141,8 +141,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
Loading