From 54d9794d4171c861a85f86af25a430b631983349 Mon Sep 17 00:00:00 2001 From: Yehoshua Sandler Date: Sun, 20 Apr 2025 16:34:16 -0500 Subject: [PATCH] feat: ui for book item --- src/app/(frontend)/[slug]/page.client.tsx | 0 src/app/(frontend)/[slug]/page.tsx | 0 .../(frontend)/books/[bookId]/page.client.tsx | 122 ++++++++++++++++++ src/app/(frontend)/books/[bookId]/page.tsx | 70 ++++++++++ src/components/BookList/index.tsx | 2 - src/components/RichText/index.tsx | 12 ++ src/components/stacked-layout.tsx | 6 +- 7 files changed, 209 insertions(+), 3 deletions(-) delete mode 100644 src/app/(frontend)/[slug]/page.client.tsx delete mode 100644 src/app/(frontend)/[slug]/page.tsx create mode 100644 src/app/(frontend)/books/[bookId]/page.client.tsx create mode 100644 src/app/(frontend)/books/[bookId]/page.tsx create mode 100644 src/components/RichText/index.tsx diff --git a/src/app/(frontend)/[slug]/page.client.tsx b/src/app/(frontend)/[slug]/page.client.tsx deleted file mode 100644 index e69de29..0000000 diff --git a/src/app/(frontend)/[slug]/page.tsx b/src/app/(frontend)/[slug]/page.tsx deleted file mode 100644 index e69de29..0000000 diff --git a/src/app/(frontend)/books/[bookId]/page.client.tsx b/src/app/(frontend)/books/[bookId]/page.client.tsx new file mode 100644 index 0000000..5b1f4a1 --- /dev/null +++ b/src/app/(frontend)/books/[bookId]/page.client.tsx @@ -0,0 +1,122 @@ +'use client' + +import { Book, Genre, Repository } from '@/payload-types' + +import { Combobox, ComboboxLabel, ComboboxOption, ComboboxDescription } from '@/components/combobox' +import { Field, Label } from '@/components/fieldset' +import { PaginatedDocs } from 'payload' +import { Button } from '@/components/ui/button' +import { Badge } from '@/components/ui/badge' + +import { Loader2 } from 'lucide-react' +import { RichText } from '@/components/RichText' + +type DropDownProps = { + currentRepository: Repository + repositories: Repository[] +} +function RepoDropdown({ currentRepository, repositories }: DropDownProps) { + return ( + + +
+ repo?.name} + defaultValue={currentRepository} + className="w" + > + {(repo) => ( + + {repo.abbreviation} + {repo.name} + + )} + + +
+
+ ) +} + +type Props = { + book: Book + repositories: PaginatedDocs +} + +export default function BookByIdPageClient(props: Props) { + const { book, repositories } = props + + const repos = repositories.docs + + return ( +
+ {/* Book */} +
+ {/* Book Cover */} +
+ book cover art +
+ + {/* Book details */} +
+
+
+

+ {book.title} +

+ +

+ Book information +

+

+ {book.publication && ( + + Published:  + + + )} +

+
+
+ +

{book.summary}

+ + + +
+

Genres

+
+
    + {(book.genre as Genre[])?.map((g) => ( + + {g.name} + + ))} +
+
+
+ + {book.description && ( +
+

Description

+ +
+ )} +
+
+
+ ) +} diff --git a/src/app/(frontend)/books/[bookId]/page.tsx b/src/app/(frontend)/books/[bookId]/page.tsx new file mode 100644 index 0000000..cc333f3 --- /dev/null +++ b/src/app/(frontend)/books/[bookId]/page.tsx @@ -0,0 +1,70 @@ +import { Book, Copy, Repository } from '@/payload-types' +import { getPayload, PaginatedDocs } from 'payload' +import configPromise from '@payload-config' +import BookByIdPageClient from './page.client' + +type Params = Promise<{ bookId: string }> +type SearchParams = Promise<{ [key: string]: string | undefined }> + +type Props = { + params: Params + searchParams: SearchParams +} +const BookByIdPage = async (props: Props) => { + const params = await props.params + + const bookIdFromUrl = parseInt(params?.bookId || '', 10) + if (Number.isNaN(bookIdFromUrl)) return null + const bookId = bookIdFromUrl as number + + const payload = await getPayload({ config: configPromise }) + + const defaultRepositoryLimit = 10 + + const foundBook = (await payload.findByID({ + collection: 'books', + depth: 3, + overrideAccess: false, + id: bookId, + select: { + title: true, + authors: true, + publication: true, + lcc: true, + genre: true, + isbn: true, + copies: true, + summary: true, + description: true, + }, + })) as Book + + const repositoryIds = foundBook.copies?.docs?.map((c) => (c as Copy).repository) + + const orQueries = repositoryIds?.map((c) => { + return { + id: { + equals: c, + }, + } + }) + + const repositories = (await payload.find({ + collection: 'repositories', + depth: 3, + limit: defaultRepositoryLimit, + select: { + id: true, + owners: true, + abbreviation: true, + name: true, + }, + where: { + or: orQueries?.length ? orQueries : [], + }, + })) as PaginatedDocs + + return +} + +export default BookByIdPage diff --git a/src/components/BookList/index.tsx b/src/components/BookList/index.tsx index bb59bde..24a4003 100644 --- a/src/components/BookList/index.tsx +++ b/src/components/BookList/index.tsx @@ -50,8 +50,6 @@ export default function BookList(props: Props) { const currentPage = page || 0 const books = docs - console.log(props) - return (
    diff --git a/src/components/RichText/index.tsx b/src/components/RichText/index.tsx new file mode 100644 index 0000000..600cbbd --- /dev/null +++ b/src/components/RichText/index.tsx @@ -0,0 +1,12 @@ +import { DefaultTypedEditorState } from '@payloadcms/richtext-lexical' +import { RichText as RichTextConverter } from '@payloadcms/richtext-lexical/react' + +type Props = { + data: DefaultTypedEditorState +} & React.HTMLAttributes + +export const RichText = (props: Props) => { + const { className, ...rest } = props + + return +} diff --git a/src/components/stacked-layout.tsx b/src/components/stacked-layout.tsx index 5b1c40e..f4d81ff 100644 --- a/src/components/stacked-layout.tsx +++ b/src/components/stacked-layout.tsx @@ -20,7 +20,11 @@ function CloseMenuIcon() { ) } -function MobileSidebar({ open, close, children }: React.PropsWithChildren<{ open: boolean; close: () => void }>) { +function MobileSidebar({ + open, + close, + children, +}: React.PropsWithChildren<{ open: boolean; close: () => void }>) { return (