/* ========================================================================== librus-tui frontend - dashboard view ========================================================================== */ "use strict"; async function renderDashboard(token) { const [bootstrap, notifications, timetable, freedays] = await Promise.all([ api("/api/bootstrap"), api("/api/notifications").catch(() => null), api("/api/timetable?week=0").catch(() => null), api("/api/freedays").catch(() => null), ]); if (token !== state.loadToken) return; applyUserChrome(bootstrap); const me = bootstrap.me || {}; const school = bootstrap.school || {}; const behaviour = bootstrap.behaviour; const lucky = bootstrap.luckyNumber; const notif = notifications || {}; const now = new Date(); const todayName = DAY_NAMES[now.getDay()]; const todayIndex = (now.getDay() + 6) % 7; // Monday = 0 const todayIso = isoDate(now); const week = (timetable && timetable.Timetable) || {}; let dayName = todayName; let lessons = week[todayName] || []; let dayDate = (lessons[0] && lessons[0].Date) || todayIso; if (!lessons.length) { // Prefer the next day that still belongs to the current week. for (let offset = 1; offset < 7 - todayIndex; offset += 1) { const candidate = WEEK_ORDER[todayIndex + offset]; const candidateLessons = week[candidate] || []; if (candidateLessons.length) { dayName = candidate; lessons = candidateLessons; dayDate = candidateLessons[0].Date || todayIso; break; } } } if (!lessons.length) { // Weekends: peek at next week so the panel is not empty. try { const nextWeek = await api("/api/timetable?week=1"); if (token !== state.loadToken) return; const nextData = (nextWeek && nextWeek.Timetable) || {}; const firstDay = WEEK_ORDER.find((day) => (nextData[day] || []).length); if (firstDay) { dayName = firstDay; lessons = nextData[firstDay]; dayDate = (lessons[0] && lessons[0].Date) || todayIso; } } catch (error) { /* dashboard works without a preview */ } } const isToday = dayDate === todayIso; const schoolFree = ((freedays && freedays.school) || []) .filter((item) => item && item.DateFrom) .slice() .sort((a, b) => (parseDate(a.DateFrom) || 0) - (parseDate(b.DateFrom) || 0)); const upcomingFree = schoolFree .filter((item) => (daysUntil(item.DateFrom) ?? -1) >= 0) .slice(0, 4); const freeRows = upcomingFree.length ? upcomingFree .map( (item) => `