Files
towercontrol/src/components/jira/sprint/SprintOverview.tsx
Julien Froidefond 0a03e40469 feat: enhance metrics dashboard with new components and data handling
- Introduced `MetricsOverview`, `MetricsMainCharts`, `MetricsDistributionCharts`, `MetricsVelocitySection`, and `MetricsProductivitySection` for improved metrics visualization.
- Updated `MetricsTab` to integrate new components and streamline data presentation.
- Added compatibility fields in `JiraTask` and `AssigneeDistribution` for better data handling.
- Refactored `calculateAssigneeDistribution` to include a count for total issues.
- Enhanced `JiraAnalyticsService` and `JiraAdvancedFiltersService` to support new metrics calculations.
- Cleaned up unused imports and components for a more maintainable codebase.
2025-09-21 15:55:11 +02:00

129 lines
4.8 KiB
TypeScript

'use client';
import { Card, CardHeader, CardContent } from '@/components/ui/Card';
import { Badge } from '@/components/ui/Badge';
import { SprintDetails } from '../SprintDetailModal';
import { formatDateForDisplay } from '@/lib/date-utils';
interface SprintOverviewProps {
sprintDetails: SprintDetails;
}
export function SprintOverview({ sprintDetails }: SprintOverviewProps) {
const { sprint, metrics, assigneeDistribution, statusDistribution } = sprintDetails;
const getVelocityTrendIcon = (trend: string) => {
switch (trend) {
case 'up': return '📈';
case 'down': return '📉';
case 'stable': return '➡️';
default: return '📊';
}
};
return (
<div className="space-y-4">
{/* Informations générales */}
<Card>
<CardHeader>
<h3 className="font-semibold">📋 Informations générales</h3>
</CardHeader>
<CardContent>
<div className="grid grid-cols-2 gap-4">
<div>
<p className="text-sm text-gray-600">Nom du sprint</p>
<p className="font-medium">{sprint.sprintName}</p>
</div>
<div>
<p className="text-sm text-gray-600">Vélocité</p>
<div className="flex items-center gap-2">
<span className="font-medium">{sprint.velocity || sprint.completedPoints} points</span>
<span>{getVelocityTrendIcon(metrics.velocityTrend)}</span>
</div>
</div>
<div>
<p className="text-sm text-gray-600">Période</p>
<p className="text-sm">
{formatDateForDisplay(new Date(sprint.startDate))} - {formatDateForDisplay(new Date(sprint.endDate))}
</p>
</div>
<div>
<p className="text-sm text-gray-600">Cycle time moyen</p>
<p className="font-medium">{metrics.averageCycleTime.toFixed(1)} jours</p>
</div>
</div>
</CardContent>
</Card>
{/* Métriques clés */}
<Card>
<CardHeader>
<h3 className="font-semibold">📊 Métriques clés</h3>
</CardHeader>
<CardContent>
<div className="grid grid-cols-2 lg:grid-cols-4 gap-4">
<div className="text-center p-3 bg-blue-50 rounded-lg">
<div className="text-2xl font-bold text-blue-600">{metrics.totalIssues}</div>
<div className="text-sm text-blue-600">Total issues</div>
</div>
<div className="text-center p-3 bg-green-50 rounded-lg">
<div className="text-2xl font-bold text-green-600">{metrics.completedIssues}</div>
<div className="text-sm text-green-600">Terminées</div>
</div>
<div className="text-center p-3 bg-orange-50 rounded-lg">
<div className="text-2xl font-bold text-orange-600">{metrics.inProgressIssues}</div>
<div className="text-sm text-orange-600">En cours</div>
</div>
<div className="text-center p-3 bg-red-50 rounded-lg">
<div className="text-2xl font-bold text-red-600">{metrics.blockedIssues}</div>
<div className="text-sm text-red-600">Bloquées</div>
</div>
</div>
</CardContent>
</Card>
{/* Répartition par assigné */}
<div className="grid grid-cols-1 lg:grid-cols-2 gap-4">
<Card>
<CardHeader>
<h3 className="font-semibold">👥 Répartition par assigné</h3>
</CardHeader>
<CardContent>
<div className="space-y-2">
{assigneeDistribution.map((assignee, index) => (
<div key={index} className="flex items-center justify-between p-2 bg-gray-50 rounded">
<span className="text-sm font-medium">
{assignee.assignee || 'Non assigné'}
</span>
<Badge variant="outline" size="sm">
{assignee.count || assignee.totalIssues} issues
</Badge>
</div>
))}
</div>
</CardContent>
</Card>
{/* Répartition par statut */}
<Card>
<CardHeader>
<h3 className="font-semibold">📈 Répartition par statut</h3>
</CardHeader>
<CardContent>
<div className="space-y-2">
{statusDistribution.map((status, index) => (
<div key={index} className="flex items-center justify-between p-2 bg-gray-50 rounded">
<span className="text-sm font-medium">{status.status}</span>
<Badge variant="outline" size="sm">
{status.count} issues
</Badge>
</div>
))}
</div>
</CardContent>
</Card>
</div>
</div>
);
}