From eac9e9a0bb723eb22b68016988b2c70a78cf91ad Mon Sep 17 00:00:00 2001 From: Julien Froidefond Date: Sat, 4 Oct 2025 07:17:39 +0200 Subject: [PATCH] feat: update TODO.md and enhance dashboard components - Marked several UI/UX tasks as complete in TODO.md, including improvements for Kanban icons, tag visibility, recent tasks display, and header responsiveness. - Updated PriorityDistributionChart to adjust height for better layout. - Refined IntegrationFilter to improve filter display and added new trigger class for dropdowns. - Replaced RecentTaskTimeline with TaskCard in RecentTasks for better consistency. - Enhanced TagDistributionChart with improved tooltip and legend styling. - Updated DesktopControls and MobileControls to use lucide-react icons for filters and search functionality. - Removed RecentTaskTimeline component for cleaner codebase. --- TODO.md | 16 +-- .../charts/PriorityDistributionChart.tsx | 2 +- .../dashboard/IntegrationFilter.tsx | 7 +- src/components/dashboard/RecentTasks.tsx | 51 ++++--- .../dashboard/TagDistributionChart.tsx | 124 +++++++++-------- src/components/kanban/DesktopControls.tsx | 37 +++-- src/components/kanban/MobileControls.tsx | 4 +- .../ui-showcase/sections/CardsSection.tsx | 47 ------- src/components/ui/Dropdown.tsx | 4 + src/components/ui/Header.tsx | 78 +++++++++-- src/components/ui/RecentTaskTimeline.tsx | 128 ------------------ src/components/ui/SearchInput.tsx | 2 +- src/components/ui/ToggleButton.tsx | 14 +- src/components/ui/index.ts | 1 - 14 files changed, 213 insertions(+), 302 deletions(-) delete mode 100644 src/components/ui/RecentTaskTimeline.tsx diff --git a/TODO.md b/TODO.md index ba1b578..d0a00ed 100644 --- a/TODO.md +++ b/TODO.md @@ -10,12 +10,12 @@ ### 🎨 Design et Interface - [X] **Homepage cards** : toute en variant glass -- [ ] **Icône Kanban homepage** - Changer icône sur la page d'accueil, pas lisible (utiliser une lib) -- [ ] **Lisibilité label graph par tag** - Améliorer la lisibilité des labels dans les graphiques par tag -- [ ] **Tag homepage** - Problème d'affichage des graphs de tags sur la homepage coté lisibilité, cezrtaines icones ne sont pas entièrement visible, et la légende est trop proche du graphe. -- [ ] **Tâches récentes** - Revoir l'affichage et la logique des tâches récentes -- [ ] **Header dépasse en tablet** - Corriger le débordement du header sur tablette -- [ ] **Icônes agenda et filtres** - Améliorer les icônes de l'agenda et des filtres dans desktop controls (utiliser une lib) +- [X] **Icône Kanban homepage** - Changer icône sur la page d'accueil, pas lisible (utiliser une lib) +- [x] **Lisibilité label graph par tag** - Améliorer la lisibilité des labels dans les graphiques par tag +- [x] **Tag homepage** - Problème d'affichage des graphs de tags sur la homepage côté lisibilité, certaines icones ne sont pas entièrement visible, et la légende est trop proche du graphe. +- [x] **Tâches récentes** - Revoir l'affichage et la logique des tâches récentes +- [x] **Header dépasse en tablet** - Corriger le débordement du header sur tablette +- [x] **Icônes agenda et filtres** - Améliorer les icônes de l'agenda et des filtres dans desktop controls (utiliser une lib) - [ ] **Réunion/tâche design** - Revoir le design des bouton dans dailySectrion : les toggles avoir un compposant ui - [ ] **Légende calendrier et padding** - Corriger l'espacement et la légende du calendrier dans daily - [ ] **EditModal task couleur calendrier** - Problème de couleur en ajout de taches dans tous les icones calendriers; colmler au thème @@ -29,13 +29,13 @@ - [ ] **Deux modales** - Problème de duplication de modales - [ ] **Control panel et select** - Problème avec les contrôles et sélecteurs - [ ] **TaskCard et Kanban transparence** - Appliquer la transparence sur le background et non sur la card -- [ ] **Recherche Kanban desktop controls** - Ajouter icône et label : "rechercher" pour rapetir +- [X] **Recherche Kanban desktop controls** - Ajouter icône et label : "rechercher" pour rapetir - [ ] **Largeur page Kanban** - Réduire légèrement la largeur et revoir toutes les autres pages - [ ] **Icône thème à gauche du profil** - Repositionner l'icône de thème dans le header - [ ] **Déconnexion trop petit et couleur** - Améliorer le bouton de déconnexion - [ ] **Fond modal trop opaque** - Réduire l'opacité du fond des modales - [ ] **Couleurs thème clair et TFS Jira Kanban** - Harmoniser les couleurs du thème clair -- [ ] **États sélectionnés desktop control** - Revoir les couleurs des états sélectionnés pour avoir le joli bleu du dropdown partout +- [X] **États sélectionnés desktop control** - Revoir les couleurs des états sélectionnés pour avoir le joli bleu du dropdown partout - [ ] **Dépasse 1000 caractères en edit modal task** - Corriger la limite (pas de limite) et revoir la quickcard description - [ ] **UI si échéance et trop de labels dans le footer de card** - Améliorer l'affichage en mode détaillé TaskCard; certains boutons sont sur deux lignes ce qui casse l'affichage - [ ] **Gravatar** - Implémenter l'affichage des avatars Gravatar diff --git a/src/components/charts/PriorityDistributionChart.tsx b/src/components/charts/PriorityDistributionChart.tsx index 7b66e2d..6875dec 100644 --- a/src/components/charts/PriorityDistributionChart.tsx +++ b/src/components/charts/PriorityDistributionChart.tsx @@ -63,7 +63,7 @@ export function PriorityDistributionChart({ data, title = "Distribution des Prio return (

