From 714f8ccd5ec377fea928ed80051f7124d815bc0e Mon Sep 17 00:00:00 2001 From: Julien Froidefond Date: Sun, 5 Oct 2025 20:29:46 +0200 Subject: [PATCH] feat: integrate emoji-mart and refactor emoji usage - Added @emoji-mart/data and @emoji-mart/react dependencies for enhanced emoji support. - Replaced static emoji characters with Emoji component in various UI components for consistency and improved rendering. - Updated generateDateTitle function to return an object with emoji and text for better structure. - Marked the task for removing emojis from the UI as complete in TODO.md. --- TODO.md | 2 +- package-lock.json | 98 +++++++++- package.json | 6 +- src/app/daily/DailyPageClient.tsx | 12 +- .../JiraDashboardPageClient.tsx | 55 +++--- src/components/AuthButton.tsx | 4 +- src/components/ThemeSelector.tsx | 1 - src/components/charts/WeeklyStatsCard.tsx | 13 +- src/components/daily/DailySection.tsx | 5 +- src/components/daily/PendingTasksSection.tsx | 9 +- .../dashboard/IntegrationFilter.tsx | 16 +- .../dashboard/ManagerWeeklySummary.tsx | 27 +-- src/components/dashboard/MetricsTab.tsx | 9 +- .../dashboard/ProductivityAnalytics.tsx | 5 +- src/components/dashboard/RecentTasks.tsx | 5 +- src/components/dashboard/WelcomeSection.tsx | 177 +++++++++--------- .../dashboard/charts/MetricsOverview.tsx | 19 +- .../dashboard/charts/ProductivityInsights.tsx | 29 +-- src/components/deadline/DeadlineOverview.tsx | 3 +- src/components/deadline/DeadlineRiskCard.tsx | 3 +- .../deadline/DeadlineSummaryCard.tsx | 3 +- src/components/jira/FilterBar.tsx | 29 +-- src/components/jira/JiraSync.tsx | 29 +-- src/components/jira/PredictabilityMetrics.tsx | 13 +- src/components/jira/SprintComparison.tsx | 11 +- src/components/jira/sprint/SprintMetrics.tsx | 25 +-- src/components/jira/sprint/SprintOverview.tsx | 17 +- .../kanban/ColumnVisibilityToggle.tsx | 3 +- src/components/kanban/KanbanFilters.tsx | 56 +++--- src/components/kanban/ObjectivesBoard.tsx | 5 +- .../kanban/filters/ColumnFilters.tsx | 3 +- src/components/kanban/filters/JiraFilters.tsx | 25 +-- src/components/kanban/filters/TfsFilters.tsx | 11 +- .../settings/GeneralSettingsPageClient.tsx | 7 +- src/components/settings/index/QuickStats.tsx | 9 +- .../settings/index/SettingsNavigation.tsx | 3 +- src/components/settings/tags/TagsFilters.tsx | 5 +- src/components/ui/AchievementCard.tsx | 3 +- src/components/ui/AlertBanner.tsx | 11 +- src/components/ui/ChallengeCard.tsx | 3 +- src/components/ui/ColumnHeader.tsx | 3 +- src/components/ui/Dropdown.tsx | 2 +- src/components/ui/DynamicIcon.tsx | 0 src/components/ui/Emoji.tsx | 58 ++++++ src/components/ui/Modal.tsx | 2 +- src/components/ui/SortIcon.tsx | 27 +++ src/components/ui/StatCard.tsx | 5 +- src/components/ui/Tabs.tsx | 4 +- src/components/ui/header/HeaderDesktop.tsx | 3 +- src/components/ui/header/ThemeDropdown.tsx | 5 +- src/lib/avatars.ts | 1 + src/lib/date-utils.ts | 8 +- src/lib/gravatar.ts | 1 + src/lib/sort-config.ts | 20 +- 54 files changed, 568 insertions(+), 340 deletions(-) create mode 100644 src/components/ui/DynamicIcon.tsx create mode 100644 src/components/ui/Emoji.tsx create mode 100644 src/components/ui/SortIcon.tsx diff --git a/TODO.md b/TODO.md index e7cf9be..09e80bd 100644 --- a/TODO.md +++ b/TODO.md @@ -21,7 +21,7 @@ - [x] **EditModal task couleur calendrier** - Problème de couleur en ajout de taches dans tous les icones calendriers; colmler au thème - [x] **Weekly deux boutons actualiser** - Corriger la duplication des boutons d'actualisation - [x] **Solarized ne doit pas être un soleil** - Corriger l'icône du thème Solarized -- [ ] **Emoji interdit dans UI** - Vérifier et supprimer toutes les emojis dans l'interface, remplacer par lucide-react +- [x] **Emoji interdit dans UI** - Vérifier et supprimer toutes les emojis dans l'interface, remplacer par lucide-react - [ ] **Settings intégration : icônes** - Problème avec les icônes "Arrêté" et "Actif" : doivent etre les memes - [ ] **Settings backup UI** - Revoir l'UI pour coller au style des intégrations - [ ] **AlertBanner : hover et bug** - Corriger les problèmes de hover et bugs diff --git a/package-lock.json b/package-lock.json index 24e5566..9261b87 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,10 +11,13 @@ "@dnd-kit/core": "^6.3.1", "@dnd-kit/sortable": "^10.0.0", "@dnd-kit/utilities": "^3.2.2", + "@emoji-mart/data": "^1.2.1", + "@emoji-mart/react": "^1.1.1", "@prisma/client": "^6.16.1", "bcryptjs": "^3.0.2", "clsx": "^2.1.1", "date-fns": "^4.1.0", + "emoji-mart": "^5.6.0", "emoji-regex": "^10.5.0", "lucide-react": "^0.544.0", "next": "15.5.3", @@ -23,7 +26,8 @@ "react": "19.1.0", "react-dom": "19.1.0", "recharts": "^3.2.1", - "tailwind-merge": "^3.3.1" + "tailwind-merge": "^3.3.1", + "twemoji": "^14.0.2" }, "devDependencies": { "@eslint/eslintrc": "^3", @@ -147,6 +151,22 @@ "tslib": "^2.4.0" } }, + "node_modules/@emoji-mart/data": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@emoji-mart/data/-/data-1.2.1.tgz", + "integrity": "sha512-no2pQMWiBy6gpBEiqGeU77/bFejDqUTRY7KX+0+iur13op3bqUsXdnwoZs6Xb1zbv0gAj5VvS1PWoUUckSr5Dw==", + "license": "MIT" + }, + "node_modules/@emoji-mart/react": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@emoji-mart/react/-/react-1.1.1.tgz", + "integrity": "sha512-NMlFNeWgv1//uPsvLxvGQoIerPuVdXwK/EUek8OOkJ6wVOWPUizRBJU0hDqWZCOROVpfBgCemaC3m6jDOXi03g==", + "license": "MIT", + "peerDependencies": { + "emoji-mart": "^5.2", + "react": "^16.8 || ^17 || ^18" + } + }, "node_modules/@esbuild/aix-ppc64": { "version": "0.25.10", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.10.tgz", @@ -2301,7 +2321,7 @@ "version": "19.1.13", "resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.13.tgz", "integrity": "sha512-hHkbU/eoO3EG5/MZkuFSKmYqPbSVk5byPFa3e7y/8TybHiLMACgI8seVYlicwk7H5K/rI2px9xrQp/C+AUDTiQ==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "csstype": "^3.0.2" @@ -3465,7 +3485,7 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/d3-array": { @@ -3808,6 +3828,12 @@ "fast-check": "^3.23.1" } }, + "node_modules/emoji-mart": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/emoji-mart/-/emoji-mart-5.6.0.tgz", + "integrity": "sha512-eJp3QRe79pjwa+duv+n7+5YsNhRcMl812EcFVwrnRvYKoNPoQb5qxU8DG6Bgwji0akHdp6D4Ln6tYLG58MFSow==", + "license": "MIT" + }, "node_modules/emoji-regex": { "version": "10.5.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.5.0.tgz", @@ -4713,6 +4739,29 @@ "node": ">=18.3.0" } }, + "node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/fs-extra/node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "license": "MIT", + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", @@ -4916,7 +4965,6 @@ "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true, "license": "ISC" }, "node_modules/graphemer": { @@ -5603,6 +5651,18 @@ "json5": "lib/cli.js" } }, + "node_modules/jsonfile": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-5.0.0.tgz", + "integrity": "sha512-NQRZ5CRo74MhMMC3/3r5g2k4fjodJ/wh8MxjFbCViWKFjxrnudWSY5vomh+23ZaXzAS7J3fBZIR2dV6WbmfM0w==", + "license": "MIT", + "dependencies": { + "universalify": "^0.1.2" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, "node_modules/jsx-ast-utils": { "version": "3.3.5", "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", @@ -6858,6 +6918,7 @@ "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "dev": true, "license": "MIT" }, "node_modules/react-redux": { @@ -7800,6 +7861,24 @@ "fsevents": "~2.3.3" } }, + "node_modules/twemoji": { + "version": "14.0.2", + "resolved": "https://registry.npmjs.org/twemoji/-/twemoji-14.0.2.tgz", + "integrity": "sha512-BzOoXIe1QVdmsUmZ54xbEH+8AgtOKUiG53zO5vVP2iUu6h5u9lN15NcuS6te4OY96qx0H7JK9vjjl9WQbkTRuA==", + "license": "MIT", + "dependencies": { + "fs-extra": "^8.0.1", + "jsonfile": "^5.0.0", + "twemoji-parser": "14.0.0", + "universalify": "^0.1.2" + } + }, + "node_modules/twemoji-parser": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/twemoji-parser/-/twemoji-parser-14.0.0.tgz", + "integrity": "sha512-9DUOTGLOWs0pFWnh1p6NF+C3CkQ96PWmEFwhOVmT3WbecRC+68AIqpsnJXygfkFcp4aXbOp8Dwbhh/HQgvoRxA==", + "license": "MIT" + }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -7895,7 +7974,7 @@ "version": "5.9.2", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz", "integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==", - "devOptional": true, + "dev": true, "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", @@ -7931,6 +8010,15 @@ "dev": true, "license": "MIT" }, + "node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "license": "MIT", + "engines": { + "node": ">= 4.0.0" + } + }, "node_modules/unrs-resolver": { "version": "1.11.1", "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.11.1.tgz", diff --git a/package.json b/package.json index 0b0198b..ff19b86 100644 --- a/package.json +++ b/package.json @@ -25,10 +25,13 @@ "@dnd-kit/core": "^6.3.1", "@dnd-kit/sortable": "^10.0.0", "@dnd-kit/utilities": "^3.2.2", + "@emoji-mart/data": "^1.2.1", + "@emoji-mart/react": "^1.1.1", "@prisma/client": "^6.16.1", "bcryptjs": "^3.0.2", "clsx": "^2.1.1", "date-fns": "^4.1.0", + "emoji-mart": "^5.6.0", "emoji-regex": "^10.5.0", "lucide-react": "^0.544.0", "next": "15.5.3", @@ -37,7 +40,8 @@ "react": "19.1.0", "react-dom": "19.1.0", "recharts": "^3.2.1", - "tailwind-merge": "^3.3.1" + "tailwind-merge": "^3.3.1", + "twemoji": "^14.0.2" }, "devDependencies": { "@eslint/eslintrc": "^3", diff --git a/src/app/daily/DailyPageClient.tsx b/src/app/daily/DailyPageClient.tsx index 41a214c..919a33b 100644 --- a/src/app/daily/DailyPageClient.tsx +++ b/src/app/daily/DailyPageClient.tsx @@ -13,8 +13,9 @@ import { DailySection } from '@/components/daily/DailySection'; import { PendingTasksSection } from '@/components/daily/PendingTasksSection'; import { dailyClient } from '@/clients/daily-client'; import { Header } from '@/components/ui/Header'; -import { getPreviousWorkday, formatDateLong, isToday, generateDateTitle, formatDateShort, isYesterday } from '@/lib/date-utils'; +import { getPreviousWorkday, formatDateLong, isToday, generateDateTitle } from '@/lib/date-utils'; import { useGlobalKeyboardShortcuts } from '@/hooks/useGlobalKeyboardShortcuts'; +import { Emoji } from '@/components/ui/Emoji'; interface DailyPageClientProps { initialDailyView?: DailyView; @@ -142,15 +143,14 @@ export function DailyPageClient({ }; const getTodayTitle = () => { - return generateDateTitle(currentDate, '🎯'); + const { emoji, text } = generateDateTitle(currentDate, '🎯'); + return <> {text}; }; const getYesterdayTitle = () => { const yesterdayDate = getYesterdayDate(); - if (isYesterday(yesterdayDate)) { - return "📋 Hier"; - } - return `📋 ${formatDateShort(yesterdayDate)}`; + const { emoji, text } = generateDateTitle(yesterdayDate, '📋'); + return <> {text}; }; // Convertir les métriques de deadline en AlertItem diff --git a/src/app/jira-dashboard/JiraDashboardPageClient.tsx b/src/app/jira-dashboard/JiraDashboardPageClient.tsx index b1a22a3..4593e48 100644 --- a/src/app/jira-dashboard/JiraDashboardPageClient.tsx +++ b/src/app/jira-dashboard/JiraDashboardPageClient.tsx @@ -29,6 +29,7 @@ import { getSprintDetails } from '../../actions/jira-sprint-details'; import { useJiraFilters } from '@/hooks/useJiraFilters'; import { SprintVelocity } from '@/lib/types'; import Link from 'next/link'; +import { Emoji } from '@/components/ui/Emoji'; interface JiraDashboardPageClientProps { initialJiraConfig: JiraConfig; @@ -109,7 +110,7 @@ export function JiraDashboardPageClient({ initialJiraConfig, initialAnalytics }:
-

