11---
22import { LANG , LOCALE } from ' ../../i18n/config'
33import { calendarT } from ' ../../i18n/calendar'
4+ import { withBase } from ' ../../lib/base-path'
45
56const t = calendarT [LANG ]
7+ const calendarApiUrl = withBase (' /api/calendar.json' )
68---
79
810<section id =' calendar' class =' reveal px-2 py-20 sm:px-6' style =' --reveal-delay: 90ms;' >
@@ -69,7 +71,7 @@ const t = calendarT[LANG]
6971 </div >
7072</section >
7173
72- <script is:inline define:vars ={ { locale: LOCALE , labels: t }} lang =' js' >
74+ <script is:inline define:vars ={ { locale: LOCALE , labels: t , calendarApiUrl }} lang =' js' >
7375 (() => {
7476 const dayEventsContainer = document.querySelector('[data-calendar-day-events]')
7577 const dayLabel = document.querySelector('[data-calendar-day-label]')
@@ -138,19 +140,39 @@ const t = calendarT[LANG]
138140 return map
139141 }
140142
143+ const hasEventsOnDate = (eventsByDay, key) => (eventsByDay.get(key) || []).length > 0
144+
141145 const getDefaultSelectedDate = (eventsByDay) => {
142- const month = displayDate.getMonth()
143146 const year = displayDate.getFullYear()
147+ const month = displayDate.getMonth()
148+ const monthStart = new Date(year, month, 1)
149+ const mondayOffset = (monthStart.getDay() + 6) % 7
150+ const weekStart = new Date(year, month, monthStart.getDate() - mondayOffset)
151+ const weekEnd = new Date(
152+ weekStart.getFullYear(),
153+ weekStart.getMonth(),
154+ weekStart.getDate() + 6,
155+ 23,
156+ 59,
157+ 59,
158+ 999,
159+ )
160+
144161 const keys = [...eventsByDay.keys()].filter((key) => {
145162 const date = keyToDate(key)
163+
164+ if (calendarView === 'week') {
165+ return date >= weekStart && date <= weekEnd
166+ }
167+
146168 return date.getFullYear() === year && date.getMonth() === month
147169 })
148170
149171 if (keys.length > 0) {
150172 return keys.sort()[0]
151173 }
152174
153- return getDateKey(new Date(year, month, 1) )
175+ return calendarView === 'week' ? getDateKey(weekStart) : getDateKey(monthStart )
154176 }
155177
156178 const renderCalendarGrid = (events) => {
@@ -173,12 +195,8 @@ const t = calendarT[LANG]
173195 calendarLabel.textContent = monthLabelFormatter.format(baseDate)
174196 }
175197
176- const eventDays = new Set(
177- events
178- .map((event) => new Date(event.start))
179- .filter((date) => !Number.isNaN(date.getTime()))
180- .map((date) => getDateKey(date)),
181- )
198+ const eventsByDay = getEventsByDay(events)
199+ const eventDays = new Set(eventsByDay.keys())
182200
183201 calendarGrid.innerHTML = ''
184202
@@ -204,15 +222,22 @@ const t = calendarT[LANG]
204222
205223 if (inMonth) {
206224 const key = getDateKey(currentDate)
225+ const hasEvents = hasEventsOnDate(eventsByDay, key)
207226 dayCell.textContent = String(currentDate.getDate())
208227 dayCell.classList.remove('text-[var(--ink-soft)]')
209- dayCell.classList.add('cursor-pointer', 'text-[var(--ink)]')
210-
211- dayCell.addEventListener('click', () => {
212- selectedDateKey = key
213- renderCalendarGrid(loadedEvents)
214- renderSelectedDayEvents(loadedEvents)
215- })
228+ dayCell.classList.add('text-[var(--ink)]')
229+
230+ if (hasEvents) {
231+ dayCell.classList.add('cursor-pointer')
232+ dayCell.addEventListener('click', () => {
233+ selectedDateKey = key
234+ renderCalendarGrid(loadedEvents)
235+ renderSelectedDayEvents(loadedEvents)
236+ })
237+ } else {
238+ dayCell.classList.add('cursor-default')
239+ dayCell.setAttribute('aria-disabled', 'true')
240+ }
216241
217242 if (eventDays.has(key)) {
218243 dayCell.classList.add('bg-primary', 'font-semibold', 'text-white')
@@ -308,13 +333,13 @@ const t = calendarT[LANG]
308333 return `${dateLabel} - ${labels.at} ${timeLabel}`
309334 }
310335
311- const loadCalendar = async () => {
336+ const loadCalendar = async () => {
312337 setVisible(loading, true)
313338 setVisible(error, false)
314- setVisible(empty , false)
339+ setVisible(dayEmpty , false)
315340
316341 try {
317- const response = await fetch('/api/calendar.json' , {
342+ const response = await fetch(calendarApiUrl , {
318343 headers: {
319344 accept: 'application/json',
320345 },
@@ -382,6 +407,7 @@ const t = calendarT[LANG]
382407 item.classList.toggle('text-[var(--ink-soft)]', !selected)
383408 })
384409
410+ selectedDateKey = getDefaultSelectedDate(getEventsByDay(loadedEvents))
385411 renderCalendarGrid(loadedEvents)
386412 renderSelectedDayEvents(loadedEvents)
387413 })
@@ -395,7 +421,7 @@ const t = calendarT[LANG]
395421 } else {
396422 displayDate = new Date(displayDate.getFullYear(), displayDate.getMonth() + 1, 1)
397423 }
398- selectedDateKey = getDateKey(new Date(displayDate.getFullYear(), displayDate.getMonth(), 1 ))
424+ selectedDateKey = getDefaultSelectedDate(getEventsByDay(loadedEvents ))
399425 renderCalendarGrid(loadedEvents)
400426 renderSelectedDayEvents(loadedEvents)
401427 })
0 commit comments