199 lines
5.9 KiB
TypeScript
199 lines
5.9 KiB
TypeScript
import { CommonModule } from '@angular/common';
|
|
import {
|
|
ChangeDetectionStrategy,
|
|
Component,
|
|
ViewChild,
|
|
signal,
|
|
effect,
|
|
untracked,
|
|
} from '@angular/core';
|
|
import { DataTable, TableColumn, SortState } from '@shared/components/data-table/data-table';
|
|
import { Paginator } from '@shared/components/paginator/paginator';
|
|
import { SearchBar } from '@shared/components/search-bar/search-bar';
|
|
import { Modal } from '@shared/components/modal/modal';
|
|
import { ZardButtonComponent } from '@shared/components/button/button.component';
|
|
import { SortDir } from '@shared/paging/paging';
|
|
import { User } from 'src/app/core/interfaces/user';
|
|
import { UserService } from 'src/app/core/services/user';
|
|
import { Role } from 'src/app/core/interfaces/role';
|
|
import { RoleService } from 'src/app/core/services/role';
|
|
import { UserForm } from '@shared/forms/user-form/user-form';
|
|
import { toast } from 'ngx-sonner';
|
|
|
|
@Component({
|
|
standalone: true,
|
|
selector: 'app-users',
|
|
templateUrl: './users.html',
|
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
imports: [CommonModule, DataTable, Paginator, SearchBar, Modal, ZardButtonComponent, UserForm],
|
|
})
|
|
export class UsersPage {
|
|
rows = signal<User[]>([]);
|
|
total = signal(0);
|
|
loading = signal(false);
|
|
roleMap = new Map<string, string>();
|
|
|
|
page = signal(1);
|
|
perPage = signal(10);
|
|
search = signal('');
|
|
sort = signal<SortState>({ key: 'nom', dir: 'asc' });
|
|
|
|
modalOpen = signal(false);
|
|
modalTitle = signal('Nouvel utilisateur');
|
|
editingItem = signal<User | null>(null);
|
|
|
|
@ViewChild(UserForm) formComp?: UserForm;
|
|
|
|
cols: TableColumn<User>[] = [
|
|
{ key: 'nom', label: 'Nom', sortable: true },
|
|
{ key: 'prenom', label: 'Prénom', sortable: true },
|
|
{ key: 'identifiant', label: 'Identifiant', sortable: true },
|
|
{ key: 'matriculeAgent', label: 'Matricule', sortable: true },
|
|
{
|
|
key: 'role.name',
|
|
label: 'Rôle',
|
|
sortable: true,
|
|
cell: (u) => this.roleMap.get(u.roleId) ?? u.role?.name ?? '—',
|
|
},
|
|
{ key: 'statut', label: 'Statut', sortable: true },
|
|
{
|
|
key: 'derniereConnexion',
|
|
label: 'Dernière connexion',
|
|
cell: (u) =>
|
|
u.derniereConnexion ? new Date(u.derniereConnexion).toLocaleDateString('fr-FR') : '—',
|
|
},
|
|
{
|
|
key: 'restrictionConnexion',
|
|
label: 'Restr. Conn.',
|
|
cell: (u) => String(u.restrictionConnexion),
|
|
},
|
|
{
|
|
key: 'restrictionAutomatique',
|
|
label: 'Restr. Auto',
|
|
cell: (u) => String(u.restrictionAutomatique),
|
|
},
|
|
{ key: 'nombreIpAutorise', label: 'IP Autorisé' },
|
|
{ key: 'nombreIpAutoAutorise', label: 'IP Auto' },
|
|
];
|
|
|
|
constructor(private api: UserService, private roleService: RoleService) {
|
|
this.roleService
|
|
.list({ page: 1, perPage: 100, search: '', sortKey: 'name', sortDir: 'asc' } as any)
|
|
.subscribe((res) => (res.data as Role[]).forEach((r) => this.roleMap.set(r.id, r.name)));
|
|
effect(() => {
|
|
const params = {
|
|
page: this.page(),
|
|
perPage: this.perPage(),
|
|
search: this.search(),
|
|
sortKey: this.sort().key,
|
|
sortDir: this.sort().dir as SortDir,
|
|
};
|
|
untracked(() => this.fetch(params));
|
|
});
|
|
}
|
|
|
|
private fetch(params: {
|
|
page: number;
|
|
perPage: number;
|
|
search: string;
|
|
sortKey: string;
|
|
sortDir: SortDir;
|
|
}) {
|
|
this.loading.set(true);
|
|
this.api.list(params).subscribe({
|
|
next: (res) => {
|
|
this.rows.set(res.data);
|
|
this.total.set(res.meta.total);
|
|
this.loading.set(false);
|
|
},
|
|
error: () => {
|
|
this.rows.set([]);
|
|
this.total.set(0);
|
|
this.loading.set(false);
|
|
},
|
|
});
|
|
}
|
|
|
|
onSearch(q: string) {
|
|
this.search.set(q);
|
|
this.page.set(1);
|
|
}
|
|
|
|
openCreate() {
|
|
this.modalTitle.set('Nouvel utilisateur');
|
|
this.editingItem.set(null);
|
|
queueMicrotask(() => this.modalOpen.set(true));
|
|
}
|
|
|
|
openEdit(row: User) {
|
|
this.modalTitle.set("Modifier l'utilisateur");
|
|
this.editingItem.set(row);
|
|
queueMicrotask(() => this.modalOpen.set(true));
|
|
}
|
|
|
|
closeModal() {
|
|
this.modalOpen.set(false);
|
|
}
|
|
|
|
submitChildForm() {
|
|
this.formComp?.onSubmit();
|
|
}
|
|
|
|
onFormSave(payload: Partial<User>) {
|
|
const current = this.editingItem();
|
|
const req$ = current?.id
|
|
? this.api.update(current.id, payload)
|
|
: this.api.create(payload as Omit<User, 'id'>);
|
|
req$.subscribe({
|
|
next: (user) => {
|
|
this.closeModal();
|
|
toast.success(
|
|
current?.id
|
|
? `L'utilisateur « ${user?.nom ?? ''} ${
|
|
user?.prenom ?? ''
|
|
} » a été mis à jour avec succès`
|
|
: `L'utilisateur « ${user?.nom ?? ''} ${user?.prenom ?? ''} » a été créé avec succès`
|
|
);
|
|
this.fetch({
|
|
page: this.page(),
|
|
perPage: this.perPage(),
|
|
search: this.search(),
|
|
sortKey: this.sort().key,
|
|
sortDir: this.sort().dir as SortDir,
|
|
});
|
|
},
|
|
error: () => {
|
|
toast.error(
|
|
current?.id
|
|
? "Erreur lors de la mise à jour de l'utilisateur"
|
|
: "Erreur lors de la création de l'utilisateur",
|
|
{ duration: 5000 }
|
|
);
|
|
},
|
|
});
|
|
}
|
|
|
|
remove(row: User) {
|
|
if (!confirm(`Supprimer l\'utilisateur « ${row.nom} ${row.prenom} » ?`)) return;
|
|
this.api.delete(row.id).subscribe({
|
|
next: (ok) => {
|
|
if (ok) {
|
|
toast.success(`L'utilisateur « ${row.nom} ${row.prenom} » a été supprimé avec succès`);
|
|
this.fetch({
|
|
page: this.page(),
|
|
perPage: this.perPage(),
|
|
search: this.search(),
|
|
sortKey: this.sort().key,
|
|
sortDir: this.sort().dir as SortDir,
|
|
});
|
|
} else {
|
|
toast.error("Erreur lors de la suppression de l'utilisateur", { duration: 5000 });
|
|
}
|
|
},
|
|
error: () => {
|
|
toast.error("Erreur lors de la suppression de l'utilisateur", { duration: 5000 });
|
|
},
|
|
});
|
|
}
|
|
}
|