{title}

-
+
); } diff --git a/src/components/dashboard/RecentTasks.tsx b/src/components/dashboard/RecentTasks.tsx index ffd3ac4..62d8d74 100644 --- a/src/components/dashboard/RecentTasks.tsx +++ b/src/components/dashboard/RecentTasks.tsx @@ -2,10 +2,10 @@ import { Task } from '@/lib/types'; import { Card } from '@/components/ui/Card'; -import { RecentTaskTimeline } from '@/components/ui/RecentTaskTimeline'; +import { TaskCard } from '@/components/ui/TaskCard'; import { useTasksContext } from '@/contexts/TasksContext'; import Link from 'next/link'; -import { Clipboard } from 'lucide-react'; +import { Clipboard, Clock } from 'lucide-react'; interface RecentTasksProps { tasks: Task[]; @@ -31,34 +31,54 @@ export function RecentTasks({ tasks, selectedSources = [], hiddenSources = [] }: ); } - // Prendre les 5 tâches les plus récentes (créées ou modifiées) + // Prendre les 5 tâches les plus pertinentes (créées récemment ou modifiées récemment) const recentTasks = filteredTasks - .sort((a, b) => b.updatedAt.getTime() - a.updatedAt.getTime()) + .filter(task => { + // Ne pas afficher les tâches terminées depuis plus de 7 jours + if (task.status === 'done' && task.completedAt) { + const sevenDaysAgo = new Date(); + sevenDaysAgo.setDate(sevenDaysAgo.getDate() - 7); + return task.completedAt > sevenDaysAgo; + } + return task.status !== 'done'; + }) + .sort((a, b) => { + // Prioriser les tâches non terminées et récentes + if (a.status === 'done' && b.status !== 'done') return 1; + if (b.status === 'done' && a.status !== 'done') return -1; + + // Sinon trier par date de modification + return b.updatedAt.getTime() - a.updatedAt.getTime(); + }) .slice(0, 5); return ( - +
-

Tâches Récentes

+
+ +

Tâches Récentes

