From e26fce092a0cb9f36a954851c1a0056ee078d574 Mon Sep 17 00:00:00 2001 From: BOHA Date: Tue, 9 Jun 2026 11:46:50 +0200 Subject: [PATCH] fix(orders): authenticated PDF open in issued-orders list The list opened the PDF route via raw window.open, an unauthenticated top-level navigation that 401s on the token-guarded endpoint. Now uses the apiFetch -> blob -> window pattern from InvoiceDetail/IssuedOrderDetail. Co-Authored-By: Claude Opus 4.8 (1M context) --- src/admin/pages/IssuedOrders.tsx | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/src/admin/pages/IssuedOrders.tsx b/src/admin/pages/IssuedOrders.tsx index 5add6a9..6e5a385 100644 --- a/src/admin/pages/IssuedOrders.tsx +++ b/src/admin/pages/IssuedOrders.tsx @@ -10,6 +10,7 @@ import useTableSort from "../hooks/useTableSort"; import useDebounce from "../hooks/useDebounce"; import { usePaginatedQuery } from "../hooks/usePaginatedQuery"; import { useApiMutation } from "../lib/queries/mutations"; +import apiFetch from "../utils/api"; import { issuedOrderListOptions, type IssuedOrder, @@ -170,6 +171,30 @@ export default function IssuedOrders() { } }; + const handleExportPdf = async (o: IssuedOrder) => { + // Authenticated open: apiFetch attaches the access token, then we hand the + // resulting PDF blob to a window. A raw window.open(url) would be an + // unauthenticated top-level navigation and 401 on the token-guarded route. + const newWindow = window.open("", "_blank"); + try { + const response = await apiFetch( + `${API_BASE}/issued-orders-pdf/${o.id}?lang=cs`, + ); + if (!response.ok) { + newWindow?.close(); + alert.error("Nepodařilo se vygenerovat PDF"); + return; + } + const blob = await response.blob(); + const url = URL.createObjectURL(blob); + if (newWindow) newWindow.location.href = url; + setTimeout(() => URL.revokeObjectURL(url), 60000); + } catch { + newWindow?.close(); + alert.error("Chyba při generování PDF"); + } + }; + if (isPending) { return ; } @@ -256,12 +281,7 @@ export default function IssuedOrders() { {hasPermission("orders.export") && ( - window.open( - `${API_BASE}/issued-orders-pdf/${o.id}?lang=cs`, - "_blank", - ) - } + onClick={() => handleExportPdf(o)} aria-label="PDF" title="PDF" >