import { useCallback } from 'react'; import { notifications } from '@mantine/notifications'; import { useTranslation } from 'react-i18next'; import { extractErrorMessage } from '@ema-platform/api'; import { authStorage } from '@ema-platform/auth'; import { API_BASE_URL, pageOptionsFor } from '../config/designer'; interface PreviewArgs { hbsSource: string; licenseTypeId: string | null; landscape: boolean; } /** * Renders the editor's current contents, not the saved row, so unsaved edits * are what you see. Opened as a blob so it never leaves a file behind. */ export function useTemplatePreview() { const { t } = useTranslation(); return useCallback( async ({ hbsSource, licenseTypeId, landscape }: PreviewArgs) => { try { // The preview returns a PDF stream, not JSON, so it bypasses RTK Query // and calls the API directly — which means spelling out the base URL and // the bearer token that the shared baseQuery would normally attach. const token = authStorage.getToken(); const response = await fetch(`${API_BASE_URL}/license-templates/preview`, { method: 'POST', headers: { 'Content-Type': 'application/json', ...(token ? { Authorization: `Bearer ${token}` } : {}), }, body: JSON.stringify({ hbsSource, licenseTypeId, pageOptions: pageOptionsFor(landscape), }), }); if (!response.ok) throw new Error(await response.text()); const url = URL.createObjectURL(await response.blob()); window.open(url, '_blank', 'noopener'); // Give the new tab time to read it before revoking. setTimeout(() => URL.revokeObjectURL(url), 60_000); } catch (err) { notifications.show({ color: 'red', title: t('designer.previewFailed', 'Could not render the preview'), message: extractErrorMessage(err), }); } }, [t], ); }