From e9f1e182b7e48d5830fa3f00509bf1335d969340 Mon Sep 17 00:00:00 2001 From: Roman Trashutin Date: Thu, 3 Sep 2026 13:25:52 +0300 Subject: [PATCH 1/4] refactor(schedule): extract getAcademicYearRange to shared util --- app/pages/index.vue | 12 ------------ app/utils/academic-year.ts | 13 +++++++++++++ 2 files changed, 13 insertions(+), 12 deletions(-) create mode 100644 app/utils/academic-year.ts diff --git a/app/pages/index.vue b/app/pages/index.vue index 8f028b3..934cb3e 100644 --- a/app/pages/index.vue +++ b/app/pages/index.vue @@ -38,18 +38,6 @@ useSeo({ const hasActiveSchedule = computed(() => !!selectedSchedule.value) const scheduleId = computed(() => selectedSchedule.value?.id) -const getAcademicYearRange = (date: Date) => { - // Academic year: Sept 1 → Sept 1. Pad ±7 days so month/week grid cells - // that overhang the boundary (up to 6 days in either direction) still have - // events fetched. Without the pad, September cells in August's grid and - // August cells in September's grid render empty. - const startYear = date.getMonth() < 8 ? date.getFullYear() - 1 : date.getFullYear() - return { - start: new Date(startYear, 8, 1 - 7, 0, 0, 0, 0), - end: new Date(startYear + 1, 8, 1 + 7, 23, 59, 59, 999), - } -} - const dateRange = computed(() => getAcademicYearRange(selectedDate.value)) const startTimestamp = computed(() => { diff --git a/app/utils/academic-year.ts b/app/utils/academic-year.ts new file mode 100644 index 0000000..0b3bbd4 --- /dev/null +++ b/app/utils/academic-year.ts @@ -0,0 +1,13 @@ +/** + * Returns the academic year date range covering the given date. + * Academic year: Sept 1 → Sept 1. Padded ±7 days so month/week grid cells + * that overhang the boundary (up to 6 days in either direction) still have + * events fetched. + */ +export const getAcademicYearRange = (date: Date) => { + const startYear = date.getMonth() < 8 ? date.getFullYear() - 1 : date.getFullYear() + return { + start: new Date(startYear, 8, 1 - 7, 0, 0, 0, 0), + end: new Date(startYear + 1, 8, 1 + 7, 23, 59, 59, 999), + } +} From 49edf90d88dca70ec1e0b5d7e601d2af044c804d Mon Sep 17 00:00:00 2001 From: Roman Trashutin Date: Thu, 3 Sep 2026 13:26:00 +0300 Subject: [PATCH 2/4] fix(calendar): dim today marker in off-month cells --- app/components/calendar/month/DayCell.vue | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/components/calendar/month/DayCell.vue b/app/components/calendar/month/DayCell.vue index 2c2728a..ddf06f5 100644 --- a/app/components/calendar/month/DayCell.vue +++ b/app/components/calendar/month/DayCell.vue @@ -43,9 +43,10 @@ const { trackEvent } = useAnalytics() // SSR serializer puts object keys first; client patchClass appends them after static. const dayClasses = computed(() => cn("flex size-6 items-center justify-center rounded-full text-xs font-medium", { - "text-muted-foreground/50": !props.cell.currentMonth, + "text-muted-foreground/50": !props.cell.currentMonth && !props.isDateToday, "text-muted-foreground": props.cell.currentMonth && !props.isDateToday, "bg-primary": props.isDateToday && props.cell.currentMonth, + "bg-primary/40": props.isDateToday && !props.cell.currentMonth, }) ) From 18abbaf30d495ff5b3509de466afc62c733ae02f Mon Sep 17 00:00:00 2001 From: Roman Trashutin Date: Thu, 3 Sep 2026 13:26:07 +0300 Subject: [PATCH 3/4] fix(sidebar): sequential today-events animation and stable year query --- app/components/SidebarTodayEvents.vue | 83 +++++++++++++++++---------- 1 file changed, 52 insertions(+), 31 deletions(-) diff --git a/app/components/SidebarTodayEvents.vue b/app/components/SidebarTodayEvents.vue index 5afdd17..a05d15f 100644 --- a/app/components/SidebarTodayEvents.vue +++ b/app/components/SidebarTodayEvents.vue @@ -6,9 +6,7 @@ import { motion, AnimatePresence } from "motion-v" import type { TEventType } from "~/types/calendar" const scheduleStore = useScheduleStore() -const calendarStore = useCalendarStore() const { selectedSchedule } = storeToRefs(scheduleStore) -const { allEvents } = storeToRefs(calendarStore) const { formatTime, formatDate } = useEventFormatting() const { effectiveTimezone } = useTimezone() @@ -24,13 +22,33 @@ const formattedDate = computed(() => { return `${day}, ${date}` }) -// Filter the already-loaded full-year events to the preview date — no extra network request. -// 3.3 fix: guard auditorium?.name — auditorium can be null for online lessons. +// Own query pinned to today's academic year — independent of the calendar's +// navigation date. TanStack dedupes when the user is in the same academic year +// (zero extra requests); diverges only when they navigate to a different year. +const scheduleId = computed(() => selectedSchedule.value?.id) +const todayRange = getAcademicYearRange(new Date()) +const todayStart = computed(() => { + if (!selectedSchedule.value) return undefined + return Math.floor(todayRange.start.getTime() / 1000) +}) +const todayEnd = computed(() => { + if (!selectedSchedule.value) return undefined + return Math.floor(todayRange.end.getTime() / 1000) +}) + +const { data: todayRangeEvents, isLoading } = useScheduleQuery(scheduleId, todayStart, todayEnd) + +// Filter the year-range events down to just previewDate — no extra network request. +// dayKey drives the outer AnimatePresence key so changing date triggers a full +// wait-mode swap: old list exits, then new list enters (no stacking). +const dayKey = computed(() => + formatInTimeZone(previewDate.value, effectiveTimezone.value, "yyyy-MM-dd") +) const todayEvents = computed(() => { + if (!todayRangeEvents.value) return [] const tz = effectiveTimezone.value - const targetKey = formatInTimeZone(previewDate.value, tz, "yyyy-MM-dd") - return allEvents.value.filter( - (e) => formatInTimeZone(new Date(e.startedAt * 1000), tz, "yyyy-MM-dd") === targetKey + return todayRangeEvents.value.filter( + (e) => formatInTimeZone(new Date(e.startedAt * 1000), tz, "yyyy-MM-dd") === dayKey.value ) }) @@ -86,39 +104,42 @@ const hasEvents = computed(() => todayEvents.value.length > 0)
- + +
+ +
+ - +
- - - - - + + +
From 62c0201528d16c64e6fb6239b0ed250c4b15595f Mon Sep 17 00:00:00 2001 From: Roman Trashutin Date: Thu, 3 Sep 2026 13:36:39 +0300 Subject: [PATCH 4/4] chore(release): bump version to 1.2.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 52ee446..5114e2c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mindenit-schedule", - "version": "1.2.1", + "version": "1.2.2", "private": true, "type": "module", "scripts": {