摘要
Day 14 我們完成了「精神狀態小測驗」:使用者能分別填寫早/午/晚三個時段的精神狀態,且會自動記住上次勾選。
今天 Day 15,我們把小測驗串接到下一步的「行動分支頁」,在轉場前加上一段「今日整體回顧」,讓使用者先看到自己的能量分布,再做選擇:
- Start now(馬上開始!):鼓勵趁精神好立刻行動
- Later(我有點累…):溫柔引導先休息、晚點再安排
這一步把 Day 12–14 的情緒與能量資訊轉化為行動,從「知道」跨到「去做」。
HTML:小測驗提交 & 行動分支頁
註:其他區塊(Day 12–14)維持不變,此處僅展示 Day 15 新增的 HTML。
<!-- ★ Day15-NEW:小測驗提交,前往條件分支頁 -->
<div style="margin-top:0.5rem;">
<button id="moodSubmitBtn" type="button" aria-controls="moodDecisionSection">
submit
</button>
</div>
<!-- Day 15 新增:條件分支頁 -->
<section id="moodDecisionSection" hidden>
<p id="todayRecap" aria-live="polite"></p> <!-- ★ 今日整體回顧(新) -->
<h2>要不要在精神最好的時段完成任務?</h2>
<button id="btnStartNow">馬上開始!</button>
<button id="btnLater_2">我有點累…</button>
<p id="decisionFeedback" aria-live="polite"></p>
</section>
JavaScript:
註:safeParseJSON、PERIOD_LABEL、小測驗的 radio 事件綁定與 showAggregateFeedback 等 Day 14 內容均沿用,不在此重複。
JS:DOM 參照(新增):
// === Day 15 新增節點 ===
const moodDecisionSection = document.getElementById('moodDecisionSection');
const btnStartNow = document.getElementById('btnStartNow');
const decisionFeedback = document.getElementById('decisionFeedback');
const moodSubmitBtn = document.getElementById('moodSubmitBtn');
const btnLater_2 = document.getElementById('btnLater_2');
JS:提交小測驗 ➜ 產生「今日整體回顧」並切頁:
// 取得並渲染今日整體回顧(Day15-NEW)
function getMoodData() {
return safeParseJSON(localStorage.getItem(MOOD_KEY), {});
}
function renderTodayRecap() {
const el = document.getElementById('todayRecap');
if (!el) return;
const moodData = getMoodData();
const parts = ['morning','afternoon','evening']
.filter(p => moodData[p])
.map(p => `${PERIOD_LABEL[p]}:${moodData[p]}`);
el.textContent = parts.length
? `今天整體回顧 → ${parts.join('; ')}`
: '今天尚未填寫精神狀態(可稍後在小測驗補填)';
}
// 小測驗提交(Day15-NEW)
moodSubmitBtn?.addEventListener('click', () => {
const moodData = safeParseJSON(localStorage.getItem(MOOD_KEY), {});
const hasAny = ['morning','afternoon','evening'].some(p => !!moodData[p]);
if (!hasAny && !confirm('今天尚未選任何時段的狀態,仍要前往任務提問頁嗎?')) return;
renderTodayRecap(); // 先填好回顧
showPage('moodDecision'); // 再切到分支頁
});
JS:頁面切換支援新分支頁:
// ---- 顯示/切換主要區塊(加入 Day15 分支)----
function showPage(page) {
// 先隱藏所有主要區塊(存在才動作,避免 null)
if (formSection) formSection.hidden = true;
if (historySection) historySection.hidden = true;
if (moodTestSection) moodTestSection.hidden = true;
if (moodDecisionSection) moodDecisionSection.hidden = true; // Day15
if (taskScheduleSection) taskScheduleSection.hidden = true; // Day15
// 小工具:嘗試聚焦標題;若失敗,將區塊設為可聚焦並聚焦
function focusOrFallback(sectionEl, titleElId) {
const titleEl = titleElId ? document.getElementById(titleElId) : null;
if (titleEl && typeof titleEl.focus === 'function') {
titleEl.focus();
} else if (sectionEl) {
sectionEl.setAttribute('tabindex', '-1');
sectionEl.focus && sectionEl.focus();
}
}
// 依 page 顯示 + 聚焦
if (page === 'history') {
if (historySection) {
historySection.hidden = false;
if (typeof renderHistory === 'function') renderHistory();
focusOrFallback(historySection, 'history-title'); // 與較早版一致
}
} else if (page === 'moodTest') {
if (moodTestSection) {
moodTestSection.hidden = false;
focusOrFallback(moodTestSection, 'mood-title'); // 與較早版一致
}
} else if (page === 'moodDecision') { // Day15
if (moodDecisionSection) {
moodDecisionSection.hidden = false;
moodSubmitBtn?.setAttribute('aria-expanded', 'true');
// 這頁以按鈕為第一焦點,若不存在退而聚焦區塊本身
const first = document.getElementById('btnStartNow');
if (first && typeof first.focus === 'function') first.focus();
else focusOrFallback(moodDecisionSection);
}
} else { // 'home' or default
if (formSection) {
formSection.hidden = false;
moodSubmitBtn?.setAttribute('aria-expanded', 'false');
if (typeof focusFirstField === 'function') focusFirstField();
else {
formSection.setAttribute('tabindex', '-1');
formSection.focus && formSection.focus();
}
}
}
}
JS:分支頁按鈕的即時回饋:
// ---- 條件分支互動(Day15-NEW)----
btnStartNow?.addEventListener('click', () => {
decisionFeedback.textContent = "太好了!那就趁精神好,完成任務吧!💪";
// TODO:未來可導到「番茄鐘」或「切片任務」頁
});
btnLater_2?.addEventListener('click', () => {
decisionFeedback.textContent = "沒關係,先休息一下,等等再安排。😌";
// TODO:未來可導到「行程規劃」或「稍後提醒」頁
});