- Introduced `projectKey` and `ignoredProjects` fields in Jira configuration to enhance analytics capabilities. - Implemented project validation logic in `JiraConfigClient` and integrated it into the `JiraConfigForm` for user input. - Updated `IntegrationsSettingsPageClient` to display analytics dashboard link based on the configured project key. - Enhanced API routes to handle project key in Jira sync and user preferences. - Marked related tasks as complete in `TODO.md`.
81 lines
2.9 KiB
TypeScript
81 lines
2.9 KiB
TypeScript
'use client';
|
|
|
|
import { BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer, Cell } from 'recharts';
|
|
import { SprintVelocity } from '@/lib/types';
|
|
|
|
interface VelocityChartProps {
|
|
sprintHistory: SprintVelocity[];
|
|
className?: string;
|
|
}
|
|
|
|
export function VelocityChart({ sprintHistory, className }: VelocityChartProps) {
|
|
// Préparer les données pour le graphique
|
|
const chartData = sprintHistory.map(sprint => ({
|
|
name: sprint.sprintName,
|
|
completed: sprint.completedPoints,
|
|
planned: sprint.plannedPoints,
|
|
completionRate: sprint.completionRate
|
|
}));
|
|
|
|
const CustomTooltip = ({ active, payload, label }: {
|
|
active?: boolean;
|
|
payload?: Array<{ payload: { completed: number; planned: number; completionRate: 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 text-sm mb-2">{label}</p>
|
|
<div className="space-y-1 text-xs">
|
|
<div className="flex justify-between gap-4">
|
|
<span>Complétés:</span>
|
|
<span className="font-mono text-green-500">{data.completed} pts</span>
|
|
</div>
|
|
<div className="flex justify-between gap-4">
|
|
<span>Planifiés:</span>
|
|
<span className="font-mono text-blue-500">{data.planned} pts</span>
|
|
</div>
|
|
<div className="flex justify-between gap-4">
|
|
<span>Taux de réussite:</span>
|
|
<span className="font-mono text-orange-500">{data.completionRate}%</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
return null;
|
|
};
|
|
|
|
return (
|
|
<div className={className}>
|
|
<ResponsiveContainer width="100%" height="100%">
|
|
<BarChart data={chartData} margin={{ top: 20, right: 30, left: 20, bottom: 5 }}>
|
|
<CartesianGrid strokeDasharray="3 3" stroke="var(--border)" />
|
|
<XAxis
|
|
dataKey="name"
|
|
stroke="var(--muted-foreground)"
|
|
fontSize={12}
|
|
/>
|
|
<YAxis
|
|
stroke="var(--muted-foreground)"
|
|
fontSize={12}
|
|
/>
|
|
<Tooltip content={<CustomTooltip />} />
|
|
<Bar dataKey="planned" fill="var(--muted)" opacity={0.6} radius={[4, 4, 0, 0]} />
|
|
<Bar dataKey="completed" fill="hsl(142, 76%, 36%)" radius={[4, 4, 0, 0]}>
|
|
{chartData.map((entry, index) => (
|
|
<Cell
|
|
key={`cell-${index}`}
|
|
fill={entry.completionRate >= 80 ? 'hsl(142, 76%, 36%)' :
|
|
entry.completionRate >= 60 ? 'hsl(45, 93%, 47%)' :
|
|
'hsl(0, 84%, 60%)'}
|
|
/>
|
|
))}
|
|
</Bar>
|
|
</BarChart>
|
|
</ResponsiveContainer>
|
|
</div>
|
|
);
|
|
}
|