Skip to content

Commit

Permalink
refactor: specify sort options and their icons in the InstantSearchView
Browse files Browse the repository at this point in the history
  • Loading branch information
kevinstadler committed Jan 7, 2025
1 parent c1365e1 commit 127dd30
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 31 deletions.
12 changes: 9 additions & 3 deletions components/instantsearch-view.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,20 @@ interface InstantSearchViewProps extends Partial<ThomasBernhardInstantSearchProv
refinementDropdowns?: Record<string, string>;
}

const sortOptions = {
"year:desc": CalendarArrowUp,

Check failure on line 24 in components/instantsearch-view.tsx

View workflow job for this annotation

GitHub Actions / Validate (22.x, ubuntu-latest)

Unsafe assignment of an error typed value
"year:asc": CalendarArrowDown,

Check failure on line 25 in components/instantsearch-view.tsx

View workflow job for this annotation

GitHub Actions / Validate (22.x, ubuntu-latest)

Unsafe assignment of an error typed value
"title:asc": ArrowDownAZ,

Check failure on line 26 in components/instantsearch-view.tsx

View workflow job for this annotation

GitHub Actions / Validate (22.x, ubuntu-latest)

Unsafe assignment of an error typed value
};

export function InstantSearchView(props: InstantSearchViewProps): ReactNode {
const t = useTranslations("InstantSearch");

// TODO encode current state in URL
// TODO encode current view state in URL
const [view, setView] = useState<"covers" | "detail">("covers");

return (
<ThomasBernhardInstantSearchProvider {...props}>
<ThomasBernhardInstantSearchProvider defaultSort={Object.keys(sortOptions)[0]} {...props}>
<div className="grid h-full grid-cols-[12rem_1fr] gap-6 px-2">
<div className="relative h-full">{props.children}</div>
<div className="h-full">
Expand All @@ -47,7 +53,7 @@ export function InstantSearchView(props: InstantSearchViewProps): ReactNode {
);
})
: null}
<InstantSearchSortBy sortOptions={["year:asc", "year:desc", "title:asc"]} />
<InstantSearchSortBy sortOptions={sortOptions} />
<Switch
isSelected={view === "detail"}
onChange={(isSelected) => {
Expand Down
40 changes: 12 additions & 28 deletions components/instantsearch/sortby.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ArrowDownAZ, ArrowDownUp, CalendarArrowDown, CalendarArrowUp } from "lucide-react";
import { ArrowUpDown, type LucideIcon } from "lucide-react";
import { type MessageKeys, useTranslations } from "next-intl";
import type { ReactNode } from "react";
import { Label } from "react-aria-components";
Expand All @@ -9,27 +9,13 @@ import { collectionName } from "@/lib/data";
import { Select, SelectContent, SelectItem, SelectPopover, SelectTrigger } from "../ui/select";

interface InstantSearchSortByProps {
sortOptions: Array<string>;
}

function SortIcon(props: { field: string | undefined; size: number }): ReactNode {
switch (props.field?.split("/")[2]) {
case "year:desc":
return <CalendarArrowUp size={props.size} />; // alternatively: ClockArrow?
case "year:asc":
return <CalendarArrowDown size={props.size} />;
case "title:asc":
return <ArrowDownAZ size={props.size} />;
case undefined:
default:
return <ArrowDownUp size={props.size} />;
}
sortOptions: Record<string, LucideIcon>;
}

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

const sortByItems = props.sortOptions.map((field) => {
const sortByItems = Object.keys(props.sortOptions).map((field) => {
return {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
label: t(`sort.${field}` as MessageKeys<any, any>),
Expand All @@ -40,6 +26,12 @@ export function InstantSearchSortBy(props: InstantSearchSortByProps): ReactNode
const { currentRefinement, options, refine } = useSortBy({
items: sortByItems,
});

const getIcon = (value: string): LucideIcon => {
return props.sortOptions[value.split("/")[2]!] ?? ArrowUpDown;
};

const SelectedIcon = getIcon(currentRefinement);
return (
<Select
defaultSelectedKey={currentRefinement}
Expand All @@ -49,23 +41,15 @@ export function InstantSearchSortBy(props: InstantSearchSortByProps): ReactNode
>
<Label className="sr-only">sort order</Label>
<SelectTrigger>
{
<SortIcon
field={
sortByItems.find(({ value }) => {
return value === currentRefinement;
})?.value
}
size={20}
/>
}
<SelectedIcon size={20} />
</SelectTrigger>
<SelectPopover className="w-fit">
<SelectContent>
{options.map((o) => {
const Icon = getIcon(o.value);
return (
<SelectItem key={o.value} className="gap-2" id={o.value} textValue={o.label}>
<SortIcon field={o.value} size={20} />
<Icon size={20} />
<span>{o.label}</span>
</SelectItem>
);
Expand Down

0 comments on commit 127dd30

Please sign in to comment.