feat(slip-preview): render PDFs in an iframe instead of download-only
This commit is contained in:
parent
6df78d8ccd
commit
20d12f46d9
1 changed files with 70 additions and 0 deletions
70
src/components/slip-preview.tsx
Normal file
70
src/components/slip-preview.tsx
Normal 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>
|
||||
);
|
||||
}
|
||||
Loading…
Reference in a new issue