fix(ui): the filter rail shows no tag counts until the facets land
It printed the tag's whole-library count as the current filter's while the facets loaded, and for good when they failed: live, "Music 238" beside a search that matched 3 of its channels. Ordering still falls back to it.
This commit is contained in:
@@ -14,9 +14,10 @@ import FilterRail from "./FilterRail";
|
|||||||
import { type PanelItem } from "./ui/PanelGroups";
|
import { type PanelItem } from "./ui/PanelGroups";
|
||||||
import { type MediaSourceKind } from "../lib/mediaSource";
|
import { type MediaSourceKind } from "../lib/mediaSource";
|
||||||
import ChannelPicker from "./ChannelPicker";
|
import ChannelPicker from "./ChannelPicker";
|
||||||
|
import { facetOption } from "./facetOption";
|
||||||
import DateFilterSelect from "./DateFilterSelect";
|
import DateFilterSelect from "./DateFilterSelect";
|
||||||
import YearFilter from "./YearFilter";
|
import YearFilter from "./YearFilter";
|
||||||
import Combobox, { type ComboboxOption } from "./ui/Combobox";
|
import Combobox from "./ui/Combobox";
|
||||||
import MatchToggle from "./ui/MatchToggle";
|
import MatchToggle from "./ui/MatchToggle";
|
||||||
import { useFeedFilters, useFeedFiltersActions } from "./feedFiltersContext";
|
import { useFeedFilters, useFeedFiltersActions } from "./feedFiltersContext";
|
||||||
import { useChannelsActions } from "./channelsContext";
|
import { useChannelsActions } from "./channelsContext";
|
||||||
@@ -72,6 +73,8 @@ export default function Sidebar({
|
|||||||
});
|
});
|
||||||
const facetsReady = !!summaryQuery.data;
|
const facetsReady = !!summaryQuery.data;
|
||||||
const facetCounts = summaryQuery.data?.facets ?? {};
|
const facetCounts = summaryQuery.data?.facets ?? {};
|
||||||
|
// Ordering falls back to the tag's whole-library count until the facets land; the number shown does
|
||||||
|
// not (facetOption).
|
||||||
const chipCount = (tag: Tag): number =>
|
const chipCount = (tag: Tag): number =>
|
||||||
facetsReady ? (facetCounts[String(tag.id)] ?? 0) : tag.channel_count;
|
facetsReady ? (facetCounts[String(tag.id)] ?? 0) : tag.channel_count;
|
||||||
const visibleChips = (list: Tag[]): Tag[] => {
|
const visibleChips = (list: Tag[]): Tag[] => {
|
||||||
@@ -93,11 +96,7 @@ export default function Sidebar({
|
|||||||
|
|
||||||
// The language/topic/tags sections all write into the one `filters.tags` list, so each combobox owns
|
// The language/topic/tags sections all write into the one `filters.tags` list, so each combobox owns
|
||||||
// only its own slice: its selection replaces the ids that belong to its list, leaving the others.
|
// only its own slice: its selection replaces the ids that belong to its list, leaving the others.
|
||||||
const tagOption = (tg: Tag): ComboboxOption => ({
|
const tagOption = (tg: Tag) => facetOption(tg, summaryQuery.data?.facets);
|
||||||
value: String(tg.id),
|
|
||||||
label: tg.name,
|
|
||||||
count: chipCount(tg),
|
|
||||||
});
|
|
||||||
const selectedIn = (list: Tag[]): string[] =>
|
const selectedIn = (list: Tag[]): string[] =>
|
||||||
filters.tags.filter((id) => list.some((tg) => tg.id === id)).map(String);
|
filters.tags.filter((id) => list.some((tg) => tg.id === id)).map(String);
|
||||||
function setTagSelection(list: Tag[], next: string[]) {
|
function setTagSelection(list: Tag[], next: string[]) {
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
import { describe, expect, it } from "vitest";
|
||||||
|
|
||||||
|
import type { Tag } from "../lib/api";
|
||||||
|
import { facetOption } from "./facetOption";
|
||||||
|
|
||||||
|
const music = { id: 7, name: "Music", category: "topic", channel_count: 238 } as Tag;
|
||||||
|
|
||||||
|
describe("a tag as a filter row", () => {
|
||||||
|
it("counts the current filter's channels", () => {
|
||||||
|
expect(facetOption(music, { "7": 3 }).count).toBe(3);
|
||||||
|
expect(facetOption(music, {}).count).toBe(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
// E31 review 2, live: with the summary failed, the rail read "Music 238" beside a search that matched
|
||||||
|
// 3 Music channels — the whole library's count printed as the filter's.
|
||||||
|
it("shows no count until the facets land, rather than the whole library's", () => {
|
||||||
|
expect(facetOption(music, undefined).count).toBeUndefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
import type { Tag } from "../lib/api";
|
||||||
|
import type { ComboboxOption } from "./ui/Combobox";
|
||||||
|
|
||||||
|
// A tag as a filter row: its count is the CURRENT filter's (the summary's facets), or none at all while
|
||||||
|
// the facets load or after they failed. The rail printed the tag's whole-library count in that gap, as
|
||||||
|
// if it were the filter's: "Music 238" beside a search that matched 3 of its channels (E31 review 2).
|
||||||
|
export const facetOption = (
|
||||||
|
tag: Tag,
|
||||||
|
facets: Record<string, number> | undefined,
|
||||||
|
): ComboboxOption => ({
|
||||||
|
value: String(tag.id),
|
||||||
|
label: tag.name,
|
||||||
|
count: facets ? (facets[String(tag.id)] ?? 0) : undefined,
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user