login et register + chat et discussion services
This commit is contained in:
@@ -2,7 +2,7 @@
|
|||||||
import { HttpClient } from '@angular/common/http';
|
import { HttpClient } from '@angular/common/http';
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
import { firstValueFrom } from 'rxjs';
|
import { firstValueFrom } from 'rxjs';
|
||||||
import {LoggedUser} from "../../models/user.model";
|
import { LoggedUser } from "../../models/user.model";
|
||||||
|
|
||||||
interface LoginResponse {
|
interface LoginResponse {
|
||||||
token: string;
|
token: string;
|
||||||
@@ -14,6 +14,11 @@ interface LoginResponse {
|
|||||||
description: string | null;
|
description: string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface RegisterRequest {
|
||||||
|
username: string;
|
||||||
|
password: string;
|
||||||
|
}
|
||||||
|
|
||||||
@Injectable({ providedIn: 'root' })
|
@Injectable({ providedIn: 'root' })
|
||||||
export class AuthService {
|
export class AuthService {
|
||||||
private http = inject(HttpClient);
|
private http = inject(HttpClient);
|
||||||
@@ -56,7 +61,15 @@ export class AuthService {
|
|||||||
localStorage.setItem(this.USER_KEY, JSON.stringify(user));
|
localStorage.setItem(this.USER_KEY, JSON.stringify(user));
|
||||||
this.currentUser.set(user);
|
this.currentUser.set(user);
|
||||||
|
|
||||||
await this.router.navigate(['/']); // adapte la route
|
await this.router.navigate(['/main/menu']);
|
||||||
|
}
|
||||||
|
|
||||||
|
async register(username: string, password: string): Promise<void> {
|
||||||
|
await firstValueFrom(
|
||||||
|
this.http.post<void>('/API/users/register', { username, password } as RegisterRequest)
|
||||||
|
);
|
||||||
|
|
||||||
|
await this.login(username, password);
|
||||||
}
|
}
|
||||||
|
|
||||||
logout(): void {
|
logout(): void {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import {
|
|||||||
import { CommonModule } from "@angular/common";
|
import { CommonModule } from "@angular/common";
|
||||||
import { FormBuilder, ReactiveFormsModule, Validators } from "@angular/forms";
|
import { FormBuilder, ReactiveFormsModule, Validators } from "@angular/forms";
|
||||||
import { Router } from "@angular/router";
|
import { Router } from "@angular/router";
|
||||||
import { LoginService } from "../../services/api/login.service";
|
import { AuthService } from "../../core/auth/auth.service";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'login-form',
|
selector: 'login-form',
|
||||||
@@ -16,9 +16,8 @@ import { LoginService } from "../../services/api/login.service";
|
|||||||
export class LoginFormComponent {
|
export class LoginFormComponent {
|
||||||
|
|
||||||
private fb = inject(FormBuilder);
|
private fb = inject(FormBuilder);
|
||||||
private loginService = inject(LoginService);
|
private authService = inject(AuthService);
|
||||||
private router = inject(Router);
|
private router = inject(Router);
|
||||||
private navCtrl = inject(NavController);
|
|
||||||
|
|
||||||
isLoading = false;
|
isLoading = false;
|
||||||
|
|
||||||
@@ -35,26 +34,20 @@ export class LoginFormComponent {
|
|||||||
if (this.loginForm.valid) {
|
if (this.loginForm.valid) {
|
||||||
this.isLoading = true;
|
this.isLoading = true;
|
||||||
|
|
||||||
const request = {
|
try {
|
||||||
name: this.loginForm.value.name!,
|
await this.authService.login(
|
||||||
password: this.loginForm.value.password!
|
this.loginForm.value.name!,
|
||||||
};
|
this.loginForm.value.password!
|
||||||
|
);
|
||||||
this.loginService.login(request).subscribe({
|
} catch (err: any) {
|
||||||
next: (response) => {
|
if (err.status === 401) {
|
||||||
this.isLoading = false;
|
console.error('Identifiant ou mot de passe incorrect.');
|
||||||
// Le discussionId vient de la réponse de l'API
|
} else {
|
||||||
this.navCtrl.navigateRoot(['main/messages', response.discussionId]);
|
console.error('Impossible de contacter le serveur.');
|
||||||
},
|
|
||||||
error: (err) => {
|
|
||||||
this.isLoading = false;
|
|
||||||
if (err.status === 401) {
|
|
||||||
console.error('Identifiant ou mot de passe incorrect.');
|
|
||||||
} else {
|
|
||||||
console.error('Impossible de contacter le serveur.');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
} finally {
|
||||||
|
this.isLoading = false;
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
Object.values(this.loginForm.controls).forEach(control => {
|
Object.values(this.loginForm.controls).forEach(control => {
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ export class MessagesSend {
|
|||||||
|
|
||||||
private chatService = inject(ChatService);
|
private chatService = inject(ChatService);
|
||||||
|
|
||||||
@Input() discussionId!: string; // passé par le composant parent
|
@Input() discussionId!: string;
|
||||||
|
|
||||||
sendMessage = new FormControl();
|
sendMessage = new FormControl();
|
||||||
isSending = false;
|
isSending = false;
|
||||||
@@ -21,7 +21,7 @@ export class MessagesSend {
|
|||||||
const message = this.sendMessage.value;
|
const message = this.sendMessage.value;
|
||||||
|
|
||||||
if (!message || message.trim() === '') return;
|
if (!message || message.trim() === '') return;
|
||||||
if (this.isSending) return; // évite le double envoi
|
if (this.isSending) return;
|
||||||
|
|
||||||
this.isSending = true;
|
this.isSending = true;
|
||||||
|
|
||||||
@@ -30,7 +30,6 @@ export class MessagesSend {
|
|||||||
this.sendMessage.reset();
|
this.sendMessage.reset();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Erreur lors de l\'envoi :', error);
|
console.error('Erreur lors de l\'envoi :', error);
|
||||||
// Afficher une notification d'erreur ici
|
|
||||||
} finally {
|
} finally {
|
||||||
this.isSending = false;
|
this.isSending = false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
<ion-content [fullscreen]="true" class="bg">
|
<ion-content [fullscreen]="true" class="bg">
|
||||||
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
|
|
||||||
<div class="logo-box">
|
<div class="logo-box">
|
||||||
@@ -8,34 +7,37 @@
|
|||||||
|
|
||||||
<h1>Knots</h1>
|
<h1>Knots</h1>
|
||||||
|
|
||||||
<div class="card">
|
<div class="card" [formGroup]="registerForm">
|
||||||
|
|
||||||
<h3>Inscrivez-vous à Knots !</h3>
|
<h3>Inscrivez-vous à Knots !</h3>
|
||||||
<p class="subtitle">Commencez à nouer des liens !</p>
|
<p class="subtitle">Commencez à nouer des liens !</p>
|
||||||
|
|
||||||
<ion-item lines="none" class="input">
|
<ion-item lines="none" class="input">
|
||||||
<ion-input placeholder="Nom d'utilisateur..."></ion-input>
|
<ion-input placeholder="Nom d'utilisateur..." formControlName="username"></ion-input>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
|
|
||||||
<ion-item lines="none" class="input">
|
<ion-item lines="none" class="input">
|
||||||
<ion-input type="password" placeholder="Mot de passe..."></ion-input>
|
<ion-input type="password" placeholder="Mot de passe..." formControlName="password"></ion-input>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
|
|
||||||
<ion-item lines="none" class="input">
|
<ion-item lines="none" class="input">
|
||||||
<ion-input type="password" placeholder="Confirmez votre mot de passe..."></ion-input>
|
<ion-input type="password" placeholder="Confirmez votre mot de passe..." formControlName="confirmPassword"></ion-input>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
|
|
||||||
<ion-button expand="block" class="btn">
|
<p *ngIf="registerForm.hasError('passwordMismatch')" style="color:#d97070; font-size:13px; text-align:center; margin:0;">
|
||||||
Créer son compte
|
Les mots de passe ne correspondent pas.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<ion-button expand="block" class="btn" (click)="submitForm()" [disabled]="isLoading">
|
||||||
|
{{ isLoading ? 'Création...' : 'Créer son compte' }}
|
||||||
</ion-button>
|
</ion-button>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="signup">
|
<div class="signup">
|
||||||
Déjà un compte ?<br>
|
Déjà un compte ?<br>
|
||||||
<a (click)="goToLogin()" >Connectez-vous ici</a>
|
<a (click)="goToLogin()">Connectez-vous ici</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</ion-content>
|
</ion-content>
|
||||||
@@ -1,30 +1,59 @@
|
|||||||
import {Component, inject} from '@angular/core';
|
import { Component, inject } from '@angular/core';
|
||||||
import {
|
import {
|
||||||
IonButton,
|
IonButton, IonContent, IonInput, IonItem
|
||||||
IonCard,
|
|
||||||
IonCardContent,
|
|
||||||
IonCardHeader,
|
|
||||||
IonCardSubtitle,
|
|
||||||
IonCardTitle, IonContent, IonInput, IonItem
|
|
||||||
} from "@ionic/angular/standalone";
|
} from "@ionic/angular/standalone";
|
||||||
import {Router} from "@angular/router";
|
import { Router } from "@angular/router";
|
||||||
|
import { FormBuilder, ReactiveFormsModule, Validators } from "@angular/forms";
|
||||||
|
import { CommonModule } from "@angular/common";
|
||||||
|
import {AuthService} from "../../core/auth/auth.service";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-register-form',
|
selector: 'app-register-form',
|
||||||
imports: [
|
imports: [IonButton, IonInput, IonContent, IonItem, ReactiveFormsModule, CommonModule],
|
||||||
IonButton,
|
templateUrl: './register-form.component.html',
|
||||||
IonInput,
|
styleUrl: './register-form.component.css'
|
||||||
IonContent,
|
|
||||||
IonItem
|
|
||||||
],
|
|
||||||
templateUrl: './register-form.component.html',
|
|
||||||
styleUrl: './register-form.component.css'
|
|
||||||
})
|
})
|
||||||
export class RegisterFormComponent {
|
export class RegisterFormComponent {
|
||||||
|
|
||||||
private router = inject(Router)
|
private router = inject(Router);
|
||||||
|
private fb = inject(FormBuilder);
|
||||||
|
private authService = inject(AuthService);
|
||||||
|
|
||||||
|
isLoading = false;
|
||||||
|
|
||||||
|
registerForm = this.fb.group({
|
||||||
|
username: ['', [Validators.required, Validators.maxLength(50)]],
|
||||||
|
password: ['', [Validators.required, Validators.minLength(12), Validators.maxLength(50)]],
|
||||||
|
confirmPassword: ['', [Validators.required]]
|
||||||
|
}, { validators: this.passwordMatchValidator });
|
||||||
|
|
||||||
|
passwordMatchValidator(form: any) {
|
||||||
|
const password = form.get('password')?.value;
|
||||||
|
const confirm = form.get('confirmPassword')?.value;
|
||||||
|
return password === confirm ? null : { passwordMismatch: true };
|
||||||
|
}
|
||||||
|
|
||||||
goToLogin() {
|
goToLogin() {
|
||||||
this.router.navigate(['/login']);
|
this.router.navigate(['/login']);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
async submitForm() {
|
||||||
|
if (this.registerForm.valid) {
|
||||||
|
this.isLoading = true;
|
||||||
|
try {
|
||||||
|
await this.authService.register(
|
||||||
|
this.registerForm.value.username!,
|
||||||
|
this.registerForm.value.password!
|
||||||
|
);
|
||||||
|
} catch (err: any) {
|
||||||
|
if (err.status === 409) {
|
||||||
|
console.error('Ce nom d\'utilisateur est déjà pris.');
|
||||||
|
} else {
|
||||||
|
console.error('Impossible de contacter le serveur.');
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
this.isLoading = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { HubConnection, HubConnectionBuilder, HubConnectionState } from '@microsoft/signalr';
|
||||||
|
|
||||||
|
@Injectable({ providedIn: 'root' })
|
||||||
|
export class ChatService {
|
||||||
|
|
||||||
|
private hub: HubConnection;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.hub = new HubConnectionBuilder()
|
||||||
|
.withUrl('https://localhost:5001/hubs/chat')
|
||||||
|
.withAutomaticReconnect()
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
async connect() {
|
||||||
|
if (this.hub.state === HubConnectionState.Disconnected) {
|
||||||
|
await this.hub.start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async sendMessage(discussionId: string, content: string) {
|
||||||
|
await this.connect(); // s'assure que la connexion est active
|
||||||
|
await this.hub.invoke('SendMessage', discussionId, content);
|
||||||
|
}
|
||||||
|
|
||||||
|
onMessage(callback: (message: any) => void) {
|
||||||
|
this.hub.on('ReceiveMessage', callback);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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<Discussion[]> {
|
||||||
|
return this.http.get<Discussion[]>(`${this.apiUrl}/discussions`);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user