This commit is contained in:
OnlyPapy98
2025-12-30 19:09:01 +01:00
parent ed79cae77d
commit f21a5fd4e6
22 changed files with 554 additions and 315 deletions

View File

@@ -88,54 +88,16 @@ export class AgentsPage {
}
cols: TableColumn<Agent>[] = [
{ key: 'code', label: 'Code', sortable: true },
{ key: 'nom', label: 'Nom', sortable: true },
{ key: 'prenom', label: 'Prénom', sortable: true },
{ key: 'phone', label: 'Téléphone', sortable: true },
{
key: 'tpes',
label: 'TPE assignés',
cell: (a) => {
const tpes = this.agentTpesMap.get(a.id) || [];
if (tpes.length === 0) {
return '<span class="text-muted-foreground text-sm">Aucun</span>';
}
// Show up to 2 TPEs with full details, then count for the rest
const displayCount = Math.min(2, tpes.length);
const displayed = tpes.slice(0, displayCount);
const remaining = tpes.length - displayCount;
const tpeCards = displayed
.map((t) => {
const imei = `<div class="font-medium text-xs">${t.imei}</div>`;
const details = [
t.marque && t.modele ? `${t.marque} ${t.modele}` : t.marque || t.modele || '',
t.statut ? this.formatTpeStatut(t.statut) : '',
]
.filter(Boolean)
.join(' • ');
const detailsHtml = details
? `<div class="text-xs text-muted-foreground">${details}</div>`
: '';
return `<div class="px-2 py-1.5 rounded bg-primary/10 border border-primary/20 flex flex-col gap-0.5">${imei}${detailsHtml}</div>`;
})
.join(' ');
const moreHtml =
remaining > 0
? `<div class="text-xs text-muted-foreground px-2 py-1.5">+${remaining} autre${
remaining > 1 ? 's' : ''
}</div>`
: '';
return `<div class="flex flex-col gap-1">${tpeCards}${moreHtml}</div>`;
},
},
{ key: 'code', label: 'Code', sortable: true, defaultVisible: true },
{ key: 'nomPrenom', label: 'Nom complet', sortable: true, defaultVisible: true, cell: (a) => `${a.nom} ${a.prenom}` },
{ key: 'profile', label: 'Profil', sortable: true, defaultVisible: true },
{ key: 'statut', label: 'Statut', sortable: true, defaultVisible: true, cell: (a) => this.renderStatutBadge(a.statut) },
{ key: 'phone', label: 'Téléphone', sortable: true, defaultVisible: true },
{ key: 'zone', label: 'Zone', sortable: true },
{ key: 'kiosk', label: 'Kiosque', sortable: true },
{ key: 'profile', label: 'Profil', sortable: true },
{ key: 'statut', label: 'Statut', sortable: true },
{ key: 'limiteSuperieure', label: 'Limite sup.', sortable: true },
{ key: 'tpes', label: 'TPE', cell: (a) => `${(this.getAgentTpes(a.id) || []).length}` },
{ key: 'limites', label: 'Limites', cell: (a) => this.formatLimits(a) },
{ key: 'dateEmbauche', label: 'Embauché le', cell: (a) => (a.dateEmbauche ? new Date(a.dateEmbauche).toLocaleDateString() : '') },
];
tpeMap = new Map<string, TpeDevice>();
@@ -216,6 +178,26 @@ export class AgentsPage {
return this.agentTpesMap.get(agentId) || [];
}
renderStatutBadge(statut: Agent['statut'] | string | undefined): string {
if (!statut) return '';
const s = String(statut).toUpperCase();
if (s === 'ACTIF') {
return `<span class="inline-flex items-center gap-1 px-2 py-1 rounded bg-green-500/10 text-green-600 dark:text-green-400 text-xs font-medium"><i class="icon-check"></i> Actif</span>`;
}
if (s === 'INACTIF') {
return `<span class="inline-flex items-center gap-1 px-2 py-1 rounded bg-gray-500/10 text-gray-600 dark:text-gray-400 text-xs font-medium"><i class="icon-x"></i> Inactif</span>`;
}
return `<span class="inline-flex items-center gap-1 px-2 py-1 rounded bg-orange-500/10 text-orange-600 dark:text-orange-400 text-xs font-medium"><i class="icon-alert-circle"></i> Suspendu</span>`;
}
formatLimits(a: Agent): string {
const parts: string[] = [];
const nf = new Intl.NumberFormat(undefined, { maximumFractionDigits: 2 });
if (a.limiteInferieure !== undefined) parts.push(nf.format(a.limiteInferieure));
if (a.limiteSuperieure !== undefined) parts.push(nf.format(a.limiteSuperieure));
return parts.length ? parts.join(' — ') : '';
}
onSearch(q: string) {
this.search.set(q);
this.page.set(1);