diff --git a/frontend/app/components/BookCard/BookCard.tsx b/frontend/app/components/BookCard/BookCard.tsx index b6d6e102..34d4f44a 100644 --- a/frontend/app/components/BookCard/BookCard.tsx +++ b/frontend/app/components/BookCard/BookCard.tsx @@ -14,12 +14,13 @@ interface BookCardProps { function BookCard({ book, searchListParams }: BookCardProps) { const [searchParams] = useSearchParams(); const location = useLocation(); + const isProfilePage = location.pathname === "/profile"; const nextSearchParams = new URLSearchParams( searchListParams ?? searchParams, ); - if (location.pathname === "/profile") { + if (isProfilePage) { nextSearchParams.set("origin", "favorites"); } @@ -40,8 +41,18 @@ function BookCard({ book, searchListParams }: BookCardProps) {

{book.authors.join(", ")}

-

{book.publishYear ?? "Unknown"}

-

+

+ {book.publishYear ?? "Year unknown"} +

+

{book.rating == null ? ( "No ratings yet" ) : ( @@ -53,7 +64,8 @@ function BookCard({ book, searchListParams }: BookCardProps) { {book.rating.toFixed(2)} - ({(book.numRatings ?? 0).toLocaleString("en")} ratings) + ({(book.numRatings ?? 0).toLocaleString("en")} + {!isProfilePage && " ratings"}) )}

diff --git a/frontend/app/components/BookCard/__snapshots__/BookCard.test.tsx.snap b/frontend/app/components/BookCard/__snapshots__/BookCard.test.tsx.snap index 62eede47..b05b6a16 100644 --- a/frontend/app/components/BookCard/__snapshots__/BookCard.test.tsx.snap +++ b/frontend/app/components/BookCard/__snapshots__/BookCard.test.tsx.snap @@ -44,7 +44,9 @@ exports[`BookCard > matches the snapshot 1`] = `

Joe Abercrombie

-

+

2001

-

+
{!isPending && session ? ( <> diff --git a/frontend/app/components/books/SearchBar/SearchBar.tsx b/frontend/app/components/books/SearchBar/SearchBar.tsx index 4bfa4fc3..ffacd7c6 100644 --- a/frontend/app/components/books/SearchBar/SearchBar.tsx +++ b/frontend/app/components/books/SearchBar/SearchBar.tsx @@ -69,7 +69,7 @@ function SearchBar({ resultCount }: SearchBarProps) { const filtersDescription = `${filtersCount} ${filtersCount === 1 ? "filter" : "filters"} active`; return ( -
+

Browse books

diff --git a/frontend/app/components/ui/Combobox.tsx b/frontend/app/components/ui/Combobox.tsx index 534a2525..ea40bae7 100644 --- a/frontend/app/components/ui/Combobox.tsx +++ b/frontend/app/components/ui/Combobox.tsx @@ -143,7 +143,7 @@ function ComboboxItem({ - Readr + {`${message === "404" ? "Page not found" : "Error"} | Readr`}

{message}

{details}

{stack && ( diff --git a/frontend/app/routes/book/selectedBook.tsx b/frontend/app/routes/book/selectedBook.tsx index 657b9e17..7095e159 100644 --- a/frontend/app/routes/book/selectedBook.tsx +++ b/frontend/app/routes/book/selectedBook.tsx @@ -33,6 +33,8 @@ export default function SelectedBookPage({ params }: Route.ComponentProps) { const origin = searchParams.get("origin"); const { book, loading, error } = useBook({ id: params.bookId }); + const pageTitle = book ? `${book.title} | Readr` : "Book details | Readr"; + const { books: searchBooks } = useSearchBooks({ filters, title: query, @@ -65,6 +67,8 @@ export default function SelectedBookPage({ params }: Route.ComponentProps) { if (loading) { return (
+ {/* Uses instead of meta() to allow the document title to be defined dynamically in the route. */} + <title>{pageTitle}

Loading Book Details

The requested book details are currently being loaded.

@@ -74,6 +78,8 @@ export default function SelectedBookPage({ params }: Route.ComponentProps) { if (error || !book || !books) { return (
+ {/* Uses instead of meta() to allow the document title to be defined dynamically in the route. */} + <title>{pageTitle}

Book Not Found

The requested book could not be found.

@@ -91,6 +97,8 @@ export default function SelectedBookPage({ params }: Route.ComponentProps) { return (
+ {/* Uses instead of meta() to allow the document title to be defined dynamically in the route. */} + <title>{pageTitle} {origin === "favorites" ? ( -
- +
+ -
- +
+

{book.title}

diff --git a/frontend/app/routes/books.test.tsx b/frontend/app/routes/books.test.tsx index 365f8e8e..7fd5bf97 100644 --- a/frontend/app/routes/books.test.tsx +++ b/frontend/app/routes/books.test.tsx @@ -1,5 +1,5 @@ import { describe, expect, it, vi } from "vitest"; -import { screen } from "@testing-library/react"; +import { screen, within } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; import BooksPage from "~/routes/books"; import SelectedBookPage from "~/routes/book/selectedBook"; @@ -71,9 +71,12 @@ describe("BooksPage", () => { }); expect(await screen.findByText("15 results")).toBeInTheDocument(); - expect(screen.getByRole("link", { current: "page" })).toHaveTextContent( - "2", - ); + expect( + within(screen.getByRole("navigation", { name: "pagination" })).getByRole( + "link", + { current: "page" }, + ), + ).toHaveTextContent("2"); }); it("tells the user when no books match the search", async () => { diff --git a/frontend/app/routes/books.tsx b/frontend/app/routes/books.tsx index c08e3932..d1914315 100644 --- a/frontend/app/routes/books.tsx +++ b/frontend/app/routes/books.tsx @@ -3,6 +3,7 @@ import { useSearchBooks, type SearchBook } from "~/hooks/useSearchBooks"; import { SearchBar } from "~/components/books/SearchBar/SearchBar"; import { BookCard } from "~/components/BookCard/BookCard"; import { SortSelect } from "~/components/books/SortSelect/SortSelect"; +import { PageBreadcrumb } from "~/components/PageBreadcrumb/PageBreadcrumb"; import { useBookSearchParams } from "~/hooks/useBookSearchParams"; import { useSuggestedBooks } from "~/hooks/useSuggestedBooks"; import { useSearchParams } from "react-router"; @@ -33,6 +34,12 @@ function BookList({ ); } +function BooksBreadcrumb() { + return ( + + ); +} + export default function BooksPage() { const [searchParams] = useSearchParams(); const { query, page, filters, sort } = useBookSearchParams(); @@ -69,6 +76,7 @@ export default function BooksPage() { if (loading) { return (
+

+

0) { return (

+
+

+ diff --git a/frontend/app/routes/profile.tsx b/frontend/app/routes/profile.tsx index 905216be..dd86b28b 100644 --- a/frontend/app/routes/profile.tsx +++ b/frontend/app/routes/profile.tsx @@ -8,7 +8,7 @@ import { PageBreadcrumb } from "~/components/PageBreadcrumb/PageBreadcrumb"; import { ReviewList } from "~/components/ReviewList/ReviewList"; import { Avatar, AvatarFallback } from "~/components/ui/Avatar"; import { Badge } from "~/components/ui/Badge"; -import { buttonVariants } from "~/components/ui/Button"; +import { Button, buttonVariants } from "~/components/ui/Button"; import { Card, CardContent, @@ -131,7 +131,7 @@ export default function ProfilePage() {

)} - + Edit profile +