From dcb62664932ef4d8607d3ee6d9efc103b4d39c4f Mon Sep 17 00:00:00 2001 From: Ian Gulliver Date: Sat, 15 Aug 2026 22:48:34 -0700 Subject: [PATCH] Add heart toggle on person pages, drop it elsewhere --- docs/plan.md | 2 +- web/static/directory/app.js | 16 +++++++++++----- web/static/directory/style.css | 12 ++++++++++++ 3 files changed, 24 insertions(+), 6 deletions(-) diff --git a/docs/plan.md b/docs/plan.md index ec5f7b6..290977b 100644 --- a/docs/plan.md +++ b/docs/plan.md @@ -7,7 +7,7 @@ What remains to build. Current behavior is documented in `docs/dev.md`, `docs/da - Remaining sections: My Family, Map. - Mobile chrome: brand-teal top bar and bottom tab navigation on narrow screens (see `docs/directory.md`); today only the desktop chrome is faithful. - Filter button behavior — currently visual only; the original filters by grade and classroom. -- Favorites: heart toggles on detail pages; email-list rows already heart into the bookmarks tab, saved per-device in the browser. +- Favorites: per-account storage; hearts on person pages and email-list rows feed the bookmarks tab, saved per-device in the browser. - Installable-app plumbing: manifest, icons, and meta tags per `docs/pwa.md`. - Self-service flows: photo and pronunciation upload, address update, opt-out. diff --git a/web/static/directory/app.js b/web/static/directory/app.js index 182eb52..9624473 100644 --- a/web/static/directory/app.js +++ b/web/static/directory/app.js @@ -378,7 +378,7 @@ function referrerCrumbs() { return null; } -function breadcrumbs(parts) { +function breadcrumbs(parts, favoriteEmail) { const top = el('div', 'detail-top container'); const crumbs = el('div', 'crumbs'); const back = el('a', 'crumb-back'); @@ -399,9 +399,15 @@ function breadcrumbs(parts) { } }); top.append(crumbs); - const heart = el('button', 'heart-button'); - heart.append(svg('heart')); - top.append(heart); + if (favoriteEmail) { + const heart = el('button', 'heart-button' + (favorites.has(favoriteEmail) ? ' active' : '')); + heart.append(svg('heart')); + heart.addEventListener('click', () => { + toggleFavorite(favoriteEmail); + heart.classList.toggle('active'); + }); + top.append(heart); + } return top; } @@ -521,7 +527,7 @@ function renderPersonDetail(email) { return; } const origin = referrerCrumbs() || [['People', '/people']]; - main.append(breadcrumbs([...origin, [p.fullName, null]])); + main.append(breadcrumbs([...origin, [p.fullName, null]], p.email)); const content = el('div', 'container detail-content'); const grid = el('div', 'detail-grid'); diff --git a/web/static/directory/style.css b/web/static/directory/style.css index 8fce8cf..f723aae 100644 --- a/web/static/directory/style.css +++ b/web/static/directory/style.css @@ -636,6 +636,18 @@ a.student-card:hover { padding: 4px; } +.heart-button:hover { + color: var(--brand); +} + +.heart-button.active { + color: var(--brand); +} + +.heart-button.active svg { + fill: currentColor; +} + .detail-content { padding-bottom: 44px; }