Unify calendar code
Some checks failed
Build and Deploy / build-and-push (push) Failing after 1m16s

This commit is contained in:
2026-04-20 23:44:18 +02:00
parent c43b3766cd
commit 08a275093c
7 changed files with 783 additions and 486 deletions

View File

@@ -1,4 +1,5 @@
import { addDays, startOfMonth, startOfWeekMonday } from '../services/dateUtils.js';
import { addDays, startOfMonth } from '../services/dateUtils.js';
import { renderCalendarGrid } from './mealCalendar.js?v=15';
const DEFAULT_WEEKDAYS = ['pn', 'wt', 'śr', 'cz', 'pt', 'sb', 'nd'];
const DEFAULT_MONTHS_LONG = [
@@ -8,13 +9,16 @@ const DEFAULT_MONTHS_LONG = [
const DEFAULT_THEME = {
selectedBorder: 'rgba(var(--text-emphasis-rgb),0.34)',
selectedBorderClass: 'border',
selectedText: 'rgb(var(--text-emphasis-rgb))',
selectedDot: 'rgb(var(--text-emphasis-rgb))',
selectedShadow: '0 0 0 1px rgba(var(--text-emphasis-rgb),0.10)',
bg: 'rgb(var(--app-bg-rgb))',
border: 'transparent',
borderClass: 'border-0',
text: 'rgb(var(--text-body-soft-rgb))',
dimmedBg: 'transparent',
dimmedBorderClass: 'border-0',
dimText: 'rgb(var(--text-faint-rgb))',
dimOpacity: 0.58,
dot: 'rgb(var(--text-faint-rgb))',
@@ -186,57 +190,37 @@ export function initSwipePopoverCalendar({
const renderMonthGrid = (targetGrid, monthAnchor, selectedSet) => {
if (!targetGrid) return;
const first = startOfMonth(monthAnchor);
const gridStart = startOfWeekMonday(first);
const cells = Array.from({ length: 42 }, (_, i) => addDays(gridStart, i));
targetGrid.innerHTML = cells.map((day) => {
const dk = dateKeyLocal(day);
const inCurrentMonth = day.getMonth() === first.getMonth();
const isSelected = selectedSet.has(dk);
const resolved = (typeof resolveDayState === 'function'
? resolveDayState(day, { inCurrentMonth, isSelected })
: {}) || {};
const disabled = !!resolved.disabled;
const dimmed = !!resolved.dimmed;
const showDot = !!resolved.showDot;
const calendarTheme = {
...DEFAULT_THEME,
...theme,
borderClass: theme.borderClass || DEFAULT_THEME.borderClass,
dimmedBorderClass: theme.dimmedBorderClass || DEFAULT_THEME.dimmedBorderClass,
selectedBorderClass: theme.selectedBorderClass || DEFAULT_THEME.selectedBorderClass,
};
let bg;
let borderColor;
let text;
let shadow = 'none';
let borderClass = 'border-0';
if (dimmed) {
bg = theme.dimmedBg ?? DEFAULT_THEME.dimmedBg;
borderColor = 'transparent';
text = theme.dimText || DEFAULT_THEME.dimText;
} else {
bg = theme.bg || DEFAULT_THEME.bg;
borderColor = theme.border || DEFAULT_THEME.border;
text = theme.text || DEFAULT_THEME.text;
}
if (isSelected) {
borderColor = theme.selectedBorder || DEFAULT_THEME.selectedBorder;
text = theme.selectedText || DEFAULT_THEME.selectedText;
shadow = theme.selectedShadow || DEFAULT_THEME.selectedShadow;
borderClass = 'border';
}
const opacity = dimmed && !isSelected ? String(theme.dimOpacity ?? 0.58) : '1';
const dotColor = isSelected ? theme.selectedDot : theme.dot;
const tag = disabled ? 'div' : 'button';
const attrs = disabled ? '' : `type="button" data-dk="${dk}"`;
const dayClass = disabled ? '' : ' swc-day';
return `
<${tag} ${attrs}
class="mx-auto flex h-[2.05rem] w-full min-w-0 max-w-full items-center justify-center rounded-full ${borderClass}${dayClass} text-xs font-medium leading-tight overflow-hidden"
style="background:${bg}; border-color:${borderColor}; color:${text}; opacity:${opacity}; box-shadow:${shadow}; touch-action:pan-y;">
<span class="relative flex h-full w-full flex-col items-center justify-center">
<span class="text-[13px] font-semibold leading-none ${showDot ? '-translate-y-[0.18rem]' : ''}">${day.getDate()}</span>
${showDot ? `<span class="absolute left-1/2 w-1 h-1 -translate-x-1/2 rounded-full opacity-75" style="bottom:0.24rem; background:${dotColor};" aria-hidden="true"></span>` : ''}
</span>
</${tag}>
`;
}).join('');
renderCalendarGrid({
gridEl: targetGrid,
mode: 'month',
anchorDate: monthAnchor,
fixedWeekCount: 6,
selectedDate: null,
isSelectedDate: (day) => selectedSet.has(dateKeyLocal(day)),
dayAttr: 'data-dk',
getDayAttrValue: dateKeyLocal,
dayClassName: 'swc-day',
dayStyle: 'touch-action:pan-y;',
theme: calendarTheme,
resolveDayState: (day, { inCurrentMonth, isSelected }) => {
const resolved = (typeof resolveDayState === 'function'
? resolveDayState(day, { inCurrentMonth, isSelected })
: {}) || {};
return {
disabled: !!resolved.disabled,
dimmed: !!resolved.dimmed,
showIndicator: !!resolved.showDot,
};
},
});
};
const render = (previewSelection = null) => {