From c73940e22af723a1a401c2db71769a76398e4d58 Mon Sep 17 00:00:00 2001 From: Linus Rath <139418639+rathlinus@users.noreply.github.com> Date: Sat, 21 Mar 2026 13:28:31 +0100 Subject: [PATCH] feat: add option to show week numbers in mini-calendar --- app/[locale]/calendar/page.tsx | 3 +- components/calendar/mini-calendar.tsx | 65 ++++++++++++++++------- components/settings/calendar-settings.tsx | 11 ++++ locales/de/common.json | 4 +- locales/en/common.json | 4 +- locales/es/common.json | 4 +- locales/fr/common.json | 4 +- locales/it/common.json | 4 +- locales/ja/common.json | 4 +- locales/nl/common.json | 4 +- locales/pt/common.json | 4 +- stores/settings-store.ts | 3 ++ 12 files changed, 86 insertions(+), 28 deletions(-) diff --git a/app/[locale]/calendar/page.tsx b/app/[locale]/calendar/page.tsx index 671b7ffe..3ff546ed 100644 --- a/app/[locale]/calendar/page.tsx +++ b/app/[locale]/calendar/page.tsx @@ -63,7 +63,7 @@ export default function CalendarPage() { setSelectedDate, setViewMode, toggleCalendarVisibility, updateCalendar, refreshAllSubscriptions, } = useCalendarStore(); - const { firstDayOfWeek, timeFormat } = useSettingsStore(); + const { firstDayOfWeek, timeFormat, showWeekNumbers } = useSettingsStore(); const { identities } = useIdentityStore(); const normalizedViewMode = isCalendarViewMode(viewMode) ? viewMode : "month"; @@ -751,6 +751,7 @@ export default function CalendarPage() { onChangeMonth={handleMiniMonthChange} events={events} firstDayOfWeek={firstDayOfWeek} + showWeekNumbers={showWeekNumbers} /> void; events?: CalendarEvent[]; firstDayOfWeek?: number; + showWeekNumbers?: boolean; } export function MiniCalendar({ @@ -35,6 +36,7 @@ export function MiniCalendar({ onChangeMonth, events = [], firstDayOfWeek = 1, + showWeekNumbers = false, }: MiniCalendarProps) { const t = useTranslations("calendar"); const intlFormatter = useFormatter(); @@ -61,6 +63,17 @@ export function MiniCalendar({ ? ["sun", "mon", "tue", "wed", "thu", "fri", "sat"] as const : ["mon", "tue", "wed", "thu", "fri", "sat", "sun"] as const; + // Compute week numbers for each row (one per 7-day chunk) + const weekNumbers = useMemo(() => { + if (!showWeekNumbers) return []; + const nums: number[] = []; + for (let i = 0; i < days.length; i += 7) { + // Use the first day of each row to determine the week number + nums.push(weekStart === 1 ? getISOWeek(days[i]) : getWeek(days[i], { weekStartsOn: 0 })); + } + return nums; + }, [days, showWeekNumbers, weekStart]); + const currentYear = getYear(displayMonth); const currentMonth = getMonth(displayMonth); const decadeStart = Math.floor(currentYear / 10) * 10; @@ -135,35 +148,49 @@ export function MiniCalendar({ {pickerView === "days" && ( -
+
+ {showWeekNumbers && ( +
+ )} {dayHeaders.map((d) => (
{t(`days.${d}`)}
))} - {days.map((day) => { + {days.map((day, index) => { const inMonth = isSameMonth(day, displayMonth); const selected = isSameDay(day, selectedDate); const today = isToday(day); const hasEvent = eventDates.has(format(day, "yyyy-MM-dd")); + const isFirstDayOfRow = index % 7 === 0; return ( - + + ); })}
diff --git a/components/settings/calendar-settings.tsx b/components/settings/calendar-settings.tsx index 6f858f4a..942a57a7 100644 --- a/components/settings/calendar-settings.tsx +++ b/components/settings/calendar-settings.tsx @@ -15,6 +15,7 @@ export function CalendarSettings() { timeFormat, firstDayOfWeek, showTimeInMonthView, + showWeekNumbers, calendarNotificationsEnabled, calendarNotificationSound, calendarInvitationParsingEnabled, @@ -68,6 +69,16 @@ export function CalendarSettings() { /> + + updateSetting('showWeekNumbers', checked)} + /> + + ()( calendarNotificationSound: state.calendarNotificationSound, calendarInvitationParsingEnabled: state.calendarInvitationParsingEnabled, showTimeInMonthView: state.showTimeInMonthView, + showWeekNumbers: state.showWeekNumbers, toolbarPosition: state.toolbarPosition, senderFavicons: state.senderFavicons, folderIcons: state.folderIcons,