Add birthday previews and restore checklist taps
This commit is contained in:
parent
d2c7f004ea
commit
aaa3013890
11 changed files with 146 additions and 27 deletions
|
|
@ -2,6 +2,7 @@
|
|||
const data = window.VALLEY_DATA;
|
||||
const sync = window.ValleySync;
|
||||
const availability = window.ValleyAvailability;
|
||||
const calendar = window.ValleyCalendar;
|
||||
const weekdays = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"];
|
||||
const seasonNames = { spring: "Spring", summer: "Summer", fall: "Fall", winter: "Winter" };
|
||||
const state = {
|
||||
|
|
@ -59,15 +60,19 @@
|
|||
$$("[data-season]").forEach(button => button.setAttribute("aria-selected", String(button.dataset.season === state.season)));
|
||||
$("#day-grid").innerHTML = Array.from({ length: 28 }, (_, index) => {
|
||||
const day = index + 1;
|
||||
return `<button type="button" class="${day === state.day ? "selected" : ""}" data-day="${day}" aria-label="${seasonNames[state.season]} ${day}, ${weekday(day)}" aria-pressed="${day === state.day}"><small>${weekdays[index % 7].slice(0, 2)}</small>${day}</button>`;
|
||||
const birthday = birthdayOn(day);
|
||||
const label = `${seasonNames[state.season]} ${day}, ${weekday(day)}${birthday ? `, ${birthday}'s birthday` : ""}`;
|
||||
const marker = birthday ? `<span class="birthday-marker" title="${escapeHtml(`${birthday}'s birthday`)}" aria-hidden="true">🎂</span>` : "";
|
||||
return `<button type="button" class="${day === state.day ? "selected" : ""}" data-day="${day}" aria-label="${escapeHtml(label)}" aria-pressed="${day === state.day}"><small>${weekdays[index % 7].slice(0, 2)}</small><span class="day-number">${day}</span>${marker}</button>`;
|
||||
}).join("");
|
||||
}
|
||||
|
||||
function birthdayOn(day) {
|
||||
return calendar.birthdayOn(data.birthdays, state.season, day, state.year);
|
||||
}
|
||||
|
||||
function currentBirthday() {
|
||||
const entry = data.birthdays[state.season][state.day];
|
||||
if (!entry) return null;
|
||||
if (entry[1] && entry[1] !== state.year) return null;
|
||||
return entry[0];
|
||||
return birthdayOn(state.day);
|
||||
}
|
||||
|
||||
function currentEvent() {
|
||||
|
|
@ -96,9 +101,19 @@
|
|||
return `daily-${state.year}-${state.season}-${state.day}-${kind}-${slug}`;
|
||||
}
|
||||
|
||||
function card(kind, label, title, copy, itemId = null) {
|
||||
function giftGuide(name) {
|
||||
const profile = data.giftProfiles[name];
|
||||
if (!profile) return "";
|
||||
const giftList = entries => entries.map(entry => `<li>${escapeHtml(entry)}</li>`).join("");
|
||||
return `<div class="gift-guide" aria-label="Gift preferences for ${escapeHtml(name)}">
|
||||
<div><strong><span aria-hidden="true">♥</span> Loves</strong><ul>${giftList(profile.loves)}</ul></div>
|
||||
<div><strong><span aria-hidden="true">×</span> Avoid</strong><ul>${giftList(profile.avoid)}</ul></div>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
function card(kind, label, title, copy, itemId = null, extra = "") {
|
||||
const checked = itemId ? Boolean(state.checks[itemId]) : false;
|
||||
const content = `${itemId ? `<input type="checkbox" data-check-id="${itemId}" ${checked ? "checked" : ""} ${state.saving.has(itemId) ? "disabled" : ""}><span class="checkmark" aria-hidden="true"></span>` : ""}<div class="card-label"><span></span>${escapeHtml(label)}</div><h3>${escapeHtml(title)}</h3><p>${escapeHtml(copy)}</p>`;
|
||||
const content = `${itemId ? `<input type="checkbox" data-check-id="${itemId}" aria-label="Mark ${escapeHtml(title)} complete" ${checked ? "checked" : ""} ${state.saving.has(itemId) ? "disabled" : ""}><span class="checkmark" aria-hidden="true"></span>` : ""}<div class="card-label"><span></span>${escapeHtml(label)}</div><h3>${escapeHtml(title)}</h3><p>${escapeHtml(copy)}</p>${extra}`;
|
||||
return itemId
|
||||
? `<label class="today-card ${kind} ${checked ? "complete" : ""}">${content}</label>`
|
||||
: `<article class="today-card ${kind}">${content}</article>`;
|
||||
|
|
@ -108,7 +123,7 @@
|
|||
const cards = [];
|
||||
const birthday = currentBirthday();
|
||||
const event = currentEvent();
|
||||
if (birthday) cards.push(card("birthday", "Birthday", birthday, "A birthday gift gives 8× the usual friendship effect.", dailyId("birthday", birthday)));
|
||||
if (birthday) cards.push(card("birthday", "Birthday", birthday, "A birthday gift gives 8× the usual friendship effect.", dailyId("birthday", birthday), giftGuide(birthday)));
|
||||
if (event) cards.push(card("event", "Event", event[0], event[1], dailyId("event", event[0])));
|
||||
reminders().forEach(([title, copy]) => cards.push(card("reminder", "Reminder", title, copy, dailyId("reminder", title))));
|
||||
cropDeadlineCards().forEach(crop => cards.push(card("deadline", "Plant by today", crop.name, crop.purpose, itemKey(crop))));
|
||||
|
|
@ -126,7 +141,7 @@
|
|||
const overdue = state.day > crop.last && !checked;
|
||||
const today = state.day === crop.last && !checked;
|
||||
return `<label class="crop-row ${checked ? "complete" : ""} ${overdue ? "overdue" : ""}">
|
||||
<input type="checkbox" data-check-id="${key}" ${checked ? "checked" : ""} ${state.saving.has(key) ? "disabled" : ""}>
|
||||
<input type="checkbox" data-check-id="${key}" aria-label="Mark ${escapeHtml(crop.name)} complete" ${checked ? "checked" : ""} ${state.saving.has(key) ? "disabled" : ""}>
|
||||
<span class="checkmark" aria-hidden="true"></span>
|
||||
<span class="crop-name"><strong>${escapeHtml(crop.name)}</strong><small>${escapeHtml(crop.purpose)}</small></span>
|
||||
<span class="grow-time">${crop.grow} days<small>to grow</small></span>
|
||||
|
|
@ -203,7 +218,7 @@
|
|||
const checked = Boolean(state.checks[entry.id]);
|
||||
const status = entryStatus(entry, group);
|
||||
const classes = [checked ? "complete" : "", status.needed ? "needed" : "optional", status.needed && status.availableNow ? "available-now" : "", status.seasonExclusive ? "season-exclusive" : "", status.weather ? "weather-specific" : ""].filter(Boolean).join(" ");
|
||||
return `<label class="bundle-item ${classes}"><input type="checkbox" data-check-id="${entry.id}" ${checked ? "checked" : ""} ${state.saving.has(entry.id) ? "disabled" : ""}><span class="checkmark" aria-hidden="true"></span><span class="item-copy"><strong>${escapeHtml(entry.label)}</strong><small>${escapeHtml(entry.meta)}</small>${statusBadges(status)}</span></label>`;
|
||||
return `<label class="bundle-item ${classes}"><input type="checkbox" data-check-id="${entry.id}" aria-label="Mark ${escapeHtml(entry.label)} complete" ${checked ? "checked" : ""} ${state.saving.has(entry.id) ? "disabled" : ""}><span class="checkmark" aria-hidden="true"></span><span class="item-copy"><strong>${escapeHtml(entry.label)}</strong><small>${escapeHtml(entry.meta)}</small>${statusBadges(status)}</span></label>`;
|
||||
}).join("")}</div>
|
||||
</article>`;
|
||||
}).filter(Boolean).join("");
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue