diff --git a/package-lock.json b/package-lock.json index c76d3ae..ce0fa02 100644 --- a/package-lock.json +++ b/package-lock.json @@ -247,6 +247,7 @@ "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-19.2.23.tgz", "integrity": "sha512-RazHPQkUEsNU/OZ75w9UeHxGFMthRiuAW2B/uA7eXExBj/1meHrrBfoCA56ujW2GUxVjRtSrMjylKh4R4meiYA==", "license": "MIT", + "peer": true, "dependencies": { "ajv": "8.18.0", "ajv-formats": "3.0.1", @@ -283,6 +284,7 @@ "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-19.2.23.tgz", "integrity": "sha512-Jzs7YM4X6azmHU7Mw5tQSPMuvaqYS8SLnZOJbtiXCy1JyuW9bm/WBBecNHMiuZ8LHXKhvQ6AVX1tKrzF6uiDmw==", "license": "MIT", + "peer": true, "dependencies": { "@angular-devkit/core": "19.2.23", "jsonc-parser": "3.3.1", @@ -430,6 +432,7 @@ "resolved": "https://registry.npmjs.org/@angular/common/-/common-19.2.20.tgz", "integrity": "sha512-1M3W3FjUUbVKXDMs+yQpBhnkD/pCe0Jn79rPE5W+EGWWxFoLSyGX+fhnRO5m4c9k66p3nvYrikWQ0ZzMv3M5tw==", "license": "MIT", + "peer": true, "dependencies": { "tslib": "^2.3.0" }, @@ -446,6 +449,7 @@ "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-19.2.20.tgz", "integrity": "sha512-LvjE8W58EACgTFaAoqmNe7FRsbvoQ0GvCB/rmm6AEMWx/0W/JBvWkQTrOQlwpoeYOHcMZRGdmPcZoUDwU3JySQ==", "license": "MIT", + "peer": true, "dependencies": { "tslib": "^2.3.0" }, @@ -459,6 +463,7 @@ "integrity": "sha512-tYYQk8AUz2sEkVl0a3uebduDUXPuKiGEKl2Jryrbn0xh9i1EsxoCjt1VvHnGnksGp3mz4DQihFVEnte0KeVQ5g==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/core": "7.26.9", "@jridgewell/sourcemap-codec": "^1.4.14", @@ -535,6 +540,7 @@ "resolved": "https://registry.npmjs.org/@angular/core/-/core-19.2.20.tgz", "integrity": "sha512-pxzQh8ouqfE57lJlXjIzXFuRETwkfMVwS+NFCfv2yh01Qtx+vymO8ZClcJMgLPfBYinhBYX+hrRYVSa1nzlkRQ==", "license": "MIT", + "peer": true, "dependencies": { "tslib": "^2.3.0" }, @@ -551,6 +557,7 @@ "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-19.2.20.tgz", "integrity": "sha512-agi7InbMzop1jrud6L7SlNwnZk3iNolORcFIwBQMvKxLkcJ+ttbSYuM0KAw56IundWHf4dL9GP4cSygm4kUeFA==", "license": "MIT", + "peer": true, "dependencies": { "tslib": "^2.3.0" }, @@ -569,6 +576,7 @@ "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-19.2.20.tgz", "integrity": "sha512-O9ZoQKILPC1T2c64OASS75XlOLBxY81m5AAgsBKhwiFWq+V28RsO0cnwpi1YSh/z4ryH8Fe7IUFz8jGrsJi3hQ==", "license": "MIT", + "peer": true, "dependencies": { "tslib": "^2.3.0" }, @@ -609,6 +617,7 @@ "resolved": "https://registry.npmjs.org/@angular/router/-/router-19.2.20.tgz", "integrity": "sha512-y0fyKycxJHr82kxXKE50Vac5hPn5Kx3gw9CfqyEuwJ9VQzEixDljU+chrQK4Wods14jJn9Tt2ncNPGH1rLya3Q==", "license": "MIT", + "peer": true, "dependencies": { "tslib": "^2.3.0" }, @@ -653,6 +662,7 @@ "integrity": "sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.26.2", @@ -2509,6 +2519,7 @@ "resolved": "https://registry.npmjs.org/@capacitor/core/-/core-8.3.1.tgz", "integrity": "sha512-UF8ItlHguU1Z6GXfPTeT2gakf+ctNI8pAS1kwSBQlsJMlfD4OPoto/SmKnOxKCQvnF4WRcdWeg6C0zREUNaAQg==", "license": "MIT", + "peer": true, "dependencies": { "tslib": "^2.1.0" } @@ -3202,6 +3213,7 @@ "integrity": "sha512-G1ytyOoHh5BphmEBxSwALin3n1KGNYB6yImbICcRQdzXfOGbuJ9Jske/Of5Sebk339NSGGNfUshnzK8YWkTPsQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@inquirer/checkbox": "^4.1.2", "@inquirer/confirm": "^5.1.6", @@ -4953,6 +4965,7 @@ "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-11.1.17.tgz", "integrity": "sha512-hLODw5Abp8OQgA+mUO4tHou4krKgDtUcM9j5Ihxncst9XeyxYBTt2bwZm4e4EQr5E352S4Fyy6V3iFx9ggxKAg==", "license": "MIT", + "peer": true, "dependencies": { "file-type": "21.3.2", "iterare": "1.2.1", @@ -7001,6 +7014,7 @@ "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", "dev": true, "license": "MIT", + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -7064,6 +7078,7 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", "license": "MIT", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", @@ -7294,6 +7309,7 @@ "resolved": "https://registry.npmjs.org/axios/-/axios-1.16.0.tgz", "integrity": "sha512-6hp5CwvTPlN2A31g5dxnwAX0orzM7pmCRDLnZSX772mv8WDqICwFjowHuPs04Mc8deIld1+ejhtaMn5vp6b+1w==", "license": "MIT", + "peer": true, "dependencies": { "follow-redirects": "^1.16.0", "form-data": "^4.0.5", @@ -7619,6 +7635,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "baseline-browser-mapping": "^2.10.12", "caniuse-lite": "^1.0.30001782", @@ -8802,29 +8819,6 @@ "node": ">= 0.8" } }, - "node_modules/encoding": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", - "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", - "license": "MIT", - "optional": true, - "dependencies": { - "iconv-lite": "^0.6.2" - } - }, - "node_modules/encoding/node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "license": "MIT", - "optional": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/enhanced-resolve": { "version": "5.20.1", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.20.1.tgz", @@ -10569,6 +10563,7 @@ "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==", "dev": true, "license": "MIT", + "peer": true, "bin": { "jiti": "bin/jiti.js" } @@ -10710,6 +10705,7 @@ "integrity": "sha512-tkuLHQlvWUTeQ3doAqnHbNn8T6WX1KA8yvbKG9x4VtKtIjHsVKQZCH11zRgAfbDAXC2UNIg/K9BYAAcEzUIrNg==", "dev": true, "license": "Apache-2.0", + "peer": true, "dependencies": { "copy-anything": "^2.0.1", "parse-node-version": "^1.0.1", @@ -12551,6 +12547,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "nanoid": "^3.3.8", "picocolors": "^1.1.1", @@ -12958,7 +12955,8 @@ "version": "0.2.2", "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.2.tgz", "integrity": "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==", - "license": "Apache-2.0" + "license": "Apache-2.0", + "peer": true }, "node_modules/regenerate": { "version": "1.4.2", @@ -13374,6 +13372,7 @@ "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==", "license": "Apache-2.0", + "peer": true, "dependencies": { "tslib": "^2.1.0" } @@ -14432,6 +14431,7 @@ "integrity": "sha512-LBAhFyLho16harJoWMg/nZsQYgTrg5jXOn2nCYjRUcZZEdE3qa2zb8QEDRUGVZBW4rlazf2fxkg8tztybTaqWw==", "dev": true, "license": "BSD-2-Clause", + "peer": true, "dependencies": { "@jridgewell/source-map": "^0.3.3", "acorn": "^8.8.2", @@ -14631,7 +14631,8 @@ "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" + "license": "0BSD", + "peer": true }, "node_modules/tuf-js": { "version": "3.1.0", @@ -14687,6 +14688,7 @@ "integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==", "dev": true, "license": "Apache-2.0", + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -15092,6 +15094,7 @@ "integrity": "sha512-gX/dMkRQc7QOMzgTe6KsYFM7DxeIONQSui1s0n/0xht36HvrgbxtM1xBlgx596NbpHuQU8P7QpKwrZYwUX48nw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@types/eslint-scope": "^3.7.7", "@types/estree": "^1.0.8", @@ -15171,6 +15174,7 @@ "integrity": "sha512-QcQ72gh8a+7JO63TAx/6XZf/CWhgMzu5m0QirvPfGvptOusAxG12w2+aua1Jkjr7hzaWDnJ2n6JFeexMHI+Zjg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@types/bonjour": "^3.5.13", "@types/connect-history-api-fallback": "^1.5.4", @@ -15766,7 +15770,8 @@ "version": "0.15.1", "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.15.1.tgz", "integrity": "sha512-XE96n56IQpJM7NAoXswY3XRLcWFW83xe0BiAOeMD7K5k5xecOeul3Qcpx6GqEeeHNkW5DWL5zOyTbEfB4eti8w==", - "license": "MIT" + "license": "MIT", + "peer": true } } } diff --git a/src/app/app.config.ts b/src/app/app.config.ts index 0d75611..af498c9 100644 --- a/src/app/app.config.ts +++ b/src/app/app.config.ts @@ -3,7 +3,9 @@ import { provideRouter } from '@angular/router'; import { routes } from './app.routes'; import { provideIonicAngular } from '@ionic/angular/standalone'; +import {provideHttpClient} from "@angular/common/http"; export const appConfig: ApplicationConfig = { - providers: [provideZoneChangeDetection({ eventCoalescing: true }), provideRouter(routes), provideIonicAngular({})] + providers: [provideZoneChangeDetection({ eventCoalescing: true }), provideRouter(routes), provideIonicAngular({}), provideHttpClient()], }; + diff --git a/src/app/app.routes.ts b/src/app/app.routes.ts index 4be8256..0103fa8 100644 --- a/src/app/app.routes.ts +++ b/src/app/app.routes.ts @@ -16,7 +16,7 @@ export const routes: Routes = [ },*/ { - path:'messages', + path: 'messages/:discussionId', loadComponent: () => import('./pages/messages/messages-main/messages-main.component').then(x => x.MessagesMain) }, { diff --git a/src/app/login.service.ts b/src/app/login.service.ts deleted file mode 100644 index db8c4f6..0000000 --- a/src/app/login.service.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { Injectable } from '@angular/core'; -import {tap} from "rxjs"; - -@Injectable({ - providedIn: 'root' -}) -export class LoginService { - - /* - login(credentials: { name: string; password: string }) { - return this.http.post(`${this.apiUrl}/login`, credentials).pipe( - tap(response => this.setSession(response.token)) - ); - } - */ - - /* - refreshToken(): Observable { - this.isRefreshing = true; - - return this.http.post(`${this.apiUrl}/refresh`, {}) - .pipe( - tap(response => { - this.setSession(response.token); - }), - finalize(() => { - this.isRefreshing = false; - }) - ); - } - */ - - /* - logout(){ - return localStorage.removeItem('token'); - this.currentUser.set(null); - this.router.navigate(['/login']); - } - */ - -} diff --git a/src/app/pages/login-form/login-form.component.html b/src/app/pages/login-form/login-form.component.html index 9d94226..dd001a6 100644 --- a/src/app/pages/login-form/login-form.component.html +++ b/src/app/pages/login-form/login-form.component.html @@ -20,7 +20,7 @@ - + Se connecter diff --git a/src/app/pages/login-form/login-form.component.ts b/src/app/pages/login-form/login-form.component.ts index 9ccb887..d406036 100644 --- a/src/app/pages/login-form/login-form.component.ts +++ b/src/app/pages/login-form/login-form.component.ts @@ -1,21 +1,17 @@ -import {Component, inject} from '@angular/core'; +import { Component, inject } from '@angular/core'; import { - IonButton, - IonCard, - IonCardContent, - IonCardHeader, - IonCardTitle, IonContent, IonInput, IonItem, NavController, + IonButton, IonContent, IonInput, IonItem, NavController, } from '@ionic/angular/standalone'; -import {CommonModule} from "@angular/common"; -import {FormBuilder, ReactiveFormsModule, Validators} from "@angular/forms"; -import {Router} from "@angular/router"; -import {LoginService} from "../../login.service"; +import { CommonModule } from "@angular/common"; +import { FormBuilder, ReactiveFormsModule, Validators } from "@angular/forms"; +import { Router } from "@angular/router"; +import { LoginService } from "../../services/api/login.service"; @Component({ selector: 'login-form', templateUrl: 'login-form.component.html', styleUrls: ['login-form.component.css'], - imports: [IonButton, CommonModule, ReactiveFormsModule, IonItem, IonInput, IonContent,], + imports: [IonButton, CommonModule, ReactiveFormsModule, IonItem, IonInput, IonContent], }) export class LoginFormComponent { @@ -37,11 +33,6 @@ export class LoginFormComponent { async submitForm(): Promise { if (this.loginForm.valid) { - - - - await this.navCtrl.navigateRoot(['main/messages']); - this.isLoading = true; const request = { @@ -49,31 +40,29 @@ export class LoginFormComponent { password: this.loginForm.value.password! }; - /*this.authService.login(request).subscribe({ - next: () => { + this.loginService.login(request).subscribe({ + next: (response) => { this.isLoading = false; - this.notification.success('Succès', 'Connexion réussie !'); - - this.router.navigate(['/main/discussions']); + // Le discussionId vient de la réponse de l'API + this.navCtrl.navigateRoot(['main/messages', response.discussionId]); }, error: (err) => { this.isLoading = false; - // Gestion des erreurs (inchangée) if (err.status === 401) { - this.notification.error('Erreur', 'Identifiant ou mot de passe incorrect.'); + console.error('Identifiant ou mot de passe incorrect.'); } else { - this.notification.error('Erreur', 'Impossible de contacter le serveur.'); + console.error('Impossible de contacter le serveur.'); } } }); + } else { - // Affiche les erreurs de validation visuelles Object.values(this.loginForm.controls).forEach(control => { if (control.invalid) { control.markAsDirty(); control.updateValueAndValidity({ onlySelf: true }); } - });*/ + }); } } } \ No newline at end of file diff --git a/src/app/pages/menu/menu-users/menu-users.component.css b/src/app/pages/menu/menu-users/menu-users.component.css index e69de29..6aecf64 100644 --- a/src/app/pages/menu/menu-users/menu-users.component.css +++ b/src/app/pages/menu/menu-users/menu-users.component.css @@ -0,0 +1,52 @@ +@import url('https://fonts.googleapis.com/css2?family=Nunito:wght@400;600;700;800&display=swap'); + +.discussions-list { + display: flex; + flex-direction: column; + gap: 10px; + width: 100%; +} + +.discussion-btn { + display: flex; + align-items: center; + gap: 14px; + width: 100%; + padding: 12px 16px; + background: rgba(255, 255, 255, 0.88); + border: none; + border-radius: 50px; + box-shadow: 0 2px 10px rgba(180, 80, 80, 0.10); + cursor: pointer; + transition: transform 0.15s, box-shadow 0.15s; + + img { + opacity: 0.7; + flex-shrink: 0; + } + + &:active { + transform: scale(0.97); + box-shadow: 0 1px 5px rgba(180, 80, 80, 0.08); + } +} + +.discussion-info { + display: flex; + flex-direction: column; + align-items: flex-start; +} + +.username { + font-family: 'Nunito', sans-serif; + font-size: 15px; + font-weight: 700; + color: #b05050; +} + +.members { + font-family: 'Nunito', sans-serif; + font-size: 12px; + font-weight: 600; + color: #c98080; +} \ No newline at end of file diff --git a/src/app/pages/menu/menu-users/menu-users.component.html b/src/app/pages/menu/menu-users/menu-users.component.html index 7c36e4b..c132732 100644 --- a/src/app/pages/menu/menu-users/menu-users.component.html +++ b/src/app/pages/menu/menu-users/menu-users.component.html @@ -1,4 +1,22 @@ - \ No newline at end of file +
+ +
\ No newline at end of file diff --git a/src/app/pages/menu/menu-users/menu-users.component.ts b/src/app/pages/menu/menu-users/menu-users.component.ts index bfe687a..1a44d20 100644 --- a/src/app/pages/menu/menu-users/menu-users.component.ts +++ b/src/app/pages/menu/menu-users/menu-users.component.ts @@ -1,11 +1,34 @@ -import { Component } from '@angular/core'; +import { Component, inject } from '@angular/core'; +import { Router } from "@angular/router"; +import { CommonModule } from "@angular/common"; + +export interface Discussion { + id: number; + name: string; + isGroup: boolean; + membersCount?: number; +} @Component({ selector: 'app-menu-users', - imports: [], + imports: [CommonModule], templateUrl: './menu-users.component.html', styleUrl: './menu-users.component.css' }) export class MenuUsersComponent { -} + private router = inject(Router); + + discussions: Discussion[] = [ + { id: 1, name: 'Um-Bro', isGroup: false }, + { id: 2, name: 'Doggeybag', isGroup: false }, + { id: 3, name: '', isGroup: false }, + { id: 4, name: 'Abel Paradigm', isGroup: false }, + { id: 5, name: 'Um-Brothers', isGroup: true, membersCount: 7 }, + { id: 6, name: 'Hoodie G', isGroup: false }, + ]; + + openDiscussion(discussionId: number) { + this.router.navigate(['/main/messages', discussionId]); + } +} \ No newline at end of file diff --git a/src/app/pages/messages/messages-main/messages-main.component.html b/src/app/pages/messages/messages-main/messages-main.component.html index a93f441..51deabe 100644 --- a/src/app/pages/messages/messages-main/messages-main.component.html +++ b/src/app/pages/messages/messages-main/messages-main.component.html @@ -17,7 +17,7 @@
- +
diff --git a/src/app/pages/messages/messages-main/messages-main.component.ts b/src/app/pages/messages/messages-main/messages-main.component.ts index 7d815be..155285f 100644 --- a/src/app/pages/messages/messages-main/messages-main.component.ts +++ b/src/app/pages/messages/messages-main/messages-main.component.ts @@ -1,19 +1,22 @@ -import { Component } from '@angular/core'; -import {MessagesMenu} from "../messages-menu/messages-menu.component"; -import {MessagesInfoUser} from "../messages-infouser/messages-infouser.component"; -import {MessagesSend} from "../messages-send/messages-send.component"; -import {Router} from '@angular/router'; +import { Component, inject, OnInit } from '@angular/core'; +import { MessagesMenu } from "../messages-menu/messages-menu.component"; +import { MessagesInfoUser } from "../messages-infouser/messages-infouser.component"; +import { MessagesSend } from "../messages-send/messages-send.component"; +import { ActivatedRoute } from '@angular/router'; @Component({ selector: 'app-messages-main', - imports: [ - MessagesMenu, - MessagesInfoUser, - MessagesSend - ], + imports: [MessagesMenu, MessagesInfoUser, MessagesSend], templateUrl: './messages-main.component.html', styleUrl: './messages-main.component.css' }) -export class MessagesMain { +export class MessagesMain implements OnInit { -} + private route = inject(ActivatedRoute); + + currentdiscussionId!: string; + + ngOnInit() { + this.currentdiscussionId = this.route.snapshot.paramMap.get('discussionId')!; + } +} \ No newline at end of file diff --git a/src/app/pages/messages/messages-send/messages-send.component.ts b/src/app/pages/messages/messages-send/messages-send.component.ts index bbff094..c38c11c 100644 --- a/src/app/pages/messages/messages-send/messages-send.component.ts +++ b/src/app/pages/messages/messages-send/messages-send.component.ts @@ -1,27 +1,38 @@ -import { Component } from '@angular/core'; -import {FormControl, FormsModule, ReactiveFormsModule} from "@angular/forms"; +import { Component, inject, Input } from '@angular/core'; +import { FormControl, FormsModule, ReactiveFormsModule } from "@angular/forms"; +import { ChatService } from "../../../services/api/chat.service"; @Component({ selector: 'app-messages-send', - imports: [ - FormsModule, - ReactiveFormsModule - ], - templateUrl:'./messages-send.component.html', + imports: [FormsModule, ReactiveFormsModule], + templateUrl: './messages-send.component.html', styleUrl: './messages-send.component.css' }) export class MessagesSend { - sendMessage = new FormControl(); - onSubmit() { + private chatService = inject(ChatService); + + @Input() discussionId!: string; // passé par le composant parent + + sendMessage = new FormControl(); + isSending = false; + + async onSubmit() { const message = this.sendMessage.value; if (!message || message.trim() === '') return; + if (this.isSending) return; // évite le double envoi - console.log('Message envoyé :', message); + this.isSending = true; - // Logique d'envoi - - this.sendMessage.reset(); + try { + await this.chatService.sendMessage(this.discussionId, message.trim()); + this.sendMessage.reset(); + } catch (error) { + console.error('Erreur lors de l\'envoi :', error); + // Afficher une notification d'erreur ici + } finally { + this.isSending = false; + } } } diff --git a/src/app/services/api/chat.service.ts b/src/app/services/api/chat.service.ts index 9c5caec..a4dd04d 100644 --- a/src/app/services/api/chat.service.ts +++ b/src/app/services/api/chat.service.ts @@ -1,38 +1,30 @@ -// chat.service.ts -import * as signalR from '@microsoft/signalr'; -import {Injectable} from "@angular/core"; +import { Injectable } from '@angular/core'; +import { HubConnection, HubConnectionBuilder, HubConnectionState } from '@microsoft/signalr'; @Injectable({ providedIn: 'root' }) export class ChatService { - private hub: signalR.HubConnection; + private hub: HubConnection; constructor() { - this.hub = new signalR.HubConnectionBuilder() + this.hub = new HubConnectionBuilder() .withUrl('https://localhost:5001/hubs/chat') - .withAutomaticReconnect() // reconnexion auto si coupure réseau + .withAutomaticReconnect() .build(); } async connect() { - await this.hub.start(); + if (this.hub.state === HubConnectionState.Disconnected) { + await this.hub.start(); + } } - async joinConversation(conversationId: string) { - await this.hub.invoke('JoinConversation', conversationId); + async sendMessage(discussionId: string, content: string) { + await this.connect(); // s'assure que la connexion est active + await this.hub.invoke('SendMessage', discussionId, content); } - async sendMessage(conversationId: string, content: string) { - await this.hub.invoke('SendMessage', conversationId, content); - } - - // Écouter les messages entrants - onMessage(callback: (msg: any) => void) { + onMessage(callback: (message: any) => void) { this.hub.on('ReceiveMessage', callback); } - - // Écouter l'indicateur de frappe - onTyping(callback: (userId: string) => void) { - this.hub.on('UserTyping', callback); - } } \ No newline at end of file diff --git a/src/app/services/api/discussion.service.ts b/src/app/services/api/discussion.service.ts new file mode 100644 index 0000000..4c14d21 --- /dev/null +++ b/src/app/services/api/discussion.service.ts @@ -0,0 +1,15 @@ +import {Observable} from "rxjs"; +import {Discussion} from "../../pages/menu/menu-users/menu-users.component"; +import {HttpClient} from "@angular/common/http"; +import {inject, Injectable} from "@angular/core"; + +@Injectable({ providedIn: 'root' }) +export class discussionsService { + + private http = inject(HttpClient); + private apiUrl = 'https://localhost:5001/API'; + + getDiscussions(): Observable { + return this.http.get(`${this.apiUrl}/discussions`); + } +} \ No newline at end of file diff --git a/src/app/services/api/login.service.ts b/src/app/services/api/login.service.ts new file mode 100644 index 0000000..44fd835 --- /dev/null +++ b/src/app/services/api/login.service.ts @@ -0,0 +1,42 @@ +import { Injectable, inject } from '@angular/core'; +import { HttpClient } from "@angular/common/http"; +import { Observable, tap, finalize } from "rxjs"; + +export interface LoginRequest { + name: string; + password: string; +} + +export interface LoginResponse { + token: string; + discussionId: string; +} + +@Injectable({ + providedIn: 'root' +}) +export class LoginService { + + private http = inject(HttpClient); + private apiUrl = 'https://localhost:5001/API'; + private isRefreshing = false; + + login(credentials: LoginRequest): Observable { + return this.http.post(`${this.apiUrl}/auth/login`, credentials).pipe( + tap(response => localStorage.setItem('token', response.token)) + ); + } + + refreshToken(): Observable<{ token: string }> { + this.isRefreshing = true; + + return this.http.post<{ token: string }>(`${this.apiUrl}/auth/refresh`, {}).pipe( + tap(response => localStorage.setItem('token', response.token)), + finalize(() => { this.isRefreshing = false; }) + ); + } + + logout() { + localStorage.removeItem('token'); + } +} \ No newline at end of file