From d8e76b0122a25a204ef8b7c59ad5540980841e9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Katharina=20W=C3=BCnsche?= Date: Wed, 26 Jun 2024 15:02:24 +0200 Subject: [PATCH] Add facets for gender and type --- components/search-page.vue | 120 ++++++++++++++++++++++++++++--------- messages/de.json | 4 +- messages/en.json | 4 +- 3 files changed, 98 insertions(+), 30 deletions(-) diff --git a/components/search-page.vue b/components/search-page.vue index 4b5ba74..293d610 100644 --- a/components/search-page.vue +++ b/components/search-page.vue @@ -38,17 +38,26 @@ const comQuery = computed(() => { per_page: limitNum.value || pageLimit, sort_by: String(query.sort ?? ""), related_entity: String(query.related_entity ?? ""), + gender: String(query.gender ?? ""), + type: String(query.type ?? ""), }; }); const { data, isFetching } = useQuery({ queryKey: ["search", props.className, comQuery] as const, queryFn: async () => { + let optionalQueryParams = Object.fromEntries( + Object.entries({ + gender: comQuery.value.gender, + type: comQuery.value.type, + }).filter(([_k, v]) => v !== ""), + ); const response = await props.endpoint({ queries: { offset: comQuery.value.per_page * (comQuery.value.page - 1), limit: comQuery.value.per_page, search: comQuery.value.q, related_entity: comQuery.value.related_entity, + ...optionalQueryParams, }, }); return response; @@ -56,13 +65,22 @@ const { data, isFetching } = useQuery({ }); // Facets -const facets = computed(() => { +function hasMatchingFacetType(val: unknown): val is Record { + return ( + val != null && + Object.values(val as Record).length > 0 && + Object.values(val as Record).every( + (entry) => "name" in entry && "count" in entry, + ) + ); +} +const relationFacets = computed(() => { let facetObject: Record> = {}; if (!data.value) return facetObject; Object.entries(data.value.facets).forEach(([key, value]) => { - if (key.startsWith("related_")) { - facetObject[key] = Object.entries(value as Record) + if (key.startsWith("related_") && hasMatchingFacetType(value)) { + facetObject[key] = Object.entries(value) .map(([k, v]) => { return { ...v, id: k }; }) @@ -71,37 +89,83 @@ const facets = computed(() => { }); return facetObject; }); -const facetSelection = ref>>({}); -const initFacetSelection = () => { - Object.keys(facets.value).forEach((k) => (facetSelection.value[k] = [])); -}; +const relationFacetSelection = ref>>({}); -watch( - facetSelection, - (selection) => - Object.values(selection).flat().length > 0 - ? router.replace({ - query: { - ...route.query, - related_entity: Object.values(selection) - .flat() - .map((entry) => entry.id) - .filter((entry) => entry) - .join(","), - page: 1, - }, +// class-specific facets such as gender and type +const classFacets = computed(() => { + let facetObject: Record> = {}; + if (!data.value) return facetObject; + Object.entries(data.value.facets).forEach(([key, value]) => { + if (!key.startsWith("related_") && hasMatchingFacetType(value)) { + facetObject[key] = Object.entries(value) + .filter(([_, v]) => v.name !== "") + .map(([k, v]) => { + return { ...v, id: k }; }) - : null, + .sort((a, b) => b.count - a.count); + } + }); + return facetObject; +}); +const classFacetSelection = ref>>({}); + +// Update route when facet selection changes +async function updateRouter() { + await router.replace({ + query: { + ...route.query, + related_entity: Object.values(relationFacetSelection.value) + .flat() + .map((entry) => entry.id) + .filter((entry) => entry) + .join(","), + page: 1, + ...Object.fromEntries( + Object.entries(classFacetSelection.value).map(([key, value]) => [ + key, + value.map((v) => v.name).join(","), + ]), + ), + }, + }); +} +watch( + classFacetSelection, + (selection) => (Object.keys(selection).length > 0 ? updateRouter() : null), + { deep: true }, +); +watch( + relationFacetSelection, + (selection) => (Object.keys(selection).length > 0 ? updateRouter() : null), { deep: true }, ); -watch(facets, () => { - if (Object.keys(facets.value).some((key) => !(key in facetSelection.value))) initFacetSelection(); + +// Update selection arrays when facets change +watch(relationFacets, () => { + if (Object.keys(relationFacets.value).some((key) => !(key in relationFacetSelection.value))) + initFacetSelection(); +}); +watch(classFacets, () => { + if (Object.keys(classFacets.value).some((key) => !(key in classFacetSelection.value))) + initFacetSelection(); }); +const initFacetSelection = () => { + Object.keys(relationFacets.value).forEach((k) => (relationFacetSelection.value[k] = [])); + Object.keys(classFacets.value).forEach((k) => (classFacetSelection.value[k] = [])); +};