import { ActionIcon, Button, FileInput, Group, Modal, Stack, Text, Tooltip, } from '@mantine/core'; import { notifications } from '@mantine/notifications'; import { IconFileDollar, IconUpload } from '@tabler/icons-react'; import axios from 'axios'; import { useMemo, useState } from 'react'; type InvoicePdfButtonProps = { invoiceId: number; invoiceNo?: string | null; display?: 'icon' | 'button'; label?: string; }; type InvoicePdfUploadResponse = { message?: string; pdf_url?: string; }; export default function InvoicePdfButton({ invoiceId, invoiceNo, display = 'icon', label = 'View Invoice', }: InvoicePdfButtonProps) { const [opened, setOpened] = useState(false); const [file, setFile] = useState(null); const [checking, setChecking] = useState(false); const [uploading, setUploading] = useState(false); const [error, setError] = useState(null); const urls = useMemo( () => ({ view: route('client-invoices.getPdfInvoice', { id: invoiceId }), upload: route('client-invoices.pdf.upload', { invoice: invoiceId, }), }), [invoiceId], ); const openInvoice = (url = urls.view) => { window.open(url, '_blank', 'noopener,noreferrer'); }; const handleView = async () => { setChecking(true); setError(null); try { const response = await axios.get(urls.view, { responseType: 'blob', validateStatus: (status) => (status >= 200 && status < 300) || status === 404, }); if (response.status === 404) { setOpened(true); return; } const blobUrl = URL.createObjectURL(response.data); openInvoice(blobUrl); window.setTimeout(() => URL.revokeObjectURL(blobUrl), 60_000); } catch { notifications.show({ title: 'Unable to open invoice', message: 'Please try again later.', color: 'red', }); } finally { setChecking(false); } }; const handleUpload = async () => { if (!file) { setError('Select a PDF invoice to upload.'); return; } setUploading(true); setError(null); const formData = new FormData(); formData.append('invoice_pdf', file); try { const response = await axios.post( urls.upload, formData, { headers: { 'Content-Type': 'multipart/form-data' }, }, ); notifications.show({ title: 'Invoice uploaded', message: response.data.message ?? 'Invoice uploaded successfully.', color: 'green', }); setOpened(false); setFile(null); } catch (caught) { if (axios.isAxiosError(caught) && caught.response?.status === 422) { setError('Upload a valid PDF file up to 20 MB.'); return; } setError('The invoice could not be uploaded. Please try again.'); } finally { setUploading(false); } }; const button = display === 'button' ? ( ) : ( ); return ( <> {button} setOpened(false)} title="Upload invoice" centered > {invoiceNo ? `Invoice ${invoiceNo} is not available yet. Upload the PDF to view it.` : 'This invoice PDF is not available yet. Upload the PDF to view it.'} } value={file} onChange={(value) => { setFile(value); setError(null); }} error={error} /> ); }