diff --git a/web/src/components/RequestToAddSection.test.tsx b/web/src/components/RequestToAddSection.test.tsx index 40255a1a..22002e36 100644 --- a/web/src/components/RequestToAddSection.test.tsx +++ b/web/src/components/RequestToAddSection.test.tsx @@ -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(); + 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( + , + ); + 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(); + expect(markup).toContain("Result 0"); + expect(markup).toContain("Result 19"); + expect(markup).not.toContain("Result 20"); + }); +}); diff --git a/web/src/components/RequestToAddSection.tsx b/web/src/components/RequestToAddSection.tsx index 12e71a3e..6e7492e2 100644 --- a/web/src/components/RequestToAddSection.tsx +++ b/web/src/components/RequestToAddSection.tsx @@ -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 ( + + + + + {libraryHadHits ? "Request to Add" : "Not in your library, but you can request"} + + + + + {items.map((item) => ( + + ))} + + + ); }