feat(slip-preview): render PDFs in an iframe instead of download-only

This commit is contained in:
DEls 2026-08-26 23:03:41 +02:00
parent 6df78d8ccd
commit 20d12f46d9

View file

@ -0,0 +1,70 @@
"use client";
import { Download, FileImage } from "lucide-react";
import { PB_BASE_URL } from "@/lib/pb";
/**
* Renders a delivery-note slip image or PDF download link.
*
* `filename` is the PB file-store path PocketBase stores on the
* `delivery_notes.slip_image` field — shaped `recordId/collectionId/stored`.
* PB exposes the bytes at
* {PB_BASE_URL}/api/files/<collectionId>/<recordId>/<encoded stored path>
* so we split + reassemble + URL-encode to fetch from the browser.
*
* Shared between the PO detail view (existing) and the "Awaiting PO
* assignment" modal (new). Keep the URL builder consistent with
* api/delivery-notes/[id]/slip/route.ts which uses the same pattern
* server-side.
*/
export function SlipPreview({ filename }: { filename: string }) {
if (!filename) {
return (
<div className="flex items-center justify-center gap-2 rounded-md border border-dashed border-border bg-muted/30 p-6 text-sm text-muted-foreground">
<FileImage className="h-6 w-6" />
<span>No slip uploaded for this delivery note.</span>
</div>
);
}
const parts = filename.split("/");
const recordId = parts[0];
const collectionId = parts[1];
const stored = parts.slice(2).join("/");
const url = `${PB_BASE_URL}/api/files/${collectionId}/${recordId}/${encodeURIComponent(stored)}`;
const isPdf = filename.toLowerCase().endsWith(".pdf");
return (
<div className="space-y-3">
{isPdf ? (
<>
<iframe
src={url}
title="Delivery slip"
className="h-[70vh] w-full rounded-md border border-border bg-white"
/>
<p className="text-xs text-muted-foreground">
<a
href={url}
target="_blank"
rel="noreferrer"
className="inline-flex items-center gap-1.5 text-[#F2B165] hover:underline"
>
<Download className="h-3.5 w-3.5" />
Download PDF slip
</a>
{" · opens in a new tab if the viewer above is blank"}
</p>
</>
) : (
// eslint-disable-next-line @next/next/no-img-element
<img
src={url}
alt="Delivery slip"
className="max-h-[70vh] w-full rounded-md border border-border object-contain"
/>
)}
<p className="text-xs text-muted-foreground">
Stored at <span className="font-mono">{filename}</span>
</p>
</div>
);
}