feat(calendar): add week number display to DateStrip

Add optional calendar week (KW) display setting for the DateStrip component.
Week numbers appear above the first day of each week without affecting spacing.

- Add dateStripShowWeekNumbers setting to settings store
- Implement week number label in DateStrip with responsive styling
- Add toggle to DateStripContextMenu for easy access
- Respects weekStartsOn setting for correct week start detection

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Till-JS 2025-12-14 15:35:51 +01:00
parent 7bbeb7c13d
commit 9eb3f42483
3 changed files with 54 additions and 0 deletions

View file

@ -11,6 +11,8 @@
subDays,
startOfDay,
isWithinInterval,
getWeek,
startOfWeek,
} from 'date-fns';
import { de } from 'date-fns/locale';
import { onMount, tick } from 'svelte';
@ -72,6 +74,17 @@
return { significant: false, emoji: '' };
}
// Check if a date is the first day of the week (respects weekStartsOn setting)
function isFirstDayOfWeek(date: Date): boolean {
const weekStart = startOfWeek(date, { weekStartsOn: settingsStore.weekStartsOn });
return isSameDay(date, weekStart);
}
// Get week number for a date
function getWeekNumber(date: Date): number {
return getWeek(date, { weekStartsOn: settingsStore.weekStartsOn });
}
// Reactive view range - needed to trigger re-renders
let viewRange = $derived(viewStore.viewRange);
let currentDate = $derived(viewStore.currentDate);
@ -262,6 +275,7 @@
{@const isFirstOfMonth = day.getDate() === 1}
{@const moonPhase = isSignificantMoonPhase(day)}
{@const eventCount = getEventCount(day)}
{@const showWeekNumber = settingsStore.dateStripShowWeekNumbers && isFirstDayOfWeek(day)}
{#if isFirstOfMonth}
<div
class="month-divider"
@ -280,6 +294,9 @@
onclick={() => handleDayClick(day)}
class:is-today={dayIsToday}
>
{#if showWeekNumber}
<span class="week-number-label">KW {getWeekNumber(day)}</span>
{/if}
{#if moonPhase.significant && settingsStore.dateStripShowMoonPhases}
<span class="moon-indicator">{moonPhase.emoji}</span>
{/if}
@ -468,6 +485,20 @@
line-height: 1;
}
.week-number-label {
position: absolute;
top: -14px;
left: 50%;
transform: translateX(-50%);
font-size: 0.5625rem;
font-weight: 600;
color: hsl(var(--color-muted-foreground));
white-space: nowrap;
pointer-events: none;
text-transform: uppercase;
letter-spacing: 0.02em;
}
.event-dots {
display: flex;
gap: 2px;
@ -602,6 +633,11 @@
top: -14px;
}
.week-number-label {
top: -12px;
font-size: 0.5rem;
}
.day-number {
font-size: 1rem;
}
@ -648,6 +684,11 @@
top: -12px;
}
.date-strip-wrapper.compact .week-number-label {
top: -10px;
font-size: 0.5rem;
}
.date-strip-wrapper.compact .month-divider {
height: 28px;
}

View file

@ -35,6 +35,14 @@
checked: settingsStore.dateStripShowWeekday,
action: () => toggleSetting('dateStripShowWeekday'),
},
{
id: 'week-numbers',
label: 'Kalenderwochen',
icon: Calendar,
toggle: true,
checked: settingsStore.dateStripShowWeekNumbers,
action: () => toggleSetting('dateStripShowWeekNumbers'),
},
{
id: 'divider-1',
label: '',

View file

@ -33,6 +33,7 @@ export interface CalendarAppSettings {
dateStripHighlightWeekends: boolean; // Visually highlight weekend days
dateStripShowMonthDividers: boolean; // Show vertical dividers between months
dateStripCompact: boolean; // Use compact/smaller DateStrip
dateStripShowWeekNumbers: boolean; // Show week numbers at start of week
// UI settings
sidebarCollapsed: boolean;
@ -59,6 +60,7 @@ const DEFAULT_SETTINGS: CalendarAppSettings = {
dateStripHighlightWeekends: true,
dateStripShowMonthDividers: true,
dateStripCompact: false,
dateStripShowWeekNumbers: false,
// UI defaults
sidebarCollapsed: false,
defaultEventDuration: 60,
@ -177,6 +179,9 @@ export const settingsStore = {
get dateStripCompact() {
return settings.dateStripCompact;
},
get dateStripShowWeekNumbers() {
return settings.dateStripShowWeekNumbers;
},
get defaultEventDuration() {
return settings.defaultEventDuration;
},