feat(fristenrechner/inbox-chip): wire inbox into B2 fine-forum chips
The page-top inbox chip now drives the existing 10-bucket B2 forum
filter so search results inherit the same narrowing as the Pathway A
picker. CMS auto-selects upc_cfi + upc_coa; beA / Posteingang
auto-select de_lg + de_olg + de_bgh + de_bpatg; "Alle" clears both the
inbox and the fine chips.
State-priority discipline:
- User chip click always replaces activeForums with
the inbox-derived set.
- Hydrate (URL ?inbox=, no
?forum=) derives activeForums from inbox.
initForumFilter (which runs first)
has already loaded URL ?forum= when
present, so the explicit forum= wins.
- Hydrate (no URL ?inbox=,
/api/me forum_pref set) same as above: derive when ?forum=
is empty.
- popstate re-applies the same rule so browser
back/forward stays consistent.
The "explicit URL forum= wins" rule means a colleague's CMS-narrowed
share link still works when the recipient has a different saved pref —
they see the shared narrowing, not their own.
Refs m/paliad#15.
This commit is contained in:
@@ -2827,6 +2827,32 @@ function inboxChannelToForum(ch: InboxChannel): "upc" | "de" | null {
|
||||
return null;
|
||||
}
|
||||
|
||||
// inboxToFineForumSlugs maps the inbox channel to the matching subset
|
||||
// of the 10-bucket B2 forum filter. CMS narrows to UPC CFI + CoA;
|
||||
// beA / Posteingang narrow to all four national-DE buckets (LG / OLG /
|
||||
// BGH / BPatG). Null returns an empty list — caller handles the
|
||||
// "no inbox set" case explicitly because the meaning differs between
|
||||
// hydrate (don't touch fine chips) and click-clear (clear them).
|
||||
function inboxToFineForumSlugs(ch: InboxChannel): string[] {
|
||||
if (ch === "cms") return ["upc_cfi", "upc_coa"];
|
||||
if (ch === "bea" || ch === "posteingang") return ["de_lg", "de_olg", "de_bgh", "de_bpatg"];
|
||||
return [];
|
||||
}
|
||||
|
||||
// applyFineForumsFromInbox replaces activeForums with the inbox's
|
||||
// implied fine-bucket set and re-renders the B2 chip strip + reissues
|
||||
// the active search. Caller decides when to invoke (user click always;
|
||||
// hydrate / popstate only when URL ?forum= is empty so an explicit
|
||||
// link-share wins over the inbox derivation).
|
||||
function applyFineForumsFromInbox(ch: InboxChannel) {
|
||||
activeForums.clear();
|
||||
for (const slug of inboxToFineForumSlugs(ch)) activeForums.add(slug);
|
||||
// renderForumChips guards on missing container, so calling from
|
||||
// contexts where Pathway B isn't yet rendered is safe.
|
||||
renderForumChips();
|
||||
reissueSearchWithCurrentFilters();
|
||||
}
|
||||
|
||||
function applyInboxFilter(ch: InboxChannel) {
|
||||
const forum = inboxChannelToForum(ch);
|
||||
|
||||
@@ -2884,18 +2910,41 @@ async function initInboxFilter() {
|
||||
}
|
||||
applyInboxFilter(initial);
|
||||
|
||||
// Sync B2 fine-bucket chips from the inbox on hydrate ONLY when the
|
||||
// URL doesn't explicitly carry ?forum=… — an explicit forum= comes
|
||||
// from a shared link and should win over the user's saved inbox
|
||||
// preference. initForumFilter (which runs first) has already
|
||||
// populated activeForums from URL forum=, so we leave it alone here.
|
||||
if (initial !== null && readForumsFromURL().length === 0) {
|
||||
applyFineForumsFromInbox(initial);
|
||||
writeForumsToURL(true);
|
||||
}
|
||||
|
||||
bar.querySelectorAll<HTMLButtonElement>(".fristen-inbox-chip").forEach((btn) => {
|
||||
btn.addEventListener("click", () => {
|
||||
const isClear = btn.hasAttribute("data-inbox-clear");
|
||||
const next: InboxChannel = isClear ? null : ((btn.dataset.inbox as InboxChannel) ?? null);
|
||||
writeInboxToURL(next);
|
||||
applyInboxFilter(next);
|
||||
// User click is an explicit signal: re-narrow the B2 fine chips
|
||||
// to match the new inbox. "Alle" clears both inbox and fine chips
|
||||
// — that's the user's reset affordance.
|
||||
applyFineForumsFromInbox(next);
|
||||
writeForumsToURL(true);
|
||||
void persistInboxPref(next);
|
||||
});
|
||||
});
|
||||
|
||||
window.addEventListener("popstate", () => {
|
||||
applyInboxFilter(readInboxFromURL());
|
||||
const newInbox = readInboxFromURL();
|
||||
applyInboxFilter(newInbox);
|
||||
// popstate can land on a URL with inbox= but no forum= (the user
|
||||
// navigated to a state where derivation should re-apply). Don't
|
||||
// touch activeForums when forum= is explicit — initForumFilter's
|
||||
// own popstate handler has already loaded it from the URL.
|
||||
if (newInbox !== null && readForumsFromURL().length === 0) {
|
||||
applyFineForumsFromInbox(newInbox);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user