Skip to content

Commit

Permalink
improvement: implement custom sort-by widget
Browse files Browse the repository at this point in the history
when first navigating onto a faceted-listing page, exhaustive sorting (chronologically from newest
to oldest) now gets applied by default (see #2)
  • Loading branch information
kevinstadler committed Oct 9, 2024
1 parent 3596691 commit bbf4a2b
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 19 deletions.
62 changes: 62 additions & 0 deletions components/instantsearch-sortby.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { type MessageKeys, useTranslations } from "next-intl";
import type { ReactNode } from "react";
import { Label } from "react-aria-components";
import { useSortBy } from "react-instantsearch";

import { collectionName } from "@/lib/data";

import { Select, SelectContent, SelectItem, SelectPopover, SelectTrigger } from "./ui/select";

interface InstantSearchSortByProps {
sortOptions: Array<string>;
}

export function InstantSearchSortBy(props: InstantSearchSortByProps): ReactNode {
const t = useTranslations("SearchPage");

const sortByItems = props.sortOptions.map((field) => {
return {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
label: t(`sort.${field}` as MessageKeys<any, any>),
value: `${collectionName}/sort/${field}`,
};
});

const { currentRefinement, options, refine } = useSortBy({
items: sortByItems,
});
// enforce initial sort
if (currentRefinement === collectionName) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
refine(`${collectionName}/sort/${props.sortOptions[0]!}`);
}

return (
<Select
defaultSelectedKey={sortByItems[0]?.value}
onSelectionChange={(selected) => {
refine(selected as string);
}}
>
<Label className="sr-only">sort order</Label>
<SelectTrigger>
{
sortByItems.find(({ value }) => {
return value === currentRefinement;
})?.label
}
</SelectTrigger>
<SelectPopover>
<SelectContent>
{options.map((o) => {
return (
<SelectItem key={o.value} id={o.value} textValue={o.label}>
{o.label}
</SelectItem>
);
})}
</SelectContent>
</SelectPopover>
</Select>
);
}
21 changes: 5 additions & 16 deletions components/instantsearch.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,17 @@
import type { UiState } from "instantsearch.js";
import { useTranslations } from "next-intl";
import { type ReactNode, useEffect, useRef } from "react";
import { Configure, SearchBox, SortBy, useInfiniteHits } from "react-instantsearch";
import { Configure, SearchBox, useInfiniteHits } from "react-instantsearch";
import { InstantSearchNext } from "react-instantsearch-nextjs";
import TypesenseInstantSearchAdapter, { type SearchClient } from "typesense-instantsearch-adapter";

import { collectionName } from "@/lib/data";
import type { Publication } from "@/lib/model";

import { InstantSearchSortBy } from "./instantsearch-sortby";
import { InstantSearchStats } from "./instantsearch-stats";
import { PublicationGrid } from "./publication-grid";

// TODO put into props
const sortOptions = ["year:desc", "year:asc", "title:asc"];

interface InstantSearchProps {
queryArgsToRefinementFields: Record<string, string>;
children?: ReactNode;
Expand Down Expand Up @@ -54,8 +52,8 @@ function InfiniteScroll(): ReactNode {
const observer = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting && !isLastPage) {
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
showMore && showMore();
showMore();
// showMore && showMore();
}
});
});
Expand Down Expand Up @@ -145,16 +143,7 @@ export function InstantSearch(props: InstantSearchProps): ReactNode {
<div className="flex place-content-between">
<InstantSearchStats />
<SearchBox placeholder={t("query_placeholder")} />
sort by{" "}
<SortBy
items={sortOptions.map((field) => {
return {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
label: t(`sort.${field}` as MessageKeys<any, any>),
value: `${collectionName}/sort/${field}`,
};
})}
/>
<InstantSearchSortBy sortOptions={["year:desc", "year:asc", "title:asc"]} />
</div>
<InfiniteScroll />
</div>
Expand Down
6 changes: 3 additions & 3 deletions messages/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -90,9 +90,9 @@
"query_placeholder": "search publications",
"sort_by": "sort by",
"sort": {
"year:asc": "oldest to newest",
"year:desc": "newest to oldest",
"title:asc": "publication title"
"title:asc": "alphabetically",
"year:asc": "oldest first",
"year:desc": "newest first"
}
},
"TranslatorPage": {
Expand Down

0 comments on commit bbf4a2b

Please sign in to comment.