From 03d55bbe8fe86c61a840c8f5248c3ad5d2d26efb Mon Sep 17 00:00:00 2001 From: Kevin Stadler Date: Mon, 7 Oct 2024 14:01:27 +0200 Subject: [PATCH] feat: make faceted listing use instantsearch with single refinement list --- app/languages/[language]/page.tsx | 2 +- app/works/[category]/page.tsx | 18 ++++-- components/faceted-listing.tsx | 18 +++--- components/instantsearch.tsx | 85 ++++++++++----------------- components/single-refinement-list.tsx | 27 +++++++++ messages/en.json | 1 + 6 files changed, 84 insertions(+), 67 deletions(-) create mode 100644 components/single-refinement-list.tsx diff --git a/app/languages/[language]/page.tsx b/app/languages/[language]/page.tsx index 505ee39..c8c54f4 100644 --- a/app/languages/[language]/page.tsx +++ b/app/languages/[language]/page.tsx @@ -1,5 +1,5 @@ import { FacetedListing } from "@/components/faceted-listing"; export default function LanguagesPage() { - return ; + return ; } diff --git a/app/works/[category]/page.tsx b/app/works/[category]/page.tsx index e4896a2..d24734b 100644 --- a/app/works/[category]/page.tsx +++ b/app/works/[category]/page.tsx @@ -1,11 +1,21 @@ -import WorksPage from "./[work]/page"; +import { getTranslations } from "next-intl/server"; -interface BlankWorksPageProps { +import { FacetedListing } from "@/components/faceted-listing"; + +interface WorksPageProps { params: { category: string; }; } -export default function BlankWorksPage(props: BlankWorksPageProps) { - return ; +export default async function WorksPage(props: WorksPageProps) { + const t = await getTranslations("BernhardCategories"); + return ( + + ); } diff --git a/components/faceted-listing.tsx b/components/faceted-listing.tsx index adfe65d..1a3ff3d 100644 --- a/components/faceted-listing.tsx +++ b/components/faceted-listing.tsx @@ -1,20 +1,24 @@ import { MainContent } from "@/components/main-content"; import { InstantSearch } from "./instantsearch"; +import { SingleRefinementList } from "./single-refinement-list"; export interface FacetedListingProps { - queryArgToRefinementFields: Record; + queryArgsToRefinementFields: Record; + filters?: Record; } export function FacetedListing(props: FacetedListingProps) { - // const data = await getFaceted(props.facet, safeParams.facetValue); - // const publications = data.hits?.map((h) => { - // return h.document; - // }); - return ( - + + {Object.values(props.queryArgsToRefinementFields).map((attribute) => { + return ; + })} + ); } diff --git a/components/instantsearch.tsx b/components/instantsearch.tsx index 653129b..9b170b3 100644 --- a/components/instantsearch.tsx +++ b/components/instantsearch.tsx @@ -3,7 +3,7 @@ import type { UiState } from "instantsearch.js"; import { type MessageKeys, useTranslations } from "next-intl"; import { type ReactNode, useEffect, useRef } from "react"; -import { Configure, RefinementList, SearchBox, SortBy, useInfiniteHits } from "react-instantsearch"; +import { Configure, SearchBox, SortBy, useInfiniteHits } from "react-instantsearch"; import { InstantSearchNext } from "react-instantsearch-nextjs"; import TypesenseInstantSearchAdapter, { type SearchClient } from "typesense-instantsearch-adapter"; @@ -11,14 +11,16 @@ import { ClickablePublicationThumbnail } from "@/components/publication-cover"; import { collectionName } from "@/lib/data"; import type { Publication } from "@/lib/model"; +import { InstantSearchStats } from "./instantsearch-stats"; import { PublicationGrid } from "./publication-grid"; // TODO put into props const sortOptions = ["year:desc", "year:asc", "title:asc"]; interface InstantSearchProps { - queryArgToRefinementFields: Record; + queryArgsToRefinementFields: Record; children?: ReactNode; + filters?: Record; // ugly } const typesenseInstantsearchAdapter = new TypesenseInstantSearchAdapter({ @@ -53,7 +55,8 @@ function InfiniteScroll(): ReactNode { const observer = new IntersectionObserver((entries) => { entries.forEach((entry) => { if (entry.isIntersecting && !isLastPage) { - showMore(); + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition + showMore && showMore(); } }); }); @@ -79,37 +82,11 @@ function InfiniteScroll(): ReactNode { ); } -function DefaultRefinementList({ - attribute, - placeholder, -}: { - attribute: string; - placeholder: string; -}) { - return ( - - ); -} - type RouteState = Record; export function InstantSearch(props: InstantSearchProps): ReactNode { const t = useTranslations("SearchPage"); - const { children, queryArgToRefinementFields } = props; + const { children, filters, queryArgsToRefinementFields } = props; return ( { + const queryarg = Object.entries(queryArgsToRefinementFields).find(([_k, v]) => { return v === field; })?.[0]; // eslint-disable-next-line @typescript-eslint/no-non-null-assertion @@ -141,14 +118,16 @@ export function InstantSearch(props: InstantSearchProps): ReactNode { sortBy: routeState.sort ? `${collectionName}/sort/${routeState.sort}` : undefined, }, } as UiState; - Object.entries(queryArgToRefinementFields).forEach(([queryArg, field]) => { - if (routeState[queryArg]) { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - uiState[collectionName]!.refinementList![field] = routeState[queryArg] - .split(";") - .map(decodeURI); - } - }); + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition + queryArgsToRefinementFields && + Object.entries(queryArgsToRefinementFields).forEach(([queryArg, field]) => { + if (routeState[queryArg]) { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + uiState[collectionName]!.refinementList![field] = routeState[queryArg] + .split(";") + .map(decodeURI); + } + }); return uiState; }, }, @@ -157,25 +136,21 @@ export function InstantSearch(props: InstantSearchProps): ReactNode { searchClient={searchClient} > { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + return `${k}:= ${filters[k]!}`; + }) + .join(" and ") + : undefined + } /> -
- {Object.keys(queryArgToRefinementFields).map((attribute) => { - return ( - )}`} - /> - ); - })} - {children} -
+
{children}
+ sort by{" "} + ); +} diff --git a/messages/en.json b/messages/en.json index 880f349..e019474 100644 --- a/messages/en.json +++ b/messages/en.json @@ -84,6 +84,7 @@ "category": "categories", "language": "languages", "translator": "translators", + "title": "works", "work": "works" }, "query_placeholder": "search publications",