import { useEffect, useMemo, useState } from 'react';
import { BarChart3, CalendarDays, CarFront, Clock3, RefreshCw, Sun } from 'lucide-react';
import MainCard from '@/components/MainCard';
import LoadingCard from '@/components/LoadingCard';
import { Button } from '@/components/ui/button';
import { Badge } from '@/components/ui/badge';
import { timeApi } from '@/api/time';
import { planningApi } from '@/api/planning';
import { useAuth } from '@/context/useAuth';
import { dateKey, formatMinutes, personLabel, inputClass } from '@/components/planning/utils';
import StatisticsPeriodSelector from '@/components/statistics/StatisticsPeriodSelector';
const StatCard = ({ icon: Icon, label, value, detail }) => (
{label}
{value}
{detail &&
{detail}
}
);
const rangeLabel = (stats) => {
if (!stats) return '';
const start = new Date(`${stats.start}T12:00:00`);
const end = new Date(`${stats.end}T12:00:00`);
if (stats.period === 'day') {
return start.toLocaleDateString('fr-FR', { weekday: 'long', day: 'numeric', month: 'long', year: 'numeric' });
}
if (stats.period === 'week') {
const startText = start.toLocaleDateString('fr-FR', { day: 'numeric', month: 'short' });
const endText = end.toLocaleDateString('fr-FR', { day: 'numeric', month: 'long', year: 'numeric' });
return `Du ${startText} au ${endText}`;
}
if (stats.period === 'month') {
return start.toLocaleDateString('fr-FR', { month: 'long', year: 'numeric' });
}
return String(start.getFullYear());
};
export default function UserStatisticsPage() {
const { user } = useAuth();
const [people, setPeople] = useState([]);
const [selectedUserId, setSelectedUserId] = useState('');
const [period, setPeriod] = useState('month');
const [anchor, setAnchor] = useState(dateKey());
const [stats, setStats] = useState(null);
const [loadingPeople, setLoadingPeople] = useState(true);
const [loading, setLoading] = useState(false);
const [error, setError] = useState('');
const [reload, setReload] = useState(0);
const statsPermission = user?.management_permissions?.view_statistics;
const allowedIds = useMemo(() => {
if (user?.is_admin || statsPermission?.all_users) return null;
return new Set((statsPermission?.user_ids || []).map(String));
}, [user, statsPermission]);
useEffect(() => {
const controller = new AbortController();
setLoadingPeople(true);
setError('');
planningApi.people(controller.signal)
.then((rows) => {
const visible = (Array.isArray(rows) ? rows : []).filter((person) => (
user?.is_admin || allowedIds === null || allowedIds.has(String(person.id))
));
setPeople(visible);
setSelectedUserId((current) => (
visible.some((person) => String(person.id) === String(current))
? String(current)
: String(visible[0]?.id || '')
));
})
.catch((e) => { if (!controller.signal.aborted) setError(e.message); })
.finally(() => { if (!controller.signal.aborted) setLoadingPeople(false); });
return () => controller.abort();
}, [user, allowedIds]);
useEffect(() => {
if (!selectedUserId) {
setStats(null);
return undefined;
}
const controller = new AbortController();
setLoading(true);
setError('');
timeApi.getStats({ user_id: selectedUserId, period, anchor }, controller.signal)
.then((data) => { if (!controller.signal.aborted) setStats(data); })
.catch((e) => { if (!controller.signal.aborted) setError(e.message); })
.finally(() => { if (!controller.signal.aborted) setLoading(false); });
return () => controller.abort();
}, [selectedUserId, period, anchor, reload]);
if (loadingPeople) {
return ;
}
return (
{error &&
{error}
}
{stats && (
<>
{rangeLabel(stats)}
{personLabel(stats.user)}
{stats.incomplete_entries > 0 && (
{stats.incomplete_entries} pointage(s) incomplet(s) non compté(s)
)}
>
)}
);
}