diff --git a/dental-server/dental-client/src/pages/GtosPage.jsx b/dental-server/dental-client/src/pages/GtosPage.jsx index 1b65e04..1dfd86f 100644 --- a/dental-server/dental-client/src/pages/GtosPage.jsx +++ b/dental-server/dental-client/src/pages/GtosPage.jsx @@ -59,6 +59,14 @@ function GtoDetailModal({ isOpen, onClose, gto, onUpdated }) { } }, [selectedImage]); + const getExtension = (filename) => { + if (!filename) return 'jpg'; + const parts = filename.split('.'); + if (parts.length < 2) return 'jpg'; + const ext = parts[parts.length - 1].toLowerCase(); + return ext === 'jpeg' ? 'jpg' : ext; + }; + const handleDownload = async (img) => { try { const url = img.filename?.startsWith('http') @@ -67,10 +75,11 @@ function GtoDetailModal({ isOpen, onClose, gto, onUpdated }) { const response = await fetch(url); const blob = await response.blob(); + const ext = getExtension(img.filename); const pName = (img.patient_name || 'paciente').trim().replace(/[\/\\:*?"<>|]/g, '').replace(/\s+/g, '_'); const obs = (img.remark || '').trim().replace(/[\/\\:*?"<>|]/g, '').replace(/\s+/g, '_'); - const fileName = obs ? `${pName}-${obs}.jpg` : `${pName}.jpg`; + const fileName = obs ? `${pName}-${obs}.${ext}` : `${pName}.${ext}`; const a = document.createElement('a'); a.href = URL.createObjectURL(blob); @@ -84,37 +93,61 @@ function GtoDetailModal({ isOpen, onClose, gto, onUpdated }) { } }; - const handleCopy = (img) => { + const handleCopyImage = async (img) => { const url = img.filename?.startsWith('http') ? img.filename : `/uploads/${img.filename}`; - const imageObj = new Image(); - imageObj.crossOrigin = 'anonymous'; - imageObj.onload = () => { - try { - const canvas = document.createElement('canvas'); - canvas.width = imageObj.naturalWidth; - canvas.height = imageObj.naturalHeight; - const ctx = canvas.getContext('2d'); - ctx.drawImage(imageObj, 0, 0); - canvas.toBlob(async (blob) => { - try { - await navigator.clipboard.write([ - new ClipboardItem({ 'image/png': blob }) - ]); - showToast('Imagem copiada para a área de transferência!', 'success'); - } catch (err) { - showToast('Erro ao copiar imagem para área de transferência.', 'error'); - console.error(err); - } - }, 'image/png'); - } catch (e) { - showToast('Erro ao processar imagem para cópia.', 'error'); - console.error(e); - } - }; - imageObj.onerror = () => showToast('Erro ao carregar imagem para cópia.', 'error'); - imageObj.src = url; + + try { + showToast('Processando cópia da imagem...', 'info'); + await navigator.clipboard.write([ + new ClipboardItem({ + 'image/png': new Promise((resolve, reject) => { + const imageObj = new Image(); + imageObj.crossOrigin = 'anonymous'; + imageObj.onload = () => { + try { + const canvas = document.createElement('canvas'); + canvas.width = imageObj.naturalWidth; + canvas.height = imageObj.naturalHeight; + const ctx = canvas.getContext('2d'); + ctx.drawImage(imageObj, 0, 0); + canvas.toBlob((blob) => { + if (blob) { + resolve(blob); + } else { + reject(new Error('Erro ao converter imagem em blob')); + } + }, 'image/png'); + } catch (e) { + reject(e); + } + }; + imageObj.onerror = () => reject(new Error('Erro ao carregar a imagem')); + imageObj.src = url; + }) + }) + ]); + showToast('Imagem copiada para a área de transferência!', 'success'); + } catch (err) { + showToast('Erro ao copiar imagem. Certifique-se de que a página está focada.', 'error'); + console.error(err); + } + }; + + const handleCopyFilename = async (img) => { + try { + const ext = getExtension(img.filename); + const pName = (img.patient_name || 'paciente').trim().replace(/[\/\\:*?"<>|]/g, '').replace(/\s+/g, '_'); + const obs = (img.remark || '').trim().replace(/[\/\\:*?"<>|]/g, '').replace(/\s+/g, '_'); + + const fileName = obs ? `${pName}-${obs}.${ext}` : `${pName}.${ext}`; + + await navigator.clipboard.writeText(fileName); + showToast('Nome do arquivo copiado para a área de transferência!', 'success'); + } catch (err) { + showToast('Erro ao copiar nome do arquivo.', 'error'); + } }; const saveImageRemark = async () => { @@ -329,22 +362,30 @@ function GtoDetailModal({ isOpen, onClose, gto, onUpdated }) { )} -
+
+
diff --git a/dental-server/dental-client/src/pages/ImageDetailsPage.jsx b/dental-server/dental-client/src/pages/ImageDetailsPage.jsx index 8cbd485..da157bf 100644 --- a/dental-server/dental-client/src/pages/ImageDetailsPage.jsx +++ b/dental-server/dental-client/src/pages/ImageDetailsPage.jsx @@ -246,47 +246,54 @@ export default function ImageDetailsPage() { img.src = url; }; - const copyImageToClipboard = () => { + const copyImageToClipboard = async () => { const url = imageUrl; - const img = new Image(); - img.crossOrigin = 'anonymous'; - img.onload = () => { - try { - const w = img.naturalWidth, h = img.naturalHeight; - const deg = totalRotation; - const fH = baseFlipH; - const fV = baseFlipV; - const rad = (deg * Math.PI) / 180; - const cos = Math.abs(Math.cos(rad)), sin = Math.abs(Math.sin(rad)); - const cw = Math.round(w * cos + h * sin); - const ch = Math.round(w * sin + h * cos); - const canvas = document.createElement('canvas'); - canvas.width = cw; canvas.height = ch; - const ctx = canvas.getContext('2d'); - ctx.translate(cw / 2, ch / 2); - ctx.scale(fH ? -1 : 1, fV ? -1 : 1); - ctx.rotate(rad); - ctx.drawImage(img, -w / 2, -h / 2); - canvas.toBlob(async (blob) => { - try { - await navigator.clipboard.write([ - new ClipboardItem({ - 'image/png': blob - }) - ]); - showToast('Imagem copiada para a área de transferência!', 'success'); - } catch (err) { - showToast('Erro ao copiar imagem para clipboard.', 'error'); - console.error(err); - } - }, 'image/png'); - } catch (e) { - showToast('Erro ao processar imagem para cópia.', 'error'); - console.error(e); - } - }; - img.onerror = () => showToast('Erro ao carregar imagem para cópia.', 'error'); - img.src = url; + + try { + showToast('Processando cópia da imagem...', 'info'); + await navigator.clipboard.write([ + new ClipboardItem({ + 'image/png': new Promise((resolve, reject) => { + const img = new Image(); + img.crossOrigin = 'anonymous'; + img.onload = () => { + try { + const w = img.naturalWidth, h = img.naturalHeight; + const deg = totalRotation; + const fH = baseFlipH; + const fV = baseFlipV; + const rad = (deg * Math.PI) / 180; + const cos = Math.abs(Math.cos(rad)), sin = Math.abs(Math.sin(rad)); + const cw = Math.round(w * cos + h * sin); + const ch = Math.round(w * sin + h * cos); + const canvas = document.createElement('canvas'); + canvas.width = cw; canvas.height = ch; + const ctx = canvas.getContext('2d'); + ctx.translate(cw / 2, ch / 2); + ctx.scale(fH ? -1 : 1, fV ? -1 : 1); + ctx.rotate(rad); + ctx.drawImage(img, -w / 2, -h / 2); + canvas.toBlob((blob) => { + if (blob) { + resolve(blob); + } else { + reject(new Error('Erro ao converter canvas em blob')); + } + }, 'image/png'); + } catch (e) { + reject(e); + } + }; + img.onerror = () => reject(new Error('Erro ao carregar imagem para cópia.')); + img.src = url; + }) + }) + ]); + showToast('Imagem copiada para a área de transferência!', 'success'); + } catch (err) { + showToast('Erro ao copiar imagem. Certifique-se de que a página está focada.', 'error'); + console.error(err); + } }; const markGtoSent = async (gtoId, sent) => {