From bd979cdb68283649e20c73681254f91b887e75d1 Mon Sep 17 00:00:00 2001 From: mkelvers Date: Thu, 28 May 2026 11:28:02 +0200 Subject: [PATCH] chore: format schedule_board --- static/schedule_board.ts | 150 +++++++++++++++++++-------------------- 1 file changed, 75 insertions(+), 75 deletions(-) diff --git a/static/schedule_board.ts b/static/schedule_board.ts index 18072ba..0f491db 100644 --- a/static/schedule_board.ts +++ b/static/schedule_board.ts @@ -1,8 +1,8 @@ export {}; -type WeekStart = 'monday' | 'sunday' | 'saturday'; -type TimeFormat = '24' | '12'; -type SortBy = 'time' | 'alpha' | 'score'; +type WeekStart = "monday" | "sunday" | "saturday"; +type TimeFormat = "24" | "12"; +type SortBy = "time" | "alpha" | "score"; interface ScheduleSettings { weekStart: WeekStart; @@ -12,13 +12,13 @@ interface ScheduleSettings { weekOffset: number; } -const settingsKey = 'schedule_settings_v1'; +const settingsKey = "schedule_settings_v1"; const defaultSettings: ScheduleSettings = { - weekStart: 'monday', - timeFormat: '24', + weekStart: "monday", + timeFormat: "24", showImages: true, - sortBy: 'time', + sortBy: "time", weekOffset: 0, }; @@ -32,22 +32,22 @@ const parseJSON = (value: string | null): unknown => { }; const isWeekStart = (value: unknown): value is WeekStart => - value === 'monday' || value === 'sunday' || value === 'saturday'; + value === "monday" || value === "sunday" || value === "saturday"; -const isTimeFormat = (value: unknown): value is TimeFormat => value === '24' || value === '12'; +const isTimeFormat = (value: unknown): value is TimeFormat => value === "24" || value === "12"; const isSortBy = (value: unknown): value is SortBy => - value === 'time' || value === 'alpha' || value === 'score'; + value === "time" || value === "alpha" || value === "score"; const loadSettings = (): ScheduleSettings => { const raw = parseJSON(localStorage.getItem(settingsKey)); - if (!raw || typeof raw !== 'object') return { ...defaultSettings }; + if (!raw || typeof raw !== "object") return { ...defaultSettings }; const obj = raw as Record; const weekStart = isWeekStart(obj.weekStart) ? obj.weekStart : defaultSettings.weekStart; const timeFormat = isTimeFormat(obj.timeFormat) ? obj.timeFormat : defaultSettings.timeFormat; const showImages = - typeof obj.showImages === 'boolean' ? obj.showImages : defaultSettings.showImages; + typeof obj.showImages === "boolean" ? obj.showImages : defaultSettings.showImages; const sortBy = isSortBy(obj.sortBy) ? obj.sortBy : defaultSettings.sortBy; const weekOffset = Number.isFinite(obj.weekOffset) ? Number(obj.weekOffset) @@ -86,7 +86,7 @@ const parseHHMM = (value: string | null): ParsedTime | null => { const normalizeWeekday = (value: string | null): number | null => { if (!value) return null; - const key = value.trim().toLowerCase().replace(/s$/, ''); + const key = value.trim().toLowerCase().replace(/s$/, ""); const map: Record = { sun: 0, sunday: 0, @@ -106,13 +106,13 @@ const normalizeWeekday = (value: string | null): number | null => { sat: 6, saturday: 6, }; - return typeof map[key] === 'number' ? map[key] : null; + return typeof map[key] === "number" ? map[key] : null; }; const isJstTimezone = (tz: string | null): boolean => { - const normalized = (tz ?? '').trim().toLowerCase(); + const normalized = (tz ?? "").trim().toLowerCase(); if (!normalized) return true; - return normalized === 'asia/tokyo' || normalized === 'jst'; + return normalized === "asia/tokyo" || normalized === "jst"; }; interface LocalSlot { @@ -122,12 +122,12 @@ interface LocalSlot { } const formatLocalTime = (hour: number, minute: number, format: TimeFormat): string => { - const use12h = format === '12'; + const use12h = format === "12"; const date = new Date(); date.setHours(hour, minute, 0, 0); const formatter = new Intl.DateTimeFormat(undefined, { - hour: 'numeric', - minute: '2-digit', + hour: "numeric", + minute: "2-digit", hour12: use12h, }); return formatter.format(date); @@ -137,7 +137,7 @@ const getLocalSlot = ( broadcastDay: string | null, broadcastTime: string | null, broadcastTimezone: string | null, - timeFormat: TimeFormat + timeFormat: TimeFormat, ): LocalSlot | null => { const sourceDayIndex = normalizeWeekday(broadcastDay); const parsed = parseHHMM(broadcastTime); @@ -164,8 +164,8 @@ const getLocalSlot = ( }; const orderedDayIndexes = (weekStart: WeekStart): number[] => { - if (weekStart === 'sunday') return [0, 1, 2, 3, 4, 5, 6]; - if (weekStart === 'saturday') return [6, 0, 1, 2, 3, 4, 5]; + if (weekStart === "sunday") return [0, 1, 2, 3, 4, 5, 6]; + if (weekStart === "saturday") return [6, 0, 1, 2, 3, 4, 5]; return [1, 2, 3, 4, 5, 6, 0]; }; @@ -181,71 +181,71 @@ const startOfWeek = (weekStart: WeekStart, weekOffset: number): Date => { }; const dayName = (index: number): string => - ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'][index] ?? 'Day'; + ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"][index] ?? "Day"; const wireControls = ( root: HTMLElement, settings: ScheduleSettings, - rerender: () => void + rerender: () => void, ): void => { const sync = (): void => { const buttons = root.querySelectorAll( - '[data-schedule-setting][data-schedule-value]' + "[data-schedule-setting][data-schedule-value]", ); for (const button of buttons) { - const key = button.getAttribute('data-schedule-setting'); - const value = button.getAttribute('data-schedule-value'); + const key = button.getAttribute("data-schedule-setting"); + const value = button.getAttribute("data-schedule-value"); if (!key || value === null) continue; const isActive = - (key === 'timeFormat' && value === settings.timeFormat) || - (key === 'showImages' && value === String(settings.showImages)); + (key === "timeFormat" && value === settings.timeFormat) || + (key === "showImages" && value === String(settings.showImages)); - button.classList.toggle('bg-background-button-hover', isActive); + button.classList.toggle("bg-background-button-hover", isActive); } - const selects = root.querySelectorAll('select[data-schedule-setting]'); + const selects = root.querySelectorAll("select[data-schedule-setting]"); for (const select of selects) { - const key = select.getAttribute('data-schedule-setting'); + const key = select.getAttribute("data-schedule-setting"); if (!key) continue; - if (key === 'sortBy') select.value = settings.sortBy; - if (key === 'weekStart') select.value = settings.weekStart; + if (key === "sortBy") select.value = settings.sortBy; + if (key === "weekStart") select.value = settings.weekStart; } }; - root.addEventListener('click', event => { + root.addEventListener("click", (event) => { const target = - event.target instanceof Element ? event.target.closest('[data-schedule-setting]') : null; + event.target instanceof Element ? event.target.closest("[data-schedule-setting]") : null; if (!target) return; - const key = target.getAttribute('data-schedule-setting'); - const value = target.getAttribute('data-schedule-value'); + const key = target.getAttribute("data-schedule-setting"); + const value = target.getAttribute("data-schedule-value"); if (!key || value === null) return; - if (key === 'timeFormat' && isTimeFormat(value)) settings.timeFormat = value; - if (key === 'showImages') settings.showImages = value === 'true'; + if (key === "timeFormat" && isTimeFormat(value)) settings.timeFormat = value; + if (key === "showImages") settings.showImages = value === "true"; saveSettings(settings); sync(); rerender(); }); - root.addEventListener('change', event => { + root.addEventListener("change", (event) => { const target = event.target instanceof HTMLElement ? event.target : null; if (!(target instanceof HTMLSelectElement)) return; - const key = target.getAttribute('data-schedule-setting'); + const key = target.getAttribute("data-schedule-setting"); if (!key) return; - if (key === 'sortBy' && isSortBy(target.value)) settings.sortBy = target.value; - if (key === 'weekStart' && isWeekStart(target.value)) settings.weekStart = target.value; + if (key === "sortBy" && isSortBy(target.value)) settings.sortBy = target.value; + if (key === "weekStart" && isWeekStart(target.value)) settings.weekStart = target.value; saveSettings(settings); sync(); rerender(); }); - root.addEventListener('click', event => { + root.addEventListener("click", (event) => { const target = - event.target instanceof Element ? event.target.closest('[data-schedule-week-nav]') : null; + event.target instanceof Element ? event.target.closest("[data-schedule-week-nav]") : null; if (!target) return; - const delta = Number.parseInt(target.getAttribute('data-schedule-week-nav') ?? '0', 10); + const delta = Number.parseInt(target.getAttribute("data-schedule-week-nav") ?? "0", 10); if (!Number.isFinite(delta) || delta === 0) return; settings.weekOffset += delta; saveSettings(settings); @@ -265,8 +265,8 @@ interface Item { } const buildBoard = (section: HTMLElement): void => { - const board = section.querySelector('[data-schedule-board]'); - const source = section.querySelector('[data-schedule-items-source]'); + const board = section.querySelector("[data-schedule-board]"); + const source = section.querySelector("[data-schedule-items-source]"); if (!board || !source) return; const settings = loadSettings(); @@ -285,49 +285,49 @@ const buildBoard = (section: HTMLElement): void => { // Reorder day columns to match week start const ordered = dayOrder - .map(i => daySections.get(i)) + .map((i) => daySections.get(i)) .filter((n): n is HTMLElement => n instanceof HTMLElement); for (const node of ordered) board.appendChild(node); const weekStartDate = startOfWeek(settings.weekStart, settings.weekOffset); - const dateFormatter = new Intl.DateTimeFormat(undefined, { month: 'short', day: 'numeric' }); + const dateFormatter = new Intl.DateTimeFormat(undefined, { month: "short", day: "numeric" }); for (const dayIndex of dayOrder) { const daySection = daySections.get(dayIndex); if (!daySection) continue; - const labelNode = daySection.querySelector('[data-schedule-day-label]'); + const labelNode = daySection.querySelector("[data-schedule-day-label]"); if (labelNode) labelNode.textContent = dayName(dayIndex); - const dateNode = daySection.querySelector('[data-schedule-date-label]'); + const dateNode = daySection.querySelector("[data-schedule-date-label]"); if (dateNode) { const date = new Date(weekStartDate); const dayOffset = (dayIndex - dayOrder[0] + 7) % 7; date.setDate(date.getDate() + dayOffset); dateNode.textContent = dateFormatter.format(date); } - const itemsNode = daySection.querySelector('[data-schedule-day-items]'); - if (itemsNode) itemsNode.textContent = ''; - const countNode = daySection.querySelector('[data-schedule-count]'); - if (countNode) countNode.textContent = '0'; + const itemsNode = daySection.querySelector("[data-schedule-day-items]"); + if (itemsNode) itemsNode.textContent = ""; + const countNode = daySection.querySelector("[data-schedule-count]"); + if (countNode) countNode.textContent = "0"; } - const rawItems = Array.from(source.querySelectorAll('[data-schedule-item]')); + const rawItems = Array.from(source.querySelectorAll("[data-schedule-item]")); const parsed: Item[] = []; for (const node of rawItems) { - const title = node.getAttribute('data-title') ?? ''; - const score = Number(node.getAttribute('data-score') ?? '0'); + const title = node.getAttribute("data-title") ?? ""; + const score = Number(node.getAttribute("data-score") ?? "0"); const slot = getLocalSlot( - node.getAttribute('data-broadcast-day'), - node.getAttribute('data-broadcast-time'), - node.getAttribute('data-broadcast-timezone'), - settings.timeFormat + node.getAttribute("data-broadcast-day"), + node.getAttribute("data-broadcast-time"), + node.getAttribute("data-broadcast-timezone"), + settings.timeFormat, ); if (!slot) continue; - const timeNode = node.querySelector('[data-schedule-time]'); + const timeNode = node.querySelector("[data-schedule-time]"); if (timeNode) timeNode.textContent = slot.timeLabel; - const poster = node.querySelector('[data-schedule-poster]'); - if (poster) poster.classList.toggle('hidden', !settings.showImages); + const poster = node.querySelector("[data-schedule-poster]"); + if (poster) poster.classList.toggle("hidden", !settings.showImages); parsed.push({ node, @@ -340,8 +340,8 @@ const buildBoard = (section: HTMLElement): void => { } const sorter = (a: Item, b: Item): number => { - if (settings.sortBy === 'alpha') return a.title.localeCompare(b.title); - if (settings.sortBy === 'score') + if (settings.sortBy === "alpha") return a.title.localeCompare(b.title); + if (settings.sortBy === "score") return (b.score || 0) - (a.score || 0) || a.title.localeCompare(b.title); return a.minutes - b.minutes || a.title.localeCompare(b.title); }; @@ -351,13 +351,13 @@ const buildBoard = (section: HTMLElement): void => { for (const dayIndex of dayOrder) { const daySection = daySections.get(dayIndex); if (!daySection) continue; - const itemsNode = daySection.querySelector('[data-schedule-day-items]'); + const itemsNode = daySection.querySelector("[data-schedule-day-items]"); if (!itemsNode) continue; - const items = parsed.filter(i => i.dayIndex === dayIndex).sort(sorter); + const items = parsed.filter((i) => i.dayIndex === dayIndex).sort(sorter); for (const item of items) itemsNode.appendChild(item.node); - const countNode = daySection.querySelector('[data-schedule-count]'); + const countNode = daySection.querySelector("[data-schedule-count]"); if (countNode) countNode.textContent = String(items.length); } }; @@ -368,12 +368,12 @@ const buildBoard = (section: HTMLElement): void => { const initScheduleBoard = (): void => { const run = (): void => { - const sections = document.querySelectorAll('[data-schedule-section]'); + const sections = document.querySelectorAll("[data-schedule-section]"); sections.forEach(buildBoard); }; - document.addEventListener('DOMContentLoaded', run); - document.body.addEventListener('htmx:afterSwap', run); + document.addEventListener("DOMContentLoaded", run); + document.body.addEventListener("htmx:afterSwap", run); }; initScheduleBoard();