diff --git a/frontend/components/Project/useProjectMetrics.ts b/frontend/components/Project/useProjectMetrics.ts index 8a03101..e9aba33 100644 --- a/frontend/components/Project/useProjectMetrics.ts +++ b/frontend/components/Project/useProjectMetrics.ts @@ -7,7 +7,7 @@ import { isTaskPlanned, isTaskWaiting, } from '../../constants/taskStatus'; -import { parseDateString, getTodayDateString } from '../../utils/dateUtils'; +import { parseDateString, getTodayDateString, toLocalDateString } from '../../utils/dateUtils'; // Check if task is in today's plan (has active status) const isTaskInTodayPlan = (task: Task): boolean => @@ -181,7 +181,7 @@ export const useProjectMetrics = ( for (let i = days - 1; i >= 0; i--) { const d = new Date(today); d.setDate(today.getDate() - i); - const key = d.toISOString().split('T')[0]; + const key = toLocalDateString(d); labels.push({ dateKey: key, label: `${d.getMonth() + 1}/${d.getDate()}`, @@ -193,7 +193,7 @@ export const useProjectMetrics = ( tasks.forEach((task) => { if (!task.completed_at) return; - const key = new Date(task.completed_at).toISOString().split('T')[0]; + const key = toLocalDateString(new Date(task.completed_at)); if (counts[key] !== undefined) { counts[key] += 1; } @@ -213,7 +213,7 @@ export const useProjectMetrics = ( for (let i = days - 1; i >= 0; i--) { const d = new Date(today); d.setDate(today.getDate() - i); - const key = d.toISOString().split('T')[0]; + const key = toLocalDateString(d); labels.push({ dateKey: key, label: `${d.getMonth() + 1}/${d.getDate()}`, @@ -225,7 +225,7 @@ export const useProjectMetrics = ( tasks.forEach((task) => { if (!task.created_at) return; - const key = new Date(task.created_at).toISOString().split('T')[0]; + const key = toLocalDateString(new Date(task.created_at)); if (counts[key] !== undefined) { counts[key] += 1; } @@ -245,7 +245,7 @@ export const useProjectMetrics = ( for (let i = 0; i < days; i++) { const d = new Date(today); d.setDate(today.getDate() + i); - const key = d.toISOString().split('T')[0]; + const key = toLocalDateString(d); labels.push({ dateKey: key, label: `${d.getMonth() + 1}/${d.getDate()}`, diff --git a/frontend/components/Task/TaskDetails/TaskRecurrenceCard.tsx b/frontend/components/Task/TaskDetails/TaskRecurrenceCard.tsx index 2078397..d07ad0a 100644 --- a/frontend/components/Task/TaskDetails/TaskRecurrenceCard.tsx +++ b/frontend/components/Task/TaskDetails/TaskRecurrenceCard.tsx @@ -5,6 +5,7 @@ import TaskRecurrenceSection from '../TaskForm/TaskRecurrenceSection'; import TaskRecurringInstanceInfo from './TaskRecurringInstanceInfo'; import { Task, RecurrenceType } from '../../../entities/Task'; import { TaskIteration } from '../../../utils/tasksService'; +import { getTodayDateString } from '../../../utils/dateUtils'; interface TaskRecurrenceCardProps { task: Task; @@ -48,7 +49,7 @@ const TaskRecurrenceCard: React.FC = ({ const formatDateWithDayName = (dateString: string) => { const date = new Date(dateString); - const today = new Date().toISOString().split('T')[0]; + const today = getTodayDateString(); const isToday = dateString === today; const dayName = date.toLocaleDateString(i18n.language, { diff --git a/frontend/components/Task/TaskDueDate.tsx b/frontend/components/Task/TaskDueDate.tsx index 1923a54..bb50240 100644 --- a/frontend/components/Task/TaskDueDate.tsx +++ b/frontend/components/Task/TaskDueDate.tsx @@ -1,6 +1,6 @@ import React from 'react'; import { useTranslation } from 'react-i18next'; -import { parseDateString } from '../../utils/dateUtils'; +import { parseDateString, getTodayDateString, getTomorrowDateString, getYesterdayDateString } from '../../utils/dateUtils'; interface TaskDueDateProps { dueDate: string; @@ -10,10 +10,8 @@ interface TaskDueDateProps { const TaskDueDate: React.FC = ({ dueDate, className }) => { const { t } = useTranslation(); const getDueDateClass = () => { - const today = new Date().toISOString().split('T')[0]; - const tomorrow = new Date(Date.now() + 24 * 60 * 60 * 1000) - .toISOString() - .split('T')[0]; + const today = getTodayDateString(); + const tomorrow = getTomorrowDateString(); if (dueDate === today) return 'border-blue-700 dark:text-white'; if (dueDate === tomorrow) return 'border-blue-700 dark:text-white'; @@ -22,13 +20,9 @@ const TaskDueDate: React.FC = ({ dueDate, className }) => { }; const formatDueDate = () => { - const today = new Date().toISOString().split('T')[0]; - const tomorrow = new Date(Date.now() + 24 * 60 * 60 * 1000) - .toISOString() - .split('T')[0]; - const yesterday = new Date(Date.now() - 24 * 60 * 60 * 1000) - .toISOString() - .split('T')[0]; + const today = getTodayDateString(); + const tomorrow = getTomorrowDateString(); + const yesterday = getYesterdayDateString(); if (dueDate === today) return t('dateIndicators.today', 'TODAY'); if (dueDate === tomorrow) diff --git a/frontend/components/Task/TaskHeader.tsx b/frontend/components/Task/TaskHeader.tsx index 32349c2..a63ca2f 100644 --- a/frontend/components/Task/TaskHeader.tsx +++ b/frontend/components/Task/TaskHeader.tsx @@ -16,7 +16,7 @@ import { Task } from '../../entities/Task'; import { fetchSubtasks } from '../../utils/tasksService'; import { isTaskCompleted, isTaskInProgress } from '../../constants/taskStatus'; import TaskStatusControl from './TaskStatusControl'; -import { parseDateString } from '../../utils/dateUtils'; +import { parseDateString, getTodayDateString, getTomorrowDateString, getYesterdayDateString } from '../../utils/dateUtils'; interface TaskHeaderProps { task: Task; @@ -90,13 +90,9 @@ const TaskHeader: React.FC = ({ }; const formatDueDate = (dueDate: string) => { - const today = new Date().toISOString().split('T')[0]; - const tomorrow = new Date(Date.now() + 24 * 60 * 60 * 1000) - .toISOString() - .split('T')[0]; - const yesterday = new Date(Date.now() - 24 * 60 * 60 * 1000) - .toISOString() - .split('T')[0]; + const today = getTodayDateString(); + const tomorrow = getTomorrowDateString(); + const yesterday = getYesterdayDateString(); if (dueDate === today) return t('dateIndicators.today', 'TODAY'); if (dueDate === tomorrow) diff --git a/frontend/components/Task/TaskTimeline.tsx b/frontend/components/Task/TaskTimeline.tsx index dcf1f1b..25c8ef4 100644 --- a/frontend/components/Task/TaskTimeline.tsx +++ b/frontend/components/Task/TaskTimeline.tsx @@ -11,6 +11,7 @@ import { ExclamationTriangleIcon, SparklesIcon, } from '@heroicons/react/24/outline'; +import { getTodayDateString, getTomorrowDateString, getYesterdayDateString } from '../../utils/dateUtils'; interface TaskTimelineProps { taskUid: string | undefined; @@ -177,15 +178,11 @@ const TaskTimeline: React.FC = ({ taskUid, refreshKey }) => { // Handle ISO date strings (e.g., "2025-07-15T00:00:00.000Z") const date = new Date(dateString); - // Check if it's today, tomorrow, or yesterday - const today = new Date().toISOString().split('T')[0]; - const tomorrow = new Date(Date.now() + 24 * 60 * 60 * 1000) - .toISOString() - .split('T')[0]; - const yesterday = new Date(Date.now() - 24 * 60 * 60 * 1000) - .toISOString() - .split('T')[0]; - const dateOnly = date.toISOString().split('T')[0]; + // Check if it's today, tomorrow, or yesterday using local time + const today = getTodayDateString(); + const tomorrow = getTomorrowDateString(); + const yesterday = getYesterdayDateString(); + const dateOnly = dateString.split('T')[0]; if (dateOnly === today) return t('dateIndicators.today'); if (dateOnly === tomorrow) return t('dateIndicators.tomorrow'); diff --git a/frontend/utils/dateUtils.ts b/frontend/utils/dateUtils.ts index 5ea32eb..d1722d5 100644 --- a/frontend/utils/dateUtils.ts +++ b/frontend/utils/dateUtils.ts @@ -25,6 +25,31 @@ export const getTodayDateString = (): string => { return `${year}-${month}-${day}`; }; +export const getTomorrowDateString = (): string => { + const d = new Date(); + d.setDate(d.getDate() + 1); + const year = d.getFullYear(); + const month = String(d.getMonth() + 1).padStart(2, '0'); + const day = String(d.getDate()).padStart(2, '0'); + return `${year}-${month}-${day}`; +}; + +export const getYesterdayDateString = (): string => { + const d = new Date(); + d.setDate(d.getDate() - 1); + const year = d.getFullYear(); + const month = String(d.getMonth() + 1).padStart(2, '0'); + const day = String(d.getDate()).padStart(2, '0'); + return `${year}-${month}-${day}`; +}; + +export const toLocalDateString = (date: Date): string => { + const year = date.getFullYear(); + const month = String(date.getMonth() + 1).padStart(2, '0'); + const day = String(date.getDate()).padStart(2, '0'); + return `${year}-${month}-${day}`; +}; + let userTimezone: string | null = null; export const setUserTimezone = (timezone: string): void => {