Decide a feed's phase from the store. Pure, so the two non-obvious rules are
testable in isolation:
The badge count and the item LIST arrive separately — the count rides the
SSE snapshot, the list comes from GET /events. While the badge says there
ARE unread but the list hasn't resolved, an empty feed must read as
loading; claiming "all caught up" would contradict the badge.
Any failed load with nothing cached must say so even at count 0 — when
the backend is down the snapshot fails too, so a zero count proves nothing.
Data already cached always wins: a stale-but-usable list is shown rather than
torn down, matching the RequireData rule that only a dataless view is an
error.
Decide a feed's phase from the store. Pure, so the two non-obvious rules are testable in isolation:
GET /events. While the badge says there ARE unread but the list hasn't resolved, an empty feed must read as loading; claiming "all caught up" would contradict the badge.Data already cached always wins: a stale-but-usable list is shown rather than torn down, matching the
RequireDatarule that only a dataless view is an error.