diff --git a/src/components/forms/task/TaskBasicFields.tsx b/src/components/forms/task/TaskBasicFields.tsx index ca33305..ecab819 100644 --- a/src/components/forms/task/TaskBasicFields.tsx +++ b/src/components/forms/task/TaskBasicFields.tsx @@ -3,6 +3,7 @@ import { Input } from '@/components/ui/Input'; import { TaskPriority, TaskStatus } from '@/lib/types'; import { getAllStatuses, getAllPriorities } from '@/lib/status-config'; +import { ensureDate, formatDateForDateTimeInput } from '@/lib/date-utils'; interface TaskBasicFieldsProps { title: string; @@ -109,7 +110,10 @@ export function TaskBasicFields({ { + const date = ensureDate(dueDate); + return date ? formatDateForDateTimeInput(date) : ''; + })()} onChange={(e) => onDueDateChange(e.target.value ? new Date(e.target.value) : undefined)} disabled={loading} /> diff --git a/src/lib/date-utils.ts b/src/lib/date-utils.ts index ff758c4..c951c2f 100644 --- a/src/lib/date-utils.ts +++ b/src/lib/date-utils.ts @@ -34,26 +34,28 @@ export function normalizeDate(date: Date): Date { * @param date - Date à formater * @returns Format YYYY-MM-DD */ -export function formatDateForAPI(date: Date): string { - if (!isValid(date)) { +export function formatDateForAPI(date: Date | string): string { + const ensuredDate = ensureDate(date); + if (!ensuredDate || !isValid(ensuredDate)) { throw new Error('Date invalide fournie à formatDateForAPI'); } - const year = date.getFullYear(); - const month = String(date.getMonth() + 1).padStart(2, '0'); - const day = String(date.getDate()).padStart(2, '0'); + const year = ensuredDate.getFullYear(); + const month = String(ensuredDate.getMonth() + 1).padStart(2, '0'); + const day = String(ensuredDate.getDate()).padStart(2, '0'); return `${year}-${month}-${day}`; } /** * Formate une date pour l'affichage en français */ -export function formatDateForDisplay(date: Date, formatType: keyof typeof DATE_FORMATS = 'DISPLAY_MEDIUM'): string { - if (!isValid(date)) { +export function formatDateForDisplay(date: Date | string, formatType: keyof typeof DATE_FORMATS = 'DISPLAY_MEDIUM'): string { + const ensuredDate = ensureDate(date); + if (!ensuredDate || !isValid(ensuredDate)) { throw new Error('Date invalide fournie à formatDateForDisplay'); } - return format(date, DATE_FORMATS[formatType], { locale: fr }); + return format(ensuredDate, DATE_FORMATS[formatType], { locale: fr }); } /** @@ -66,9 +68,14 @@ export function formatDateShort(date: Date): string { /** * Calcule le nombre de jours écoulés depuis une date */ -export function getDaysAgo(date: Date): number { +export function getDaysAgo(date: Date | string): number { + const ensuredDate = ensureDate(date); + if (!ensuredDate) { + throw new Error('Date invalide fournie à getDaysAgo'); + } + const today = getToday(); - const diffTime = today.getTime() - normalizeDate(date).getTime(); + const diffTime = today.getTime() - normalizeDate(ensuredDate).getTime(); return Math.floor(diffTime / (1000 * 60 * 60 * 24)); } @@ -82,25 +89,36 @@ export function formatDateLong(date: Date): string { /** * Vérifie si une date est aujourd'hui */ -export function isToday(date: Date): boolean { +export function isToday(date: Date | string): boolean { + const ensuredDate = ensureDate(date); + if (!ensuredDate) return false; + const today = new Date(); - return normalizeDate(date).getTime() === normalizeDate(today).getTime(); + return normalizeDate(ensuredDate).getTime() === normalizeDate(today).getTime(); } /** * Vérifie si une date est hier */ -export function isYesterday(date: Date): boolean { +export function isYesterday(date: Date | string): boolean { + const ensuredDate = ensureDate(date); + if (!ensuredDate) return false; + const yesterday = new Date(); yesterday.setDate(yesterday.getDate() - 1); - return normalizeDate(date).getTime() === normalizeDate(yesterday).getTime(); + return normalizeDate(ensuredDate).getTime() === normalizeDate(yesterday).getTime(); } /** * Compare deux dates (sans tenir compte de l'heure) */ -export function isSameDay(date1: Date, date2: Date): boolean { - return normalizeDate(date1).getTime() === normalizeDate(date2).getTime(); +export function isSameDay(date1: Date | string, date2: Date | string): boolean { + const ensuredDate1 = ensureDate(date1); + const ensuredDate2 = ensureDate(date2); + + if (!ensuredDate1 || !ensuredDate2) return false; + + return normalizeDate(ensuredDate1).getTime() === normalizeDate(ensuredDate2).getTime(); } /** @@ -258,3 +276,52 @@ export function formatDistanceToNow(date: Date, options?: { addSuffix?: boolean addSuffix: options?.addSuffix ?? true }); } + +/** + * S'assure qu'une valeur est un objet Date valide + * Convertit les chaînes de caractères en Date si nécessaire + */ +export function ensureDate(value: Date | string | null | undefined): Date | null { + if (value === null || value === undefined) { + return null; + } + + // Si c'est déjà un objet Date valide + if (value instanceof Date && isValid(value)) { + return value; + } + + // Si c'est une chaîne de caractères, essayer de la parser + if (typeof value === 'string') { + try { + const parsed = parseDate(value); + return parsed; + } catch { + console.warn(`Impossible de parser la date: ${value}`); + return null; + } + } + + // Si c'est un objet Date mais invalide, essayer de le recréer + if (value instanceof Date) { + try { + const time = value.getTime(); + if (!isNaN(time)) { + return value; + } + } catch { + console.warn('Objet Date invalide détecté'); + } + } + + console.warn('Valeur de date non supportée:', value); + return null; +} + +/** + * S'assure qu'une valeur est un objet Date valide, avec une valeur par défaut + */ +export function ensureDateWithDefault(value: Date | string | null | undefined, defaultValue: Date = new Date()): Date { + const result = ensureDate(value); + return result || defaultValue; +}