chore: refactor project structure and clean up unused components

- Updated `TODO.md` to reflect new testing tasks and final structure expectations.
- Simplified TypeScript path mappings in `tsconfig.json` for better clarity.
- Revised business logic separation rules in `.cursor/rules` to align with new directory structure.
- Deleted unused client components and services to streamline the codebase.
- Adjusted import paths in scripts to match the new structure.
This commit is contained in:
Julien Froidefond
2025-09-21 10:26:35 +02:00
parent 9dc1fafa76
commit 4152b0bdfc
130 changed files with 360 additions and 413 deletions

View File

@@ -0,0 +1,123 @@
'use client';
import { DailyMetrics } from '@/services/metrics';
interface WeeklyActivityHeatmapProps {
data: DailyMetrics[];
className?: string;
}
export function WeeklyActivityHeatmap({ data, className }: WeeklyActivityHeatmapProps) {
// Calculer l'intensité max pour la normalisation
const maxActivity = Math.max(...data.map(day => day.completed + day.newTasks));
// Obtenir l'intensité relative (0-1)
const getIntensity = (day: DailyMetrics) => {
const activity = day.completed + day.newTasks;
return maxActivity > 0 ? activity / maxActivity : 0;
};
// Obtenir la couleur basée sur l'intensité
const getColorClass = (intensity: number) => {
if (intensity === 0) return 'bg-gray-100 dark:bg-gray-800';
if (intensity < 0.2) return 'bg-green-100 dark:bg-green-900/30';
if (intensity < 0.4) return 'bg-green-200 dark:bg-green-800/50';
if (intensity < 0.6) return 'bg-green-300 dark:bg-green-700/70';
if (intensity < 0.8) return 'bg-green-400 dark:bg-green-600/80';
return 'bg-green-500 dark:bg-green-500';
};
return (
<div className={className}>
<div className="space-y-4">
{/* Titre */}
<div className="text-center">
<h4 className="text-sm font-medium text-[var(--foreground)] mb-2">
Heatmap d&apos;activité hebdomadaire
</h4>
<p className="text-xs text-[var(--muted-foreground)]">
Intensité basée sur les tâches complétées + nouvelles tâches
</p>
</div>
{/* Heatmap */}
<div className="flex justify-center">
<div className="flex gap-1">
{data.map((day, index) => {
const intensity = getIntensity(day);
const colorClass = getColorClass(intensity);
const totalActivity = day.completed + day.newTasks;
return (
<div key={index} className="text-center">
{/* Carré de couleur */}
<div
className={`w-8 h-8 rounded ${colorClass} border border-[var(--border)] flex items-center justify-center transition-all hover:scale-110 cursor-help group relative`}
title={`${day.dayName}: ${totalActivity} activités (${day.completed} complétées, ${day.newTasks} créées)`}
>
{/* Tooltip au hover */}
<div className="opacity-0 group-hover:opacity-100 absolute bottom-10 left-1/2 transform -translate-x-1/2 bg-[var(--card)] border border-[var(--border)] rounded p-2 text-xs whitespace-nowrap z-10 shadow-lg transition-opacity">
<div className="font-medium">{day.dayName}</div>
<div className="text-[var(--muted-foreground)]">
{day.completed} terminées, {day.newTasks} créées
</div>
<div className="text-[var(--muted-foreground)]">
Taux: {day.completionRate.toFixed(1)}%
</div>
</div>
{/* Indicator si jour actuel */}
{new Date(day.date).toDateString() === new Date().toDateString() && (
<div className="w-2 h-2 bg-blue-500 rounded-full"></div>
)}
</div>
{/* Label du jour */}
<div className="text-xs text-[var(--muted-foreground)] mt-1">
{day.dayName.substring(0, 3)}
</div>
</div>
);
})}
</div>
</div>
{/* Légende */}
<div className="flex items-center justify-center gap-2 text-xs text-[var(--muted-foreground)]">
<span>Moins</span>
<div className="flex gap-1">
<div className="w-3 h-3 bg-gray-100 dark:bg-gray-800 border border-[var(--border)] rounded"></div>
<div className="w-3 h-3 bg-green-100 dark:bg-green-900/30 border border-[var(--border)] rounded"></div>
<div className="w-3 h-3 bg-green-200 dark:bg-green-800/50 border border-[var(--border)] rounded"></div>
<div className="w-3 h-3 bg-green-300 dark:bg-green-700/70 border border-[var(--border)] rounded"></div>
<div className="w-3 h-3 bg-green-400 dark:bg-green-600/80 border border-[var(--border)] rounded"></div>
<div className="w-3 h-3 bg-green-500 dark:bg-green-500 border border-[var(--border)] rounded"></div>
</div>
<span>Plus</span>
</div>
{/* Stats rapides */}
<div className="grid grid-cols-3 gap-2 text-center text-xs">
<div className="p-2 bg-[var(--card)] rounded border">
<div className="font-medium text-green-600">
{data.reduce((sum, day) => sum + day.completed, 0)}
</div>
<div className="text-[var(--muted-foreground)]">Terminées</div>
</div>
<div className="p-2 bg-[var(--card)] rounded border">
<div className="font-medium text-blue-600">
{data.reduce((sum, day) => sum + day.newTasks, 0)}
</div>
<div className="text-[var(--muted-foreground)]">Créées</div>
</div>
<div className="p-2 bg-[var(--card)] rounded border">
<div className="font-medium text-purple-600">
{(data.reduce((sum, day) => sum + day.completionRate, 0) / data.length).toFixed(1)}%
</div>
<div className="text-[var(--muted-foreground)]">Taux moyen</div>
</div>
</div>
</div>
</div>
);
}