diff --git a/README.md b/README.md
index 6ffcdbb..3aad24d 100644
--- a/README.md
+++ b/README.md
@@ -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)
diff --git a/app/languages/[language]/page.tsx b/app/languages/[language]/page.tsx
index 86cef32..6f20a94 100644
--- a/app/languages/[language]/page.tsx
+++ b/app/languages/[language]/page.tsx
@@ -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 ;
+interface LanguagesPageProps {
+ params?: {
+ language: string;
+ };
+}
+
+export default function LanguagesPage(props: LanguagesPageProps) {
+ return (
+
+ );
}
diff --git a/app/languages/page.tsx b/app/languages/page.tsx
new file mode 100644
index 0000000..8696087
--- /dev/null
+++ b/app/languages/page.tsx
@@ -0,0 +1,5 @@
+import LanguagesPage from "./[language]/page";
+
+export default function BlankLanguagesPage() {
+ return ;
+}
diff --git a/app/translators/[id]/page.tsx b/app/translators/[id]/page.tsx
new file mode 100644
index 0000000..14011bc
--- /dev/null
+++ b/app/translators/[id]/page.tsx
@@ -0,0 +1,18 @@
+import { SimpleListing } from "@/components/simple-listing";
+
+interface TranslatorsPageProps {
+ params?: {
+ id: string;
+ };
+}
+
+export default function TranslatorsPage(props: TranslatorsPageProps) {
+ return (
+
+ );
+}
diff --git a/app/translators/page.tsx b/app/translators/page.tsx
index 313609c..fa924f4 100644
--- a/app/translators/page.tsx
+++ b/app/translators/page.tsx
@@ -1,5 +1,5 @@
-import { FacetedListing, type FacetedListingProps } from "@/components/faceted-listing";
+import TranslatorsPage from "./[id]/page";
-export default function TranslatorPage(props: FacetedListingProps) {
- return ;
+export default function BlankTranslatorsPage() {
+ return ;
}
diff --git a/app/works/[...args]/page.tsx b/app/works/[...args]/page.tsx
deleted file mode 100644
index 1cacde7..0000000
--- a/app/works/[...args]/page.tsx
+++ /dev/null
@@ -1,51 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unsafe-member-access */
-/* eslint-disable @typescript-eslint/no-unsafe-assignment */
-"use client";
-import { useTranslations } from "next-intl";
-
-import { AppNavLink } from "@/components/app-nav-link";
-import { MainContent } from "@/components/main-content";
-import { ClickablePublicationThumbnail } from "@/components/publication-cover";
-import { PublicationGrid } from "@/components/publication-grid";
-import { getPublications } from "@/lib/data";
-import { type Category, otherCategories } from "@/lib/model";
-
-interface WorkPageProps {
- params: {
- args: [Category?, string?];
- };
-}
-
-// eslint-disable-next-line @next/next/no-async-client-component
-export default async function WorkPage(props: WorkPageProps) {
- const catt = useTranslations("BernhardCategories");
- const _t = useTranslations("WorkPage");
-
- const category = props.params.args[0];
-
- const publications = await getPublications({ q: "*", filter: { erstpublikation: true } });
-
- return (
-
-
- {otherCategories.map((c) => {
- return (
-
- {catt(c)}
-
- );
- })}
-
-
-
-
- {publications.map((p) => {
- return ;
- })}
-
-
- );
-}
diff --git a/app/works/[category]/[work]/page.tsx b/app/works/[category]/[work]/page.tsx
new file mode 100644
index 0000000..bcccbd2
--- /dev/null
+++ b/app/works/[category]/[work]/page.tsx
@@ -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 (
+ <>
+
+ {otherCategories.map((c) => {
+ return (
+
+ {c}
+
+ );
+ })}
+
+
+ {props.params?.category === "prose" ||
+ (proseCategories as unknown as Array
).includes(
+ props.params?.category as unknown as string,
+ )
+ ? proseCategories.map((c) => {
+ return (
+
+ {c}
+
+ );
+ })
+ : null}
+
+
+ >
+ );
+}
diff --git a/app/works/[category]/page.tsx b/app/works/[category]/page.tsx
new file mode 100644
index 0000000..e4896a2
--- /dev/null
+++ b/app/works/[category]/page.tsx
@@ -0,0 +1,11 @@
+import WorksPage from "./[work]/page";
+
+interface BlankWorksPageProps {
+ params: {
+ category: string;
+ };
+}
+
+export default function BlankWorksPage(props: BlankWorksPageProps) {
+ return ;
+}
diff --git a/components/app-header.tsx b/components/app-header.tsx
index 490bb31..555dd80 100644
--- a/components/app-header.tsx
+++ b/components/app-header.tsx
@@ -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: {
diff --git a/components/bernhard-links.tsx b/components/bernhard-links.tsx
index ee8c9f9..a9372d2 100644
--- a/components/bernhard-links.tsx
+++ b/components/bernhard-links.tsx
@@ -1,4 +1,4 @@
-import type { BernhardWork } from "@/types/model";
+import type { BernhardWork } from "@/lib/model";
interface BernhardWorkProps {
work: BernhardWork;
diff --git a/components/faceted-listing.tsx b/components/faceted-listing.tsx
index 49e5a5a..485f8b3 100644
--- a/components/faceted-listing.tsx
+++ b/components/faceted-listing.tsx
@@ -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;
});
diff --git a/components/instantsearch.tsx b/components/instantsearch.tsx
new file mode 100644
index 0000000..2b1ceec
--- /dev/null
+++ b/components/instantsearch.tsx
@@ -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 (
+
+
+
+ sort by{" "}
+
+
+ {
+ return ;
+ }}
+ />
+
+
+ );
+}
diff --git a/components/publication-cover.tsx b/components/publication-cover.tsx
index 486e5aa..ea1947c 100644
--- a/components/publication-cover.tsx
+++ b/components/publication-cover.tsx
@@ -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";
diff --git a/components/simple-listing.tsx b/components/simple-listing.tsx
new file mode 100644
index 0000000..1f7b9c8
--- /dev/null
+++ b/components/simple-listing.tsx
@@ -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 (
+
+
+ {counts?.map((c) => {
+ return (
+
+
+ {c.value} ({c.count})
+
+
+ );
+ })}
+
+ {props.facetingValue ? : null}
+
+ );
+}
diff --git a/lib/data.ts b/lib/data.ts
index 62a2cc7..def5238 100644
--- a/lib/data.ts
+++ b/lib/data.ts
@@ -3,8 +3,6 @@ import type { SearchResponse } from "typesense/lib/Typesense/Documents";
import type { Publication } from "@/lib/model";
-const perPage = 16;
-
export const client = new Client({
nodes: [
{
@@ -26,35 +24,18 @@ export const collectionName = "thomas-bernhard";
const collection = client.collections(collectionName);
-const searchDefaults = {
- q: "*",
- filter: {} as Partial,
- query_by: "title, contains.title",
- page: 1,
- per_page: 12,
- sort_by: "title:desc", //"_rand:asc", // requires typesense 0.28 !
-};
-
-type SearchArgs = Partial;
-
+// TODO rename 'getcounts' as this is only used in SimpleListing
export async function getFaceted(
- facetFields: Array,
- search = "*",
- page = 1,
- sortAlphabetic = false,
+ facetField: string,
+ filter_by?: string,
): Promise> {
return collection.documents().search({
- q: search,
+ q: "*",
query_by: "*",
- facet_by: facetFields
- .map((name) => {
- return sortAlphabetic ? `${name}(sort_by: _alpha:asc)` : name;
- })
- .join(),
- // filter_by: facetValue && `${facet}: \`${facetValue}\``,
- max_facet_values: 100,
- page: page,
- per_page: perPage,
+ facet_by: `${facetField}(sort_by: _alpha:asc)`,
+ filter_by: filter_by,
+ max_facet_values: 500,
+ per_page: 1, // don't really need the data
}) as unknown as Promise>;
}
@@ -62,6 +43,16 @@ export async function getPublication(id: string) {
return collection.documents(id).retrieve() as Promise;
}
+const searchDefaults = {
+ q: "*",
+ filter: {} as Partial,
+ query_by: "title, contains.title",
+ page: 1,
+ per_page: 12,
+ sort_by: "title:desc", //"_rand:asc", // requires typesense 0.28 !
+};
+
+type SearchArgs = Partial;
export async function getPublications(
args: SearchArgs = searchDefaults,
): Promise> {