feat(search): add RequestToAddSection grid variant for Catalog page
This commit is contained in:
@@ -194,3 +194,63 @@ describe("RequestToAddSection (dialog variant)", () => {
|
||||
expect(markup).toMatch(/title="[^"]+"/);
|
||||
});
|
||||
});
|
||||
|
||||
describe("RequestToAddSection (grid variant)", () => {
|
||||
beforeEach(() => {
|
||||
mocks.useCanRequest.mockReset();
|
||||
mocks.useRequestSearch.mockReset();
|
||||
mocks.useCanRequest.mockReturnValue({ discoveryEnabled: true, submitDisabledReason: null });
|
||||
});
|
||||
|
||||
it("renders a card per result with the Request to Add header when library had hits", () => {
|
||||
mocks.useRequestSearch.mockReturnValue({
|
||||
data: {
|
||||
page: 1,
|
||||
total_pages: 1,
|
||||
total_results: 2,
|
||||
results: [
|
||||
missingResult({ tmdb_id: 1, title: "Dune: Prophecy" }),
|
||||
missingResult({ tmdb_id: 2, title: "Dune (1984)" }),
|
||||
],
|
||||
},
|
||||
isLoading: false,
|
||||
isError: false,
|
||||
});
|
||||
const markup = render(<RequestToAddSection variant="grid" query="dune" libraryHadHits />);
|
||||
expect(markup).toContain("Request to Add");
|
||||
expect(markup).toContain("Dune: Prophecy");
|
||||
expect(markup).toContain("Dune (1984)");
|
||||
});
|
||||
|
||||
it("renders the soft framing in the grid variant when library had 0 hits", () => {
|
||||
mocks.useRequestSearch.mockReturnValue({
|
||||
data: {
|
||||
page: 1,
|
||||
total_pages: 1,
|
||||
total_results: 1,
|
||||
results: [missingResult({ tmdb_id: 1, title: "Dune: Prophecy" })],
|
||||
},
|
||||
isLoading: false,
|
||||
isError: false,
|
||||
});
|
||||
const markup = render(
|
||||
<RequestToAddSection variant="grid" query="dune" libraryHadHits={false} />,
|
||||
);
|
||||
expect(markup).toContain("Not in your library, but you can request");
|
||||
});
|
||||
|
||||
it("limits the grid to at most 20 cards", () => {
|
||||
const many = Array.from({ length: 30 }, (_, i) =>
|
||||
missingResult({ tmdb_id: i + 100, title: `Result ${i}` }),
|
||||
);
|
||||
mocks.useRequestSearch.mockReturnValue({
|
||||
data: { page: 1, total_pages: 1, total_results: many.length, results: many },
|
||||
isLoading: false,
|
||||
isError: false,
|
||||
});
|
||||
const markup = render(<RequestToAddSection variant="grid" query="dune" libraryHadHits />);
|
||||
expect(markup).toContain("Result 0");
|
||||
expect(markup).toContain("Result 19");
|
||||
expect(markup).not.toContain("Result 20");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -5,6 +5,7 @@ import { useRequestSearch } from "@/hooks/queries/useRequests";
|
||||
import type { RequestMediaResult } from "@/api/types";
|
||||
import { formatRequestReason, tmdbImageURL } from "@/lib/mediaRequests";
|
||||
import { cn } from "@/lib/utils";
|
||||
import RequestPosterCard from "./RequestPosterCard";
|
||||
|
||||
const DIALOG_LIMIT = 4;
|
||||
const GRID_LIMIT = 20;
|
||||
@@ -130,11 +131,31 @@ function DialogRow({ item }: { item: RequestMediaResult }) {
|
||||
}
|
||||
|
||||
function GridVariant({
|
||||
items: _items,
|
||||
libraryHadHits: _libraryHadHits,
|
||||
items,
|
||||
libraryHadHits,
|
||||
}: {
|
||||
items: RequestMediaResult[];
|
||||
libraryHadHits: boolean;
|
||||
}) {
|
||||
return null;
|
||||
return (
|
||||
<section className="space-y-3">
|
||||
<div className="flex items-center gap-3 text-amber-300/85">
|
||||
<div className="h-px flex-1 bg-amber-400/20" />
|
||||
<h2 className="text-[11px] font-semibold tracking-[0.12em] uppercase">
|
||||
{libraryHadHits ? "Request to Add" : "Not in your library, but you can request"}
|
||||
</h2>
|
||||
<div className="h-px flex-1 bg-amber-400/20" />
|
||||
</div>
|
||||
<div className="grid grid-cols-3 gap-3 sm:grid-cols-4 md:grid-cols-5 lg:grid-cols-7 xl:grid-cols-8">
|
||||
{items.map((item) => (
|
||||
<RequestPosterCard
|
||||
key={`${item.media_type}-${item.tmdb_id}`}
|
||||
variant="discover"
|
||||
item={item}
|
||||
fluid
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user