From 557cdebc13dfe84c9db6f06721b7e1fba78b7cec Mon Sep 17 00:00:00 2001 From: Julien Froidefond Date: Sun, 21 Sep 2025 11:41:17 +0200 Subject: [PATCH] refactor: date utils and all calls --- TODO.md | 4 +- scripts/backup-manager.ts | 3 +- src/actions/daily.ts | 15 +- src/actions/jira-export.ts | 3 +- src/actions/metrics.ts | 3 +- src/app/api/daily/route.ts | 18 +- src/app/daily/DailyPageClient.tsx | 30 +-- src/clients/daily-client.ts | 14 +- .../charts/CompletionTrendChart.tsx | 11 +- src/components/daily/DailyCalendar.tsx | 26 +-- src/components/dashboard/MetricsTab.tsx | 3 +- .../dashboard/charts/DailyStatusChart.tsx | 3 +- .../charts/WeeklyActivityHeatmap.tsx | 3 +- src/components/forms/RelatedTodos.tsx | 7 +- src/components/jira/AnomalyDetectionPanel.tsx | 3 +- .../settings/BackupSettingsPageClient.tsx | 13 +- src/hooks/useDaily.ts | 9 +- src/lib/backup-utils.ts | 3 +- src/lib/date-utils.ts | 206 ++++++++++++++++++ src/services/daily.ts | 21 +- src/services/jira.ts | 7 +- src/services/metrics.ts | 7 +- src/services/tasks.ts | 5 +- 23 files changed, 300 insertions(+), 117 deletions(-) create mode 100644 src/lib/date-utils.ts diff --git a/TODO.md b/TODO.md index 9535f7f..a887d4c 100644 --- a/TODO.md +++ b/TODO.md @@ -2,9 +2,9 @@ ## Autre Todos #2 - [x] Synchro Jira auto en background timé comme pour la synchro de sauvegarde -- [ ] refacto des allpreferences : ca devrait eter un contexte dans le layout qui balance serverside dans le hook +- [ ] refacto des getallpreferences en frontend : ca devrait eter un contexte dans le layout qui balance serverside dans le hook - [x] backups : ne backuper que si il y a eu un changement entre le dernier backup et la base actuelle -- [ ] refacto des dates avec le utils qui pour l'instant n'est pas utilisé +- [x] refacto des dates avec le utils qui pour l'instant n'est pas utilisé - [ ] split de certains gros composants. - [x] Page jira-dashboard : onglets analytics avancés et Qualité et collaboration : les charts sortent des cards; il faut reprendre la UI pour que ce soit consistant. - [x] Page Daily : les mots aujourd'hui et hier ne fonctionnent dans les titres que si c'est vraiment aujourd'hui :) diff --git a/scripts/backup-manager.ts b/scripts/backup-manager.ts index 01e4fce..539ff03 100644 --- a/scripts/backup-manager.ts +++ b/scripts/backup-manager.ts @@ -6,6 +6,7 @@ import { backupService, BackupConfig } from '../src/services/backup'; import { backupScheduler } from '../src/services/backup-scheduler'; +import { formatDateForDisplay } from '../src/lib/date-utils'; interface CliOptions { command: string; @@ -92,7 +93,7 @@ OPTIONS: } private formatDate(date: Date): string { - return new Date(date).toLocaleString('fr-FR'); + return formatDateForDisplay(date, 'DISPLAY_LONG'); } async run(args: string[]): Promise { diff --git a/src/actions/daily.ts b/src/actions/daily.ts index b239594..2f3789f 100644 --- a/src/actions/daily.ts +++ b/src/actions/daily.ts @@ -3,6 +3,7 @@ import { dailyService } from '@/services/daily'; import { UpdateDailyCheckboxData, DailyCheckbox, CreateDailyCheckboxData } from '@/lib/types'; import { revalidatePath } from 'next/cache'; +import { getToday, getPreviousWorkday, parseDate, normalizeDate } from '@/lib/date-utils'; /** * Toggle l'état d'une checkbox @@ -19,7 +20,7 @@ export async function toggleCheckbox(checkboxId: string): Promise<{ // (le front-end gère déjà l'état optimiste) // Récupérer toutes les checkboxes d'aujourd'hui et hier pour trouver celle à toggle - const today = new Date(); + const today = getToday(); const dailyView = await dailyService.getDailyView(today); let checkbox = dailyView.today.find(cb => cb.id === checkboxId); @@ -57,7 +58,7 @@ export async function addCheckboxToDaily(dailyId: string, content: string, taskI }> { try { // Le dailyId correspond à la date au format YYYY-MM-DD - const date = new Date(dailyId); + const date = parseDate(dailyId); const newCheckbox = await dailyService.addCheckbox({ date, @@ -86,7 +87,7 @@ export async function addTodayCheckbox(content: string, type?: 'task' | 'meeting }> { try { const newCheckbox = await dailyService.addCheckbox({ - date: new Date(), + date: getToday(), text: content, type: type || 'task', taskId @@ -112,8 +113,7 @@ export async function addYesterdayCheckbox(content: string, type?: 'task' | 'mee error?: string; }> { try { - const yesterday = new Date(); - yesterday.setDate(yesterday.getDate() - 1); + const yesterday = getPreviousWorkday(getToday()); const newCheckbox = await dailyService.addCheckbox({ date: yesterday, @@ -209,8 +209,7 @@ export async function addTodoToTask(taskId: string, text: string, date?: Date): error?: string; }> { try { - const targetDate = date || new Date(); - targetDate.setHours(0, 0, 0, 0); + const targetDate = normalizeDate(date || getToday()); const checkboxData: CreateDailyCheckboxData = { date: targetDate, @@ -243,7 +242,7 @@ export async function reorderCheckboxes(dailyId: string, checkboxIds: string[]): }> { try { // Le dailyId correspond à la date au format YYYY-MM-DD - const date = new Date(dailyId); + const date = parseDate(dailyId); await dailyService.reorderCheckboxes(date, checkboxIds); diff --git a/src/actions/jira-export.ts b/src/actions/jira-export.ts index 5221e7c..49ed8be 100644 --- a/src/actions/jira-export.ts +++ b/src/actions/jira-export.ts @@ -1,6 +1,7 @@ 'use server'; import { getJiraAnalytics } from './jira-analytics'; +import { formatDateForDisplay, getToday } from '@/lib/date-utils'; export type ExportFormat = 'csv' | 'json'; @@ -142,7 +143,7 @@ function generateCSV(analytics: JiraAnalytics): string { // Header du rapport lines.push('# Rapport Analytics Jira'); lines.push(`# Projet: ${analytics.project.name} (${analytics.project.key})`); - lines.push(`# Généré le: ${new Date().toLocaleString('fr-FR')}`); + lines.push(`# Généré le: ${formatDateForDisplay(getToday(), 'DISPLAY_LONG')}`); lines.push(`# Total tickets: ${analytics.project.totalIssues}`); lines.push(''); diff --git a/src/actions/metrics.ts b/src/actions/metrics.ts index 71b4322..d94a0ab 100644 --- a/src/actions/metrics.ts +++ b/src/actions/metrics.ts @@ -1,6 +1,7 @@ 'use server'; import { MetricsService, WeeklyMetricsOverview, VelocityTrend } from '@/services/metrics'; +import { getToday } from '@/lib/date-utils'; import { revalidatePath } from 'next/cache'; /** @@ -12,7 +13,7 @@ export async function getWeeklyMetrics(date?: Date): Promise<{ error?: string; }> { try { - const targetDate = date || new Date(); + const targetDate = date || getToday(); const metrics = await MetricsService.getWeeklyMetrics(targetDate); return { diff --git a/src/app/api/daily/route.ts b/src/app/api/daily/route.ts index e05254b..06716b0 100644 --- a/src/app/api/daily/route.ts +++ b/src/app/api/daily/route.ts @@ -1,5 +1,6 @@ import { NextResponse } from 'next/server'; import { dailyService } from '@/services/daily'; +import { getToday, parseDate, isValidAPIDate } from '@/lib/date-utils'; /** * API route pour récupérer la vue daily (hier + aujourd'hui) @@ -32,13 +33,18 @@ export async function GET(request: Request) { } // Vue daily pour une date donnée (ou aujourd'hui par défaut) - const targetDate = date ? new Date(date) : new Date(); + let targetDate: Date; - if (date && isNaN(targetDate.getTime())) { - return NextResponse.json( - { error: 'Format de date invalide. Utilisez YYYY-MM-DD' }, - { status: 400 } - ); + if (date) { + if (!isValidAPIDate(date)) { + return NextResponse.json( + { error: 'Format de date invalide. Utilisez YYYY-MM-DD' }, + { status: 400 } + ); + } + targetDate = parseDate(date); + } else { + targetDate = getToday(); } const dailyView = await dailyService.getDailyView(targetDate); diff --git a/src/app/daily/DailyPageClient.tsx b/src/app/daily/DailyPageClient.tsx index 19b5bd1..589f154 100644 --- a/src/app/daily/DailyPageClient.tsx +++ b/src/app/daily/DailyPageClient.tsx @@ -10,7 +10,7 @@ import { DailyCalendar } from '@/components/daily/DailyCalendar'; import { DailySection } from '@/components/daily/DailySection'; import { dailyClient } from '@/clients/daily-client'; import { Header } from '@/components/ui/Header'; -import { getPreviousWorkday } from '@/lib/workday-utils'; +import { getPreviousWorkday, formatDateLong, isToday, generateDateTitle, formatDateShort, isYesterday } from '@/lib/date-utils'; interface DailyPageClientProps { initialDailyView?: DailyView; @@ -112,37 +112,23 @@ export function DailyPageClient({ }; const formatCurrentDate = () => { - return currentDate.toLocaleDateString('fr-FR', { - weekday: 'long', - year: 'numeric', - month: 'long', - day: 'numeric' - }); + return formatDateLong(currentDate); }; - const isToday = () => { - const today = new Date(); - return currentDate.toDateString() === today.toDateString(); + const isTodayDate = () => { + return isToday(currentDate); }; const getTodayTitle = () => { - const today = new Date(); - if (currentDate.toDateString() === today.toDateString()) { - return "🎯 Aujourd'hui"; - } - return `🎯 ${currentDate.toLocaleDateString('fr-FR', { day: '2-digit', month: '2-digit', year: '2-digit' })}`; + return generateDateTitle(currentDate, '🎯'); }; const getYesterdayTitle = () => { - const today = new Date(); - const yesterday = new Date(today); - yesterday.setDate(yesterday.getDate() - 1); - const yesterdayDate = getYesterdayDate(); - if (yesterdayDate.toDateString() === yesterday.toDateString()) { + if (isYesterday(yesterdayDate)) { return "📋 Hier"; } - return `📋 ${yesterdayDate.toLocaleDateString('fr-FR', { day: '2-digit', month: '2-digit', year: '2-digit' })}`; + return `📋 ${formatDateShort(yesterdayDate)}`; }; if (loading) { @@ -198,7 +184,7 @@ export function DailyPageClient({
{formatCurrentDate()}
- {!isToday() && ( + {!isTodayDate() && (