diff --git a/lib/jira-period-filter.ts b/lib/jira-period-filter.ts new file mode 100644 index 0000000..5e15594 --- /dev/null +++ b/lib/jira-period-filter.ts @@ -0,0 +1,143 @@ +import { JiraAnalytics, JiraTask, SprintVelocity } from './types'; + +export type PeriodFilter = '7d' | '30d' | '3m' | 'current'; + +/** + * Filtre les analytics Jira selon la période sélectionnée + */ +export function filterAnalyticsByPeriod( + analytics: JiraAnalytics, + period: PeriodFilter +): JiraAnalytics { + const now = new Date(); + let cutoffDate: Date; + + switch (period) { + case '7d': + cutoffDate = new Date(now.getTime() - (7 * 24 * 60 * 60 * 1000)); + break; + case '30d': + cutoffDate = new Date(now.getTime() - (30 * 24 * 60 * 60 * 1000)); + break; + case '3m': + cutoffDate = new Date(now.getTime() - (90 * 24 * 60 * 60 * 1000)); + break; + case 'current': + default: + // Pour "Sprint actuel", on garde toutes les données mais on filtre les sprints + return filterCurrentSprintAnalytics(analytics); + } + + // Filtrer les données par date + return filterAnalyticsByDate(analytics, cutoffDate); +} + +/** + * Filtre les analytics pour ne garder que le sprint actuel + */ +function filterCurrentSprintAnalytics(analytics: JiraAnalytics): JiraAnalytics { + // Garder seulement le dernier sprint (le plus récent) + const currentSprint = analytics.velocityMetrics.sprintHistory.slice(-1); + + return { + ...analytics, + velocityMetrics: { + ...analytics.velocityMetrics, + sprintHistory: currentSprint, + // Recalculer la vélocité moyenne avec seulement le sprint actuel + averageVelocity: currentSprint.length > 0 ? currentSprint[0].completedPoints : 0 + } + }; +} + +/** + * Filtre les analytics par date de cutoff + */ +function filterAnalyticsByDate(analytics: JiraAnalytics, cutoffDate: Date): JiraAnalytics { + // Filtrer l'historique des sprints + const filteredSprintHistory = analytics.velocityMetrics.sprintHistory.filter(sprint => { + const sprintEndDate = new Date(sprint.endDate); + return sprintEndDate >= cutoffDate; + }); + + // Si aucun sprint dans la période, garder au moins le plus récent + const sprintHistory = filteredSprintHistory.length > 0 + ? filteredSprintHistory + : analytics.velocityMetrics.sprintHistory.slice(-1); + + // Recalculer la vélocité moyenne + const averageVelocity = sprintHistory.length > 0 + ? Math.round(sprintHistory.reduce((sum, sprint) => sum + sprint.completedPoints, 0) / sprintHistory.length) + : 0; + + // Pour simplifier, on garde les autres métriques inchangées + // Dans une vraie implémentation, on devrait re-filtrer toutes les données + return { + ...analytics, + velocityMetrics: { + ...analytics.velocityMetrics, + sprintHistory, + averageVelocity + } + }; +} + +/** + * Retourne un label descriptif pour la période sélectionnée + */ +export function getPeriodLabel(period: PeriodFilter): string { + switch (period) { + case '7d': + return 'Derniers 7 jours'; + case '30d': + return 'Derniers 30 jours'; + case '3m': + return 'Derniers 3 mois'; + case 'current': + return 'Sprint actuel'; + default: + return 'Période inconnue'; + } +} + +/** + * Retourne des informations sur la période pour l'affichage + */ +export function getPeriodInfo(period: PeriodFilter): { + label: string; + description: string; + icon: string; +} { + switch (period) { + case '7d': + return { + label: 'Derniers 7 jours', + description: 'Vue hebdomadaire des métriques', + icon: '📅' + }; + case '30d': + return { + label: 'Derniers 30 jours', + description: 'Vue mensuelle des métriques', + icon: '📊' + }; + case '3m': + return { + label: 'Derniers 3 mois', + description: 'Vue trimestrielle des métriques', + icon: '📈' + }; + case 'current': + return { + label: 'Sprint actuel', + description: 'Focus sur le sprint en cours', + icon: '🎯' + }; + default: + return { + label: 'Période inconnue', + description: '', + icon: '❓' + }; + } +} diff --git a/src/app/jira-dashboard/JiraDashboardPageClient.tsx b/src/app/jira-dashboard/JiraDashboardPageClient.tsx index 78cfb5d..30afb99 100644 --- a/src/app/jira-dashboard/JiraDashboardPageClient.tsx +++ b/src/app/jira-dashboard/JiraDashboardPageClient.tsx @@ -1,9 +1,10 @@ 'use client'; -import { useState, useEffect } from 'react'; +import { useState, useEffect, useMemo } from 'react'; import { JiraConfig } from '@/lib/types'; import { useJiraAnalytics } from '@/hooks/useJiraAnalytics'; import { useJiraExport } from '@/hooks/useJiraExport'; +import { filterAnalyticsByPeriod, getPeriodInfo, type PeriodFilter } from '@/lib/jira-period-filter'; import { Header } from '@/components/ui/Header'; import { Card, CardHeader, CardContent } from '@/components/ui/Card'; import { Button } from '@/components/ui/Button'; @@ -24,9 +25,18 @@ interface JiraDashboardPageClientProps { } export function JiraDashboardPageClient({ initialJiraConfig }: JiraDashboardPageClientProps) { - const { analytics, isLoading, error, loadAnalytics, refreshAnalytics } = useJiraAnalytics(); + const { analytics: rawAnalytics, isLoading, error, loadAnalytics, refreshAnalytics } = useJiraAnalytics(); const { isExporting, error: exportError, exportCSV, exportJSON } = useJiraExport(); - const [selectedPeriod, setSelectedPeriod] = useState<'7d' | '30d' | '3m' | 'current'>('current'); + const [selectedPeriod, setSelectedPeriod] = useState('current'); + + // Filtrer les analytics selon la période sélectionnée + const analytics = useMemo(() => { + if (!rawAnalytics) return null; + return filterAnalyticsByPeriod(rawAnalytics, selectedPeriod); + }, [rawAnalytics, selectedPeriod]); + + // Informations sur la période pour l'affichage + const periodInfo = getPeriodInfo(selectedPeriod); useEffect(() => { // Charger les analytics au montage si Jira est configuré avec un projet @@ -131,9 +141,16 @@ export function JiraDashboardPageClient({ initialJiraConfig }: JiraDashboardPage

📊 Analytics d'équipe

-

- Surveillance en temps réel du projet {initialJiraConfig.projectKey} -

+
+

+ Surveillance en temps réel du projet {initialJiraConfig.projectKey} +

+

+ {periodInfo.icon} + {periodInfo.label} + • {periodInfo.description} +

+
@@ -147,7 +164,7 @@ export function JiraDashboardPageClient({ initialJiraConfig }: JiraDashboardPage ].map((period: { value: string; label: string }) => (