fix(documents): source the condition chips from the usage endpoint

The filter bar derived its condition chips from the loaded corpus, so an
episode whose only linked documents sat pages deep in the timeline never
surfaced a chip — the condition route into an older document silently
disappeared at four-digit corpus sizes. The usage endpoint (already read
on page mount) now returns `linkedEpisodes` — every episode carrying at
least one live document link, one indexed grouped query, no blobs — and
the view unions it with the active-filter fallback. Additive DTO change;
OpenAPI regenerated.
This commit is contained in:
Marc-André Bombeck committed 2026-07-07 14:15:40 +02:00
1 parent af45899f89
commit d937991af4
6 files changed
+82 -13

No files matched your search

+8 -8
View File
@@ -244,15 +244,15 @@ export function DocumentsView() {
const episodes = useIllnessEpisodes(true);
// Condition chips: the user's episodes that actually carry links in the
// loaded corpus — plus the actively filtered episode (a deep link must
// always show its own chip, even before its documents load).
// Condition chips: every episode carrying at least one live document
// link, served by the usage endpoint (NOT derived from the loaded corpus
// — an old linked document pages deep must still surface its chip), plus
// the actively filtered episode (a deep link must always show its own
// chip, even when its last link was just removed).
const conditionChips = useMemo<ConditionChip[]>(() => {
const byId = new Map<string, string>();
for (const doc of documents) {
for (const link of doc.conditionLinks) {
if (!byId.has(link.episodeId)) byId.set(link.episodeId, link.name);
}
for (const link of usage.data?.linkedEpisodes ?? []) {
byId.set(link.episodeId, link.name);
}
if (filters.episodeId && !byId.has(filters.episodeId)) {
const episode = episodes.data?.find((e) => e.id === filters.episodeId);
@@ -261,7 +261,7 @@ export function DocumentsView() {
return [...byId.entries()]
.map(([episodeId, name]) => ({ episodeId, name }))
.sort((a, b) => a.name.localeCompare(b.name));
}, [documents, filters.episodeId, episodes.data]);
}, [usage.data?.linkedEpisodes, filters.episodeId, episodes.data]);
// Year segmenter: years present in the loaded corpus (+ the active year).
const years = useMemo(() => {