258 lines
7.5 KiB
TypeScript
258 lines
7.5 KiB
TypeScript
import { Component, inject, OnInit, Output, EventEmitter, ChangeDetectorRef } from '@angular/core';
|
|
import { CommonModule } from '@angular/common';
|
|
import { FormsModule } from '@angular/forms';
|
|
import { NgIcon } from '@ng-icons/core';
|
|
import { NgbPaginationModule } from '@ng-bootstrap/ng-bootstrap';
|
|
import { UsersService } from '../services/users.service';
|
|
import { UserResponse } from '../models/user';
|
|
import { UiCard } from '@app/components/ui-card';
|
|
|
|
@Component({
|
|
selector: 'app-users-list',
|
|
standalone: true,
|
|
imports: [
|
|
CommonModule,
|
|
FormsModule,
|
|
NgIcon,
|
|
UiCard,
|
|
NgbPaginationModule
|
|
],
|
|
templateUrl: './list.html',
|
|
})
|
|
export class UsersList implements OnInit {
|
|
private usersService = inject(UsersService);
|
|
private cdRef = inject(ChangeDetectorRef);
|
|
|
|
@Output() userSelected = new EventEmitter<string>();
|
|
@Output() openCreateModal = new EventEmitter<void>();
|
|
@Output() openResetPasswordModal = new EventEmitter<string>();
|
|
@Output() openDeleteUserModal = new EventEmitter<string>();
|
|
|
|
|
|
|
|
// Données
|
|
allUsers: UserResponse[] = [];
|
|
filteredUsers: UserResponse[] = [];
|
|
displayedUsers: UserResponse[] = [];
|
|
|
|
// États
|
|
loading = false;
|
|
error = '';
|
|
|
|
// Recherche et filtres
|
|
searchTerm = '';
|
|
statusFilter: 'all' | 'enabled' | 'disabled' = 'all';
|
|
emailVerifiedFilter: 'all' | 'verified' | 'not-verified' = 'all';
|
|
|
|
// Pagination
|
|
currentPage = 1;
|
|
itemsPerPage = 10;
|
|
totalItems = 0;
|
|
totalPages = 0;
|
|
|
|
// Tri
|
|
sortField: keyof UserResponse = 'username';
|
|
sortDirection: 'asc' | 'desc' = 'asc';
|
|
|
|
ngOnInit() {
|
|
this.loadUsers();
|
|
}
|
|
|
|
loadUsers() {
|
|
this.loading = true;
|
|
this.error = '';
|
|
|
|
this.usersService.findAllUsers().subscribe({
|
|
next: (response) => {
|
|
this.allUsers = response.data;
|
|
this.applyFiltersAndPagination();
|
|
this.loading = false;
|
|
this.cdRef.detectChanges();
|
|
},
|
|
error: (error) => {
|
|
this.error = 'Erreur lors du chargement des utilisateurs';
|
|
this.loading = false;
|
|
this.cdRef.detectChanges();
|
|
console.error('Error loading users:', error);
|
|
}
|
|
});
|
|
}
|
|
|
|
// Recherche et filtres
|
|
onSearch() {
|
|
this.currentPage = 1;
|
|
this.applyFiltersAndPagination();
|
|
}
|
|
|
|
onClearFilters() {
|
|
this.searchTerm = '';
|
|
this.statusFilter = 'all';
|
|
this.emailVerifiedFilter = 'all';
|
|
this.currentPage = 1;
|
|
this.applyFiltersAndPagination();
|
|
}
|
|
|
|
applyFiltersAndPagination() {
|
|
// Appliquer les filtres
|
|
this.filteredUsers = this.allUsers.filter(user => {
|
|
// Filtre de recherche
|
|
const matchesSearch = !this.searchTerm ||
|
|
user.username.toLowerCase().includes(this.searchTerm.toLowerCase()) ||
|
|
user.email.toLowerCase().includes(this.searchTerm.toLowerCase()) ||
|
|
user.firstName?.toLowerCase().includes(this.searchTerm.toLowerCase()) ||
|
|
user.lastName?.toLowerCase().includes(this.searchTerm.toLowerCase());
|
|
|
|
// Filtre par statut
|
|
const matchesStatus = this.statusFilter === 'all' ||
|
|
(this.statusFilter === 'enabled' && user.enabled) ||
|
|
(this.statusFilter === 'disabled' && !user.enabled);
|
|
|
|
// Filtre par email vérifié
|
|
const matchesEmailVerified = this.emailVerifiedFilter === 'all' ||
|
|
(this.emailVerifiedFilter === 'verified' && user.emailVerified) ||
|
|
(this.emailVerifiedFilter === 'not-verified' && !user.emailVerified);
|
|
|
|
return matchesSearch && matchesStatus && matchesEmailVerified;
|
|
});
|
|
|
|
// Appliquer le tri
|
|
this.filteredUsers.sort((a, b) => {
|
|
const aValue = a[this.sortField];
|
|
const bValue = b[this.sortField];
|
|
|
|
if (aValue === bValue) return 0;
|
|
|
|
let comparison = 0;
|
|
if (typeof aValue === 'string' && typeof bValue === 'string') {
|
|
comparison = aValue.localeCompare(bValue);
|
|
} else if (typeof aValue === 'number' && typeof bValue === 'number') {
|
|
comparison = aValue - bValue;
|
|
} else if (typeof aValue === 'boolean' && typeof bValue === 'boolean') {
|
|
comparison = (aValue === bValue) ? 0 : aValue ? -1 : 1;
|
|
}
|
|
|
|
return this.sortDirection === 'asc' ? comparison : -comparison;
|
|
});
|
|
|
|
// Calculer la pagination
|
|
this.totalItems = this.filteredUsers.length;
|
|
this.totalPages = Math.ceil(this.totalItems / this.itemsPerPage);
|
|
|
|
// Appliquer la pagination
|
|
const startIndex = (this.currentPage - 1) * this.itemsPerPage;
|
|
const endIndex = startIndex + this.itemsPerPage;
|
|
this.displayedUsers = this.filteredUsers.slice(startIndex, endIndex);
|
|
}
|
|
|
|
// Tri
|
|
sort(field: keyof UserResponse) {
|
|
if (this.sortField === field) {
|
|
this.sortDirection = this.sortDirection === 'asc' ? 'desc' : 'asc';
|
|
} else {
|
|
this.sortField = field;
|
|
this.sortDirection = 'asc';
|
|
}
|
|
this.applyFiltersAndPagination();
|
|
}
|
|
|
|
getSortIcon(field: keyof UserResponse): string {
|
|
if (this.sortField !== field) return 'lucideArrowUpDown';
|
|
return this.sortDirection === 'asc' ? 'lucideArrowUp' : 'lucideArrowDown';
|
|
}
|
|
|
|
// Pagination
|
|
onPageChange(page: number) {
|
|
this.currentPage = page;
|
|
this.applyFiltersAndPagination();
|
|
}
|
|
|
|
getStartIndex(): number {
|
|
return (this.currentPage - 1) * this.itemsPerPage + 1;
|
|
}
|
|
|
|
getEndIndex(): number {
|
|
return Math.min(this.currentPage * this.itemsPerPage, this.totalItems);
|
|
}
|
|
|
|
// Actions
|
|
viewUserProfile(userId: string) {
|
|
this.userSelected.emit(userId);
|
|
}
|
|
|
|
// Méthode pour réinitialiser le mot de passe
|
|
resetPassword(user: UserResponse) {
|
|
this.openResetPasswordModal.emit(user.id);
|
|
}
|
|
|
|
// Méthode pour ouvrir le modal de suppression
|
|
deleteUser(user: UserResponse) {
|
|
this.openDeleteUserModal.emit(user.id);
|
|
}
|
|
|
|
|
|
enableUser(user: UserResponse) {
|
|
this.usersService.enableUser(user.id).subscribe({
|
|
next: () => {
|
|
user.enabled = true;
|
|
this.applyFiltersAndPagination();
|
|
this.cdRef.detectChanges();
|
|
},
|
|
error: (error) => {
|
|
console.error('Error enabling user:', error);
|
|
alert('Erreur lors de l\'activation de l\'utilisateur');
|
|
}
|
|
});
|
|
}
|
|
|
|
disableUser(user: UserResponse) {
|
|
this.usersService.disableUser(user.id).subscribe({
|
|
next: () => {
|
|
user.enabled = false;
|
|
this.applyFiltersAndPagination();
|
|
this.cdRef.detectChanges();
|
|
},
|
|
error: (error) => {
|
|
console.error('Error disabling user:', error);
|
|
alert('Erreur lors de la désactivation de l\'utilisateur');
|
|
}
|
|
});
|
|
}
|
|
|
|
// Utilitaires d'affichage
|
|
getStatusBadgeClass(user: UserResponse): string {
|
|
if (!user.enabled) return 'badge bg-danger';
|
|
if (!user.emailVerified) return 'badge bg-warning';
|
|
return 'badge bg-success';
|
|
}
|
|
|
|
getStatusText(user: UserResponse): string {
|
|
if (!user.enabled) return 'Désactivé';
|
|
if (!user.emailVerified) return 'Email non vérifié';
|
|
return 'Actif';
|
|
}
|
|
|
|
getRoleBadgeClass(role: string): string {
|
|
switch (role) {
|
|
case 'admin': return 'bg-danger';
|
|
case 'merchant': return 'bg-success';
|
|
case 'support': return 'bg-info';
|
|
case 'user': return 'bg-secondary';
|
|
default: return 'bg-secondary';
|
|
}
|
|
}
|
|
|
|
formatTimestamp(timestamp: number): string {
|
|
return new Date(timestamp).toLocaleDateString('fr-FR');
|
|
}
|
|
|
|
getUserInitials(user: UserResponse): string {
|
|
return (user.firstName?.charAt(0) || '') + (user.lastName?.charAt(0) || '') || 'U';
|
|
}
|
|
|
|
getUserDisplayName(user: UserResponse): string {
|
|
if (user.firstName && user.lastName) {
|
|
return `${user.firstName} ${user.lastName}`;
|
|
}
|
|
return user.username;
|
|
}
|
|
} |