Files
towercontrol/components/jira/CycleTimeChart.tsx
Julien Froidefond 78a96b9c92 feat: add project key support for Jira analytics
- 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`.
2025-09-18 22:08:29 +02:00

86 lines
2.7 KiB
TypeScript

'use client';
import { BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer } from 'recharts';
import { CycleTimeByType } from '@/lib/types';
interface CycleTimeChartProps {
cycleTimeByType: CycleTimeByType[];
className?: string;
}
export function CycleTimeChart({ cycleTimeByType, className }: CycleTimeChartProps) {
// Préparer les données pour le graphique
const chartData = cycleTimeByType.map(type => ({
name: type.issueType,
average: type.averageDays,
median: type.medianDays,
samples: type.samples
}));
const CustomTooltip = ({ active, payload, label }: {
active?: boolean;
payload?: Array<{ payload: { average: number; median: number; samples: 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>Moyenne:</span>
<span className="font-mono text-blue-500">{data.average} jours</span>
</div>
<div className="flex justify-between gap-4">
<span>Médiane:</span>
<span className="font-mono text-green-500">{data.median} jours</span>
</div>
<div className="flex justify-between gap-4">
<span>Échantillons:</span>
<span className="font-mono text-orange-500">{data.samples}</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}
angle={-45}
textAnchor="end"
height={60}
/>
<YAxis
stroke="var(--muted-foreground)"
fontSize={12}
label={{ value: 'Jours', angle: -90, position: 'insideLeft' }}
/>
<Tooltip content={<CustomTooltip />} />
<Bar
dataKey="average"
fill="hsl(217, 91%, 60%)"
radius={[4, 4, 0, 0]}
name="Moyenne"
/>
<Bar
dataKey="median"
fill="hsl(142, 76%, 36%)"
radius={[4, 4, 0, 0]}
name="Médiane"
/>
</BarChart>
</ResponsiveContainer>
</div>
);
}