diff --git a/frontend/src/components/common/CalendarDay.test.tsx b/frontend/src/components/common/CalendarDay.test.tsx index b58ae1a..6e10ab0 100644 --- a/frontend/src/components/common/CalendarDay.test.tsx +++ b/frontend/src/components/common/CalendarDay.test.tsx @@ -157,6 +157,51 @@ describe('CalendarDay', () => { expect(day).toHaveAttribute('aria-label', '2026-06-15') expect(day).not.toHaveAttribute('title') }) + + it('shows the holiday name as visible text in the cell, not just title/aria-label', () => { + const { getByTestId } = render( + + ) + expect(getByTestId('calendar-day-holiday-name')).toHaveTextContent('Midsommardagen') + }) + + it('does not render holiday-name text for a plain working day', () => { + const { queryByTestId } = render() + expect(queryByTestId('calendar-day-holiday-name')).not.toBeInTheDocument() + }) + }) + + describe('Saturday/Sunday almanacka parity', () => { + it('marks a plain Saturday with the neutral weekend class, not red', () => { + const { getByTestId } = render() + const day = getByTestId('calendar-day') + expect(day).toHaveClass('calendar-day--weekend') + expect(day).not.toHaveClass('calendar-day--red-day') + expect(day.querySelector('[data-testid="calendar-day-type-badge"]')).not.toBeInTheDocument() + }) + + it('marks a plain Sunday as a red day even without a holiday name', () => { + const { getByTestId } = render() + const day = getByTestId('calendar-day') + expect(day).toHaveClass('calendar-day--red-day') + expect(day).not.toHaveClass('calendar-day--weekend') + expect(getByTestId('calendar-day-type-badge')).toHaveTextContent('R') + expect(day.getAttribute('aria-label')).toContain('söndag') + }) + + it('does not show holiday-name text for a bare Sunday (there is no name to show)', () => { + const { queryByTestId } = render() + expect(queryByTestId('calendar-day-holiday-name')).not.toBeInTheDocument() + }) + + it('still treats a holiday landing on Saturday as a full red day, not neutral weekend', () => { + const { getByTestId } = render( + + ) + const day = getByTestId('calendar-day') + expect(day).toHaveClass('calendar-day--red-day') + expect(day).not.toHaveClass('calendar-day--weekend') + }) }) describe('§3.6 workspace day overrides', () => { diff --git a/frontend/src/components/common/CalendarDay.tsx b/frontend/src/components/common/CalendarDay.tsx index 8198deb..00fd56a 100644 --- a/frontend/src/components/common/CalendarDay.tsx +++ b/frontend/src/components/common/CalendarDay.tsx @@ -39,7 +39,20 @@ export function CalendarDay({ overrideIsWorkingDay = null, }: CalendarDayProps): ReactNode { const { t } = useTranslation() - const dayNum = new Date(date + 'T00:00:00Z').getUTCDate() + const dateObj = new Date(date + 'T00:00:00Z') + const dayNum = dateObj.getUTCDate() + + // §3.4 (Swedish almanacka parity) — the backend collapses Saturday and + // Sunday into a single "weekend" day_type (see calendar_service.py), but + // the almanacka the user compares against marks Sunday red and Saturday + // neutral grey. A holiday that happens to land on Sunday already arrives + // as day_type "red_day" (see get_red_days's exact-match on "Söndag" — a + // *bare* Sunday is never "red_day"), so a plain Sunday is detected here + // from the weekday, not from day_type. + const weekday = dateObj.getUTCDay() // 0 = Sunday, 6 = Saturday + const isBareSunday = dayType === 'weekend' && weekday === 0 + const isPlainSaturday = dayType === 'weekend' && weekday === 6 + const isRedDay = dayType === 'red_day' || isBareSunday const handleKeyDown = (e: React.KeyboardEvent) => { if (e.key === 'Enter' || e.key === ' ') { @@ -61,6 +74,8 @@ export function CalendarDay({ descriptors.push(cleanHolidayName) } else if (dayType === 'klamdag') { descriptors.push(t('calendarDay.klamdagAria')) + } else if (isBareSunday) { + descriptors.push(t('calendarDay.sundayAria')) } if (isOverride) { descriptors.push( @@ -78,8 +93,9 @@ export function CalendarDay({ events.length > 0 ? 'calendar-day--has-events' : '', isToday ? 'calendar-day--today' : '', isSelected ? 'calendar-day--selected' : '', - dayType === 'red_day' ? 'calendar-day--red-day' : '', + isRedDay ? 'calendar-day--red-day' : '', dayType === 'klamdag' ? 'calendar-day--klamdag' : '', + isPlainSaturday ? 'calendar-day--weekend' : '', isOverride ? 'calendar-day--override' : '', ] .filter(Boolean) @@ -99,11 +115,16 @@ export function CalendarDay({ onPointerEnter={() => onPointerEnter?.(date)} >
{dayNum}
- {(dayType === 'red_day' || dayType === 'klamdag') && ( + {(isRedDay || dayType === 'klamdag') && ( )} + {cleanHolidayName && ( +
+ {cleanHolidayName} +
+ )} {isOverride && (