From 51bf195664127a37b174ec0e0d1a475bf3f3b1fb Mon Sep 17 00:00:00 2001 From: Sebastian Krupinski Date: Mon, 29 Jun 2026 21:41:27 -0400 Subject: [PATCH] feat: visible date range Signed-off-by: Sebastian Krupinski --- src/components/AgendaView.vue | 41 +++++++----------- src/components/CalendarView.vue | 31 ++++++++++++-- src/components/DaysView.vue | 20 +++------ src/components/MonthView.vue | 34 ++++++--------- src/pages/ChronoPage.vue | 9 +++- src/stores/chronoOperationsStore.ts | 17 +++++++- src/stores/chronoUiStore.ts | 5 +++ src/types/index.ts | 6 +++ src/utils/dateRanges.ts | 55 +++++++++++++++++++++++++ tests/js/unit/dateRanges.test.ts | 64 +++++++++++++++++++++++++++++ 10 files changed, 214 insertions(+), 68 deletions(-) create mode 100644 src/utils/dateRanges.ts create mode 100644 tests/js/unit/dateRanges.test.ts diff --git a/src/components/AgendaView.vue b/src/components/AgendaView.vue index 9aeaa5a..9a26701 100644 --- a/src/components/AgendaView.vue +++ b/src/components/AgendaView.vue @@ -53,6 +53,7 @@ import { AGENDA_VIEW_SPANS, spanToDays, type AgendaViewSpan } from '@/types/span import type { EntityObject } from '@ChronoManager/models/entity'; import type { CollectionObject } from '@ChronoManager/models/collection'; import { EventObject } from '@ChronoManager/models/event'; +import { daysVisibleRange, shiftLocalDays } from '@/utils/dateRanges'; type CalendarEntity = EntityObject; type CalendarCollection = CollectionObject; @@ -60,25 +61,18 @@ type CalendarCollection = CollectionObject; const props = defineProps<{ events: CalendarEntity[]; calendars: CalendarCollection[]; - currentDate?: Date; + currentDate: Date; initialSpan?: AgendaViewSpan; }>(); const selectedSpan = ref(props.initialSpan ?? '1w'); -const localDate = ref(new Date(props.currentDate ?? new Date())); const emit = defineEmits<{ 'event-click': [event: CalendarEntity]; 'update:span': [span: AgendaViewSpan]; + 'update:current-date': [date: Date]; }>(); -// Watch for external date changes (e.g., from mini calendar) -watch(() => props.currentDate, (newDate) => { - if (newDate) { - localDate.value = new Date(newDate); - } -}); - watch(() => props.initialSpan, (newSpan) => { if (newSpan && newSpan !== selectedSpan.value) { selectedSpan.value = newSpan; @@ -95,34 +89,29 @@ function getSpanDays(): number { } function previousPeriod() { - const date = new Date(localDate.value); - date.setDate(date.getDate() - getSpanDays()); - localDate.value = date; + emit('update:current-date', shiftLocalDays(props.currentDate, -getSpanDays())); } function nextPeriod() { - const date = new Date(localDate.value); - date.setDate(date.getDate() + getSpanDays()); - localDate.value = date; + emit('update:current-date', shiftLocalDays(props.currentDate, getSpanDays())); } function goToToday() { - localDate.value = new Date(); + emit('update:current-date', new Date()); } const dateRange = computed(() => { - const start = new Date(localDate.value); - start.setHours(0, 0, 0, 0); - - const end = new Date(start); - end.setDate(end.getDate() + getSpanDays() - 1); - end.setHours(23, 59, 59, 999); - - return { start, end }; + const range = daysVisibleRange(props.currentDate, getSpanDays()); + return { + start: new Date(range.startMs), + end: new Date(range.endMs), + }; }); const dateRangeLabel = computed(() => { - const { start, end } = dateRange.value; + const { start, end: exclusiveEnd } = dateRange.value; + const end = new Date(exclusiveEnd); + end.setDate(end.getDate() - 1); const formatOptions: Intl.DateTimeFormatOptions = { month: 'short', day: 'numeric' }; if (getSpanDays() === 1) { @@ -144,7 +133,7 @@ const groupedEvents = computed(() => { const startsOn = getEventProperties(e).startsOn; if (typeof startsOn !== 'string') return false; const eventStart = new Date(startsOn); - return eventStart >= start && eventStart <= end; + return eventStart >= start && eventStart < end; }); const sorted = filtered.sort((a, b) => diff --git a/src/components/CalendarView.vue b/src/components/CalendarView.vue index 3bc0968..26c5b4b 100644 --- a/src/components/CalendarView.vue +++ b/src/components/CalendarView.vue @@ -15,6 +15,7 @@ @date-click="$emit('date-click', $event)" @event-hover="handleEventHover" @event-hover-end="hidePopup" + @update:current-date="$emit('update:current-date', $event)" />