+
+
+ {!isMobile ? (
+
+ ) : null}
+
+ {filename}
+
+ {!isMobile ? (
+
+ Viewing
+
+ ) : null}
+
+
+ {/* Zoom controls — grouped so the visual unit is
+ obvious. `icon-sm` is 32px (a comfortable touch
+ target on mobile) and the surrounding gap of 0.5
+ keeps the cluster compact enough to fit on a
+ 360px-wide phone header. */}
+
+
+
+
+
+
+
+
+
+
+ {/* PDF area. The wrapper is sized to `${zoom * 100}% × zoom
+ * 100%` so scrollbars appear at the right zoom levels.
+ The iframe's CSS box is pre-shrunk to `${100 / zoom}%`
+ (so its layout footprint matches the wrapper) and
+ scaled back via `transform: scale(zoom)`. This is the
+ only reliable way to zoom a PDF iframe — resizing the
+ iframe's CSS dimensions alone doesn't work because the
+ browser's PDF viewer caches the initial render size. */}
+
+
+ );
+}
+
+export default InvoiceViewer;
diff --git a/src/components/collection-confirm/photo-strip.test.tsx b/src/components/collection-confirm/photo-strip.test.tsx
index 4330930..804bbe3 100644
--- a/src/components/collection-confirm/photo-strip.test.tsx
+++ b/src/components/collection-confirm/photo-strip.test.tsx
@@ -46,19 +46,56 @@ describe("PhotoStrip", () => {
expect(screen.getByText(/Attach dialog/i)).toBeInTheDocument();
});
- it("opens the file from its first row in a new tab", async () => {
- const user = userEvent.setup();
- const openSpy = vi.spyOn(window, "open").mockImplementation(() => null);
+ it("calls onOpen with the attachment when a chip is clicked (page-level toggle path)", async () => {
+ const onOpen = vi.fn();
const rows: ConfirmRow[] = [
{ id: "row/one", order_item_attachements: ["invoice copy.pdf"] },
{ id: "row-2", order_item_attachements: ["invoice copy.pdf"] },
];
- render(