diff --git a/frontend/src/pages/chat/composables/useSidebarPlan.ts b/frontend/src/pages/chat/composables/useSidebarPlan.ts index e4e17d8..2499587 100644 --- a/frontend/src/pages/chat/composables/useSidebarPlan.ts +++ b/frontend/src/pages/chat/composables/useSidebarPlan.ts @@ -19,15 +19,15 @@ export const sidebarCollapsedModules = [ ] function formatDateKey(date: Date) { - const year = date.getFullYear() - const month = String(date.getMonth() + 1).padStart(2, '0') - const day = String(date.getDate()).padStart(2, '0') + const year = date.getUTCFullYear() + const month = String(date.getUTCMonth() + 1).padStart(2, '0') + const day = String(date.getUTCDate()).padStart(2, '0') return `${year}-${month}-${day}` } function formatMonthKey(date: Date) { - const year = date.getFullYear() - const month = String(date.getMonth() + 1).padStart(2, '0') + const year = date.getUTCFullYear() + const month = String(date.getUTCMonth() + 1).padStart(2, '0') return `${year}-${month}` } @@ -39,8 +39,10 @@ export function useSidebarPlan(clientTimeRef: { value: Date }, loadDailyDigestFn // Build a map of date -> has conversation const conversationDateMap = computed(() => { const map = new Map() - conversationsRef.forEach((conv) => { - const dateKey = formatDateKey(new Date(conv.updated_at)) + const conversations = Array.isArray(conversationsRef) ? conversationsRef : (conversationsRef.value ?? []) + conversations.forEach((conv) => { + const date = new Date(conv.updated_at) + const dateKey = formatDateKey(date) map.set(dateKey, true) }) return map @@ -50,21 +52,22 @@ export function useSidebarPlan(clientTimeRef: { value: Date }, loadDailyDigestFn const monthPlanSummaryMap = computed(() => new Map(monthPlanDays.value.map((item) => [item.date, item]))) const calendarCells = computed(() => { - const year = clientTimeRef.value.getFullYear() - const month = clientTimeRef.value.getMonth() - const daysInMonth = new Date(year, month + 1, 0).getDate() - const firstDayOffset = (new Date(year, month, 1).getDay() + 6) % 7 + const year = clientTimeRef.value.getUTCFullYear() + const month = clientTimeRef.value.getUTCMonth() + const daysInMonth = new Date(Date.UTC(year, month + 1, 0)).getUTCDate() + const firstDayOffset = (new Date(Date.UTC(year, month, 1)).getUTCDay() + 6) % 7 + const today = clientTimeRef.value.getUTCDate() const cells: Array<{ key: string; value: number | null; active: boolean; busy: boolean; selected: boolean; hasConversation: boolean }> = [] for (let index = 0; index < firstDayOffset; index += 1) { cells.push({ key: `blank-start-${index}`, value: null, active: false, busy: false, selected: false, hasConversation: false }) } for (let day = 1; day <= daysInMonth; day += 1) { - const monthDate = new Date(year, month, day) + const monthDate = new Date(Date.UTC(year, month, day)) const dateKey = formatDateKey(monthDate) const summary = monthPlanSummaryMap.value.get(dateKey) const busy = Boolean(summary && (summary.todo_total + summary.task_due_total + summary.goal_total + summary.reminder_total) > 0) const hasConv = conversationDateMap.value.get(dateKey) || false - cells.push({ key: dateKey, value: day, active: day === clientTimeRef.value.getDate(), busy, selected: dateKey === selectedDate.value, hasConversation: hasConv }) + cells.push({ key: dateKey, value: day, active: day === today, busy, selected: dateKey === selectedDate.value, hasConversation: hasConv }) } while (cells.length % 7 !== 0) { cells.push({ key: `blank-end-${cells.length}`, value: null, active: false, busy: false, selected: false, hasConversation: false }) @@ -72,8 +75,8 @@ export function useSidebarPlan(clientTimeRef: { value: Date }, loadDailyDigestFn return cells }) - const calendarYear = computed(() => clientTimeRef.value.getFullYear()) - const calendarMonth = computed(() => clientTimeRef.value.getMonth() + 1) + const calendarYear = computed(() => clientTimeRef.value.getUTCFullYear()) + const calendarMonth = computed(() => clientTimeRef.value.getUTCMonth() + 1) const todayPlanCounters = computed(() => { const detail = todayPlanDetail.value diff --git a/frontend/src/pages/chat/index.vue b/frontend/src/pages/chat/index.vue index 3cc2d9b..95f2b89 100644 --- a/frontend/src/pages/chat/index.vue +++ b/frontend/src/pages/chat/index.vue @@ -121,12 +121,14 @@ function handleCalendarDateSelect(dateKey: string) { // Reload conversations to get latest data loadConversations().then(() => { // Find conversation that matches the selected date (by updated_at) - const targetDate = new Date(dateKey) - const targetDateStart = new Date(targetDate.getFullYear(), targetDate.getMonth(), targetDate.getDate()) - const targetDateEnd = new Date(targetDate.getFullYear(), targetDate.getMonth(), targetDate.getDate() + 1) + // Use UTC to avoid timezone issues + const [year, month, day] = dateKey.split('-').map(Number) + const targetDateStart = new Date(Date.UTC(year, month - 1, day)) + const targetDateEnd = new Date(Date.UTC(year, month - 1, day + 1)) // Find conversation that falls on the selected date - const conversation = store.conversations.find((conv) => { + const conversations = store.conversations.value ?? store.conversations + const conversation = conversations.find((conv) => { const convDate = new Date(conv.updated_at) return convDate >= targetDateStart && convDate < targetDateEnd }) @@ -300,8 +302,8 @@ function renderMarkdown(content: string) { v-for="cell in calendarCells" :key="cell.key" class="calendar-day" - :class="{ active: cell.active, busy: cell.busy, muted: cell.value === null, selected: cell.selected, clickable: cell.hasConversation || cell.active }" - @click="(cell.hasConversation || cell.active) && handleCalendarDateSelect(cell.key)" + :class="{ active: cell.active, busy: cell.busy, muted: cell.value === null, selected: cell.selected, clickable: cell.active || cell.hasConversation }" + @click="(cell.active || cell.hasConversation) && handleCalendarDateSelect(cell.key)" > {{ cell.value ?? '' }}