Make day-nav/language-toggle real links, group hours into rows
Deploy / deploy (push) Successful in 1m19s

Day navigation (prev/today/next) and the language toggle were plain
buttons wired to click handlers only; switched them to real <a href>
elements (built via router's new exported urlFor) so right-click,
middle-click, and open-in-new-tab work, with a click handler that
still SPA-routes on a plain left-click and lets modified clicks fall
through to normal browser navigation.

Language selection is now reflected in the URL as a ?lang= query
param (parsed/pushed by router.ts, omitted for the default single-
English case to keep that URL clean), so a shared link preserves the
viewer's chosen language(s).

hour-list.ts now groups the 8 hours into three traditional rows
(night office, day hours, evening) instead of one flat wrapped list.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014axryJBrRswYh2niA7WCUc
This commit is contained in:
2026-08-26 06:47:15 -04:00
parent 7fb37f6237
commit d94b871bf8
6 changed files with 101 additions and 30 deletions
+24 -8
View File
@@ -1,6 +1,7 @@
import { getState, shiftDate, goToToday } from '../app-state';
import { getState, shiftDate, goToToday, addDays, todayIso } from '../app-state';
import { resolveDay } from '../calendar';
import { getDayLabel } from '../calendar/day-label';
import { urlFor } from '../router';
import { formatDateLong, renderBilingual } from './format';
/** Renders navigation plus the merged "when" header: the civil date/
@@ -11,22 +12,37 @@ import { formatDateLong, renderBilingual } from './format';
* hour on a given date), so it's resolved directly here via `resolveDay`
* rather than through any particular hour's `resolveOrdo`. */
export function renderDayNav(container: HTMLElement): void {
const { date, languages } = getState();
const { date, selectedHour, languages } = getState();
const day = resolveDay(date);
const dateLabel = formatDateLong(date);
const dayLabel = getDayLabel(day);
const prevUrl = urlFor(addDays(date, -1), selectedHour, languages);
const nextUrl = urlFor(addDays(date, 1), selectedHour, languages);
const todayUrl = urlFor(todayIso(), selectedHour, languages);
container.innerHTML = `
<nav class="day-nav" aria-label="Day navigation">
<button type="button" class="day-nav-btn" data-action="prev" aria-label="Previous day">&larr;</button>
<button type="button" class="day-nav-btn day-nav-today" data-action="today">Today</button>
<a href="${prevUrl}" class="day-nav-btn" data-action="prev" aria-label="Previous day">&larr;</a>
<a href="${todayUrl}" class="day-nav-btn day-nav-today" data-action="today">Today</a>
<div class="day-nav-header">
${renderBilingual(dateLabel, languages, 'day-nav-date')}
${renderBilingual(dayLabel, languages, 'day-nav-label')}
</div>
<button type="button" class="day-nav-btn" data-action="next" aria-label="Next day">&rarr;</button>
<a href="${nextUrl}" class="day-nav-btn" data-action="next" aria-label="Next day">&rarr;</a>
</nav>
`;
container.querySelector('[data-action="prev"]')?.addEventListener('click', () => shiftDate(-1));
container.querySelector('[data-action="next"]')?.addEventListener('click', () => shiftDate(1));
container.querySelector('[data-action="today"]')?.addEventListener('click', () => goToToday());
const bindNav = (action: string, mutate: () => void): void => {
container.querySelector<HTMLAnchorElement>(`[data-action="${action}"]`)?.addEventListener('click', (event) => {
// Let modifier/middle clicks fall through to normal browser navigation
// (open in new tab, etc.) — only plain left-clicks are SPA-routed.
if (event.defaultPrevented || (event as MouseEvent).button !== 0 || (event as MouseEvent).metaKey || (event as MouseEvent).ctrlKey || (event as MouseEvent).shiftKey || (event as MouseEvent).altKey) {
return;
}
event.preventDefault();
mutate();
});
};
bindNav('prev', () => shiftDate(-1));
bindNav('next', () => shiftDate(1));
bindNav('today', () => goToToday());
}