Merge pull request 'friend' (#26) from friend into master

Reviewed-on: #26
tutorial
Alexis FERON 3 weeks ago
commit 685fbf1103

@ -51,14 +51,46 @@
id="search-friends"
class="w-full p-2 border rounded-lg dark:bg-gray-700 dark:text-white"
placeholder="Rechercher un ami..."
[(ngModel)]="searchTerm"
(ngModelChange)="onSearchTermChange($event)"
/>
<div *ngIf="listUser" class="text-gray-500 text-sm">
<div
style="padding-top: 10px;"
*ngFor="let user of listUser"
class="friend flex items-center justify-between space-x-3"
>
<div class="friend flex items-center space-x-3">
<img
class="w-10 h-10 rounded-full"
src="https://latelierduformateur.fr/wp-content/uploads/2021/05/Multiavatar-Formatrice.png"
alt="Friend 2"
/>
<span class="text-gray-900 dark:text-white">{{
user.username
}}</span>
</div>
<button
(click)="addUser(user.uid)"
class="p-2 bg-green-500 text-white rounded-full"
>
<svg class="w-6 h-6 text-gray-800 dark:text-white" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" viewBox="0 0 24 24">
<path fill-rule="evenodd" d="M9 4a4 4 0 1 0 0 8 4 4 0 0 0 0-8Zm-2 9a4 4 0 0 0-4 4v1a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2v-1a4 4 0 0 0-4-4H7Zm8-1a1 1 0 0 1 1-1h1v-1a1 1 0 1 1 2 0v1h1a1 1 0 1 1 0 2h-1v1a1 1 0 1 1-2 0v-1h-1a1 1 0 0 1-1-1Z" clip-rule="evenodd"/>
</svg>
</button>
</div>
</div>
</div>
<div class="p-4 space-y-3">
<p class="dark:text-white">Mes Amis</p>
<p class="dark:text-white">Amis</p>
<div *ngIf="hasNoAcceptedFriends()" class="text-gray-500 dark:text-gray-300">
<p><small><em>Aucun amis</em></small></p>
</div>
<div
*ngFor="let friend of listFriend"
class="friend flex items-center justify-between space-x-3"
>
<div
*ngIf="friend.status == 'accepted'"
@ -95,11 +127,13 @@
</button>
</div>
</div>
<hr class="border-gray-300 my-3" />
<p class="dark:text-white">Mes demandes d'amis</p>
<div *ngIf="hasPendingApprovalFriend()">
<p class="dark:text-white">Demandes</p>
<hr class="border-gray-300 my-3" />
</div>
<div *ngFor="let friend of listFriend">
<div
*ngIf="friend.status == 'pending'"
*ngIf="friend.status == 'pending_approval'"
class="flex justify-between items-center w-full"
>
<div class="friend flex items-center space-x-3">
@ -141,7 +175,7 @@
class="w-4 h-4"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
stroke="currentColor"private
>
<path
stroke-linecap="round"
@ -154,6 +188,31 @@
</div>
</div>
</div>
<div *ngIf="hasPendingFriend()">
<p class="dark:text-white">En attente</p>
<hr class="border-gray-300 my-3" />
</div>
<div *ngFor="let friend of listFriend">
<div
*ngIf="friend.status == 'pending'"
class="flex justify-between items-center w-full"
>
<div class="friend flex items-center space-x-3">
<img
class="w-10 h-10 rounded-full"
src="https://latelierduformateur.fr/wp-content/uploads/2021/05/Multiavatar-Formatrice.png"
alt="Friend 2"
/>
<span class="text-gray-900 dark:text-white">{{
friend.username
}}</span>
</div>
<svg class="w-6 h-6 text-gray-800 dark:text-white" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24">
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M18.5 4h-13m13 16h-13M8 20v-3.333a2 2 0 0 1 .4-1.2L10 12.6a1 1 0 0 0 0-1.2L8.4 8.533a2 2 0 0 1-.4-1.2V4h8v3.333a2 2 0 0 1-.4 1.2L13.957 11.4a1 1 0 0 0 0 1.2l1.643 2.867a2 2 0 0 1 .4 1.2V20H8Z"/>
</svg>
</div>
</div>
<!-- Pied du modal -->

@ -1,10 +1,14 @@
import { CommonModule } from '@angular/common';
import { Component, OnInit } from '@angular/core';
import { FriendsService } from '../../services/friends/friends.service';
import { FormsModule, NgModel } from '@angular/forms';
import { UserService } from '../../services/user/user.service';
import { LocalStorageService } from '../../services/local-storage/local-storage.service';
import { debounceTime, distinctUntilChanged, Subject } from 'rxjs';
@Component({
selector: 'app-friend-page',
imports: [CommonModule],
imports: [CommonModule, FormsModule],
templateUrl: './friend-page.component.html',
})
export class FriendPageComponent implements OnInit {
@ -14,23 +18,78 @@ export class FriendPageComponent implements OnInit {
friend_user_id: string;
id: string;
}[] = [];
protected listUser: {
uid: string,
username: string
}[] = [];
userId: string = '';
status: string = '';
isFriendModalOpen: boolean = false;
hasAcceptedFriends: boolean = false;
hasPendingFriends: boolean = false;
hasPendingFriends: boolean = false;;
searchTerm: string = '';
searchTermChanged = new Subject<string>();
constructor(private friendService: FriendsService) {}
constructor(private friendService: FriendsService, private userService:UserService, private localStorage: LocalStorageService) {
}
ngOnInit(): void {
this.getFriendData();
this.searchTermChanged
.pipe(
debounceTime(200),
distinctUntilChanged()
)
.subscribe((username: string) => {
this.searchUser(username);
});
}
protected searchUser(username: string) {
this.searchTerm = username
if (this.searchTerm) {
this.getUserData(this.searchTerm.trim())
}
else {
this.listUser = []
}
}
onSearchTermChange(username: string) {
this.searchTermChanged.next(username);
}
private getUserData(search:string): void{
const username = this.localStorage.getUsername()
this.userService.getUser('^(?!'+username+')'+search).subscribe((data:any[]) => {
if (data.length > 0) {
const existingFriendIds = this.listFriend.map(friend => friend.friend_user_id);
this.listUser = data.filter(user => !existingFriendIds.includes(user.uid));
}
})
}
protected addUser(user_id:string): void {
this.friendService.addFriend(user_id).subscribe((data:any) => {
if(data.id){
const add_user = this.listUser.find(x => x.uid == user_id)
if (add_user){
this.listFriend.push({username:add_user.username, status:"pending", friend_user_id:add_user.uid, id:data.id})
this.searchTerm = '';
this.listUser = [];
}
}
})
}
private getFriendData(): void {
this.friendService.getFriend().subscribe((data: any[]) => {
if (data.length > 0) {
data.forEach((friend) => {
console.log(friend);
let status = friend['status'];
let userId = friend['friend_user_id'];
let id = friend['id'];
@ -84,6 +143,27 @@ export class FriendPageComponent implements OnInit {
}
deleteFriend(id: string) {
this.friendService.deleteFriend(id).subscribe();
this.friendService.deleteFriend(id).subscribe((data :any) => {
if (data.message == 'Friend deleted') {
this.listFriend.forEach((friend, index) => {
if(friend.id == id) {
this.listFriend.splice(index, 1)
}
})
}
});
}
hasNoAcceptedFriends(): boolean {
return this.listFriend.filter(friend => friend.status === 'accepted').length === 0;
}
hasPendingApprovalFriend(): boolean {
return this.listFriend.filter(friend => friend.status === 'pending_approval').length !== 0;
}
hasPendingFriend(): boolean {
return this.listFriend.filter(friend => friend.status === 'pending').length !== 0;
}
}

@ -69,6 +69,7 @@ export class LoginPageComponent {
this.loginService.login(this.user.login, this.user.password).subscribe({
next: (response) => {
this.localStorageService.setToken(response.access_token);
this.localStorageService.setUsername(this.user.login)
this.closeLoginModal();
setTimeout(() => {
this.router.navigate(['/map']);

@ -150,6 +150,7 @@ export class NavbarComponent implements OnInit {
public logout() {
this.localStorageService.removeToken();
this.localStorageService.removeUsername();
this.router.navigate(['/']);
}
}

@ -30,6 +30,15 @@ export class FriendsService {
return this.http.get<any>(url, { headers });
}
addFriend(user_id: string){
const url = `${this.apiURL}/friend/add`;
const headers = new HttpHeaders({
'Content-Type': 'application/json',
Authorization: 'Bearer ' + localStorage.getItem('auth_token'),
});
return this.http.post<any>(url, { friend_user_id:user_id } , { headers })
}
acceptFriendById(id: string){
const url = `${this.apiURL}/friend/${id}/accept`;
const headers = new HttpHeaders({

@ -7,6 +7,7 @@ import { ModalService } from '../modal/modal.service';
})
export class LocalStorageService {
private readonly AUTH_TOKEN_KEY = 'auth_token';
private readonly USERNAME_KEY = 'username';
constructor(private router: Router, private modalService: ModalService) {}
@ -14,6 +15,18 @@ export class LocalStorageService {
localStorage.setItem(this.AUTH_TOKEN_KEY, token);
}
setUsername(username: string): void {
localStorage.setItem(this.USERNAME_KEY, username);
}
getUsername(): string | null{
return localStorage.getItem(this.USERNAME_KEY);
}
removeUsername(): void {
localStorage.removeItem(this.USERNAME_KEY);
}
getToken(): string | null {
// Check if token is expired
const token = localStorage.getItem(this.AUTH_TOKEN_KEY);

@ -0,0 +1,16 @@
import { TestBed } from '@angular/core/testing';
import { UserService } from './user.service';
describe('UserService', () => {
let service: UserService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(UserService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
});

@ -0,0 +1,26 @@
import { Injectable, OnInit } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { environment } from '../../../environments/environment';
@Injectable({
providedIn: 'root'
})
export class UserService {
private apiURL = environment.apiURL;
constructor(private http: HttpClient) {
}
getUser(username:string) {
const url = `${this.apiURL}/users`;
const headers = new HttpHeaders({
'Content-Type': 'application/json',
Authorization: 'Bearer ' + localStorage.getItem('auth_token'),
});
const params = { name : username };
return this.http.get<any[]>(url,{ headers:headers, params:params })
}
}
Loading…
Cancel
Save