Files
towercontrol/src/components/dashboard/charts/CompletionRateChart.tsx
Julien Froidefond 0ffcec7ffc refactor: update CustomTooltip types in chart components for better type safety
- Enhanced type definitions for the payload in CustomTooltip across multiple chart components to improve TypeScript support and maintainability.
2025-10-09 13:50:10 +02:00

122 lines
3.4 KiB
TypeScript

'use client';
import {
LineChart,
Line,
XAxis,
YAxis,
CartesianGrid,
Tooltip,
ResponsiveContainer,
} from 'recharts';
import { DailyMetrics } from '@/services/analytics/metrics';
import { parseDate, formatDateShort } from '@/lib/date-utils';
interface CompletionRateChartProps {
data: DailyMetrics[];
className?: string;
}
export function CompletionRateChart({
data,
className,
}: CompletionRateChartProps) {
// Transformer les données pour le graphique
const chartData = data.map((day) => ({
day: day.dayName.substring(0, 3), // Lun, Mar, etc.
date: formatDateShort(parseDate(day.date)),
completionRate: day.completionRate,
completed: day.completed,
total: day.totalTasks,
}));
const CustomTooltip = ({
active,
payload,
label,
}: {
active?: boolean;
payload?: Array<{
payload: {
day: string;
date: string;
completionRate: number;
completed: number;
total: number;
};
}>;
label?: string;
}) => {
if (active && payload && payload.length) {
const data = payload[0].payload;
return (
<div className="bg-[var(--card)] border border-[var(--border)] rounded-lg p-3 shadow-lg">
<p className="font-medium mb-2">{`${label} (${data.date})`}</p>
<p className="text-sm text-[var(--foreground)]">
Taux de completion: {data.completionRate.toFixed(1)}%
</p>
<p className="text-sm text-[var(--muted-foreground)]">
{data.completed} / {data.total} tâches
</p>
</div>
);
}
return null;
};
// Calculer la moyenne pour la ligne de référence
const averageRate =
data.reduce((sum, day) => sum + day.completionRate, 0) / data.length;
return (
<div className={className}>
<ResponsiveContainer width="100%" height={250}>
<LineChart
data={chartData}
margin={{ top: 20, right: 30, left: 20, bottom: 5 }}
>
<CartesianGrid strokeDasharray="3 3" stroke="var(--border)" />
<XAxis dataKey="day" stroke="var(--muted-foreground)" fontSize={12} />
<YAxis
stroke="var(--muted-foreground)"
fontSize={12}
domain={[0, 100]}
tickFormatter={(value) => `${value}%`}
/>
<Tooltip content={<CustomTooltip />} />
<Line
type="monotone"
dataKey="completionRate"
stroke="#10b981"
strokeWidth={3}
dot={{ fill: '#10b981', strokeWidth: 2, r: 4 }}
activeDot={{ r: 6, stroke: '#10b981', strokeWidth: 2 }}
/>
{/* Ligne de moyenne */}
<Line
type="monotone"
dataKey={() => averageRate}
stroke="#94a3b8"
strokeWidth={1}
strokeDasharray="5 5"
dot={false}
activeDot={false}
/>
</LineChart>
</ResponsiveContainer>
{/* Légende */}
<div className="flex items-center justify-center gap-4 mt-2 text-xs text-[var(--muted-foreground)]">
<div className="flex items-center gap-1">
<div className="w-3 h-0.5 bg-green-500"></div>
<span>Taux quotidien</span>
</div>
<div className="flex items-center gap-1">
<div className="w-3 h-0.5 bg-gray-400 border-dashed"></div>
<span>Moyenne ({averageRate.toFixed(1)}%)</span>
</div>
</div>
</div>
);
}