Skip to content

Commit

Permalink
improvement: switch all pages to SimpleListing
Browse files Browse the repository at this point in the history
  • Loading branch information
kevinstadler committed Sep 14, 2024
1 parent 1833e78 commit c71ca06
Show file tree
Hide file tree
Showing 15 changed files with 252 additions and 89 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@

bugs / open questions

- [ ] how should languages be encoded in urls (queries with special characters like `portuguese (brazil)` are currently also broken/unreliable)
- [ ] how should languages be encoded in urls (queries with special characters like
`portuguese (brazil)` are currently also broken/unreliable)
18 changes: 15 additions & 3 deletions app/languages/[language]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
import { FacetedListing, type FacetedListingProps } from "@/components/faceted-listing";
import { SimpleListing } from "@/components/simple-listing";

export default function LanguagesPage(props: FacetedListingProps) {
return <FacetedListing facet="language" searchParams={props.searchParams} />;
interface LanguagesPageProps {
params?: {
language: string;
};
}

export default function LanguagesPage(props: LanguagesPageProps) {
return (
<SimpleListing
facetingField="language"
facetingValue={props.params?.language}
path="languages"
/>
);
}
5 changes: 5 additions & 0 deletions app/languages/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import LanguagesPage from "./[language]/page";

export default function BlankLanguagesPage() {
return <LanguagesPage />;
}
18 changes: 18 additions & 0 deletions app/translators/[id]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { SimpleListing } from "@/components/simple-listing";

interface TranslatorsPageProps {
params?: {
id: string;
};
}

export default function TranslatorsPage(props: TranslatorsPageProps) {
return (
<SimpleListing
facetingField="contains.translators.name"
// FIXME ugly
facetingValue={props.params ? decodeURI(props.params.id) : undefined}
path="translators"
/>
);
}
6 changes: 3 additions & 3 deletions app/translators/page.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { FacetedListing, type FacetedListingProps } from "@/components/faceted-listing";
import TranslatorsPage from "./[id]/page";

export default function TranslatorPage(props: FacetedListingProps) {
return <FacetedListing facet="contains.translators.name" searchParams={props.searchParams} />;
export default function BlankTranslatorsPage() {
return <TranslatorsPage />;
}
51 changes: 0 additions & 51 deletions app/works/[...args]/page.tsx

This file was deleted.

56 changes: 56 additions & 0 deletions app/works/[category]/[work]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// import { useTranslations } from "next-intl";

import { AppNavLink } from "@/components/app-nav-link";
import { SimpleListing } from "@/components/simple-listing";
import { otherCategories, proseCategories } from "@/lib/model";

interface WorksPageProps {
params?: {
category: string;
work?: string;
};
}

export default function WorksPage(props: WorksPageProps) {
// const catt = useTranslations("BernhardCategories");
// const _t = useTranslations("WorkPage");
// const catt = (x) => {
// return x;
// };
return (
<>
<div className="flex justify-center">
{otherCategories.map((c) => {
return (
<AppNavLink key={c} className="p-4" href={`/works/${c}`}>
{c}
</AppNavLink>
);
})}
</div>
<div className="flex justify-center">
{props.params?.category === "prose" ||
(proseCategories as unknown as Array<string>).includes(
props.params?.category as unknown as string,
)
? proseCategories.map((c) => {
return (
<AppNavLink key={c} className="p-4" href={`/works/${c}`}>
{c}
</AppNavLink>
);
})
: null}
</div>
<SimpleListing
facetingField="contains.work.title"
// FIXME ugly
facetingValue={props.params?.work ? decodeURI(props.params.work) : undefined}
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
filter_by={`categories := ${props.params?.category}`}
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
path={`works/${props.params?.category}`}
/>
</>
);
}
11 changes: 11 additions & 0 deletions app/works/[category]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import WorksPage from "./[work]/page";

interface BlankWorksPageProps {
params: {
category: string;
};
}

export default function BlankWorksPage(props: BlankWorksPageProps) {
return <WorksPage params={props.params} />;
}
2 changes: 1 addition & 1 deletion components/app-header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export function AppHeader(): ReactNode {
const links = {
home: { href: createHref({ pathname: "/" }), label: t("links.home") },
works: {
href: createHref({ pathname: "/works/drama" }),
href: createHref({ pathname: "/works/poetry" }),
label: t("links.works"),
},
languages: {
Expand Down
2 changes: 1 addition & 1 deletion components/bernhard-links.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { BernhardWork } from "@/types/model";
import type { BernhardWork } from "@/lib/model";

interface BernhardWorkProps {
work: BernhardWork;
Expand Down
2 changes: 1 addition & 1 deletion components/faceted-listing.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export async function FacetedListing(props: FacetedListingProps) {
facetValue: searchParams.get(props.facet),
});

const data = await getFaceted([props.facet], safeParams.facetValue, safeParams.page);
const data = await getFaceted(props.facet, safeParams.facetValue);
const publications = data.hits?.map((h) => {
return h.document;
});
Expand Down
87 changes: 87 additions & 0 deletions components/instantsearch.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
"use client";

import type { ReactNode } from "react";
import { Configure, Hits, Pagination, SortBy, Stats } from "react-instantsearch";
import { InstantSearchNext } from "react-instantsearch-nextjs";
import TypesenseInstantSearchAdapter, { type SearchClient } from "typesense-instantsearch-adapter";

import { ClickablePublicationThumbnail } from "@/components/publication-cover";
import { collectionName } from "@/lib/data";
import type { Publication } from "@/lib/model";

import type { SimpleListingProps } from "./simple-listing";

interface InstantSearchProps {
faceting: SimpleListingProps;
// children: ReactNode;
}

const typesenseInstantsearchAdapter = new TypesenseInstantSearchAdapter({
server: {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
apiKey: process.env.NEXT_PUBLIC_TYPESENSE_API_KEY!,
nodes: [
{
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
host: process.env.NEXT_PUBLIC_TYPESENSE_HOST!,
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
port: Number(process.env.NEXT_PUBLIC_TYPESENSE_PORT!),
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
protocol: process.env.NEXT_PUBLIC_TYPESENSE_PROTOCOL!,
},
],
},
additionalSearchParameters: {
query_by: "title",
},
});

// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const searchClient = typesenseInstantsearchAdapter.searchClient as unknown as SearchClient;

export function InstantSearch(props: InstantSearchProps): ReactNode {
// const { children } = props;
return (
<InstantSearchNext
indexName={collectionName}
routing={true} // TODO encode just page and sort nicely
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
searchClient={searchClient}
>
<Configure
// when the facetingValue is undefined the search will return nothing, which is fine
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
filters={`${props.faceting.facetingField} := ${props.faceting.facetingValue}`}
hitsPerPage={12}
/>
<div className="flex">
sort by{" "}
<SortBy
items={[
{ label: "title", value: "title" },
{ label: "year", value: "year" },
]}
/>
</div>
<Hits
classNames={{
list: "m-2 grid grid-cols-1 md:grid-cols-4",
}}
hitComponent={({ hit }) => {
return <ClickablePublicationThumbnail publication={hit as unknown as Publication} />;
}}
/>
<div className="flex place-content-between">
<Stats />
<Pagination
classNames={{
root: "float-right",
list: "flex gap-1",
noRefinementRoot: "hidden",
selectedItem: "font-bold",
}}
/>
</div>
</InstantSearchNext>
);
}
2 changes: 1 addition & 1 deletion components/publication-cover.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import Image from "next/image";
import { useTranslations } from "next-intl";
import type { ReactNode } from "react";

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

import { AppLink } from "./app-link";

Expand Down
33 changes: 33 additions & 0 deletions components/simple-listing.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { getFaceted } from "@/lib/data";

import { AppNavLink } from "./app-nav-link";
import { InstantSearch } from "./instantsearch";
import { MainContent } from "./main-content";

export interface SimpleListingProps {
path: string;
filter_by?: string;
facetingField: string;
facetingValue?: string;
}

export async function SimpleListing(props: SimpleListingProps) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const counts = (await getFaceted(props.facetingField, props.filter_by)).facet_counts?.[0]!.counts;
return (
<MainContent>
<div>
{counts?.map((c) => {
return (
<li key={c.value}>
<AppNavLink href={`/${props.path}/${c.value}`}>
{c.value} ({c.count})
</AppNavLink>
</li>
);
})}
</div>
<div>{props.facetingValue ? <InstantSearch faceting={props} /> : null}</div>
</MainContent>
);
}
Loading

0 comments on commit c71ca06

Please sign in to comment.