+
-
{recentTasks.length === 0 ? ( -
- -

Aucune tâche disponible

-

Créez votre première tâche pour commencer

+
+ +

Aucune tâche récente

+

Créez une nouvelle tâche pour commencer

) : ( -
+
{recentTasks.map((task) => ( - { - // Navigation vers le kanban avec la tâche sélectionnée window.location.href = `/kanban?taskId=${task.id}`; }} /> diff --git a/src/components/dashboard/TagDistributionChart.tsx b/src/components/dashboard/TagDistributionChart.tsx index 742fac4..a55e8a9 100644 --- a/src/components/dashboard/TagDistributionChart.tsx +++ b/src/components/dashboard/TagDistributionChart.tsx @@ -10,31 +10,33 @@ interface TagDistributionChartProps { } export function TagDistributionChart({ metrics, className }: TagDistributionChartProps) { + + // Préparer les données pour le graphique en camembert const pieData = metrics.tagDistribution.slice(0, 8).map((tag) => ({ name: tag.tagName, value: tag.count, percentage: tag.percentage, - color: tag.tagColor + color: tag.tagColor // Garder la couleur originale du tag })); // Préparer les données pour le graphique en barres (top tags) - const barData = metrics.topTags.slice(0, 10).map(tag => ({ + const barData = metrics.topTags.slice(0, 10).map((tag) => ({ name: tag.tagName.length > 12 ? `${tag.tagName.substring(0, 12)}...` : tag.tagName, usage: tag.usage, completionRate: tag.completionRate, avgPriority: tag.avgPriority, - color: tag.tagColor + color: tag.tagColor // Garder la couleur originale du tag })); - // Tooltip personnalisé pour le camembert - const PieTooltip = ({ active, payload }: { active?: boolean; payload?: Array<{ payload: { name: string; value: number; percentage: number } }> }) => { + // Tooltip personnalisé pour les tags (distribution) + const TagTooltip = ({ active, payload }: { active?: boolean; payload?: Array<{ payload: { name: string; value: number; percentage: number } }> }) => { if (active && payload && payload.length) { const data = payload[0].payload; return ( -
-

{data.name}

-

+

+

{data.name}

+

{data.value} tâches ({data.percentage.toFixed(1)}%)

@@ -48,12 +50,12 @@ export function TagDistributionChart({ metrics, className }: TagDistributionChar if (active && payload && payload.length) { const data = payload[0].payload; return ( -
-

{data.name}

-

+

+

{data.name}

+

{data.usage} tâches

-

+

Taux de completion: {data.completionRate.toFixed(1)}%

@@ -62,19 +64,17 @@ export function TagDistributionChart({ metrics, className }: TagDistributionChar return null; }; - // Légende personnalisée - const CustomLegend = ({ payload }: { payload?: Array<{ value: string; color: string }> }) => { - if (!payload) return null; - + // Légende personnalisée qui utilise directement les données du graphique + const CustomLegend = () => { return ( -
- {payload.map((entry, index) => ( -
+
+ {pieData.map((entry, index) => ( +
- {entry.value} + {entry.name}
))}
@@ -83,56 +83,60 @@ export function TagDistributionChart({ metrics, className }: TagDistributionChar return (
-
+
{/* Distribution par tags - Camembert */} - -

🏷️ Distribution par Tags

- -
- - - { - const { name, percent } = props; - const percentValue = typeof percent === 'number' ? percent : 0; - return percentValue > 0.05 ? `${name}: ${(percentValue * 100).toFixed(1)}%` : ''; - }} - outerRadius={80} - fill="#8884d8" - dataKey="value" - nameKey="name" - > - {pieData.map((entry, index) => ( - - ))} - - } /> - } /> - - -
-
+ +

Distribution par Tags

+ +
+ + + { + const { percent } = props; + return typeof percent === 'number' && percent > 0.05 ? `${Math.round(percent * 100)}%` : ''; + }} + outerRadius={80} + fill="#8884d8" + dataKey="value" + nameKey="name" + > + {pieData.map((entry, index) => ( + + ))} + + } /> + + + + +
+
{/* Top tags - Barres */} -

📊 Top Tags par Usage

+

Top Tags par Usage

-
+
- + + - } /> {/* Statistiques des tags */} - -

📈 Statistiques des Tags

+ +

Statistiques des Tags

diff --git a/src/components/kanban/DesktopControls.tsx b/src/components/kanban/DesktopControls.tsx index da5dee3..9eab401 100644 --- a/src/components/kanban/DesktopControls.tsx +++ b/src/components/kanban/DesktopControls.tsx @@ -5,7 +5,7 @@ import { Button, ToggleButton, SearchInput, ControlPanel, ControlSection, Contro import { IntegrationFilter } from '@/components/dashboard/IntegrationFilter'; import { FontSizeToggle } from '@/components/ui/FontSizeToggle'; import type { KanbanFilters } from '@/lib/types'; -import { Filter, Target, Calendar, Plus, List, Grid3X3, Layout } from 'lucide-react'; +import { Target, Plus, List, Grid3X3, Layout, Clock, Search, Settings } from 'lucide-react'; interface DesktopControlsProps { showFilters: boolean; @@ -81,13 +81,17 @@ export function DesktopControls({ {/* Layout responsive : deux lignes sur tablette, une ligne sur desktop */}
{/* Section gauche : Recherche + Boutons principaux */} - - {/* Champ de recherche */} - + + {/* Champ de recherche avec icône */} +
+ + +
} + icon={} > Filtres @@ -113,14 +117,16 @@ export function DesktopControls({ variant="cyan" isActive={kanbanFilters.showWithDueDate} onClick={handleDueDateFilterToggle} - title={kanbanFilters.showWithDueDate ? "Afficher toutes les tâches" : "Afficher seulement les tâches avec date de fin"} - icon={} - /> + title={kanbanFilters.showWithDueDate ? "Afficher toutes les tâches" : "Afficher seulement les tâches avec échéance"} + icon={} + > + Échéance +
{/* Section droite : Raccourcis + Bouton Nouvelle tâche */} - + {/* Raccourcis Sources (Jira & TFS) */} : } + className="h-[33px]" > {compactView ? 'Détaillée' : 'Compacte'} @@ -144,6 +151,7 @@ export function DesktopControls({ onClick={onToggleSwimlanes} title={swimlanesByTags ? "Vue standard" : "Vue swimlanes"} icon={swimlanesByTags ? : } + className="h-[33px]" > {swimlanesByTags ? 'Standard' : 'Swimlanes'} @@ -155,9 +163,8 @@ export function DesktopControls({ {/* Bouton d'ajout de tâche */}
- {/* Recent Task Timeline */} -
-

Recent Task Timeline

-
- - - - -
-
{/* Skeleton Cards */}
diff --git a/src/components/ui/Dropdown.tsx b/src/components/ui/Dropdown.tsx index e0754ef..5ac1f26 100644 --- a/src/components/ui/Dropdown.tsx +++ b/src/components/ui/Dropdown.tsx @@ -42,6 +42,8 @@ interface DropdownProps { className?: string; /** Classe CSS additionnelle pour le contenu */ contentClassName?: string; + /** Classe CSS additionnelle pour le bouton trigger */ + triggerClassName?: string; /** Callback quand le dropdown s'ouvre */ onOpen?: () => void; /** Callback quand le dropdown se ferme */ @@ -66,6 +68,7 @@ export function Dropdown({ zIndex = 9999, className, contentClassName, + triggerClassName, onOpen, onClose, open: controlledOpen, @@ -252,6 +255,7 @@ export function Dropdown({ className={cn( 'flex items-center gap-2 px-3 py-2 text-sm font-medium rounded-md transition-colors', getVariantStyles(), + triggerClassName, disabled && 'opacity-50 cursor-not-allowed' )} > diff --git a/src/components/ui/Header.tsx b/src/components/ui/Header.tsx index 5626e33..1003bb4 100644 --- a/src/components/ui/Header.tsx +++ b/src/components/ui/Header.tsx @@ -22,6 +22,7 @@ export function Header({ title = "TowerControl", subtitle = "Task Management", s const { isConfigured: isJiraConfigured, config: jiraConfig } = useJiraConfig(); const pathname = usePathname(); const [mobileMenuOpen, setMobileMenuOpen] = useState(false); + const [tabletMenuOpen, setTabletMenuOpen] = useState(false); const [themeDropdownOpen, setThemeDropdownOpen] = useState(false); const { openModal: openShortcutsModal } = useKeyboardShortcutsModal(); const { data: session } = useSession(); @@ -171,44 +172,97 @@ export function Header({ title = "TowerControl", subtitle = "Task Management", s
- {/* Auth controls à droite mobile */} -
+ {/* Auth controls à droite mobile - dans la ligne principale */} +
+ {/* Ligne Auth séparée sur très petits écrans */} +
+ +
+ {/* Layout desktop - une seule ligne comme avant */}
{/* Titre et status */}
-
+
-
-

- {title} +
+

+ {title} + {title}

-

+

{subtitle}

{/* Navigation desktop */} -