diff --git a/src/app/dashboard/admin/tickets/AdminTicketDetailsClient.tsx b/src/app/dashboard/admin/tickets/AdminTicketDetailsClient.tsx index fe2490d..b2807ad 100644 --- a/src/app/dashboard/admin/tickets/AdminTicketDetailsClient.tsx +++ b/src/app/dashboard/admin/tickets/AdminTicketDetailsClient.tsx @@ -214,12 +214,36 @@ export default function AdminTicketDetailsClient() { {reply.attachments && reply.attachments.length > 0 && (
{reply.attachments.map((att: any) => ( - { + e.preventDefault(); + if (att.download_url) { + try { + const response = await axios.get(att.download_url, { + responseType: 'blob' + }); + const url = window.URL.createObjectURL(new Blob([response.data])); + const link = document.createElement('a'); + link.href = url; + link.setAttribute('download', att.file_name); + document.body.appendChild(link); + link.click(); + link.remove(); + window.URL.revokeObjectURL(url); + } catch (err: any) { + const errorMessage = parseApiError(err, t("toast_download_failed") || "Download failed"); + if (err.response?.status === 404) { + addToast("File not found on server.", "error"); + } else { + addToast(errorMessage, "error"); + } + } + } else { + window.open(getAttachmentUrl(att.file_path), '_blank'); + } + }} + className={`flex items-center gap-2 p-2 rounded-lg text-xs transition-colors text-left ${ isMe ? 'bg-white/10 hover:bg-white/20 text-white' : 'bg-white dark:bg-white/5 hover:bg-gray-50 dark:hover:bg-white/10 text-gray-700 dark:text-gray-300 border border-gray-200 dark:border-gray-700' @@ -227,7 +251,7 @@ export default function AdminTicketDetailsClient() { > {att.file_name} - + ))}
)} diff --git a/src/app/dashboard/support/TicketDetailsClient.tsx b/src/app/dashboard/support/TicketDetailsClient.tsx index 3dad8ac..c07c98c 100644 --- a/src/app/dashboard/support/TicketDetailsClient.tsx +++ b/src/app/dashboard/support/TicketDetailsClient.tsx @@ -224,16 +224,45 @@ export default function TicketDetailsClient() { > {reply.message} - {/* Attachments Display */} + {/* Attachments Display */} {reply.attachments && reply.attachments.length > 0 && (
{reply.attachments.map((att: any) => ( - { + e.preventDefault(); + if (att.download_url) { + try { + // Use axios to fetch with auth headers + const response = await axios.get(att.download_url, { + responseType: 'blob' + }); + + // Create object URL and trigger download + const url = window.URL.createObjectURL(new Blob([response.data])); + const link = document.createElement('a'); + link.href = url; + link.setAttribute('download', att.file_name); + document.body.appendChild(link); + link.click(); + link.remove(); + window.URL.revokeObjectURL(url); + } catch (err: any) { + const errorMessage = parseApiError(err, t("toast_download_failed") || "Download failed"); + // If 404, file might actually be missing + if (err.response?.status === 404) { + addToast("File not found on server.", "error"); + } else { + addToast(errorMessage, "error"); + } + } + } else { + // Fallback for legacy local files + window.open(getAttachmentUrl(att.file_path), '_blank'); + } + }} + className={`flex items-center gap-2 p-2 rounded-lg text-xs transition-colors text-left ${ isMe ? 'bg-white/10 hover:bg-white/20 text-white' : 'bg-white dark:bg-white/5 hover:bg-gray-50 dark:hover:bg-white/10 text-gray-700 dark:text-gray-300 border border-gray-200 dark:border-gray-700' @@ -241,7 +270,7 @@ export default function TicketDetailsClient() { > {att.file_name} - + ))}
)}