⚙️ Configuration requise

+

Configuration requise

@@ -139,7 +140,7 @@ export function JiraDashboardPageClient({ initialJiraConfig, initialAnalytics }:

-

🎯 Projet requis

+

Projet requis

@@ -184,7 +185,7 @@ export function JiraDashboardPageClient({ initialJiraConfig, initialAnalytics }:

- 📊 Analytics d'équipe + Analytics d'équipe

@@ -226,7 +227,7 @@ export function JiraDashboardPageClient({ initialJiraConfig, initialAnalytics }: variant="ghost" className="text-xs px-2 py-1 h-auto" > - {isExporting ? '⏳' : '📊'} CSV + {isExporting ? : } CSV

@@ -284,13 +285,13 @@ export function JiraDashboardPageClient({ initialJiraConfig, initialAnalytics }:

- 🎯 {analytics.project.name} + {analytics.project.name} ({periodInfo.label}) {hasActiveFilters && ( - 🔍 Filtré + Filtré )}

@@ -350,14 +351,14 @@ export function JiraDashboardPageClient({ initialJiraConfig, initialAnalytics }:
{/* Info discrète sur le calcul des points */}
- 💡 Points : Utilise les story points Jira si définis, sinon Epic(13), Story(5), Task(3), Bug(2), Subtask(1) + Points : Utilise les story points Jira si définis, sinon Epic(13), Story(5), Task(3), Bug(2), Subtask(1)
{/* Graphiques principaux */}
-

👥 Répartition de l'équipe

+

Répartition de l'équipe

-

🚀 Vélocité des sprints

+

Vélocité des sprints

-

⏱️ Cycle Time par type

+

Cycle Time par type

-

📉 Burndown Chart

+

Burndown Chart

@@ -456,7 +457,7 @@ export function JiraDashboardPageClient({ initialJiraConfig, initialAnalytics }: -

📈 Throughput

+

Throughput

@@ -472,7 +473,7 @@ export function JiraDashboardPageClient({ initialJiraConfig, initialAnalytics }: {/* Métriques de qualité */} -

🎯 Métriques de qualité

+

Métriques de qualité

@@ -487,7 +488,7 @@ export function JiraDashboardPageClient({ initialJiraConfig, initialAnalytics }: {/* Métriques de predictabilité */} -

📊 Predictabilité

+

Predictabilité

@@ -502,7 +503,7 @@ export function JiraDashboardPageClient({ initialJiraConfig, initialAnalytics }: {/* Matrice de collaboration - ligne entière */} -

🤝 Matrice de collaboration

+

Matrice de collaboration

@@ -517,7 +518,7 @@ export function JiraDashboardPageClient({ initialJiraConfig, initialAnalytics }: {/* Comparaison inter-sprints */} -

📊 Comparaison inter-sprints

+

Comparaison inter-sprints

@@ -532,7 +533,7 @@ export function JiraDashboardPageClient({ initialJiraConfig, initialAnalytics }: {/* Heatmap d'activité de l'équipe */} -

🔥 Heatmap d'activité de l'équipe

+

Heatmap d'activité de l'équipe

@@ -552,7 +553,7 @@ export function JiraDashboardPageClient({ initialJiraConfig, initialAnalytics }: {/* Graphique de vélocité */} -

🚀 Vélocité des sprints

+

Vélocité des sprints

@@ -569,7 +570,7 @@ export function JiraDashboardPageClient({ initialJiraConfig, initialAnalytics }:
-

📉 Burndown Chart

+

Burndown Chart

@@ -583,7 +584,7 @@ export function JiraDashboardPageClient({ initialJiraConfig, initialAnalytics }: -

📊 Throughput

+

Throughput

@@ -599,7 +600,7 @@ export function JiraDashboardPageClient({ initialJiraConfig, initialAnalytics }: {/* Comparaison des sprints */} -

📊 Comparaison des sprints

+

Comparaison des sprints

@@ -619,7 +620,7 @@ export function JiraDashboardPageClient({ initialJiraConfig, initialAnalytics }:
-

⏱️ Cycle Time par type

+

Cycle Time par type

@@ -659,7 +660,7 @@ export function JiraDashboardPageClient({ initialJiraConfig, initialAnalytics }:
-

🎯 Métriques de qualité

+

Métriques de qualité

@@ -673,7 +674,7 @@ export function JiraDashboardPageClient({ initialJiraConfig, initialAnalytics }: -

📈 Predictabilité

+

Predictabilité

@@ -694,7 +695,7 @@ export function JiraDashboardPageClient({ initialJiraConfig, initialAnalytics }:
-

👥 Répartition de l'équipe

+

Répartition de l'équipe

@@ -708,7 +709,7 @@ export function JiraDashboardPageClient({ initialJiraConfig, initialAnalytics }: -

🤝 Matrice de collaboration

+

Matrice de collaboration

diff --git a/src/components/AuthButton.tsx b/src/components/AuthButton.tsx index 95b2323..f37baee 100644 --- a/src/components/AuthButton.tsx +++ b/src/components/AuthButton.tsx @@ -3,8 +3,8 @@ import { useSession, signOut } from 'next-auth/react' import { useRouter } from 'next/navigation' import { Button } from '@/components/ui/Button' +import { Emoji } from '@/components/ui/Emoji' import { Avatar } from '@/components/ui/Avatar' -import { LogOut } from 'lucide-react' export function AuthButton() { const { data: session, status } = useSession() @@ -53,7 +53,7 @@ export function AuthButton() { className="p-1 h-auto" title="Déconnexion" > - +
) diff --git a/src/components/ThemeSelector.tsx b/src/components/ThemeSelector.tsx index 592bacd..6efd6fa 100644 --- a/src/components/ThemeSelector.tsx +++ b/src/components/ThemeSelector.tsx @@ -95,7 +95,6 @@ export function ThemeSelector() {
- {themeOption.icon} {themeOption.name}
diff --git a/src/components/charts/WeeklyStatsCard.tsx b/src/components/charts/WeeklyStatsCard.tsx index a84f081..e528828 100644 --- a/src/components/charts/WeeklyStatsCard.tsx +++ b/src/components/charts/WeeklyStatsCard.tsx @@ -1,6 +1,7 @@ 'use client'; import { Card } from '@/components/ui/Card'; +import { Emoji } from '@/components/ui/Emoji'; interface WeeklyStats { thisWeek: number; @@ -51,7 +52,7 @@ export function WeeklyStatsCard({ stats, title = "Performance Hebdomadaire" }: W {/* Changement */}
- {changeIcon} +
{isPositive ? '+' : ''}{stats.change} tâches @@ -66,11 +67,11 @@ export function WeeklyStatsCard({ stats, title = "Performance Hebdomadaire" }: W {/* Insight */}

- {stats.changePercent > 20 ? 'Excellente progression ! 🚀' : - stats.changePercent > 0 ? 'Bonne progression 👍' : - stats.changePercent === 0 ? 'Performance stable 📊' : - stats.changePercent > -20 ? 'Légère baisse, restez motivé 💪' : - 'Focus sur la productivité cette semaine 🎯'} + {stats.changePercent > 20 ? <> Excellente progression ! : + stats.changePercent > 0 ? <> Bonne progression : + stats.changePercent === 0 ? <> Performance stable : + stats.changePercent > -20 ? <> Légère baisse, restez motivé : + <> Focus sur la productivité cette semaine}

diff --git a/src/components/daily/DailySection.tsx b/src/components/daily/DailySection.tsx index ff4b623..8fcb99e 100644 --- a/src/components/daily/DailySection.tsx +++ b/src/components/daily/DailySection.tsx @@ -1,5 +1,6 @@ 'use client'; +import { ReactNode } from 'react'; import { DailyCheckbox, DailyCheckboxType } from '@/lib/types'; import { Card } from '@/components/ui/Card'; import { Button } from '@/components/ui/Button'; @@ -13,7 +14,7 @@ import { useState } from 'react'; import React from 'react'; interface DailySectionProps { - title: string; + title: ReactNode; date: Date; checkboxes: DailyCheckbox[]; onAddCheckbox: (text: string, type: DailyCheckboxType) => Promise; @@ -103,7 +104,7 @@ export function DailySection({ collisionDetection={closestCenter} onDragStart={handleDragStart} onDragEnd={handleDragEnd} - id={`daily-dnd-${title.replace(/[^a-zA-Z0-9]/g, '-')}`} + id={`daily-dnd-${String(title).replace(/[^a-zA-Z0-9]/g, '-')}`} > {/* Header */} diff --git a/src/components/daily/PendingTasksSection.tsx b/src/components/daily/PendingTasksSection.tsx index 25363f6..a42fb75 100644 --- a/src/components/daily/PendingTasksSection.tsx +++ b/src/components/daily/PendingTasksSection.tsx @@ -8,6 +8,7 @@ import { DailyCheckbox, DailyCheckboxType } from '@/lib/types'; import { dailyClient } from '@/clients/daily-client'; import { formatDateShort, getDaysAgo } from '@/lib/date-utils'; import { moveCheckboxToToday } from '@/actions/daily'; +import { Emoji } from '@/components/ui/Emoji'; interface PendingTasksSectionProps { onToggleCheckbox: (checkboxId: string) => Promise; @@ -128,7 +129,7 @@ export function PendingTasksSection({ // Obtenir l'icône selon le type const getTypeIcon = (type: DailyCheckboxType) => { - return type === 'meeting' ? '🤝' : '📋'; + return type === 'meeting' ? : ; }; const pendingCount = pendingTasks.length; @@ -262,7 +263,7 @@ export function PendingTasksSection({ title="Déplacer à aujourd'hui" className="text-xs px-2 py-1 text-[var(--primary)] hover:text-[var(--primary)] disabled:opacity-50" > - 📅 + )} @@ -282,7 +283,7 @@ export function PendingTasksSection({ title="Supprimer cette tâche" className="text-xs px-2 py-1 text-[var(--destructive)] hover:text-[var(--destructive)]" > - 🗑️ +
diff --git a/src/components/dashboard/IntegrationFilter.tsx b/src/components/dashboard/IntegrationFilter.tsx index cba55e4..0e87628 100644 --- a/src/components/dashboard/IntegrationFilter.tsx +++ b/src/components/dashboard/IntegrationFilter.tsx @@ -1,6 +1,7 @@ 'use client'; import { useState, useMemo } from 'react'; +import { Link, Circle, Square, Hand } from 'lucide-react'; import { useTasksContext } from '@/contexts/TasksContext'; import { Dropdown, Button } from '@/components/ui'; import type { KanbanFilters } from '@/lib/types'; @@ -23,7 +24,7 @@ interface IntegrationFilterProps { interface SourceOption { id: 'jira' | 'tfs' | 'manual'; label: string; - icon: string; + icon: React.ReactNode; hasTasks: boolean; } @@ -53,19 +54,19 @@ export function IntegrationFilter({ { id: 'jira' as const, label: 'Jira', - icon: '🔹', + icon: , hasTasks: hasJiraTasks }, { id: 'tfs' as const, label: 'TFS', - icon: '🔷', + icon: , hasTasks: hasTfsTasks }, { id: 'manual' as const, label: 'Manuel', - icon: '✋', + icon: , hasTasks: hasManualTasks } ].filter(source => source.hasTasks); @@ -264,7 +265,12 @@ export function IntegrationFilter({ + + {getMainButtonText()} + + } variant={getMainButtonVariant()} content={dropdownContent} placement={alignRight ? "bottom-end" : "bottom-start"} diff --git a/src/components/dashboard/ManagerWeeklySummary.tsx b/src/components/dashboard/ManagerWeeklySummary.tsx index c0bb61c..4e8be61 100644 --- a/src/components/dashboard/ManagerWeeklySummary.tsx +++ b/src/components/dashboard/ManagerWeeklySummary.tsx @@ -12,6 +12,7 @@ import { MetricsTab } from './MetricsTab'; import { format } from 'date-fns'; import { fr } from 'date-fns/locale'; import { Tag } from '@/lib/types'; +import { Emoji } from '@/components/ui/Emoji'; interface ManagerWeeklySummaryProps { initialSummary: ManagerSummary; @@ -50,7 +51,7 @@ export default function ManagerWeeklySummary({ initialSummary }: ManagerWeeklySu {/* Header avec navigation */}
-

👔 Weekly

+

Weekly

{formatPeriod()}

{activeView !== 'metrics' && ( @@ -59,7 +60,7 @@ export default function ManagerWeeklySummary({ initialSummary }: ManagerWeeklySu variant="secondary" size="sm" > - 🔄 Actualiser +  Actualiser )}
@@ -80,22 +81,22 @@ export default function ManagerWeeklySummary({ initialSummary }: ManagerWeeklySu

- 📊 Résumé de la semaine + Résumé de la semaine

-

🎯 Points clés accomplis

+

Points clés accomplis

{summary.narrative.weekHighlight}

-

⚡ Défis traités

+

Défis traités

{summary.narrative.mainChallenges}

-

🔮 Focus 7 prochains jours

+

Focus 7 prochains jours

{summary.narrative.nextWeekFocus}

@@ -104,7 +105,7 @@ export default function ManagerWeeklySummary({ initialSummary }: ManagerWeeklySu {/* Métriques rapides */} -

📈 Métriques en bref

+

Métriques en bref

@@ -143,7 +144,7 @@ export default function ManagerWeeklySummary({ initialSummary }: ManagerWeeklySu borderBottomColor: 'color-mix(in srgb, var(--success) 10%, var(--border))' }}>

- 🏆 Top accomplissements + Top accomplissements

@@ -176,7 +177,7 @@ export default function ManagerWeeklySummary({ initialSummary }: ManagerWeeklySu borderBottomColor: 'color-mix(in srgb, var(--destructive) 10%, var(--border))' }}>

- 🎯 Top enjeux à venir + Top enjeux à venir

@@ -208,7 +209,7 @@ export default function ManagerWeeklySummary({ initialSummary }: ManagerWeeklySu {activeView === 'accomplishments' && ( -

✅ Accomplissements des 7 derniers jours

+

Accomplissements des 7 derniers jours

{summary.keyAccomplishments.length} accomplissements significatifs • {summary.metrics.totalTasksCompleted} tâches • {summary.metrics.totalCheckboxesCompleted} todos complétés

@@ -220,7 +221,7 @@ export default function ManagerWeeklySummary({ initialSummary }: ManagerWeeklySu borderColor: 'color-mix(in srgb, var(--muted) 40%, var(--border))', color: 'var(--muted-foreground)' }}> -
📭
+

Aucun accomplissement significatif trouvé cette semaine.

Ajoutez des tâches avec priorité haute/medium ou des meetings.

@@ -246,7 +247,7 @@ export default function ManagerWeeklySummary({ initialSummary }: ManagerWeeklySu {activeView === 'challenges' && ( -

🎯 Enjeux et défis à venir

+

Enjeux et défis à venir

{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

@@ -258,7 +259,7 @@ export default function ManagerWeeklySummary({ initialSummary }: ManagerWeeklySu borderColor: 'color-mix(in srgb, var(--muted) 40%, var(--border))', color: 'var(--muted-foreground)' }}> -
🎯
+

Aucun enjeu prioritaire trouvé.

Ajoutez des tâches non complétées avec priorité haute/medium.

diff --git a/src/components/dashboard/MetricsTab.tsx b/src/components/dashboard/MetricsTab.tsx index 15d5115..0d8b8c2 100644 --- a/src/components/dashboard/MetricsTab.tsx +++ b/src/components/dashboard/MetricsTab.tsx @@ -12,6 +12,7 @@ import { MetricsVelocitySection } from './charts/MetricsVelocitySection'; import { MetricsProductivitySection } from './charts/MetricsProductivitySection'; import { format } from 'date-fns'; import { fr } from 'date-fns/locale'; +import { Emoji } from '@/components/ui/Emoji'; interface MetricsTabProps { className?: string; @@ -41,13 +42,13 @@ export function MetricsTab({ className }: MetricsTabProps) {

- ❌ Erreur lors du chargement des métriques + Erreur lors du chargement des métriques

{metricsError || trendsError}

@@ -60,7 +61,7 @@ export function MetricsTab({ className }: MetricsTabProps) { {/* Header avec période et contrôles */}
-

📊 Métriques & Analytics

+

Métriques & Analytics

{formatPeriod()}

@@ -70,7 +71,7 @@ export function MetricsTab({ className }: MetricsTabProps) { size="sm" disabled={metricsLoading || trendsLoading} > - 🔄 Actualiser + Actualiser
diff --git a/src/components/dashboard/ProductivityAnalytics.tsx b/src/components/dashboard/ProductivityAnalytics.tsx index e2c9db2..543dac4 100644 --- a/src/components/dashboard/ProductivityAnalytics.tsx +++ b/src/components/dashboard/ProductivityAnalytics.tsx @@ -9,6 +9,7 @@ import { WeeklyStatsCard } from '@/components/charts/WeeklyStatsCard'; import { TagDistributionChart } from '@/components/dashboard/TagDistributionChart'; import { Card, MetricCard } from '@/components/ui'; import { DeadlineOverview } from '@/components/deadline/DeadlineOverview'; +import { Emoji } from '@/components/ui/Emoji'; interface ProductivityAnalyticsProps { metrics: ProductivityMetrics; @@ -90,7 +91,7 @@ export function ProductivityAnalytics({ metrics, deadlineMetrics, tagMetrics, se {/* Titre de section Analytics */}
-

📊 Analytics & Métriques

+

Analytics & Métriques

Derniers 30 jours
@@ -141,7 +142,7 @@ export function ProductivityAnalytics({ metrics, deadlineMetrics, tagMetrics, se {/* Insights automatiques */} -

💡 Insights

+

Insights

- +

Tâches Récentes

diff --git a/src/components/dashboard/WelcomeSection.tsx b/src/components/dashboard/WelcomeSection.tsx index 8373cb5..bc4a5a8 100644 --- a/src/components/dashboard/WelcomeSection.tsx +++ b/src/components/dashboard/WelcomeSection.tsx @@ -2,7 +2,8 @@ import { useSession } from 'next-auth/react'; import { useState, useEffect, useRef } from 'react'; -import { Check, User, ArrowRight } from 'lucide-react'; +import { Check, User, RefreshCw } from 'lucide-react'; +import { Emoji } from '@/components/ui/Emoji'; const WELCOME_GREETINGS = [ "Bienvenue", @@ -18,99 +19,99 @@ const WELCOME_GREETINGS = [ ]; const WELCOME_MESSAGES = [ - "Prêt à conquérir la journée ? 🚀", - "Votre productivité vous attend ! ⚡", - "C'est parti pour une journée productive ! 💪", - "Organisons ensemble vos tâches ! 📋", - "Votre tableau de bord vous attend ! 🎯", - "Prêt à faire la différence ? ✨", - "Concentrons-nous sur l'essentiel ! 🎯", - "Une nouvelle journée, de nouvelles opportunités ! 🌟", - "Votre succès commence ici ! 🏆", - "Transformons vos objectifs en réalité ! 🎪", - "C'est l'heure de briller ! ⭐", - "Votre efficacité n'attend que vous ! 🔥", - "Organisons votre succès ! 📊", - "Prêt à dépasser vos limites ? 🚀", - "Votre productivité vous remercie ! 🙏", - "C'est parti pour une journée exceptionnelle ! 🌈", - "Votre organisation parfaite vous attend ! 🎨", - "Prêt à accomplir de grandes choses ? 🏅", - "Votre motivation est votre force ! 💎", - "Créons ensemble votre succès ! 🎭", + { text: "Prêt à conquérir la journée ?", icon: "🚀" }, + { text: "Votre productivité vous attend !", icon: "⚡" }, + { text: "C'est parti pour une journée productive !", icon: "💪" }, + { text: "Organisons ensemble vos tâches !", icon: "📋" }, + { text: "Votre tableau de bord vous attend !", icon: "🎯" }, + { text: "Prêt à faire la différence ?", icon: "✨" }, + { text: "Concentrons-nous sur l'essentiel !", icon: "🎯" }, + { text: "Une nouvelle journée, de nouvelles opportunités !", icon: "🌟" }, + { text: "Votre succès commence ici !", icon: "🏆" }, + { text: "Transformons vos objectifs en réalité !", icon: "🎪" }, + { text: "C'est l'heure de briller !", icon: "⭐" }, + { text: "Votre efficacité n'attend que vous !", icon: "🔥" }, + { text: "Organisons votre succès !", icon: "📊" }, + { text: "Prêt à dépasser vos limites ?", icon: "🚀" }, + { text: "Votre productivité vous remercie !", icon: "🙏" }, + { text: "C'est parti pour une journée exceptionnelle !", icon: "🌈" }, + { text: "Votre organisation parfaite vous attend !", icon: "🎨" }, + { text: "Prêt à accomplir de grandes choses ?", icon: "🏅" }, + { text: "Votre motivation est votre force !", icon: "💎" }, + { text: "Créons ensemble votre succès !", icon: "🎭" }, // Messages humoristiques - "Attention, productivité en approche ! 🚨", - "Votre cerveau va être bien occupé ! 🧠", - "Préparez-vous à être impressionné par vous-même ! 😎", - "Mode super-héros activé ! 🦸‍♂️", - "Votre liste de tâches tremble déjà ! 😱", - "Prêt à faire exploser vos objectifs ? 💥", - "Votre procrastination n'a qu'à bien se tenir ! 😤", - "C'est l'heure de montrer qui est le boss ! 👑", - "Votre café peut attendre, vos tâches non ! ☕", - "Prêt à devenir la légende de la productivité ? 🏆", - "Attention, efficacité maximale détectée ! ⚡", - "Votre motivation est plus forte que le café ! ☕", - "Prêt à faire rougir votre calendrier ? 📅", - "Votre énergie positive est contagieuse ! 😄", - "C'est parti pour une journée épique ! 🎬", - "Votre détermination brille plus que le soleil ! ☀️", - "Prêt à transformer le chaos en ordre ? 🎯", - "Votre focus est plus précis qu'un laser ! 🔴", - "C'est l'heure de montrer vos super-pouvoirs ! 🦸‍♀️", - "Votre organisation va faire des jaloux ! 😏", - "Prêt à devenir le héros de votre propre histoire ? 📚", - "Votre productivité va battre des records ! 🏃‍♂️", - "Attention, génie au travail ! 🧪", - "Votre créativité déborde ! 🎨", - "Prêt à faire trembler vos deadlines ? ⏰", - "Votre énergie positive illumine la pièce ! 💡", - "C'est parti pour une aventure productive ! 🗺️", - "Votre motivation est plus forte que la gravité ! 🌍", - "Prêt à devenir le maître de l'organisation ? 🎭", - "Votre efficacité va faire des étincelles ! ✨" + { text: "Attention, productivité en approche !", icon: "🚨" }, + { text: "Votre cerveau va être bien occupé !", icon: "🧠" }, + { text: "Préparez-vous à être impressionné par vous-même !", icon: "😎" }, + { text: "Mode super-héros activé !", icon: "🦸‍♂️" }, + { text: "Votre liste de tâches tremble déjà !", icon: "😱" }, + { text: "Prêt à faire exploser vos objectifs ?", icon: "💥" }, + { text: "Votre procrastination n'a qu'à bien se tenir !", icon: "😤" }, + { text: "C'est l'heure de montrer qui est le boss !", icon: "👑" }, + { text: "Votre café peut attendre, vos tâches non !", icon: "☕" }, + { text: "Prêt à devenir la légende de la productivité ?", icon: "🏆" }, + { text: "Attention, efficacité maximale détectée !", icon: "⚡" }, + { text: "Votre motivation est plus forte que le café !", icon: "☕" }, + { text: "Prêt à faire rougir votre calendrier ?", icon: "📅" }, + { text: "Votre énergie positive est contagieuse !", icon: "😄" }, + { text: "C'est parti pour une journée épique !", icon: "🎬" }, + { text: "Votre détermination brille plus que le soleil !", icon: "☀️" }, + { text: "Prêt à transformer le chaos en ordre ?", icon: "🎯" }, + { text: "Votre focus est plus précis qu'un laser !", icon: "🔴" }, + { text: "C'est l'heure de montrer vos super-pouvoirs !", icon: "🦸‍♀️" }, + { text: "Votre organisation va faire des jaloux !", icon: "😏" }, + { text: "Prêt à devenir le héros de votre propre histoire ?", icon: "📚" }, + { text: "Votre productivité va battre des records !", icon: "🏃‍♂️" }, + { text: "Attention, génie au travail !", icon: "🧪" }, + { text: "Votre créativité déborde !", icon: "🎨" }, + { text: "Prêt à faire trembler vos deadlines ?", icon: "⏰" }, + { text: "Votre énergie positive illumine la pièce !", icon: "💡" }, + { text: "C'est parti pour une aventure productive !", icon: "🗺️" }, + { text: "Votre motivation est plus forte que la gravité !", icon: "🌍" }, + { text: "Prêt à devenir le maître de l'organisation ?", icon: "🎭" }, + { text: "Votre efficacité va faire des étincelles !", icon: "✨" } ]; const TIME_BASED_MESSAGES = { morning: [ - "Bonjour ! Une belle journée vous attend ! ☀️", - "Réveillez-vous, c'est l'heure de briller ! 🌅", - "Le matin est le moment parfait pour commencer ! 🌄", - "Une nouvelle journée, de nouvelles possibilités ! 🌞", - "Bonjour ! Votre café vous attend ! ☕", - "Réveillez-vous, les tâches n'attendent pas ! ⏰", - "Bonjour ! Prêt à conquérir le monde ? 🌍", - "Le matin, tout est possible ! 🌅", - "Bonjour ! Votre motivation vous appelle ! 📞", - "Réveillez-vous, c'est l'heure de la productivité ! ⚡" + { text: "Bonjour ! Une belle journée vous attend !", icon: "☀️" }, + { text: "Réveillez-vous, c'est l'heure de briller !", icon: "🌅" }, + { text: "Le matin est le moment parfait pour commencer !", icon: "🌄" }, + { text: "Une nouvelle journée, de nouvelles possibilités !", icon: "🌞" }, + { text: "Bonjour ! Votre café vous attend !", icon: "☕" }, + { text: "Réveillez-vous, les tâches n'attendent pas !", icon: "⏰" }, + { text: "Bonjour ! Prêt à conquérir le monde ?", icon: "🌍" }, + { text: "Le matin, tout est possible !", icon: "🌅" }, + { text: "Bonjour ! Votre motivation vous appelle !", icon: "📞" }, + { text: "Réveillez-vous, c'est l'heure de la productivité !", icon: "⚡" } ], afternoon: [ - "Bon après-midi ! Continuons sur cette lancée ! 🌤️", - "L'après-midi est parfait pour avancer ! ☀️", - "Encore quelques heures pour accomplir vos objectifs ! ⏰", - "L'énergie de l'après-midi vous porte ! 💪", - "Bon après-midi ! Le momentum continue ! 🚀", - "L'après-midi, c'est l'heure de l'efficacité ! ⚡", - "Bon après-midi ! Votre café de 14h vous attend ! ☕", - "L'après-midi, tout s'accélère ! 🏃‍♂️", - "Bon après-midi ! Prêt pour la deuxième mi-temps ? ⚽", - "L'après-midi, c'est l'heure de briller ! ✨" + { text: "Bon après-midi ! Continuons sur cette lancée !", icon: "🌤️" }, + { text: "L'après-midi est parfait pour avancer !", icon: "☀️" }, + { text: "Encore quelques heures pour accomplir vos objectifs !", icon: "⏰" }, + { text: "L'énergie de l'après-midi vous porte !", icon: "💪" }, + { text: "Bon après-midi ! Le momentum continue !", icon: "🚀" }, + { text: "L'après-midi, c'est l'heure de l'efficacité !", icon: "⚡" }, + { text: "Bon après-midi ! Votre café de 14h vous attend !", icon: "☕" }, + { text: "L'après-midi, tout s'accélère !", icon: "🏃‍♂️" }, + { text: "Bon après-midi ! Prêt pour la deuxième mi-temps ?", icon: "⚽" }, + { text: "L'après-midi, c'est l'heure de briller !", icon: "✨" } ], evening: [ - "Bonsoir ! Terminons la journée en beauté ! 🌆", - "Le soir est idéal pour finaliser vos tâches ! 🌇", - "Une dernière poussée avant la fin de journée ! 🌃", - "Le crépuscule vous accompagne ! 🌅", - "Bonsoir ! Prêt pour le sprint final ? 🏃‍♀️", - "Le soir, c'est l'heure de la victoire ! 🏆", - "Bonsoir ! Votre récompense vous attend ! 🎁", - "Le soir, on termine en héros ! 🦸‍♂️", - "Bonsoir ! Prêt à clôturer cette journée ? 📝", - "Le soir, c'est l'heure de la satisfaction ! 😌" + { text: "Bonsoir ! Terminons la journée en beauté !", icon: "🌆" }, + { text: "Le soir est idéal pour finaliser vos tâches !", icon: "🌇" }, + { text: "Une dernière poussée avant la fin de journée !", icon: "🌃" }, + { text: "Le crépuscule vous accompagne !", icon: "🌅" }, + { text: "Bonsoir ! Prêt pour le sprint final ?", icon: "🏃‍♀️" }, + { text: "Le soir, c'est l'heure de la victoire !", icon: "🏆" }, + { text: "Bonsoir ! Votre récompense vous attend !", icon: "🎁" }, + { text: "Le soir, on termine en héros !", icon: "🦸‍♂️" }, + { text: "Bonsoir ! Prêt à clôturer cette journée ?", icon: "📝" }, + { text: "Le soir, c'est l'heure de la satisfaction !", icon: "😌" } ] }; -function getTimeBasedMessage(): string { +function getTimeBasedMessage(): { text: string; icon: string } { const hour = new Date().getHours(); if (hour >= 5 && hour < 12) { @@ -122,7 +123,7 @@ function getTimeBasedMessage(): string { } } -function getRandomWelcomeMessage(): string { +function getRandomWelcomeMessage(): { text: string; icon: string } { return WELCOME_MESSAGES[Math.floor(Math.random() * WELCOME_MESSAGES.length)]; } @@ -132,8 +133,8 @@ function getRandomGreeting(): string { export function WelcomeSection() { const { data: session } = useSession(); - const [welcomeMessage, setWelcomeMessage] = useState(''); - const [timeMessage, setTimeMessage] = useState(''); + const [welcomeMessage, setWelcomeMessage] = useState<{ text: string; icon: string }>({ text: '', icon: '' }); + const [timeMessage, setTimeMessage] = useState<{ text: string; icon: string }>({ text: '', icon: '' }); const [greeting, setGreeting] = useState(''); const [isAnimating, setIsAnimating] = useState(false); const [particleCount, setParticleCount] = useState(0); @@ -254,7 +255,7 @@ export function WelcomeSection() { }`} style={{ transitionDelay: '0.3s' }} > - {timeMessage} + {timeMessage.text}

@@ -265,7 +266,7 @@ export function WelcomeSection() { }`} style={{ transitionDelay: '0.5s' }} > - {welcomeMessage} + {welcomeMessage.text}

@@ -279,7 +280,7 @@ export function WelcomeSection() { >
-
diff --git a/src/components/dashboard/charts/MetricsOverview.tsx b/src/components/dashboard/charts/MetricsOverview.tsx index 16c5142..6c53847 100644 --- a/src/components/dashboard/charts/MetricsOverview.tsx +++ b/src/components/dashboard/charts/MetricsOverview.tsx @@ -2,6 +2,7 @@ import { Card, CardHeader, CardContent } from '@/components/ui/Card'; import { WeeklyMetrics } from '@/hooks/use-metrics'; +import { Emoji } from '@/components/ui/Emoji'; interface MetricsOverviewProps { metrics: WeeklyMetrics; @@ -10,26 +11,26 @@ interface MetricsOverviewProps { export function MetricsOverview({ metrics }: MetricsOverviewProps) { const getTrendIcon = (trend: string) => { switch (trend) { - case 'improving': return '📈'; - case 'declining': return '📉'; - case 'stable': return '➡️'; - default: return '📊'; + case 'improving': return ; + case 'declining': return ; + case 'stable': return ; + default: return ; } }; const getPatternIcon = (pattern: string) => { switch (pattern) { - case 'consistent': return '🎯'; - case 'variable': return '📊'; - case 'weekend-heavy': return '📅'; - default: return '📋'; + case 'consistent': return ; + case 'variable': return ; + case 'weekend-heavy': return ; + default: return ; } }; return ( -

🎯 Vue d'ensemble

+

Vue d'ensemble

diff --git a/src/components/dashboard/charts/ProductivityInsights.tsx b/src/components/dashboard/charts/ProductivityInsights.tsx index 0e0196b..4eed77a 100644 --- a/src/components/dashboard/charts/ProductivityInsights.tsx +++ b/src/components/dashboard/charts/ProductivityInsights.tsx @@ -1,6 +1,7 @@ 'use client'; import { DailyMetrics } from '@/services/analytics/metrics'; +import { Emoji } from '@/components/ui/Emoji'; interface ProductivityInsightsProps { data: DailyMetrics[]; @@ -46,24 +47,24 @@ export function ProductivityInsights({ data, className }: ProductivityInsightsPr const getTrendIcon = () => { switch (trend) { - case 'up': return { icon: '📈', color: 'text-green-600', label: 'En amélioration' }; - case 'down': return { icon: '📉', color: 'text-red-600', label: 'En baisse' }; - default: return { icon: '➡️', color: 'text-blue-600', label: 'Stable' }; + case 'up': return { icon: , color: 'text-green-600', label: 'En amélioration' }; + case 'down': return { icon: , color: 'text-red-600', label: 'En baisse' }; + default: return { icon: , color: 'text-blue-600', label: 'Stable' }; } }; const getConsistencyLevel = () => { - if (consistencyScore >= 80) return { label: 'Très régulier', color: 'text-green-600', icon: '🎯' }; - if (consistencyScore >= 60) return { label: 'Assez régulier', color: 'text-blue-600', icon: '📊' }; - if (consistencyScore >= 40) return { label: 'Variable', color: 'text-yellow-600', icon: '📊' }; - return { label: 'Très variable', color: 'text-red-600', icon: '📊' }; + if (consistencyScore >= 80) return { label: 'Très régulier', color: 'text-green-600', icon: }; + if (consistencyScore >= 60) return { label: 'Assez régulier', color: 'text-blue-600', icon: }; + if (consistencyScore >= 40) return { label: 'Variable', color: 'text-yellow-600', icon: }; + return { label: 'Très variable', color: 'text-red-600', icon: }; }; const getRatioStatus = () => { - if (creationRatio >= 100) return { label: 'Équilibré+', color: 'text-green-600', icon: '⚖️' }; - if (creationRatio >= 80) return { label: 'Bien équilibré', color: 'text-blue-600', icon: '⚖️' }; - if (creationRatio >= 60) return { label: 'Légèrement en retard', color: 'text-yellow-600', icon: '⚖️' }; - return { label: 'Accumulation', color: 'text-red-600', icon: '⚖️' }; + if (creationRatio >= 100) return { label: 'Équilibré+', color: 'text-green-600', icon: }; + if (creationRatio >= 80) return { label: 'Bien équilibré', color: 'text-blue-600', icon: }; + if (creationRatio >= 60) return { label: 'Légèrement en retard', color: 'text-yellow-600', icon: }; + return { label: 'Accumulation', color: 'text-red-600', icon: }; }; const trendInfo = getTrendIcon(); @@ -79,7 +80,7 @@ export function ProductivityInsights({ data, className }: ProductivityInsightsPr

- 🏆 Jour champion + Jour champion

{mostProductiveDay.completed} @@ -97,7 +98,7 @@ export function ProductivityInsights({ data, className }: ProductivityInsightsPr

- 💡 Jour créatif + Jour créatif

{mostCreativeDay.newTasks} @@ -164,7 +165,7 @@ export function ProductivityInsights({ data, className }: ProductivityInsightsPr {/* Recommandations */}

- 💡 Recommandations + Recommandations

{trend === 'down' && ( diff --git a/src/components/deadline/DeadlineOverview.tsx b/src/components/deadline/DeadlineOverview.tsx index 2410884..4516a33 100644 --- a/src/components/deadline/DeadlineOverview.tsx +++ b/src/components/deadline/DeadlineOverview.tsx @@ -2,6 +2,7 @@ import { DeadlineMetrics } from '@/services/analytics/deadline-analytics'; import { DeadlineRiskCard } from './DeadlineRiskCard'; import { CriticalDeadlinesCard } from './CriticalDeadlinesCard'; import { DeadlineSummaryCard } from './DeadlineSummaryCard'; +import { Emoji } from '@/components/ui/Emoji'; interface DeadlineOverviewProps { metrics: DeadlineMetrics; @@ -13,7 +14,7 @@ export function DeadlineOverview({ metrics }: DeadlineOverviewProps) {
{/* Titre de section */}
-

🚨 Échéances Critiques

+

Échéances Critiques

Surveillance temps réel
diff --git a/src/components/deadline/DeadlineRiskCard.tsx b/src/components/deadline/DeadlineRiskCard.tsx index d002fda..aa9b197 100644 --- a/src/components/deadline/DeadlineRiskCard.tsx +++ b/src/components/deadline/DeadlineRiskCard.tsx @@ -2,6 +2,7 @@ import { DeadlineMetrics, DeadlineAnalyticsService } from '@/services/analytics/deadline-analytics'; import { Card } from '@/components/ui/Card'; +import { Emoji } from '@/components/ui/Emoji'; interface DeadlineRiskCardProps { metrics: DeadlineMetrics; @@ -44,7 +45,7 @@ export function DeadlineRiskCard({ metrics }: DeadlineRiskCardProps) {
- {getRiskIcon(riskAnalysis.riskLevel)} +

Niveau de Risque

diff --git a/src/components/deadline/DeadlineSummaryCard.tsx b/src/components/deadline/DeadlineSummaryCard.tsx index 47ef6a4..6e01355 100644 --- a/src/components/deadline/DeadlineSummaryCard.tsx +++ b/src/components/deadline/DeadlineSummaryCard.tsx @@ -2,6 +2,7 @@ import { DeadlineMetrics } from '@/services/analytics/deadline-analytics'; import { Card } from '@/components/ui/Card'; +import { Emoji } from '@/components/ui/Emoji'; interface DeadlineSummaryCardProps { metrics: DeadlineMetrics; @@ -55,7 +56,7 @@ export function DeadlineSummaryCard({ metrics }: DeadlineSummaryCardProps) {
- {item.icon} +
{item.label}
diff --git a/src/components/jira/FilterBar.tsx b/src/components/jira/FilterBar.tsx index d171b8f..38c5a1e 100644 --- a/src/components/jira/FilterBar.tsx +++ b/src/components/jira/FilterBar.tsx @@ -6,6 +6,7 @@ import { JiraAdvancedFiltersService } from '@/services/integrations/jira/advance import { Button } from '@/components/ui/Button'; import { Badge } from '@/components/ui/Badge'; import { Modal } from '@/components/ui/Modal'; +import { Emoji } from '@/components/ui/Emoji'; interface FilterBarProps { availableFilters: AvailableFilters; @@ -64,10 +65,10 @@ export default function FilterBar({
- 🔍 Filtres + Filtres {isLoading && ( - ⏳ Chargement... + Chargement... )} {hasActiveFilters && !isLoading && ( @@ -86,7 +87,7 @@ export default function FilterBar({ className="bg-purple-100 text-purple-800 text-xs cursor-pointer hover:bg-purple-200 transition-colors" onClick={() => removeFilter('components', comp)} > - 📦 {comp} × + {comp} × ))} {activeFilters.fixVersions?.slice(0, 2).map(version => ( @@ -95,7 +96,7 @@ export default function FilterBar({ className="bg-green-100 text-green-800 text-xs cursor-pointer hover:bg-green-200 transition-colors" onClick={() => removeFilter('fixVersions', version)} > - 🏷️ {version} × + {version} × ))} {activeFilters.issueTypes?.slice(0, 3).map(type => ( @@ -104,7 +105,7 @@ export default function FilterBar({ className="bg-orange-100 text-orange-800 text-xs cursor-pointer hover:bg-orange-200 transition-colors" onClick={() => removeFilter('issueTypes', type)} > - 📋 {type} × + {type} × ))} {activeFilters.statuses?.slice(0, 2).map(status => ( @@ -113,7 +114,7 @@ export default function FilterBar({ className="bg-blue-100 text-blue-800 text-xs cursor-pointer hover:bg-blue-200 transition-colors" onClick={() => removeFilter('statuses', status)} > - 🔄 {status} × + {status} × ))} {activeFilters.assignees?.slice(0, 2).map(assignee => ( @@ -122,7 +123,7 @@ export default function FilterBar({ className="bg-yellow-100 text-yellow-800 text-xs cursor-pointer hover:bg-yellow-200 transition-colors" onClick={() => removeFilter('assignees', assignee)} > - 👤 {assignee} × + {assignee} × ))} @@ -189,7 +190,7 @@ export default function FilterBar({
{/* Types de tickets */}
-

📋 Types de tickets

+

Types de tickets

{availableFilters.issueTypes.map(option => (