diff --git a/src/components/daily/DailyCalendar.tsx b/src/components/daily/DailyCalendar.tsx
index ad7c274..148873f 100644
--- a/src/components/daily/DailyCalendar.tsx
+++ b/src/components/daily/DailyCalendar.tsx
@@ -4,6 +4,8 @@ import React, { useState } from 'react';
import { Button } from '@/components/ui/Button';
import { Card } from '@/components/ui/Card';
import { formatDateForAPI, createDate, getToday } from '@/lib/date-utils';
+import { format } from 'date-fns';
+import { fr } from 'date-fns/locale';
interface DailyCalendarProps {
currentDate: Date;
@@ -97,10 +99,7 @@ export function DailyCalendar({
};
const formatMonthYear = () => {
- return viewDate.toLocaleDateString('fr-FR', {
- month: 'long',
- year: 'numeric',
- });
+ return format(viewDate, 'MMMM yyyy', { locale: fr });
};
const weekDays = ['Lun', 'Mar', 'Mer', 'Jeu', 'Ven', 'Sam', 'Dim'];
diff --git a/src/components/dashboard/RecentTasks.tsx b/src/components/dashboard/RecentTasks.tsx
index bb19b29..92517b9 100644
--- a/src/components/dashboard/RecentTasks.tsx
+++ b/src/components/dashboard/RecentTasks.tsx
@@ -3,6 +3,7 @@
import { Task } from '@/lib/types';
import { Card } from '@/components/ui/Card';
import { TagDisplay } from '@/components/ui/TagDisplay';
+import { formatDateShort } from '@/lib/date-utils';
import { Badge } from '@/components/ui/Badge';
import { useTasksContext } from '@/contexts/TasksContext';
import { getPriorityConfig, getPriorityColorHex, getStatusBadgeClasses, getStatusLabel } from '@/lib/status-config';
@@ -18,7 +19,7 @@ export function RecentTasks({ tasks }: RecentTasksProps) {
// Prendre les 5 tâches les plus récentes (créées ou modifiées)
const recentTasks = tasks
- .sort((a, b) => new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime())
+ .sort((a, b) => b.updatedAt.getTime() - a.updatedAt.getTime())
.slice(0, 5);
// Fonctions simplifiées utilisant la configuration centralisée
@@ -116,10 +117,7 @@ export function RecentTasks({ tasks }: RecentTasksProps) {
- {new Date(task.updatedAt).toLocaleDateString('fr-FR', {
- day: 'numeric',
- month: 'short'
- })}
+ {formatDateShort(task.updatedAt)}
diff --git a/src/components/dashboard/charts/CompletionRateChart.tsx b/src/components/dashboard/charts/CompletionRateChart.tsx
index 6f9d3a6..ad45f95 100644
--- a/src/components/dashboard/charts/CompletionRateChart.tsx
+++ b/src/components/dashboard/charts/CompletionRateChart.tsx
@@ -2,6 +2,7 @@
import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer } from 'recharts';
import { DailyMetrics } from '@/services/metrics';
+import { parseDate, formatDateShort } from '@/lib/date-utils';
interface CompletionRateChartProps {
data: DailyMetrics[];
@@ -12,7 +13,7 @@ export function CompletionRateChart({ data, className }: CompletionRateChartProp
// Transformer les données pour le graphique
const chartData = data.map(day => ({
day: day.dayName.substring(0, 3), // Lun, Mar, etc.
- date: new Date(day.date).toLocaleDateString('fr-FR', { day: '2-digit', month: '2-digit' }),
+ date: formatDateShort(parseDate(day.date)),
completionRate: day.completionRate,
completed: day.completed,
total: day.totalTasks
diff --git a/src/components/forms/RelatedTodos.tsx b/src/components/forms/RelatedTodos.tsx
index 84a8d40..94e3568 100644
--- a/src/components/forms/RelatedTodos.tsx
+++ b/src/components/forms/RelatedTodos.tsx
@@ -4,7 +4,7 @@ import { useState, useEffect, useCallback, useTransition } from 'react';
import { DailyCheckbox } from '@/lib/types';
import { tasksClient } from '@/clients/tasks-client';
import { Button } from '@/components/ui/Button';
-import { formatDateSmart } from '@/lib/date-utils';
+import { formatDateSmart, parseDate } from '@/lib/date-utils';
import { Input } from '@/components/ui/Input';
import { addTodoToTask, toggleCheckbox } from '@/actions/daily';
@@ -42,7 +42,7 @@ export function RelatedTodos({ taskId }: RelatedTodosProps) {
startTransition(async () => {
try {
// Si une date est spécifiée, l'utiliser, sinon undefined (aujourd'hui par défaut)
- const targetDate = newTodoDate ? new Date(newTodoDate) : undefined;
+ const targetDate = newTodoDate ? parseDate(newTodoDate) : undefined;
const result = await addTodoToTask(taskId, newTodoText, targetDate);
@@ -79,7 +79,7 @@ export function RelatedTodos({ taskId }: RelatedTodosProps) {
const formatDate = (date: Date | string) => {
try {
- const dateObj = typeof date === 'string' ? new Date(date) : date;
+ const dateObj = typeof date === 'string' ? parseDate(date) : date;
if (isNaN(dateObj.getTime())) {
return 'Date invalide';
}
diff --git a/src/components/jira/JiraLogs.tsx b/src/components/jira/JiraLogs.tsx
index 1755df7..5cef6d4 100644
--- a/src/components/jira/JiraLogs.tsx
+++ b/src/components/jira/JiraLogs.tsx
@@ -6,6 +6,7 @@ import { Badge } from '@/components/ui/Badge';
import { Button } from '@/components/ui/Button';
import { formatDistanceToNow } from 'date-fns';
import { fr } from 'date-fns/locale';
+import { parseDate } from '@/lib/date-utils';
interface SyncLog {
id: string;
@@ -111,7 +112,7 @@ export function JiraLogs({ className = "" }: JiraLogsProps) {
{getStatusBadge(log.status)}
- {formatDistanceToNow(new Date(log.createdAt), {
+ {formatDistanceToNow(parseDate(log.createdAt), {
addSuffix: true,
locale: fr
})}
diff --git a/src/components/jira/JiraSchedulerConfig.tsx b/src/components/jira/JiraSchedulerConfig.tsx
index 549d555..1f5b7ef 100644
--- a/src/components/jira/JiraSchedulerConfig.tsx
+++ b/src/components/jira/JiraSchedulerConfig.tsx
@@ -5,6 +5,7 @@ import { Button } from '@/components/ui/Button';
import { Card, CardHeader, CardContent } from '@/components/ui/Card';
import { Badge } from '@/components/ui/Badge';
import { jiraClient, JiraSchedulerStatus } from '@/clients/jira-client';
+import { parseDate, getToday } from '@/lib/date-utils';
interface JiraSchedulerConfigProps {
className?: string;
@@ -85,8 +86,8 @@ export function JiraSchedulerConfig({ className = "" }: JiraSchedulerConfigProps
const getNextSyncText = () => {
if (!schedulerStatus?.nextSync) return 'Aucune synchronisation planifiée';
- const nextSync = new Date(schedulerStatus.nextSync);
- const now = new Date();
+ const nextSync = parseDate(schedulerStatus.nextSync);
+ const now = getToday();
const diffMs = nextSync.getTime() - now.getTime();
if (diffMs <= 0) return 'Synchronisation en cours...';
diff --git a/src/components/jira/JiraSync.tsx b/src/components/jira/JiraSync.tsx
index e7c2e90..77d53ff 100644
--- a/src/components/jira/JiraSync.tsx
+++ b/src/components/jira/JiraSync.tsx
@@ -4,6 +4,7 @@ import { useState } from 'react';
import { Button } from '@/components/ui/Button';
import { Card, CardHeader, CardContent } from '@/components/ui/Card';
import { Badge } from '@/components/ui/Badge';
+import { getToday } from '@/lib/date-utils';
import { Modal } from '@/components/ui/Modal';
import { jiraClient } from '@/clients/jira-client';
import { JiraSyncResult, JiraSyncAction } from '@/services/jira';
@@ -79,7 +80,7 @@ export function JiraSync({ onSyncComplete, className = "" }: JiraSyncProps) {
{success ? "✓ Succès" : "⚠ Erreurs"}
- {new Date().toLocaleTimeString()}
+ {getToday().toLocaleTimeString()}
diff --git a/src/components/jira/SprintDetailModal.tsx b/src/components/jira/SprintDetailModal.tsx
index 8390d6c..311452d 100644
--- a/src/components/jira/SprintDetailModal.tsx
+++ b/src/components/jira/SprintDetailModal.tsx
@@ -4,6 +4,7 @@ import { useState, useEffect, useCallback } from 'react';
import { SprintVelocity, JiraTask, AssigneeDistribution, StatusDistribution } from '@/lib/types';
import { Modal } from '@/components/ui/Modal';
import { Card, CardHeader, CardContent } from '@/components/ui/Card';
+import { parseDate, formatDateForDisplay } from '@/lib/date-utils';
import { Badge } from '@/components/ui/Badge';
import { Button } from '@/components/ui/Button';
@@ -144,7 +145,7 @@ export default function SprintDetailModal({
Période
- {new Date(sprint.startDate).toLocaleDateString('fr-FR')} - {new Date(sprint.endDate).toLocaleDateString('fr-FR')}
+ {formatDateForDisplay(parseDate(sprint.startDate))} - {formatDateForDisplay(parseDate(sprint.endDate))}
@@ -318,7 +319,7 @@ export default function SprintDetailModal({
📋 {issue.issuetype.name}
👤 {issue.assignee?.displayName || 'Non assigné'}
- 📅 {new Date(issue.created).toLocaleDateString('fr-FR')}
+ 📅 {formatDateForDisplay(parseDate(issue.created))}
diff --git a/src/components/kanban/TaskCard.tsx b/src/components/kanban/TaskCard.tsx
index 578ce03..aae8783 100644
--- a/src/components/kanban/TaskCard.tsx
+++ b/src/components/kanban/TaskCard.tsx
@@ -427,7 +427,7 @@ export function TaskCard({ task, onEdit, compactView = false }: TaskCardProps) {
{task.dueDate ? (
⏰
- {formatDistanceToNow(new Date(task.dueDate), {
+ {formatDistanceToNow(task.dueDate, {
addSuffix: true,
locale: fr
})}
diff --git a/src/components/settings/AdvancedSettingsPageClient.tsx b/src/components/settings/AdvancedSettingsPageClient.tsx
index 2f66f24..525db4e 100644
--- a/src/components/settings/AdvancedSettingsPageClient.tsx
+++ b/src/components/settings/AdvancedSettingsPageClient.tsx
@@ -8,6 +8,7 @@ import { Button } from '@/components/ui/Button';
import { UserPreferencesProvider } from '@/contexts/UserPreferencesContext';
import { backupClient, BackupListResponse } from '@/clients/backup-client';
import Link from 'next/link';
+import { parseDate, getToday, formatDateForDisplay } from '@/lib/date-utils';
interface DatabaseStats {
taskCount: number;
@@ -86,22 +87,14 @@ export function AdvancedSettingsPageClient({
const formatTimeAgo = (date: Date): string => {
// Format fixe pour éviter les erreurs d'hydratation
- const d = new Date(date);
- return d.toLocaleDateString('fr-FR', {
- day: '2-digit',
- month: '2-digit',
- year: 'numeric',
- hour: '2-digit',
- minute: '2-digit',
- hour12: false
- });
+ return formatDateForDisplay(date, 'DISPLAY_MEDIUM');
};
const getNextBackupTime = (): string => {
if (!backupData.scheduler.nextBackup) return 'Non planifiée';
- const nextBackup = new Date(backupData.scheduler.nextBackup);
- const now = new Date();
+ const nextBackup = parseDate(backupData.scheduler.nextBackup);
+ const now = getToday();
const diffMs = nextBackup.getTime() - now.getTime();
const diffMins = Math.floor(diffMs / (1000 * 60));
const diffHours = Math.floor(diffMins / 60);
diff --git a/src/components/settings/BackupSettingsPageClient.tsx b/src/components/settings/BackupSettingsPageClient.tsx
index 339c582..f98d920 100644
--- a/src/components/settings/BackupSettingsPageClient.tsx
+++ b/src/components/settings/BackupSettingsPageClient.tsx
@@ -8,7 +8,7 @@ import { Card, CardHeader, CardContent } from '@/components/ui/Card';
import { Input } from '@/components/ui/Input';
import { Modal } from '@/components/ui/Modal';
import { Header } from '@/components/ui/Header';
-import { formatDateForDisplay } from '@/lib/date-utils';
+import { formatDateForDisplay, parseDate, getToday } from '@/lib/date-utils';
import Link from 'next/link';
interface BackupSettingsPageClientProps {
@@ -209,8 +209,8 @@ export default function BackupSettingsPageClient({ initialData }: BackupSettings
const getNextBackupTime = (): string => {
if (!data?.scheduler.nextBackup) return 'Non planifiée';
- const nextBackup = new Date(data.scheduler.nextBackup);
- const now = new Date();
+ const nextBackup = parseDate(data.scheduler.nextBackup);
+ const now = getToday();
const diffMs = nextBackup.getTime() - now.getTime();
const diffMins = Math.floor(diffMs / (1000 * 60));
const diffHours = Math.floor(diffMins / 60);
diff --git a/src/components/settings/GeneralSettingsPageClient.tsx b/src/components/settings/GeneralSettingsPageClient.tsx
index b8d55a9..875e382 100644
--- a/src/components/settings/GeneralSettingsPageClient.tsx
+++ b/src/components/settings/GeneralSettingsPageClient.tsx
@@ -10,6 +10,7 @@ import { Input } from '@/components/ui/Input';
import { TagForm } from '@/components/forms/TagForm';
import { UserPreferencesProvider } from '@/contexts/UserPreferencesContext';
import Link from 'next/link';
+import { formatDateForDisplay } from '@/lib/date-utils';
interface GeneralSettingsPageClientProps {
initialPreferences: UserPreferences;
@@ -294,7 +295,7 @@ export function GeneralSettingsPageClient({ initialPreferences, initialTags }: G
{('createdAt' in tag && (tag as Tag & { createdAt: Date }).createdAt) && (
- Créé le {new Date((tag as Tag & { createdAt: Date }).createdAt).toLocaleDateString('fr-FR')}
+ Créé le {formatDateForDisplay((tag as Tag & { createdAt: Date }).createdAt)}
)}
diff --git a/src/hooks/useDaily.ts b/src/hooks/useDaily.ts
index 8af0ac5..55e831a 100644
--- a/src/hooks/useDaily.ts
+++ b/src/hooks/useDaily.ts
@@ -43,7 +43,7 @@ interface UseDailyActions {
* Hook pour la gestion d'une vue daily spécifique
*/
export function useDaily(initialDate?: Date, initialDailyView?: DailyView): UseDailyState & UseDailyActions & { currentDate: Date } {
- const [currentDate, setCurrentDate] = useState(initialDate || new Date());
+ const [currentDate, setCurrentDate] = useState(initialDate || getToday());
const [dailyView, setDailyView] = useState(initialDailyView || null);
const [loading, setLoading] = useState(!initialDailyView); // Pas de loading si on a des données SSR
const [refreshing, setRefreshing] = useState(false); // Pour les refresh silencieux
diff --git a/src/services/daily.ts b/src/services/daily.ts
index 020dcdb..ff89d1d 100644
--- a/src/services/daily.ts
+++ b/src/services/daily.ts
@@ -1,7 +1,7 @@
import { prisma } from './database';
import { Prisma } from '@prisma/client';
import { DailyCheckbox, DailyView, CreateDailyCheckboxData, UpdateDailyCheckboxData, BusinessError, DailyCheckboxType, TaskStatus, TaskPriority, TaskSource } from '@/lib/types';
-import { getPreviousWorkday, normalizeDate, formatDateForAPI } from '@/lib/date-utils';
+import { getPreviousWorkday, normalizeDate, formatDateForAPI, getToday, getYesterday } from '@/lib/date-utils';
/**
* Service pour la gestion des checkboxes daily
@@ -180,7 +180,7 @@ export class DailyService {
* Récupère la vue daily d'aujourd'hui
*/
async getTodaysDailyView(): Promise {
- return this.getDailyView(new Date());
+ return this.getDailyView(getToday());
}
/**
@@ -188,7 +188,7 @@ export class DailyService {
*/
async addTodayCheckbox(text: string, taskId?: string): Promise {
return this.addCheckbox({
- date: new Date(),
+ date: getToday(),
text,
taskId
});
@@ -198,11 +198,8 @@ export class DailyService {
* Ajoute une checkbox pour hier
*/
async addYesterdayCheckbox(text: string, taskId?: string): Promise {
- const yesterday = new Date();
- yesterday.setDate(yesterday.getDate() - 1);
-
return this.addCheckbox({
- date: yesterday,
+ date: getYesterday(),
text,
taskId
});
diff --git a/src/services/jira.ts b/src/services/jira.ts
index 4c1f0d8..4eaf516 100644
--- a/src/services/jira.ts
+++ b/src/services/jira.ts
@@ -5,7 +5,7 @@
import { JiraTask } from '@/lib/types';
import { prisma } from './database';
-import { parseDate } from '@/lib/date-utils';
+import { parseDate, formatDateForDisplay } from '@/lib/date-utils';
export interface JiraConfig {
baseUrl: string;
@@ -389,8 +389,8 @@ export class JiraService {
changes.push(`Priorité: préservée localement (${existingTask.priority})`);
}
if ((existingTask.dueDate?.getTime() || null) !== (taskData.dueDate?.getTime() || null)) {
- const oldDate = existingTask.dueDate ? existingTask.dueDate.toLocaleDateString() : 'Aucune';
- const newDate = taskData.dueDate ? taskData.dueDate.toLocaleDateString() : 'Aucune';
+ const oldDate = existingTask.dueDate ? formatDateForDisplay(existingTask.dueDate) : 'Aucune';
+ const newDate = taskData.dueDate ? formatDateForDisplay(taskData.dueDate) : 'Aucune';
changes.push(`Échéance: ${oldDate} → ${newDate}`);
}
if (existingTask.jiraProject !== taskData.jiraProject) {