Files
btpxpress-frontend/app/(main)/employes/stats/page.tsx
2025-10-01 01:39:07 +00:00

341 lines
13 KiB
TypeScript

'use client';
import React, { useState, useEffect } from 'react';
import { Card } from 'primereact/card';
import { Chart } from 'primereact/chart';
import { Button } from 'primereact/button';
import { Toolbar } from 'primereact/toolbar';
import { DataTable } from 'primereact/datatable';
import { Column } from 'primereact/column';
import { Tag } from 'primereact/tag';
import { useRouter } from 'next/navigation';
import { apiClient } from '../../../../services/api-client';
interface StatistiquesEmployes {
totalEmployes: number;
employesActifs: number;
employesInactifs: number;
employesEnConge: number;
employesEnFormation: number;
repartitionParMetier: { [key: string]: number };
repartitionParExperience: { [key: string]: number };
repartitionParEquipe: { [key: string]: number };
employesSansCertification: number;
employesAvecCertifications: number;
moyenneAgeEmployes: number;
ancienneteMoyenne: number;
tauxDisponibilite: number;
topCompetences: Array<{ competence: string; nombre: number }>;
topCertifications: Array<{ certification: string; nombre: number }>;
}
const StatistiquesEmployesPage = () => {
const [stats, setStats] = useState<StatistiquesEmployes | null>(null);
const [loading, setLoading] = useState(true);
const [chartOptions] = useState({
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
position: 'bottom'
}
}
});
const router = useRouter();
useEffect(() => {
loadStatistiques();
}, []);
const loadStatistiques = async () => {
try {
setLoading(true);
console.log('🔄 Chargement des statistiques employés...');
const response = await apiClient.get('/api/employes/statistiques');
console.log('✅ Statistiques employés chargées:', response.data);
setStats(response.data);
} catch (error) {
console.error('❌ Erreur lors du chargement des statistiques:', error);
} finally {
setLoading(false);
}
};
const getStatutChartData = () => {
if (!stats) return {};
return {
labels: ['Actifs', 'Inactifs', 'En congé', 'En formation'],
datasets: [{
data: [
stats.employesActifs,
stats.employesInactifs,
stats.employesEnConge,
stats.employesEnFormation
],
backgroundColor: [
'#4CAF50',
'#F44336',
'#FF9800',
'#2196F3'
],
borderWidth: 2
}]
};
};
const getMetierChartData = () => {
if (!stats) return {};
return {
labels: Object.keys(stats.repartitionParMetier),
datasets: [{
data: Object.values(stats.repartitionParMetier),
backgroundColor: [
'#FF6384',
'#36A2EB',
'#FFCE56',
'#4BC0C0',
'#9966FF',
'#FF9F40',
'#FF6384',
'#C9CBCF'
],
borderWidth: 2
}]
};
};
const getExperienceChartData = () => {
if (!stats) return {};
return {
labels: Object.keys(stats.repartitionParExperience),
datasets: [{
label: 'Nombre d\'employés',
data: Object.values(stats.repartitionParExperience),
backgroundColor: '#36A2EB',
borderColor: '#36A2EB',
borderWidth: 1
}]
};
};
const leftToolbarTemplate = () => {
return (
<div className="flex flex-wrap gap-2">
<Button
label="Retour aux employés"
icon="pi pi-arrow-left"
className="p-button-outlined"
onClick={() => router.push('/employes')}
/>
<Button
label="Export PDF"
icon="pi pi-file-pdf"
className="p-button-danger"
onClick={() => console.log('Export PDF')}
/>
<Button
label="Export Excel"
icon="pi pi-file-excel"
className="p-button-success"
onClick={() => console.log('Export Excel')}
/>
</div>
);
};
const rightToolbarTemplate = () => {
return (
<Button
icon="pi pi-refresh"
className="p-button-outlined"
onClick={loadStatistiques}
tooltip="Actualiser"
/>
);
};
if (loading) {
return (
<div className="grid">
<div className="col-12">
<Card>
<div className="flex justify-content-center">
<i className="pi pi-spin pi-spinner" style={{ fontSize: '2rem' }} />
</div>
</Card>
</div>
</div>
);
}
if (!stats) {
return (
<div className="grid">
<div className="col-12">
<Card>
<div className="text-center">
<p>Aucune donnée disponible</p>
</div>
</Card>
</div>
</div>
);
}
return (
<div className="grid">
<div className="col-12">
<Toolbar
className="mb-4"
left={leftToolbarTemplate}
right={rightToolbarTemplate}
/>
</div>
{/* Métriques principales */}
<div className="col-12 lg:col-3 md:col-6">
<Card className="bg-blue-100">
<div className="flex justify-content-between align-items-center">
<div>
<span className="block text-500 font-medium mb-3">Total Employés</span>
<div className="text-900 font-medium text-xl">{stats.totalEmployes}</div>
</div>
<div className="flex align-items-center justify-content-center bg-blue-500 border-round" style={{ width: '2.5rem', height: '2.5rem' }}>
<i className="pi pi-users text-white text-xl" />
</div>
</div>
</Card>
</div>
<div className="col-12 lg:col-3 md:col-6">
<Card className="bg-green-100">
<div className="flex justify-content-between align-items-center">
<div>
<span className="block text-500 font-medium mb-3">Employés Actifs</span>
<div className="text-900 font-medium text-xl">{stats.employesActifs}</div>
</div>
<div className="flex align-items-center justify-content-center bg-green-500 border-round" style={{ width: '2.5rem', height: '2.5rem' }}>
<i className="pi pi-check-circle text-white text-xl" />
</div>
</div>
</Card>
</div>
<div className="col-12 lg:col-3 md:col-6">
<Card className="bg-orange-100">
<div className="flex justify-content-between align-items-center">
<div>
<span className="block text-500 font-medium mb-3">Taux Disponibilité</span>
<div className="text-900 font-medium text-xl">{stats.tauxDisponibilite}%</div>
</div>
<div className="flex align-items-center justify-content-center bg-orange-500 border-round" style={{ width: '2.5rem', height: '2.5rem' }}>
<i className="pi pi-calendar-check text-white text-xl" />
</div>
</div>
</Card>
</div>
<div className="col-12 lg:col-3 md:col-6">
<Card className="bg-purple-100">
<div className="flex justify-content-between align-items-center">
<div>
<span className="block text-500 font-medium mb-3">Ancienneté Moyenne</span>
<div className="text-900 font-medium text-xl">{stats.ancienneteMoyenne} ans</div>
</div>
<div className="flex align-items-center justify-content-center bg-purple-500 border-round" style={{ width: '2.5rem', height: '2.5rem' }}>
<i className="pi pi-clock text-white text-xl" />
</div>
</div>
</Card>
</div>
{/* Graphiques */}
<div className="col-12 lg:col-6">
<Card title="Répartition par Statut">
<Chart type="doughnut" data={getStatutChartData()} options={chartOptions} style={{ height: '300px' }} />
</Card>
</div>
<div className="col-12 lg:col-6">
<Card title="Répartition par Métier">
<Chart type="pie" data={getMetierChartData()} options={chartOptions} style={{ height: '300px' }} />
</Card>
</div>
<div className="col-12">
<Card title="Répartition par Niveau d'Expérience">
<Chart type="bar" data={getExperienceChartData()} options={chartOptions} style={{ height: '300px' }} />
</Card>
</div>
{/* Tableaux de données */}
<div className="col-12 lg:col-6">
<Card title="Top Compétences">
<DataTable value={stats.topCompetences} responsiveLayout="scroll">
<Column field="competence" header="Compétence" />
<Column
field="nombre"
header="Nombre d'employés"
body={(rowData) => <Tag value={rowData.nombre} severity="info" />}
/>
</DataTable>
</Card>
</div>
<div className="col-12 lg:col-6">
<Card title="Top Certifications">
<DataTable value={stats.topCertifications} responsiveLayout="scroll">
<Column field="certification" header="Certification" />
<Column
field="nombre"
header="Nombre d'employés"
body={(rowData) => <Tag value={rowData.nombre} severity="success" />}
/>
</DataTable>
</Card>
</div>
{/* Informations supplémentaires */}
<div className="col-12">
<Card title="Informations Complémentaires">
<div className="grid">
<div className="col-12 md:col-4">
<div className="text-center">
<i className="pi pi-graduation-cap text-4xl text-blue-500 mb-3" />
<h4>Certifications</h4>
<p className="text-600">
{stats.employesAvecCertifications} employés avec certifications<br />
{stats.employesSansCertification} sans certification
</p>
</div>
</div>
<div className="col-12 md:col-4">
<div className="text-center">
<i className="pi pi-calendar text-4xl text-green-500 mb-3" />
<h4>Âge Moyen</h4>
<p className="text-600">
{stats.moyenneAgeEmployes} ans
</p>
</div>
</div>
<div className="col-12 md:col-4">
<div className="text-center">
<i className="pi pi-users text-4xl text-orange-500 mb-3" />
<h4>Équipes</h4>
<p className="text-600">
{Object.keys(stats.repartitionParEquipe).length} équipes actives
</p>
</div>
</div>
</div>
</Card>
</div>
</div>
);
};
export default StatistiquesEmployesPage;