fix: remove size prop from Emoji component for consistency
- Eliminated the size prop from the Emoji component across various files to standardize rendering and improve code cleanliness.
This commit is contained in:
@@ -110,7 +110,7 @@ export function JiraDashboardPageClient({ initialJiraConfig, initialAnalytics }:
|
|||||||
<div className="container mx-auto px-4 py-8">
|
<div className="container mx-auto px-4 py-8">
|
||||||
<Card className="max-w-2xl mx-auto">
|
<Card className="max-w-2xl mx-auto">
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<h2 className="text-xl font-semibold"><Emoji emoji="⚙️" size={20} /> Configuration requise</h2>
|
<h2 className="text-xl font-semibold"><Emoji emoji="⚙️" /> Configuration requise</h2>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent className="space-y-4">
|
<CardContent className="space-y-4">
|
||||||
<p className="text-[var(--muted-foreground)]">
|
<p className="text-[var(--muted-foreground)]">
|
||||||
@@ -140,7 +140,7 @@ export function JiraDashboardPageClient({ initialJiraConfig, initialAnalytics }:
|
|||||||
<div className="container mx-auto px-4 py-8">
|
<div className="container mx-auto px-4 py-8">
|
||||||
<Card className="max-w-2xl mx-auto">
|
<Card className="max-w-2xl mx-auto">
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<h2 className="text-xl font-semibold"><Emoji emoji="🎯" size={20} /> Projet requis</h2>
|
<h2 className="text-xl font-semibold"><Emoji emoji="🎯" /> Projet requis</h2>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent className="space-y-4">
|
<CardContent className="space-y-4">
|
||||||
<p className="text-[var(--muted-foreground)]">
|
<p className="text-[var(--muted-foreground)]">
|
||||||
@@ -185,7 +185,7 @@ export function JiraDashboardPageClient({ initialJiraConfig, initialAnalytics }:
|
|||||||
<div className="flex items-center justify-between mb-6">
|
<div className="flex items-center justify-between mb-6">
|
||||||
<div>
|
<div>
|
||||||
<h1 className="text-2xl font-mono font-bold text-[var(--foreground)] mb-2">
|
<h1 className="text-2xl font-mono font-bold text-[var(--foreground)] mb-2">
|
||||||
<Emoji emoji="📊" size={18} /> Analytics d'équipe
|
<Emoji emoji="📊" /> Analytics d'équipe
|
||||||
</h1>
|
</h1>
|
||||||
<div className="space-y-1">
|
<div className="space-y-1">
|
||||||
<p className="text-[var(--muted-foreground)]">
|
<p className="text-[var(--muted-foreground)]">
|
||||||
@@ -227,7 +227,7 @@ export function JiraDashboardPageClient({ initialJiraConfig, initialAnalytics }:
|
|||||||
variant="ghost"
|
variant="ghost"
|
||||||
className="text-xs px-2 py-1 h-auto"
|
className="text-xs px-2 py-1 h-auto"
|
||||||
>
|
>
|
||||||
{isExporting ? <Emoji emoji="⏳" size={16} /> : <Emoji emoji="📊" size={16} />} CSV
|
{isExporting ? <Emoji emoji="⏳" /> : <Emoji emoji="📊" />} CSV
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
onClick={exportJSON}
|
onClick={exportJSON}
|
||||||
@@ -246,7 +246,7 @@ export function JiraDashboardPageClient({ initialJiraConfig, initialAnalytics }:
|
|||||||
disabled={isLoading}
|
disabled={isLoading}
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
>
|
>
|
||||||
{isLoading ? <><Emoji emoji="🔄" size={16} /> Actualisation...</> : <><Emoji emoji="🔄" size={16} /> Actualiser</>}
|
{isLoading ? <><Emoji /> Actualisation...</> : <><Emoji emoji="🔄" /> Actualiser</>}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -285,13 +285,13 @@ export function JiraDashboardPageClient({ initialJiraConfig, initialAnalytics }:
|
|||||||
<CardHeader className="pb-4">
|
<CardHeader className="pb-4">
|
||||||
<div className="flex flex-col lg:flex-row lg:items-center lg:justify-between gap-4">
|
<div className="flex flex-col lg:flex-row lg:items-center lg:justify-between gap-4">
|
||||||
<h2 className="text-lg font-semibold flex items-center gap-2">
|
<h2 className="text-lg font-semibold flex items-center gap-2">
|
||||||
<Emoji emoji="🎯" size={16} /> {analytics.project.name}
|
<Emoji emoji="🎯" /> {analytics.project.name}
|
||||||
<span className="text-sm font-normal text-[var(--muted-foreground)]">
|
<span className="text-sm font-normal text-[var(--muted-foreground)]">
|
||||||
({periodInfo.label})
|
({periodInfo.label})
|
||||||
</span>
|
</span>
|
||||||
{hasActiveFilters && (
|
{hasActiveFilters && (
|
||||||
<Badge className="bg-purple-100 text-purple-800 text-xs">
|
<Badge className="bg-purple-100 text-purple-800 text-xs">
|
||||||
<Emoji emoji="🔍" size={12} /> Filtré
|
<Emoji emoji="🔍" /> Filtré
|
||||||
</Badge>
|
</Badge>
|
||||||
)}
|
)}
|
||||||
</h2>
|
</h2>
|
||||||
@@ -351,14 +351,14 @@ export function JiraDashboardPageClient({ initialJiraConfig, initialAnalytics }:
|
|||||||
<div className="space-y-6">
|
<div className="space-y-6">
|
||||||
{/* Info discrète sur le calcul des points */}
|
{/* Info discrète sur le calcul des points */}
|
||||||
<div className="text-xs text-[var(--muted-foreground)] bg-[var(--card-column)] px-3 py-2 rounded border border-[var(--border)]">
|
<div className="text-xs text-[var(--muted-foreground)] bg-[var(--card-column)] px-3 py-2 rounded border border-[var(--border)]">
|
||||||
<Emoji emoji="💡" size={14} /> <strong>Points :</strong> Utilise les story points Jira si définis, sinon Epic(13), Story(5), Task(3), Bug(2), Subtask(1)
|
<Emoji emoji="💡" /> <strong>Points :</strong> Utilise les story points Jira si définis, sinon Epic(13), Story(5), Task(3), Bug(2), Subtask(1)
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Graphiques principaux */}
|
{/* Graphiques principaux */}
|
||||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
||||||
<Card>
|
<Card>
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<h3 className="font-semibold"><Emoji emoji="👥" size={16} /> Répartition de l'équipe</h3>
|
<h3 className="font-semibold"><Emoji emoji="👥" /> Répartition de l'équipe</h3>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<TeamDistributionChart
|
<TeamDistributionChart
|
||||||
@@ -370,7 +370,7 @@ export function JiraDashboardPageClient({ initialJiraConfig, initialAnalytics }:
|
|||||||
|
|
||||||
<Card>
|
<Card>
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<h3 className="font-semibold"><Emoji emoji="🚀" size={16} /> Vélocité des sprints</h3>
|
<h3 className="font-semibold"><Emoji emoji="🚀" /> Vélocité des sprints</h3>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<VelocityChart
|
<VelocityChart
|
||||||
@@ -386,7 +386,7 @@ export function JiraDashboardPageClient({ initialJiraConfig, initialAnalytics }:
|
|||||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
||||||
<Card>
|
<Card>
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<h3 className="font-semibold"><Emoji emoji="⏱️" size={16} /> Cycle Time par type</h3>
|
<h3 className="font-semibold"><Emoji emoji="⏱️" /> Cycle Time par type</h3>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<CycleTimeChart
|
<CycleTimeChart
|
||||||
@@ -443,7 +443,7 @@ export function JiraDashboardPageClient({ initialJiraConfig, initialAnalytics }:
|
|||||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
||||||
<Card>
|
<Card>
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<h3 className="font-semibold"><Emoji emoji="📉" size={16} /> Burndown Chart</h3>
|
<h3 className="font-semibold"><Emoji emoji="📉" /> Burndown Chart</h3>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent className="p-4">
|
<CardContent className="p-4">
|
||||||
<div className="w-full h-96 overflow-hidden">
|
<div className="w-full h-96 overflow-hidden">
|
||||||
@@ -457,7 +457,7 @@ export function JiraDashboardPageClient({ initialJiraConfig, initialAnalytics }:
|
|||||||
|
|
||||||
<Card>
|
<Card>
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<h3 className="font-semibold"><Emoji emoji="📈" size={16} /> Throughput</h3>
|
<h3 className="font-semibold"><Emoji emoji="📈" /> Throughput</h3>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent className="p-4">
|
<CardContent className="p-4">
|
||||||
<div className="w-full h-96 overflow-hidden">
|
<div className="w-full h-96 overflow-hidden">
|
||||||
@@ -473,7 +473,7 @@ export function JiraDashboardPageClient({ initialJiraConfig, initialAnalytics }:
|
|||||||
{/* Métriques de qualité */}
|
{/* Métriques de qualité */}
|
||||||
<Card>
|
<Card>
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<h3 className="font-semibold"><Emoji emoji="🎯" size={16} /> Métriques de qualité</h3>
|
<h3 className="font-semibold"><Emoji emoji="🎯" /> Métriques de qualité</h3>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent className="p-4">
|
<CardContent className="p-4">
|
||||||
<div className="w-full overflow-hidden">
|
<div className="w-full overflow-hidden">
|
||||||
@@ -488,7 +488,7 @@ export function JiraDashboardPageClient({ initialJiraConfig, initialAnalytics }:
|
|||||||
{/* Métriques de predictabilité */}
|
{/* Métriques de predictabilité */}
|
||||||
<Card>
|
<Card>
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<h3 className="font-semibold"><Emoji emoji="📊" size={16} /> Predictabilité</h3>
|
<h3 className="font-semibold"><Emoji emoji="📊" /> Predictabilité</h3>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent className="p-4">
|
<CardContent className="p-4">
|
||||||
<div className="w-full overflow-hidden">
|
<div className="w-full overflow-hidden">
|
||||||
@@ -503,7 +503,7 @@ export function JiraDashboardPageClient({ initialJiraConfig, initialAnalytics }:
|
|||||||
{/* Matrice de collaboration - ligne entière */}
|
{/* Matrice de collaboration - ligne entière */}
|
||||||
<Card>
|
<Card>
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<h3 className="font-semibold"><Emoji emoji="🤝" size={16} /> Matrice de collaboration</h3>
|
<h3 className="font-semibold"><Emoji emoji="🤝" /> Matrice de collaboration</h3>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent className="p-4">
|
<CardContent className="p-4">
|
||||||
<div className="w-full overflow-hidden">
|
<div className="w-full overflow-hidden">
|
||||||
@@ -518,7 +518,7 @@ export function JiraDashboardPageClient({ initialJiraConfig, initialAnalytics }:
|
|||||||
{/* Comparaison inter-sprints */}
|
{/* Comparaison inter-sprints */}
|
||||||
<Card>
|
<Card>
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<h3 className="font-semibold"><Emoji emoji="📊" size={16} /> Comparaison inter-sprints</h3>
|
<h3 className="font-semibold"><Emoji emoji="📊" /> Comparaison inter-sprints</h3>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent className="p-4">
|
<CardContent className="p-4">
|
||||||
<div className="w-full overflow-hidden">
|
<div className="w-full overflow-hidden">
|
||||||
@@ -533,7 +533,7 @@ export function JiraDashboardPageClient({ initialJiraConfig, initialAnalytics }:
|
|||||||
{/* Heatmap d'activité de l'équipe */}
|
{/* Heatmap d'activité de l'équipe */}
|
||||||
<Card>
|
<Card>
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<h3 className="font-semibold"><Emoji emoji="🔥" size={16} /> Heatmap d'activité de l'équipe</h3>
|
<h3 className="font-semibold"><Emoji emoji="🔥" /> Heatmap d'activité de l'équipe</h3>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent className="p-4">
|
<CardContent className="p-4">
|
||||||
<div className="w-full overflow-hidden">
|
<div className="w-full overflow-hidden">
|
||||||
@@ -553,7 +553,7 @@ export function JiraDashboardPageClient({ initialJiraConfig, initialAnalytics }:
|
|||||||
{/* Graphique de vélocité */}
|
{/* Graphique de vélocité */}
|
||||||
<Card>
|
<Card>
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<h3 className="font-semibold"><Emoji emoji="🚀" size={16} /> Vélocité des sprints</h3>
|
<h3 className="font-semibold"><Emoji emoji="🚀" /> Vélocité des sprints</h3>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent className="p-4">
|
<CardContent className="p-4">
|
||||||
<div className="w-full h-64 overflow-hidden">
|
<div className="w-full h-64 overflow-hidden">
|
||||||
@@ -570,7 +570,7 @@ export function JiraDashboardPageClient({ initialJiraConfig, initialAnalytics }:
|
|||||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
||||||
<Card>
|
<Card>
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<h3 className="font-semibold"><Emoji emoji="📉" size={16} /> Burndown Chart</h3>
|
<h3 className="font-semibold"><Emoji emoji="📉" /> Burndown Chart</h3>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent className="p-4">
|
<CardContent className="p-4">
|
||||||
<div className="w-full h-96 overflow-hidden">
|
<div className="w-full h-96 overflow-hidden">
|
||||||
@@ -584,7 +584,7 @@ export function JiraDashboardPageClient({ initialJiraConfig, initialAnalytics }:
|
|||||||
|
|
||||||
<Card>
|
<Card>
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<h3 className="font-semibold"><Emoji emoji="📊" size={16} /> Throughput</h3>
|
<h3 className="font-semibold"><Emoji emoji="📊" /> Throughput</h3>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent className="p-4">
|
<CardContent className="p-4">
|
||||||
<div className="w-full h-96 overflow-hidden">
|
<div className="w-full h-96 overflow-hidden">
|
||||||
@@ -600,7 +600,7 @@ export function JiraDashboardPageClient({ initialJiraConfig, initialAnalytics }:
|
|||||||
{/* Comparaison des sprints */}
|
{/* Comparaison des sprints */}
|
||||||
<Card>
|
<Card>
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<h3 className="font-semibold"><Emoji emoji="📊" size={16} /> Comparaison des sprints</h3>
|
<h3 className="font-semibold"><Emoji emoji="📊" /> Comparaison des sprints</h3>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent className="p-4">
|
<CardContent className="p-4">
|
||||||
<div className="w-full overflow-hidden">
|
<div className="w-full overflow-hidden">
|
||||||
@@ -620,7 +620,7 @@ export function JiraDashboardPageClient({ initialJiraConfig, initialAnalytics }:
|
|||||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
||||||
<Card>
|
<Card>
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<h3 className="font-semibold"><Emoji emoji="⏱️" size={16} /> Cycle Time par type</h3>
|
<h3 className="font-semibold"><Emoji emoji="⏱️" /> Cycle Time par type</h3>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent className="p-4">
|
<CardContent className="p-4">
|
||||||
<div className="w-full h-64 overflow-hidden">
|
<div className="w-full h-64 overflow-hidden">
|
||||||
@@ -660,7 +660,7 @@ export function JiraDashboardPageClient({ initialJiraConfig, initialAnalytics }:
|
|||||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
||||||
<Card>
|
<Card>
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<h3 className="font-semibold"><Emoji emoji="🎯" size={16} /> Métriques de qualité</h3>
|
<h3 className="font-semibold"><Emoji emoji="🎯" /> Métriques de qualité</h3>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent className="p-4">
|
<CardContent className="p-4">
|
||||||
<div className="w-full h-64 overflow-hidden">
|
<div className="w-full h-64 overflow-hidden">
|
||||||
@@ -674,7 +674,7 @@ export function JiraDashboardPageClient({ initialJiraConfig, initialAnalytics }:
|
|||||||
|
|
||||||
<Card>
|
<Card>
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<h3 className="font-semibold"><Emoji emoji="📈" size={16} /> Predictabilité</h3>
|
<h3 className="font-semibold"><Emoji emoji="📈" /> Predictabilité</h3>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent className="p-4">
|
<CardContent className="p-4">
|
||||||
<div className="w-full h-64 overflow-hidden">
|
<div className="w-full h-64 overflow-hidden">
|
||||||
@@ -695,7 +695,7 @@ export function JiraDashboardPageClient({ initialJiraConfig, initialAnalytics }:
|
|||||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
||||||
<Card>
|
<Card>
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<h3 className="font-semibold"><Emoji emoji="👥" size={16} /> Répartition de l'équipe</h3>
|
<h3 className="font-semibold"><Emoji emoji="👥" /> Répartition de l'équipe</h3>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent className="p-4">
|
<CardContent className="p-4">
|
||||||
<div className="w-full h-64 overflow-hidden">
|
<div className="w-full h-64 overflow-hidden">
|
||||||
@@ -709,7 +709,7 @@ export function JiraDashboardPageClient({ initialJiraConfig, initialAnalytics }:
|
|||||||
|
|
||||||
<Card>
|
<Card>
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<h3 className="font-semibold"><Emoji emoji="🤝" size={16} /> Matrice de collaboration</h3>
|
<h3 className="font-semibold"><Emoji emoji="🤝" /> Matrice de collaboration</h3>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent className="p-4">
|
<CardContent className="p-4">
|
||||||
<div className="w-full h-64 overflow-hidden">
|
<div className="w-full h-64 overflow-hidden">
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ export function AuthButton() {
|
|||||||
className="p-1 h-auto"
|
className="p-1 h-auto"
|
||||||
title="Déconnexion"
|
title="Déconnexion"
|
||||||
>
|
>
|
||||||
<Emoji emoji="🚪" size={16} />
|
<Emoji emoji="🚪" />
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ export default function ManagerWeeklySummary({ initialSummary }: ManagerWeeklySu
|
|||||||
{/* Header avec navigation */}
|
{/* Header avec navigation */}
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<div>
|
<div>
|
||||||
<h1 className="text-2xl font-bold text-[var(--foreground)]"><Emoji emoji="👔" size={24} /> Weekly</h1>
|
<h1 className="text-2xl font-bold text-[var(--foreground)]"><Emoji emoji="👔" /> Weekly</h1>
|
||||||
<p className="text-[var(--muted-foreground)]">{formatPeriod()}</p>
|
<p className="text-[var(--muted-foreground)]">{formatPeriod()}</p>
|
||||||
</div>
|
</div>
|
||||||
{activeView !== 'metrics' && (
|
{activeView !== 'metrics' && (
|
||||||
@@ -60,7 +60,7 @@ export default function ManagerWeeklySummary({ initialSummary }: ManagerWeeklySu
|
|||||||
variant="secondary"
|
variant="secondary"
|
||||||
size="sm"
|
size="sm"
|
||||||
>
|
>
|
||||||
<Emoji emoji="🔄" size={16} /> Actualiser
|
<Emoji emoji="🔄" /> Actualiser
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
@@ -81,22 +81,22 @@ export default function ManagerWeeklySummary({ initialSummary }: ManagerWeeklySu
|
|||||||
<Card variant="elevated">
|
<Card variant="elevated">
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<h2 className="text-lg font-semibold flex items-center gap-2">
|
<h2 className="text-lg font-semibold flex items-center gap-2">
|
||||||
<Emoji emoji="📊" size={18} /> Résumé de la semaine
|
<Emoji emoji="📊" /> Résumé de la semaine
|
||||||
</h2>
|
</h2>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent className="space-y-4">
|
<CardContent className="space-y-4">
|
||||||
<div className="outline-card-blue p-4">
|
<div className="outline-card-blue p-4">
|
||||||
<h3 className="font-medium mb-2"><Emoji emoji="🎯" size={16} /> Points clés accomplis</h3>
|
<h3 className="font-medium mb-2"><Emoji emoji="🎯" /> Points clés accomplis</h3>
|
||||||
<p className="text-sm text-[var(--muted-foreground)]">{summary.narrative.weekHighlight}</p>
|
<p className="text-sm text-[var(--muted-foreground)]">{summary.narrative.weekHighlight}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="outline-card-orange p-4">
|
<div className="outline-card-orange p-4">
|
||||||
<h3 className="font-medium mb-2"><Emoji emoji="⚡" size={16} /> Défis traités</h3>
|
<h3 className="font-medium mb-2"><Emoji emoji="⚡" /> Défis traités</h3>
|
||||||
<p className="text-sm text-[var(--muted-foreground)]">{summary.narrative.mainChallenges}</p>
|
<p className="text-sm text-[var(--muted-foreground)]">{summary.narrative.mainChallenges}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="outline-card-green p-4">
|
<div className="outline-card-green p-4">
|
||||||
<h3 className="font-medium mb-2"><Emoji emoji="🔮" size={16} /> Focus 7 prochains jours</h3>
|
<h3 className="font-medium mb-2"><Emoji emoji="🔮" /> Focus 7 prochains jours</h3>
|
||||||
<p className="text-sm text-[var(--muted-foreground)]">{summary.narrative.nextWeekFocus}</p>
|
<p className="text-sm text-[var(--muted-foreground)]">{summary.narrative.nextWeekFocus}</p>
|
||||||
</div>
|
</div>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
@@ -105,7 +105,7 @@ export default function ManagerWeeklySummary({ initialSummary }: ManagerWeeklySu
|
|||||||
{/* Métriques rapides */}
|
{/* Métriques rapides */}
|
||||||
<Card variant="elevated">
|
<Card variant="elevated">
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<h2 className="text-lg font-semibold"><Emoji emoji="📈" size={18} /> Métriques en bref</h2>
|
<h2 className="text-lg font-semibold"><Emoji emoji="📈" /> Métriques en bref</h2>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<div className="grid grid-cols-2 gap-4">
|
<div className="grid grid-cols-2 gap-4">
|
||||||
@@ -144,7 +144,7 @@ export default function ManagerWeeklySummary({ initialSummary }: ManagerWeeklySu
|
|||||||
borderBottomColor: 'color-mix(in srgb, var(--success) 10%, var(--border))'
|
borderBottomColor: 'color-mix(in srgb, var(--success) 10%, var(--border))'
|
||||||
}}>
|
}}>
|
||||||
<h2 className="text-lg font-semibold flex items-center gap-2" style={{ color: 'var(--success)' }}>
|
<h2 className="text-lg font-semibold flex items-center gap-2" style={{ color: 'var(--success)' }}>
|
||||||
<Emoji emoji="🏆" size={18} /> Top accomplissements
|
<Emoji emoji="🏆" /> Top accomplissements
|
||||||
</h2>
|
</h2>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
@@ -177,7 +177,7 @@ export default function ManagerWeeklySummary({ initialSummary }: ManagerWeeklySu
|
|||||||
borderBottomColor: 'color-mix(in srgb, var(--destructive) 10%, var(--border))'
|
borderBottomColor: 'color-mix(in srgb, var(--destructive) 10%, var(--border))'
|
||||||
}}>
|
}}>
|
||||||
<h2 className="text-lg font-semibold flex items-center gap-2" style={{ color: 'var(--destructive)' }}>
|
<h2 className="text-lg font-semibold flex items-center gap-2" style={{ color: 'var(--destructive)' }}>
|
||||||
<Emoji emoji="🎯" size={18} /> Top enjeux à venir
|
<Emoji emoji="🎯" /> Top enjeux à venir
|
||||||
</h2>
|
</h2>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
@@ -209,7 +209,7 @@ export default function ManagerWeeklySummary({ initialSummary }: ManagerWeeklySu
|
|||||||
{activeView === 'accomplishments' && (
|
{activeView === 'accomplishments' && (
|
||||||
<Card variant="elevated">
|
<Card variant="elevated">
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<h2 className="text-lg font-semibold"><Emoji emoji="✅" size={18} /> Accomplissements des 7 derniers jours</h2>
|
<h2 className="text-lg font-semibold"><Emoji emoji="✅" /> Accomplissements des 7 derniers jours</h2>
|
||||||
<p className="text-sm text-[var(--muted-foreground)]">
|
<p className="text-sm text-[var(--muted-foreground)]">
|
||||||
{summary.keyAccomplishments.length} accomplissements significatifs • {summary.metrics.totalTasksCompleted} tâches • {summary.metrics.totalCheckboxesCompleted} todos complétés
|
{summary.keyAccomplishments.length} accomplissements significatifs • {summary.metrics.totalTasksCompleted} tâches • {summary.metrics.totalCheckboxesCompleted} todos complétés
|
||||||
</p>
|
</p>
|
||||||
@@ -221,7 +221,7 @@ export default function ManagerWeeklySummary({ initialSummary }: ManagerWeeklySu
|
|||||||
borderColor: 'color-mix(in srgb, var(--muted) 40%, var(--border))',
|
borderColor: 'color-mix(in srgb, var(--muted) 40%, var(--border))',
|
||||||
color: 'var(--muted-foreground)'
|
color: 'var(--muted-foreground)'
|
||||||
}}>
|
}}>
|
||||||
<div className="text-4xl mb-4"><Emoji emoji="📭" size={32} /></div>
|
<div className="text-4xl mb-4"><Emoji emoji="📭" /></div>
|
||||||
<p className="text-lg mb-2">Aucun accomplissement significatif trouvé cette semaine.</p>
|
<p className="text-lg mb-2">Aucun accomplissement significatif trouvé cette semaine.</p>
|
||||||
<p className="text-sm">Ajoutez des tâches avec priorité haute/medium ou des meetings.</p>
|
<p className="text-sm">Ajoutez des tâches avec priorité haute/medium ou des meetings.</p>
|
||||||
</div>
|
</div>
|
||||||
@@ -247,7 +247,7 @@ export default function ManagerWeeklySummary({ initialSummary }: ManagerWeeklySu
|
|||||||
{activeView === 'challenges' && (
|
{activeView === 'challenges' && (
|
||||||
<Card variant="elevated">
|
<Card variant="elevated">
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<h2 className="text-lg font-semibold"><Emoji emoji="🎯" size={18} /> Enjeux et défis à venir</h2>
|
<h2 className="text-lg font-semibold"><Emoji emoji="🎯" /> Enjeux et défis à venir</h2>
|
||||||
<p className="text-sm text-[var(--muted-foreground)]">
|
<p className="text-sm text-[var(--muted-foreground)]">
|
||||||
{summary.upcomingChallenges.length} défis identifiés • {summary.upcomingChallenges.filter(c => c.priority === 'high').length} priorité haute • {summary.upcomingChallenges.filter(c => c.blockers.length > 0).length} avec blockers
|
{summary.upcomingChallenges.length} défis identifiés • {summary.upcomingChallenges.filter(c => c.priority === 'high').length} priorité haute • {summary.upcomingChallenges.filter(c => c.blockers.length > 0).length} avec blockers
|
||||||
</p>
|
</p>
|
||||||
@@ -259,7 +259,7 @@ export default function ManagerWeeklySummary({ initialSummary }: ManagerWeeklySu
|
|||||||
borderColor: 'color-mix(in srgb, var(--muted) 40%, var(--border))',
|
borderColor: 'color-mix(in srgb, var(--muted) 40%, var(--border))',
|
||||||
color: 'var(--muted-foreground)'
|
color: 'var(--muted-foreground)'
|
||||||
}}>
|
}}>
|
||||||
<div className="text-4xl mb-4"><Emoji emoji="🎯" size={32} /></div>
|
<div className="text-4xl mb-4"><Emoji emoji="🎯" /></div>
|
||||||
<p className="text-lg mb-2">Aucun enjeu prioritaire trouvé.</p>
|
<p className="text-lg mb-2">Aucun enjeu prioritaire trouvé.</p>
|
||||||
<p className="text-sm">Ajoutez des tâches non complétées avec priorité haute/medium.</p>
|
<p className="text-sm">Ajoutez des tâches non complétées avec priorité haute/medium.</p>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -42,13 +42,13 @@ export function MetricsTab({ className }: MetricsTabProps) {
|
|||||||
<Card>
|
<Card>
|
||||||
<CardContent className="p-6 text-center">
|
<CardContent className="p-6 text-center">
|
||||||
<p className="text-red-500 mb-4">
|
<p className="text-red-500 mb-4">
|
||||||
<Emoji emoji="❌" size={16} /> Erreur lors du chargement des métriques
|
<Emoji emoji="❌" /> Erreur lors du chargement des métriques
|
||||||
</p>
|
</p>
|
||||||
<p className="text-sm text-[var(--muted-foreground)] mb-4">
|
<p className="text-sm text-[var(--muted-foreground)] mb-4">
|
||||||
{metricsError || trendsError}
|
{metricsError || trendsError}
|
||||||
</p>
|
</p>
|
||||||
<Button onClick={handleRefresh} variant="secondary" size="sm">
|
<Button onClick={handleRefresh} variant="secondary" size="sm">
|
||||||
<Emoji emoji="🔄" size={14} /> Réessayer
|
<Emoji emoji="🔄" /> Réessayer
|
||||||
</Button>
|
</Button>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
@@ -61,7 +61,7 @@ export function MetricsTab({ className }: MetricsTabProps) {
|
|||||||
{/* Header avec période et contrôles */}
|
{/* Header avec période et contrôles */}
|
||||||
<div className="flex items-center justify-between mb-6">
|
<div className="flex items-center justify-between mb-6">
|
||||||
<div>
|
<div>
|
||||||
<h2 className="text-xl font-bold text-[var(--foreground)]"><Emoji emoji="📊" size={20} /> Métriques & Analytics</h2>
|
<h2 className="text-xl font-bold text-[var(--foreground)]"><Emoji emoji="📊" /> Métriques & Analytics</h2>
|
||||||
<p className="text-[var(--muted-foreground)]">{formatPeriod()}</p>
|
<p className="text-[var(--muted-foreground)]">{formatPeriod()}</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
@@ -71,7 +71,7 @@ export function MetricsTab({ className }: MetricsTabProps) {
|
|||||||
size="sm"
|
size="sm"
|
||||||
disabled={metricsLoading || trendsLoading}
|
disabled={metricsLoading || trendsLoading}
|
||||||
>
|
>
|
||||||
<Emoji emoji="🔄" size={14} /> Actualiser
|
<Emoji emoji="🔄" /> Actualiser
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ export function ProductivityAnalytics({ metrics, deadlineMetrics, tagMetrics, se
|
|||||||
|
|
||||||
{/* Titre de section Analytics */}
|
{/* Titre de section Analytics */}
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<h2 className="text-2xl font-bold"><Emoji emoji="📊" size={20} /> Analytics & Métriques</h2>
|
<h2 className="text-2xl font-bold"><Emoji emoji="📊" /> Analytics & Métriques</h2>
|
||||||
<div className="text-sm text-[var(--muted-foreground)]">
|
<div className="text-sm text-[var(--muted-foreground)]">
|
||||||
Derniers 30 jours
|
Derniers 30 jours
|
||||||
</div>
|
</div>
|
||||||
@@ -142,7 +142,7 @@ export function ProductivityAnalytics({ metrics, deadlineMetrics, tagMetrics, se
|
|||||||
|
|
||||||
{/* Insights automatiques */}
|
{/* Insights automatiques */}
|
||||||
<Card variant="glass" className="p-6">
|
<Card variant="glass" className="p-6">
|
||||||
<h3 className="text-lg font-semibold mb-4"><Emoji emoji="💡" size={25} /> Insights</h3>
|
<h3 className="text-lg font-semibold mb-4"><Emoji emoji="💡" /> Insights</h3>
|
||||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
|
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
|
||||||
<MetricCard
|
<MetricCard
|
||||||
title="Vélocité Moyenne"
|
title="Vélocité Moyenne"
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ export function RecentTasks({ tasks, selectedSources = [], hiddenSources = [] }:
|
|||||||
<Card variant="glass" className="p-4 sm:p-6 mt-8">
|
<Card variant="glass" className="p-4 sm:p-6 mt-8">
|
||||||
<div className="flex items-center justify-between mb-4">
|
<div className="flex items-center justify-between mb-4">
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
<Emoji emoji="🕒" size={20} />
|
<Emoji emoji="🕒" />
|
||||||
<h3 className="text-lg font-semibold text-[var(--foreground)]">Tâches Récentes</h3>
|
<h3 className="text-lg font-semibold text-[var(--foreground)]">Tâches Récentes</h3>
|
||||||
</div>
|
</div>
|
||||||
<Link href="/kanban">
|
<Link href="/kanban">
|
||||||
|
|||||||
@@ -11,26 +11,26 @@ interface MetricsOverviewProps {
|
|||||||
export function MetricsOverview({ metrics }: MetricsOverviewProps) {
|
export function MetricsOverview({ metrics }: MetricsOverviewProps) {
|
||||||
const getTrendIcon = (trend: string) => {
|
const getTrendIcon = (trend: string) => {
|
||||||
switch (trend) {
|
switch (trend) {
|
||||||
case 'improving': return <Emoji emoji="📈" size={24} />;
|
case 'improving': return <Emoji emoji="📈" />;
|
||||||
case 'declining': return <Emoji emoji="📉" size={24} />;
|
case 'declining': return <Emoji emoji="📉" />;
|
||||||
case 'stable': return <Emoji emoji="➡️" size={24} />;
|
case 'stable': return <Emoji emoji="➡️" />;
|
||||||
default: return <Emoji emoji="📊" size={24} />;
|
default: return <Emoji emoji="📊" />;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const getPatternIcon = (pattern: string) => {
|
const getPatternIcon = (pattern: string) => {
|
||||||
switch (pattern) {
|
switch (pattern) {
|
||||||
case 'consistent': return <Emoji emoji="🎯" size={24} />;
|
case 'consistent': return <Emoji emoji="🎯" />;
|
||||||
case 'variable': return <Emoji emoji="📊" size={24} />;
|
case 'variable': return <Emoji emoji="📊" />;
|
||||||
case 'weekend-heavy': return <Emoji emoji="📅" size={24} />;
|
case 'weekend-heavy': return <Emoji emoji="📅" />;
|
||||||
default: return <Emoji emoji="📋" size={24} />;
|
default: return <Emoji emoji="📋" />;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card>
|
<Card>
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<h3 className="text-lg font-semibold"><Emoji emoji="🎯" size={18} /> Vue d'ensemble</h3>
|
<h3 className="text-lg font-semibold"><Emoji emoji="🎯" /> Vue d'ensemble</h3>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<div className="grid grid-cols-2 lg:grid-cols-5 gap-4">
|
<div className="grid grid-cols-2 lg:grid-cols-5 gap-4">
|
||||||
|
|||||||
@@ -47,24 +47,24 @@ export function ProductivityInsights({ data, className }: ProductivityInsightsPr
|
|||||||
|
|
||||||
const getTrendIcon = () => {
|
const getTrendIcon = () => {
|
||||||
switch (trend) {
|
switch (trend) {
|
||||||
case 'up': return { icon: <Emoji emoji="📈" size={24} />, color: 'text-green-600', label: 'En amélioration' };
|
case 'up': return { icon: <Emoji emoji="📈" />, color: 'text-green-600', label: 'En amélioration' };
|
||||||
case 'down': return { icon: <Emoji emoji="📉" size={24} />, color: 'text-red-600', label: 'En baisse' };
|
case 'down': return { icon: <Emoji emoji="📉" />, color: 'text-red-600', label: 'En baisse' };
|
||||||
default: return { icon: <Emoji emoji="➡️" size={24} />, color: 'text-blue-600', label: 'Stable' };
|
default: return { icon: <Emoji emoji="➡️" />, color: 'text-blue-600', label: 'Stable' };
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const getConsistencyLevel = () => {
|
const getConsistencyLevel = () => {
|
||||||
if (consistencyScore >= 80) return { label: 'Très régulier', color: 'text-green-600', icon: <Emoji emoji="🎯" size={24} /> };
|
if (consistencyScore >= 80) return { label: 'Très régulier', color: 'text-green-600', icon: <Emoji emoji="🎯" /> };
|
||||||
if (consistencyScore >= 60) return { label: 'Assez régulier', color: 'text-blue-600', icon: <Emoji emoji="📊" size={24} /> };
|
if (consistencyScore >= 60) return { label: 'Assez régulier', color: 'text-blue-600', icon: <Emoji emoji="📊" /> };
|
||||||
if (consistencyScore >= 40) return { label: 'Variable', color: 'text-yellow-600', icon: <Emoji emoji="📊" size={24} /> };
|
if (consistencyScore >= 40) return { label: 'Variable', color: 'text-yellow-600', icon: <Emoji emoji="📊" /> };
|
||||||
return { label: 'Très variable', color: 'text-red-600', icon: <Emoji emoji="📊" size={24} /> };
|
return { label: 'Très variable', color: 'text-red-600', icon: <Emoji emoji="📊" /> };
|
||||||
};
|
};
|
||||||
|
|
||||||
const getRatioStatus = () => {
|
const getRatioStatus = () => {
|
||||||
if (creationRatio >= 100) return { label: 'Équilibré+', color: 'text-green-600', icon: <Emoji emoji="⚖️" size={24} /> };
|
if (creationRatio >= 100) return { label: 'Équilibré+', color: 'text-green-600', icon: <Emoji emoji="⚖️" /> };
|
||||||
if (creationRatio >= 80) return { label: 'Bien équilibré', color: 'text-blue-600', icon: <Emoji emoji="⚖️" size={24} /> };
|
if (creationRatio >= 80) return { label: 'Bien équilibré', color: 'text-blue-600', icon: <Emoji emoji="⚖️" /> };
|
||||||
if (creationRatio >= 60) return { label: 'Légèrement en retard', color: 'text-yellow-600', icon: <Emoji emoji="⚖️" size={24} /> };
|
if (creationRatio >= 60) return { label: 'Légèrement en retard', color: 'text-yellow-600', icon: <Emoji emoji="⚖️" /> };
|
||||||
return { label: 'Accumulation', color: 'text-red-600', icon: <Emoji emoji="⚖️" size={24} /> };
|
return { label: 'Accumulation', color: 'text-red-600', icon: <Emoji emoji="⚖️" /> };
|
||||||
};
|
};
|
||||||
|
|
||||||
const trendInfo = getTrendIcon();
|
const trendInfo = getTrendIcon();
|
||||||
@@ -80,7 +80,7 @@ export function ProductivityInsights({ data, className }: ProductivityInsightsPr
|
|||||||
<div className="outline-card-green p-4">
|
<div className="outline-card-green p-4">
|
||||||
<div className="flex items-center justify-between mb-2">
|
<div className="flex items-center justify-between mb-2">
|
||||||
<h4 className="font-medium">
|
<h4 className="font-medium">
|
||||||
<Emoji emoji="🏆" size={16} /> Jour champion
|
<Emoji emoji="🏆" /> Jour champion
|
||||||
</h4>
|
</h4>
|
||||||
<span className="text-2xl font-bold">
|
<span className="text-2xl font-bold">
|
||||||
{mostProductiveDay.completed}
|
{mostProductiveDay.completed}
|
||||||
@@ -98,7 +98,7 @@ export function ProductivityInsights({ data, className }: ProductivityInsightsPr
|
|||||||
<div className="outline-card-blue p-4">
|
<div className="outline-card-blue p-4">
|
||||||
<div className="flex items-center justify-between mb-2">
|
<div className="flex items-center justify-between mb-2">
|
||||||
<h4 className="font-medium">
|
<h4 className="font-medium">
|
||||||
<Emoji emoji="💡" size={16} /> Jour créatif
|
<Emoji emoji="💡" /> Jour créatif
|
||||||
</h4>
|
</h4>
|
||||||
<span className="text-2xl font-bold">
|
<span className="text-2xl font-bold">
|
||||||
{mostCreativeDay.newTasks}
|
{mostCreativeDay.newTasks}
|
||||||
@@ -165,7 +165,7 @@ export function ProductivityInsights({ data, className }: ProductivityInsightsPr
|
|||||||
{/* Recommandations */}
|
{/* Recommandations */}
|
||||||
<div className="outline-card-yellow p-4">
|
<div className="outline-card-yellow p-4">
|
||||||
<h4 className="font-medium mb-2 flex items-center gap-2">
|
<h4 className="font-medium mb-2 flex items-center gap-2">
|
||||||
<Emoji emoji="💡" size={16} /> Recommandations
|
<Emoji emoji="💡" /> Recommandations
|
||||||
</h4>
|
</h4>
|
||||||
<div className="space-y-1 text-sm">
|
<div className="space-y-1 text-sm">
|
||||||
{trend === 'down' && (
|
{trend === 'down' && (
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ export function DeadlineOverview({ metrics }: DeadlineOverviewProps) {
|
|||||||
<div className="space-y-6">
|
<div className="space-y-6">
|
||||||
{/* Titre de section */}
|
{/* Titre de section */}
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<h2 className="text-2xl font-bold"><Emoji emoji="🚨" size={25} /> Échéances Critiques</h2>
|
<h2 className="text-2xl font-bold"><Emoji emoji="🚨" /> Échéances Critiques</h2>
|
||||||
<div className="text-sm text-[var(--muted-foreground)]">
|
<div className="text-sm text-[var(--muted-foreground)]">
|
||||||
Surveillance temps réel
|
Surveillance temps réel
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -65,10 +65,10 @@ export default function FilterBar({
|
|||||||
<div className="flex items-center justify-between gap-4">
|
<div className="flex items-center justify-between gap-4">
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<span className="text-sm font-medium text-[var(--foreground)]"><Emoji emoji="🔍" size={14} /> Filtres</span>
|
<span className="text-sm font-medium text-[var(--foreground)]"><Emoji emoji="🔍" /> Filtres</span>
|
||||||
{isLoading && (
|
{isLoading && (
|
||||||
<Badge className="bg-yellow-100 text-yellow-800 text-xs">
|
<Badge className="bg-yellow-100 text-yellow-800 text-xs">
|
||||||
<Emoji emoji="⏳" size={12} /> Chargement...
|
<Emoji emoji="⏳" /> Chargement...
|
||||||
</Badge>
|
</Badge>
|
||||||
)}
|
)}
|
||||||
{hasActiveFilters && !isLoading && (
|
{hasActiveFilters && !isLoading && (
|
||||||
@@ -87,7 +87,7 @@ export default function FilterBar({
|
|||||||
className="bg-purple-100 text-purple-800 text-xs cursor-pointer hover:bg-purple-200 transition-colors"
|
className="bg-purple-100 text-purple-800 text-xs cursor-pointer hover:bg-purple-200 transition-colors"
|
||||||
onClick={() => removeFilter('components', comp)}
|
onClick={() => removeFilter('components', comp)}
|
||||||
>
|
>
|
||||||
<Emoji emoji="📦" size={12} /> {comp} ×
|
<Emoji emoji="📦" /> {comp} ×
|
||||||
</Badge>
|
</Badge>
|
||||||
))}
|
))}
|
||||||
{activeFilters.fixVersions?.slice(0, 2).map(version => (
|
{activeFilters.fixVersions?.slice(0, 2).map(version => (
|
||||||
@@ -96,7 +96,7 @@ export default function FilterBar({
|
|||||||
className="bg-green-100 text-green-800 text-xs cursor-pointer hover:bg-green-200 transition-colors"
|
className="bg-green-100 text-green-800 text-xs cursor-pointer hover:bg-green-200 transition-colors"
|
||||||
onClick={() => removeFilter('fixVersions', version)}
|
onClick={() => removeFilter('fixVersions', version)}
|
||||||
>
|
>
|
||||||
<Emoji emoji="🏷️" size={12} /> {version} ×
|
<Emoji emoji="🏷️" /> {version} ×
|
||||||
</Badge>
|
</Badge>
|
||||||
))}
|
))}
|
||||||
{activeFilters.issueTypes?.slice(0, 3).map(type => (
|
{activeFilters.issueTypes?.slice(0, 3).map(type => (
|
||||||
@@ -105,7 +105,7 @@ export default function FilterBar({
|
|||||||
className="bg-orange-100 text-orange-800 text-xs cursor-pointer hover:bg-orange-200 transition-colors"
|
className="bg-orange-100 text-orange-800 text-xs cursor-pointer hover:bg-orange-200 transition-colors"
|
||||||
onClick={() => removeFilter('issueTypes', type)}
|
onClick={() => removeFilter('issueTypes', type)}
|
||||||
>
|
>
|
||||||
<Emoji emoji="📋" size={12} /> {type} ×
|
<Emoji emoji="📋" /> {type} ×
|
||||||
</Badge>
|
</Badge>
|
||||||
))}
|
))}
|
||||||
{activeFilters.statuses?.slice(0, 2).map(status => (
|
{activeFilters.statuses?.slice(0, 2).map(status => (
|
||||||
@@ -114,7 +114,7 @@ export default function FilterBar({
|
|||||||
className="bg-blue-100 text-blue-800 text-xs cursor-pointer hover:bg-blue-200 transition-colors"
|
className="bg-blue-100 text-blue-800 text-xs cursor-pointer hover:bg-blue-200 transition-colors"
|
||||||
onClick={() => removeFilter('statuses', status)}
|
onClick={() => removeFilter('statuses', status)}
|
||||||
>
|
>
|
||||||
<Emoji emoji="🔄" size={12} /> {status} ×
|
<Emoji emoji="🔄" /> {status} ×
|
||||||
</Badge>
|
</Badge>
|
||||||
))}
|
))}
|
||||||
{activeFilters.assignees?.slice(0, 2).map(assignee => (
|
{activeFilters.assignees?.slice(0, 2).map(assignee => (
|
||||||
@@ -123,7 +123,7 @@ export default function FilterBar({
|
|||||||
className="bg-yellow-100 text-yellow-800 text-xs cursor-pointer hover:bg-yellow-200 transition-colors"
|
className="bg-yellow-100 text-yellow-800 text-xs cursor-pointer hover:bg-yellow-200 transition-colors"
|
||||||
onClick={() => removeFilter('assignees', assignee)}
|
onClick={() => removeFilter('assignees', assignee)}
|
||||||
>
|
>
|
||||||
<Emoji emoji="👤" size={12} /> {assignee} ×
|
<Emoji emoji="👤" /> {assignee} ×
|
||||||
</Badge>
|
</Badge>
|
||||||
))}
|
))}
|
||||||
|
|
||||||
@@ -190,7 +190,7 @@ export default function FilterBar({
|
|||||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6 max-h-96 overflow-y-auto">
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-6 max-h-96 overflow-y-auto">
|
||||||
{/* Types de tickets */}
|
{/* Types de tickets */}
|
||||||
<div>
|
<div>
|
||||||
<h4 className="font-medium text-sm mb-3"><Emoji emoji="📋" size={14} /> Types de tickets</h4>
|
<h4 className="font-medium text-sm mb-3"><Emoji emoji="📋" /> Types de tickets</h4>
|
||||||
<div className="space-y-1 max-h-32 overflow-y-auto">
|
<div className="space-y-1 max-h-32 overflow-y-auto">
|
||||||
{availableFilters.issueTypes.map(option => (
|
{availableFilters.issueTypes.map(option => (
|
||||||
<label
|
<label
|
||||||
@@ -221,7 +221,7 @@ export default function FilterBar({
|
|||||||
|
|
||||||
{/* Statuts */}
|
{/* Statuts */}
|
||||||
<div>
|
<div>
|
||||||
<h4 className="font-medium text-sm mb-3"><Emoji emoji="🔄" size={14} /> Statuts</h4>
|
<h4 className="font-medium text-sm mb-3"><Emoji emoji="🔄" /> Statuts</h4>
|
||||||
<div className="space-y-1 max-h-32 overflow-y-auto">
|
<div className="space-y-1 max-h-32 overflow-y-auto">
|
||||||
{availableFilters.statuses.map(option => (
|
{availableFilters.statuses.map(option => (
|
||||||
<label
|
<label
|
||||||
@@ -252,7 +252,7 @@ export default function FilterBar({
|
|||||||
|
|
||||||
{/* Assignés */}
|
{/* Assignés */}
|
||||||
<div>
|
<div>
|
||||||
<h4 className="font-medium text-sm mb-3"><Emoji emoji="👤" size={14} /> Assignés</h4>
|
<h4 className="font-medium text-sm mb-3"><Emoji emoji="👤" /> Assignés</h4>
|
||||||
<div className="space-y-1 max-h-32 overflow-y-auto">
|
<div className="space-y-1 max-h-32 overflow-y-auto">
|
||||||
{availableFilters.assignees.map(option => (
|
{availableFilters.assignees.map(option => (
|
||||||
<label
|
<label
|
||||||
@@ -283,7 +283,7 @@ export default function FilterBar({
|
|||||||
|
|
||||||
{/* Composants */}
|
{/* Composants */}
|
||||||
<div>
|
<div>
|
||||||
<h4 className="font-medium text-sm mb-3"><Emoji emoji="📦" size={14} /> Composants</h4>
|
<h4 className="font-medium text-sm mb-3"><Emoji emoji="📦" /> Composants</h4>
|
||||||
<div className="space-y-1 max-h-32 overflow-y-auto">
|
<div className="space-y-1 max-h-32 overflow-y-auto">
|
||||||
{availableFilters.components.map(option => (
|
{availableFilters.components.map(option => (
|
||||||
<label
|
<label
|
||||||
@@ -319,21 +319,21 @@ export default function FilterBar({
|
|||||||
variant="secondary"
|
variant="secondary"
|
||||||
className="flex-1"
|
className="flex-1"
|
||||||
>
|
>
|
||||||
<Emoji emoji="❌" size={14} /> Annuler
|
<Emoji emoji="❌" /> Annuler
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
onClick={clearAllFilters}
|
onClick={clearAllFilters}
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
className="flex-1"
|
className="flex-1"
|
||||||
>
|
>
|
||||||
<Emoji emoji="🗑️" size={14} /> Effacer tout
|
<Emoji emoji="🗑️" /> Effacer tout
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
onClick={applyPendingFilters}
|
onClick={applyPendingFilters}
|
||||||
className="flex-1"
|
className="flex-1"
|
||||||
disabled={isLoading}
|
disabled={isLoading}
|
||||||
>
|
>
|
||||||
{isLoading ? <><Emoji emoji="⏳" size={14} /> Application...</> : <><Emoji emoji="✅" size={14} /> Appliquer</>}
|
{isLoading ? <><Emoji emoji="⏳" /> Application...</> : <><Emoji emoji="✅" /> Appliquer</>}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|||||||
@@ -256,7 +256,7 @@ export function JiraSync({ onSyncComplete, className = "" }: JiraSyncProps) {
|
|||||||
<SyncActionsList actions={lastSyncResult.actions || []} />
|
<SyncActionsList actions={lastSyncResult.actions || []} />
|
||||||
) : (
|
) : (
|
||||||
<div className="text-center py-8 text-[var(--muted-foreground)]">
|
<div className="text-center py-8 text-[var(--muted-foreground)]">
|
||||||
<div className="text-2xl mb-2"><Emoji emoji="📝" size={32} /></div>
|
<div className="text-2xl mb-2"><Emoji emoji="📝" /></div>
|
||||||
<div>Aucun détail disponible pour cette synchronisation</div>
|
<div>Aucun détail disponible pour cette synchronisation</div>
|
||||||
<div className="text-sm mt-1">Les détails sont disponibles pour les nouvelles synchronisations</div>
|
<div className="text-sm mt-1">Les détails sont disponibles pour les nouvelles synchronisations</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -193,7 +193,7 @@ export function PredictabilityMetrics({ sprintHistory, className }: Predictabili
|
|||||||
|
|
||||||
<div className="text-center p-3 bg-[var(--card)] rounded-lg border border-[var(--border)]">
|
<div className="text-center p-3 bg-[var(--card)] rounded-lg border border-[var(--border)]">
|
||||||
<div className={`text-lg font-bold ${trend > 5 ? 'text-green-500' : trend < -5 ? 'text-red-500' : 'text-blue-500'}`}>
|
<div className={`text-lg font-bold ${trend > 5 ? 'text-green-500' : trend < -5 ? 'text-red-500' : 'text-blue-500'}`}>
|
||||||
{trend > 0 ? <Emoji emoji="↗️" size={18} /> : trend < 0 ? <Emoji emoji="↘️" size={18} /> : <Emoji emoji="→" size={18} />} {Math.abs(Math.round(trend))}%
|
{trend > 0 ? <Emoji emoji="↗️" /> : trend < 0 ? <Emoji emoji="↘️" /> : <Emoji emoji="→" />} {Math.abs(Math.round(trend))}%
|
||||||
</div>
|
</div>
|
||||||
<div className="text-xs text-[var(--muted-foreground)]">
|
<div className="text-xs text-[var(--muted-foreground)]">
|
||||||
Tendance récente
|
Tendance récente
|
||||||
@@ -207,31 +207,31 @@ export function PredictabilityMetrics({ sprintHistory, className }: Predictabili
|
|||||||
<div className="space-y-2 text-sm">
|
<div className="space-y-2 text-sm">
|
||||||
{averageAccuracy > 80 && (
|
{averageAccuracy > 80 && (
|
||||||
<div className="flex items-center gap-2" style={{ color: 'var(--green)' }}>
|
<div className="flex items-center gap-2" style={{ color: 'var(--green)' }}>
|
||||||
<Emoji emoji="✅" size={16} />
|
<Emoji emoji="✅" />
|
||||||
<span>Excellente predictabilité - L'équipe estime bien sa capacité</span>
|
<span>Excellente predictabilité - L'équipe estime bien sa capacité</span>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{averageAccuracy < 60 && (
|
{averageAccuracy < 60 && (
|
||||||
<div className="flex items-center gap-2" style={{ color: 'var(--destructive)' }}>
|
<div className="flex items-center gap-2" style={{ color: 'var(--destructive)' }}>
|
||||||
<Emoji emoji="⚠️" size={16} />
|
<Emoji emoji="⚠️" />
|
||||||
<span>Predictabilité faible - Revoir les méthodes d'estimation</span>
|
<span>Predictabilité faible - Revoir les méthodes d'estimation</span>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{averageVariance > 25 && (
|
{averageVariance > 25 && (
|
||||||
<div className="flex items-center gap-2" style={{ color: 'var(--accent)' }}>
|
<div className="flex items-center gap-2" style={{ color: 'var(--accent)' }}>
|
||||||
<Emoji emoji="📊" size={16} />
|
<Emoji emoji="📊" />
|
||||||
<span>Variance élevée - Considérer des sprints plus courts ou un meilleur découpage</span>
|
<span>Variance élevée - Considérer des sprints plus courts ou un meilleur découpage</span>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{trend > 10 && (
|
{trend > 10 && (
|
||||||
<div className="flex items-center gap-2" style={{ color: 'var(--green)' }}>
|
<div className="flex items-center gap-2" style={{ color: 'var(--green)' }}>
|
||||||
<Emoji emoji="📈" size={16} />
|
<Emoji emoji="📈" />
|
||||||
<span>Tendance positive - L'équipe s'améliore dans ses estimations</span>
|
<span>Tendance positive - L'équipe s'améliore dans ses estimations</span>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{trend < -10 && (
|
{trend < -10 && (
|
||||||
<div className="flex items-center gap-2" style={{ color: 'var(--destructive)' }}>
|
<div className="flex items-center gap-2" style={{ color: 'var(--destructive)' }}>
|
||||||
<Emoji emoji="📉" size={16} />
|
<Emoji emoji="📉" />
|
||||||
<span>Tendance négative - Attention aux changements récents (équipe, processus)</span>
|
<span>Tendance négative - Attention aux changements récents (équipe, processus)</span>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -133,8 +133,8 @@ export function SprintComparison({ sprintHistory, className }: SprintComparisonP
|
|||||||
metrics.velocityTrend === 'improving' ? 'text-green-500' :
|
metrics.velocityTrend === 'improving' ? 'text-green-500' :
|
||||||
metrics.velocityTrend === 'declining' ? 'text-red-500' : 'text-blue-500'
|
metrics.velocityTrend === 'declining' ? 'text-red-500' : 'text-blue-500'
|
||||||
}`}>
|
}`}>
|
||||||
{metrics.velocityTrend === 'improving' ? <Emoji emoji="📈" size={18} /> :
|
{metrics.velocityTrend === 'improving' ? <Emoji emoji="📈" /> :
|
||||||
metrics.velocityTrend === 'declining' ? <Emoji emoji="📉" size={18} /> : <Emoji emoji="➡️" size={18} />}
|
metrics.velocityTrend === 'declining' ? <Emoji emoji="📉" /> : <Emoji emoji="➡️" />}
|
||||||
</div>
|
</div>
|
||||||
<div className="text-xs text-[var(--muted-foreground)] mt-1">
|
<div className="text-xs text-[var(--muted-foreground)] mt-1">
|
||||||
Tendance générale
|
Tendance générale
|
||||||
@@ -189,7 +189,7 @@ export function SprintComparison({ sprintHistory, className }: SprintComparisonP
|
|||||||
{/* Insights et recommandations */}
|
{/* Insights et recommandations */}
|
||||||
<div className="mt-6 grid grid-cols-1 lg:grid-cols-2 gap-4">
|
<div className="mt-6 grid grid-cols-1 lg:grid-cols-2 gap-4">
|
||||||
<Card className="p-4">
|
<Card className="p-4">
|
||||||
<h4 className="text-sm font-medium mb-3"><Emoji emoji="🏆" size={16} /> Meilleur sprint</h4>
|
<h4 className="text-sm font-medium mb-3"><Emoji emoji="🏆" /> Meilleur sprint</h4>
|
||||||
<div className="space-y-2 text-sm">
|
<div className="space-y-2 text-sm">
|
||||||
<div className="flex justify-between">
|
<div className="flex justify-between">
|
||||||
<span>Sprint:</span>
|
<span>Sprint:</span>
|
||||||
@@ -207,7 +207,7 @@ export function SprintComparison({ sprintHistory, className }: SprintComparisonP
|
|||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
<Card className="p-4">
|
<Card className="p-4">
|
||||||
<h4 className="text-sm font-medium mb-3"><Emoji emoji="📉" size={16} /> Sprint à améliorer</h4>
|
<h4 className="text-sm font-medium mb-3"><Emoji emoji="📉" /> Sprint à améliorer</h4>
|
||||||
<div className="space-y-2 text-sm">
|
<div className="space-y-2 text-sm">
|
||||||
<div className="flex justify-between">
|
<div className="flex justify-between">
|
||||||
<span>Sprint:</span>
|
<span>Sprint:</span>
|
||||||
@@ -227,7 +227,7 @@ export function SprintComparison({ sprintHistory, className }: SprintComparisonP
|
|||||||
|
|
||||||
{/* Recommandations */}
|
{/* Recommandations */}
|
||||||
<Card className="mt-4 p-4">
|
<Card className="mt-4 p-4">
|
||||||
<h4 className="text-sm font-medium mb-2"><Emoji emoji="💡" size={16} /> Recommandations</h4>
|
<h4 className="text-sm font-medium mb-2"><Emoji emoji="💡" /> Recommandations</h4>
|
||||||
<div className="space-y-2 text-sm">
|
<div className="space-y-2 text-sm">
|
||||||
{getRecommendations(metrics).map((recommendation, index) => (
|
{getRecommendations(metrics).map((recommendation, index) => (
|
||||||
<div key={index} className="flex items-start gap-2">
|
<div key={index} className="flex items-start gap-2">
|
||||||
|
|||||||
@@ -34,10 +34,10 @@ export function SprintMetrics({ sprintDetails }: SprintMetricsProps) {
|
|||||||
|
|
||||||
const getVelocityTrendIcon = (trend: string) => {
|
const getVelocityTrendIcon = (trend: string) => {
|
||||||
switch (trend) {
|
switch (trend) {
|
||||||
case 'up': return <Emoji emoji="📈" size={24} />;
|
case 'up': return <Emoji emoji="📈" />;
|
||||||
case 'down': return <Emoji emoji="📉" size={24} />;
|
case 'down': return <Emoji emoji="📉" />;
|
||||||
case 'stable': return <Emoji emoji="➡️" size={24} />;
|
case 'stable': return <Emoji emoji="➡️" />;
|
||||||
default: return <Emoji emoji="📊" size={24} />;
|
default: return <Emoji emoji="📊" />;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -46,7 +46,7 @@ export function SprintMetrics({ sprintDetails }: SprintMetricsProps) {
|
|||||||
{/* Métriques de performance */}
|
{/* Métriques de performance */}
|
||||||
<Card>
|
<Card>
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<h3 className="font-semibold"><Emoji emoji="⚡" size={16} /> Métriques de performance</h3>
|
<h3 className="font-semibold"><Emoji emoji="⚡" /> Métriques de performance</h3>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<div className="grid grid-cols-2 lg:grid-cols-4 gap-4">
|
<div className="grid grid-cols-2 lg:grid-cols-4 gap-4">
|
||||||
@@ -79,7 +79,7 @@ export function SprintMetrics({ sprintDetails }: SprintMetricsProps) {
|
|||||||
{/* Répartition par statut avec pourcentages */}
|
{/* Répartition par statut avec pourcentages */}
|
||||||
<Card>
|
<Card>
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<h3 className="font-semibold"><Emoji emoji="📊" size={16} /> Analyse des statuts</h3>
|
<h3 className="font-semibold"><Emoji emoji="📊" /> Analyse des statuts</h3>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<div className="space-y-3">
|
<div className="space-y-3">
|
||||||
@@ -113,7 +113,7 @@ export function SprintMetrics({ sprintDetails }: SprintMetricsProps) {
|
|||||||
{/* Charge de travail par assigné */}
|
{/* Charge de travail par assigné */}
|
||||||
<Card>
|
<Card>
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<h3 className="font-semibold"><Emoji emoji="👥" size={16} /> Charge de travail</h3>
|
<h3 className="font-semibold"><Emoji emoji="👥" /> Charge de travail</h3>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
@@ -152,7 +152,7 @@ export function SprintMetrics({ sprintDetails }: SprintMetricsProps) {
|
|||||||
{/* Insights et recommandations */}
|
{/* Insights et recommandations */}
|
||||||
<Card>
|
<Card>
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<h3 className="font-semibold"><Emoji emoji="💡" size={16} /> Insights & Recommandations</h3>
|
<h3 className="font-semibold"><Emoji emoji="💡" /> Insights & Recommandations</h3>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<div className="space-y-3">
|
<div className="space-y-3">
|
||||||
@@ -160,7 +160,7 @@ export function SprintMetrics({ sprintDetails }: SprintMetricsProps) {
|
|||||||
{parseFloat(completionRate) >= 80 && (
|
{parseFloat(completionRate) >= 80 && (
|
||||||
<div className="p-3 bg-green-50 border border-green-200 rounded">
|
<div className="p-3 bg-green-50 border border-green-200 rounded">
|
||||||
<div className="flex items-center gap-2 mb-1">
|
<div className="flex items-center gap-2 mb-1">
|
||||||
<Emoji emoji="✅" size={16} />
|
<Emoji emoji="✅" />
|
||||||
<span className="font-medium text-green-800">Excellent taux de completion</span>
|
<span className="font-medium text-green-800">Excellent taux de completion</span>
|
||||||
</div>
|
</div>
|
||||||
<p className="text-sm text-green-700">
|
<p className="text-sm text-green-700">
|
||||||
@@ -172,7 +172,7 @@ export function SprintMetrics({ sprintDetails }: SprintMetricsProps) {
|
|||||||
{parseFloat(completionRate) < 60 && (
|
{parseFloat(completionRate) < 60 && (
|
||||||
<div className="p-3 bg-orange-50 border border-orange-200 rounded">
|
<div className="p-3 bg-orange-50 border border-orange-200 rounded">
|
||||||
<div className="flex items-center gap-2 mb-1">
|
<div className="flex items-center gap-2 mb-1">
|
||||||
<Emoji emoji="⚠️" size={16} />
|
<Emoji emoji="⚠️" />
|
||||||
<span className="font-medium text-orange-800">Taux de completion faible</span>
|
<span className="font-medium text-orange-800">Taux de completion faible</span>
|
||||||
</div>
|
</div>
|
||||||
<p className="text-sm text-orange-700">
|
<p className="text-sm text-orange-700">
|
||||||
@@ -185,7 +185,7 @@ export function SprintMetrics({ sprintDetails }: SprintMetricsProps) {
|
|||||||
{parseFloat(blockedRate) > 20 && (
|
{parseFloat(blockedRate) > 20 && (
|
||||||
<div className="p-3 bg-red-50 border border-red-200 rounded">
|
<div className="p-3 bg-red-50 border border-red-200 rounded">
|
||||||
<div className="flex items-center gap-2 mb-1">
|
<div className="flex items-center gap-2 mb-1">
|
||||||
<Emoji emoji="🚨" size={16} />
|
<Emoji emoji="🚨" />
|
||||||
<span className="font-medium text-red-800">Trop d'issues bloquées</span>
|
<span className="font-medium text-red-800">Trop d'issues bloquées</span>
|
||||||
</div>
|
</div>
|
||||||
<p className="text-sm text-red-700">
|
<p className="text-sm text-red-700">
|
||||||
@@ -198,7 +198,7 @@ export function SprintMetrics({ sprintDetails }: SprintMetricsProps) {
|
|||||||
{assigneeDistribution.length > 0 && (
|
{assigneeDistribution.length > 0 && (
|
||||||
<div className="p-3 bg-blue-50 border border-blue-200 rounded">
|
<div className="p-3 bg-blue-50 border border-blue-200 rounded">
|
||||||
<div className="flex items-center gap-2 mb-1">
|
<div className="flex items-center gap-2 mb-1">
|
||||||
<Emoji emoji="📊" size={16} />
|
<Emoji emoji="📊" />
|
||||||
<span className="font-medium text-blue-800">Répartition de la charge</span>
|
<span className="font-medium text-blue-800">Répartition de la charge</span>
|
||||||
</div>
|
</div>
|
||||||
<p className="text-sm text-blue-700">
|
<p className="text-sm text-blue-700">
|
||||||
|
|||||||
@@ -15,10 +15,10 @@ export function SprintOverview({ sprintDetails }: SprintOverviewProps) {
|
|||||||
|
|
||||||
const getVelocityTrendIcon = (trend: string) => {
|
const getVelocityTrendIcon = (trend: string) => {
|
||||||
switch (trend) {
|
switch (trend) {
|
||||||
case 'up': return <Emoji emoji="📈" size={16} />;
|
case 'up': return <Emoji emoji="📈" />;
|
||||||
case 'down': return <Emoji emoji="📉" size={16} />;
|
case 'down': return <Emoji emoji="📉" />;
|
||||||
case 'stable': return <Emoji emoji="➡️" size={16} />;
|
case 'stable': return <Emoji emoji="➡️" />;
|
||||||
default: return <Emoji emoji="📊" size={16} />;
|
default: return <Emoji emoji="📊" />;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -27,7 +27,7 @@ export function SprintOverview({ sprintDetails }: SprintOverviewProps) {
|
|||||||
{/* Informations générales */}
|
{/* Informations générales */}
|
||||||
<Card>
|
<Card>
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<h3 className="font-semibold"><Emoji emoji="📋" size={16} /> Informations générales</h3>
|
<h3 className="font-semibold"><Emoji emoji="📋" /> Informations générales</h3>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<div className="grid grid-cols-2 gap-4">
|
<div className="grid grid-cols-2 gap-4">
|
||||||
@@ -59,7 +59,7 @@ export function SprintOverview({ sprintDetails }: SprintOverviewProps) {
|
|||||||
{/* Métriques clés */}
|
{/* Métriques clés */}
|
||||||
<Card>
|
<Card>
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<h3 className="font-semibold"><Emoji emoji="📊" size={16} /> Métriques clés</h3>
|
<h3 className="font-semibold"><Emoji emoji="📊" /> Métriques clés</h3>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<div className="grid grid-cols-2 lg:grid-cols-4 gap-4">
|
<div className="grid grid-cols-2 lg:grid-cols-4 gap-4">
|
||||||
@@ -87,7 +87,7 @@ export function SprintOverview({ sprintDetails }: SprintOverviewProps) {
|
|||||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-4">
|
<div className="grid grid-cols-1 lg:grid-cols-2 gap-4">
|
||||||
<Card>
|
<Card>
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<h3 className="font-semibold"><Emoji emoji="👥" size={16} /> Répartition par assigné</h3>
|
<h3 className="font-semibold"><Emoji emoji="👥" /> Répartition par assigné</h3>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
@@ -108,7 +108,7 @@ export function SprintOverview({ sprintDetails }: SprintOverviewProps) {
|
|||||||
{/* Répartition par statut */}
|
{/* Répartition par statut */}
|
||||||
<Card>
|
<Card>
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<h3 className="font-semibold"><Emoji emoji="📈" size={16} /> Répartition par statut</h3>
|
<h3 className="font-semibold"><Emoji emoji="📈" /> Répartition par statut</h3>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ function DroppableColumn({
|
|||||||
|
|
||||||
{tasks.length === 0 ? (
|
{tasks.length === 0 ? (
|
||||||
<div className="text-center py-8 text-[var(--muted-foreground)] text-sm">
|
<div className="text-center py-8 text-[var(--muted-foreground)] text-sm">
|
||||||
<div className="text-2xl mb-2"><Emoji emoji={icon} size={24} /></div>
|
<div className="text-2xl mb-2"><Emoji emoji={icon} /></div>
|
||||||
Aucun objectif {title.toLowerCase()}
|
Aucun objectif {title.toLowerCase()}
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
@@ -138,7 +138,7 @@ export function ObjectivesBoard({
|
|||||||
>
|
>
|
||||||
<div className="w-3 h-3 bg-[var(--accent)] rounded-full animate-pulse shadow-[var(--accent)]/50 shadow-lg"></div>
|
<div className="w-3 h-3 bg-[var(--accent)] rounded-full animate-pulse shadow-[var(--accent)]/50 shadow-lg"></div>
|
||||||
<h2 className="text-lg font-mono font-bold text-[var(--accent)] uppercase tracking-wider">
|
<h2 className="text-lg font-mono font-bold text-[var(--accent)] uppercase tracking-wider">
|
||||||
<Emoji emoji="🎯" size={20} /> Objectifs Principaux
|
<Emoji emoji="🎯" /> Objectifs Principaux
|
||||||
</h2>
|
</h2>
|
||||||
{pinnedTagName && (
|
{pinnedTagName && (
|
||||||
<Badge variant="outline" className="border-[var(--accent)]/50 text-[var(--accent)]">
|
<Badge variant="outline" className="border-[var(--accent)]/50 text-[var(--accent)]">
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ export function GeneralSettingsPageClient({ initialTags }: GeneralSettingsPageCl
|
|||||||
{/* Page Header */}
|
{/* Page Header */}
|
||||||
<div className="mb-6">
|
<div className="mb-6">
|
||||||
<h1 className="text-2xl font-mono font-bold text-[var(--foreground)] mb-2">
|
<h1 className="text-2xl font-mono font-bold text-[var(--foreground)] mb-2">
|
||||||
<Emoji emoji="⚙️" size={24} /> Paramètres généraux
|
<Emoji emoji="⚙️" /> Paramètres généraux
|
||||||
</h1>
|
</h1>
|
||||||
<p className="text-[var(--muted-foreground)]">
|
<p className="text-[var(--muted-foreground)]">
|
||||||
Configuration des préférences de l'interface et du comportement général
|
Configuration des préférences de l'interface et du comportement général
|
||||||
@@ -70,7 +70,7 @@ export function GeneralSettingsPageClient({ initialTags }: GeneralSettingsPageCl
|
|||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<div>
|
<div>
|
||||||
<h3 className="text-lg font-medium text-[var(--foreground)] mb-2">
|
<h3 className="text-lg font-medium text-[var(--foreground)] mb-2">
|
||||||
<Emoji emoji="🎨" size={18} /> UI Components Showcase
|
<Emoji emoji="🎨" /> UI Components Showcase
|
||||||
</h3>
|
</h3>
|
||||||
<p className="text-sm text-[var(--muted-foreground)]">
|
<p className="text-sm text-[var(--muted-foreground)]">
|
||||||
Visualisez tous les composants UI disponibles avec différents thèmes
|
Visualisez tous les composants UI disponibles avec différents thèmes
|
||||||
@@ -98,7 +98,7 @@ export function GeneralSettingsPageClient({ initialTags }: GeneralSettingsPageCl
|
|||||||
<CardContent className="p-4">
|
<CardContent className="p-4">
|
||||||
<div className="p-4 bg-[var(--warning)]/10 border border-[var(--warning)]/20 rounded">
|
<div className="p-4 bg-[var(--warning)]/10 border border-[var(--warning)]/20 rounded">
|
||||||
<p className="text-sm text-[var(--warning)] font-medium mb-2">
|
<p className="text-sm text-[var(--warning)] font-medium mb-2">
|
||||||
<Emoji emoji="🚧" size={16} /> Interface de configuration en développement
|
<Emoji emoji="🚧" /> Interface de configuration en développement
|
||||||
</p>
|
</p>
|
||||||
<p className="text-xs text-[var(--muted-foreground)]">
|
<p className="text-xs text-[var(--muted-foreground)]">
|
||||||
Les contrôles interactifs pour modifier les autres préférences seront disponibles dans une prochaine version.
|
Les contrôles interactifs pour modifier les autres préférences seront disponibles dans une prochaine version.
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ export function QuickStats({ preferences, systemInfo }: QuickStatsProps) {
|
|||||||
<Card>
|
<Card>
|
||||||
<CardContent className="p-4">
|
<CardContent className="p-4">
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
<Emoji emoji="🎨" size={24} />
|
<Emoji emoji="🎨" />
|
||||||
<div>
|
<div>
|
||||||
<p className="text-sm text-[var(--muted-foreground)]">Thème actuel</p>
|
<p className="text-sm text-[var(--muted-foreground)]">Thème actuel</p>
|
||||||
<p className="font-medium capitalize">{preferences.viewPreferences.theme}</p>
|
<p className="font-medium capitalize">{preferences.viewPreferences.theme}</p>
|
||||||
@@ -28,7 +28,7 @@ export function QuickStats({ preferences, systemInfo }: QuickStatsProps) {
|
|||||||
<Card>
|
<Card>
|
||||||
<CardContent className="p-4">
|
<CardContent className="p-4">
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
<Emoji emoji="🔌" size={24} />
|
<Emoji emoji="🔌" />
|
||||||
<div>
|
<div>
|
||||||
<p className="text-sm text-[var(--muted-foreground)]">Jira</p>
|
<p className="text-sm text-[var(--muted-foreground)]">Jira</p>
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
@@ -47,7 +47,7 @@ export function QuickStats({ preferences, systemInfo }: QuickStatsProps) {
|
|||||||
<Card>
|
<Card>
|
||||||
<CardContent className="p-4">
|
<CardContent className="p-4">
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
<Emoji emoji="📏" size={24} />
|
<Emoji emoji="📏" />
|
||||||
<div>
|
<div>
|
||||||
<p className="text-sm text-[var(--muted-foreground)]">Taille police</p>
|
<p className="text-sm text-[var(--muted-foreground)]">Taille police</p>
|
||||||
<p className="font-medium capitalize">{preferences.viewPreferences.fontSize}</p>
|
<p className="font-medium capitalize">{preferences.viewPreferences.fontSize}</p>
|
||||||
@@ -59,7 +59,7 @@ export function QuickStats({ preferences, systemInfo }: QuickStatsProps) {
|
|||||||
<Card>
|
<Card>
|
||||||
<CardContent className="p-4">
|
<CardContent className="p-4">
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
<Emoji emoji="💾" size={24} />
|
<Emoji emoji="💾" />
|
||||||
<div>
|
<div>
|
||||||
<p className="text-sm text-[var(--muted-foreground)]">Sauvegardes</p>
|
<p className="text-sm text-[var(--muted-foreground)]">Sauvegardes</p>
|
||||||
<p className="font-medium">
|
<p className="font-medium">
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ export function SettingsNavigation({ settingsPages }: SettingsNavigationProps) {
|
|||||||
<CardContent className="p-6">
|
<CardContent className="p-6">
|
||||||
<div className="flex items-start justify-between">
|
<div className="flex items-start justify-between">
|
||||||
<div className="flex items-start gap-4">
|
<div className="flex items-start gap-4">
|
||||||
<span className="text-3xl"><Emoji emoji={page.icon} size={30} /></span>
|
<span className="text-3xl"><Emoji emoji={page.icon} /></span>
|
||||||
<div className="flex-1">
|
<div className="flex-1">
|
||||||
<h3 className="text-lg font-semibold text-[var(--foreground)] mb-1">
|
<h3 className="text-lg font-semibold text-[var(--foreground)] mb-1">
|
||||||
{page.title}
|
{page.title}
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ export function TagsFilters({
|
|||||||
onClick={onToggleUnused}
|
onClick={onToggleUnused}
|
||||||
className="flex items-center gap-2"
|
className="flex items-center gap-2"
|
||||||
>
|
>
|
||||||
<Emoji emoji="⚠️" size={12} />
|
<Emoji emoji="⚠️" />
|
||||||
Tags non utilisés ({unusedCount})
|
Tags non utilisés ({unusedCount})
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
@@ -57,7 +57,7 @@ export function TagsFilters({
|
|||||||
onClick={onToggleWithoutIcons}
|
onClick={onToggleWithoutIcons}
|
||||||
className="flex items-center gap-2"
|
className="flex items-center gap-2"
|
||||||
>
|
>
|
||||||
<Emoji emoji="🚫" size={12} />
|
<Emoji emoji="🚫" />
|
||||||
Tags sans icônes ({withoutIconsCount})
|
Tags sans icônes ({withoutIconsCount})
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ export function AchievementCard({
|
|||||||
{/* Count de todos - seulement pour les tâches, pas pour les todos standalone */}
|
{/* Count de todos - seulement pour les tâches, pas pour les todos standalone */}
|
||||||
{!isTodo && achievement.todosCount !== undefined && achievement.todosCount > 0 && (
|
{!isTodo && achievement.todosCount !== undefined && achievement.todosCount > 0 && (
|
||||||
<div className="flex items-center gap-1 text-xs text-[var(--muted-foreground)]">
|
<div className="flex items-center gap-1 text-xs text-[var(--muted-foreground)]">
|
||||||
<span><Emoji emoji="📋" size={16} /></span>
|
<span><Emoji emoji="📋" /></span>
|
||||||
<span>{achievement.todosCount} todo{achievement.todosCount > 1 ? 's' : ''}</span>
|
<span>{achievement.todosCount} todo{achievement.todosCount > 1 ? 's' : ''}</span>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ export function ChallengeCard({
|
|||||||
{/* Count de todos */}
|
{/* Count de todos */}
|
||||||
{challenge.todosCount !== undefined && challenge.todosCount > 0 && (
|
{challenge.todosCount !== undefined && challenge.todosCount > 0 && (
|
||||||
<div className="flex items-center gap-1 text-xs text-[var(--muted-foreground)]">
|
<div className="flex items-center gap-1 text-xs text-[var(--muted-foreground)]">
|
||||||
<span><Emoji emoji="📋" size={16} /></span>
|
<span><Emoji emoji="📋" /></span>
|
||||||
<span>{challenge.todosCount} todo{challenge.todosCount > 1 ? 's' : ''}</span>
|
<span>{challenge.todosCount} todo{challenge.todosCount > 1 ? 's' : ''}</span>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ const ColumnHeader = forwardRef<HTMLDivElement, ColumnHeaderProps>(
|
|||||||
accentColor || "text-[var(--foreground)]"
|
accentColor || "text-[var(--foreground)]"
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{title} {icon && <Emoji emoji={icon} size={16} />}
|
{title} {icon && <Emoji emoji={icon} />}
|
||||||
</h3>
|
</h3>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -9,13 +9,12 @@ interface EmojiProps {
|
|||||||
size?: number;
|
size?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Emoji({ emoji, className = '', size = 16 }: EmojiProps) {
|
export function Emoji({ emoji, className = '' }: EmojiProps) {
|
||||||
// Utiliser les fonts système pour un rendu cohérent et performant
|
// Utiliser les fonts système pour un rendu cohérent et performant
|
||||||
return (
|
return (
|
||||||
<span
|
<span
|
||||||
className={`inline-block ${className}`}
|
className={`inline-block ${className}`}
|
||||||
style={{
|
style={{
|
||||||
fontSize: `${size}px`,
|
|
||||||
fontFamily: 'Apple Color Emoji, Segoe UI Emoji, Noto Color Emoji, sans-serif',
|
fontFamily: 'Apple Color Emoji, Segoe UI Emoji, Noto Color Emoji, sans-serif',
|
||||||
lineHeight: 1,
|
lineHeight: 1,
|
||||||
verticalAlign: 'middle'
|
verticalAlign: 'middle'
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ export function StatCard({
|
|||||||
</div>
|
</div>
|
||||||
{icon && (
|
{icon && (
|
||||||
<div className="text-3xl">
|
<div className="text-3xl">
|
||||||
<Emoji emoji={icon} size={32} />
|
<Emoji emoji={icon} />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ export function HeaderDesktop({ title, subtitle, syncing }: HeaderDesktopProps)
|
|||||||
className="text-[var(--muted-foreground)] hover:text-[var(--primary)] transition-colors p-1 rounded-md hover:bg-[var(--card-hover)]"
|
className="text-[var(--muted-foreground)] hover:text-[var(--primary)] transition-colors p-1 rounded-md hover:bg-[var(--card-hover)]"
|
||||||
title="Raccourcis clavier (Cmd+?)"
|
title="Raccourcis clavier (Cmd+?)"
|
||||||
>
|
>
|
||||||
<Emoji emoji="⌨️" size={16} />
|
<Emoji emoji="⌨️" />
|
||||||
</button>
|
</button>
|
||||||
<ThemeDropdown variant="desktop" />
|
<ThemeDropdown variant="desktop" />
|
||||||
<AuthButton />
|
<AuthButton />
|
||||||
|
|||||||
Reference in New Issue
Block a user