Download src/hooks/use-note-export.ts from Vrda/clinicpal: direct link, hf CLI and curl.
- Browser
- Download file 4.93 kB
-
https://huggingface.co/spaces/Vrda/clinicpal/resolve/main/src/hooks/use-note-export.ts
- Command line
-
hf download hf://spaces/Vrda/clinicpal/src/hooks/use-note-export.ts
-
curl -L -o use-note-export.ts https://huggingface.co/spaces/Vrda/clinicpal/resolve/main/src/hooks/use-note-export.ts
4.93 kB
| 'use client'; | |
| import { useCallback } from 'react'; | |
| export type NoteExportFormat = 'pdf' | 'docx' | 'txt'; | |
| export function useNoteExport() { | |
| // Export to plain text | |
| const exportToText = useCallback((noteText: string): void => { | |
| downloadFile( | |
| noteText, | |
| `clinical-note-${new Date().toISOString().split('T')[0]}.txt`, | |
| 'text/plain' | |
| ); | |
| }, []); | |
| // Export to PDF (using print dialog) | |
| const exportToPDF = useCallback((noteText: string): void => { | |
| const printWindow = window.open('', '', 'width=800,height=600'); | |
| if (!printWindow) { | |
| alert('Please allow popups to export to PDF'); | |
| return; | |
| } | |
| const html = generatePrintHTML(noteText); | |
| printWindow.document.write(html); | |
| printWindow.document.close(); | |
| printWindow.onload = () => { | |
| printWindow.focus(); | |
| printWindow.print(); | |
| }; | |
| }, []); | |
| // Export to DOCX (using docx library) | |
| const exportToDocx = useCallback(async (noteText: string): Promise<void> => { | |
| const { Document, Packer, Paragraph, TextRun, AlignmentType } = await import('docx'); | |
| // Split text into paragraphs | |
| const paragraphs = noteText.split('\n').map(line => | |
| new Paragraph({ | |
| children: [ | |
| new TextRun({ | |
| text: line || ' ', // Add space for empty lines to preserve spacing | |
| font: 'Arial', | |
| size: 22, // 11pt in half-points | |
| }), | |
| ], | |
| spacing: { | |
| after: 200, // spacing after paragraph | |
| }, | |
| }) | |
| ); | |
| // Create document with header | |
| const doc = new Document({ | |
| sections: [{ | |
| properties: {}, | |
| children: [ | |
| new Paragraph({ | |
| children: [ | |
| new TextRun({ | |
| text: 'Clinical Note', | |
| bold: true, | |
| font: 'Arial', | |
| size: 28, // 14pt in half-points | |
| }), | |
| ], | |
| alignment: AlignmentType.CENTER, | |
| spacing: { | |
| after: 400, | |
| }, | |
| }), | |
| ...paragraphs, | |
| ], | |
| }], | |
| }); | |
| // Generate and download | |
| const blob = await Packer.toBlob(doc); | |
| const url = URL.createObjectURL(blob); | |
| const link = document.createElement('a'); | |
| link.href = url; | |
| link.download = `clinical-note-${new Date().toISOString().split('T')[0]}.docx`; | |
| document.body.appendChild(link); | |
| link.click(); | |
| document.body.removeChild(link); | |
| URL.revokeObjectURL(url); | |
| }, []); | |
| // Main export function | |
| const exportNote = useCallback( | |
| async (format: NoteExportFormat, noteText: string) => { | |
| if (!noteText.trim()) { | |
| return; | |
| } | |
| switch (format) { | |
| case 'txt': | |
| exportToText(noteText); | |
| break; | |
| case 'pdf': | |
| exportToPDF(noteText); | |
| break; | |
| case 'docx': | |
| await exportToDocx(noteText); | |
| break; | |
| } | |
| }, | |
| [exportToText, exportToPDF, exportToDocx] | |
| ); | |
| return { exportNote }; | |
| } | |
| // Utility function to download file | |
| function downloadFile(content: string, filename: string, mimeType: string) { | |
| const blob = new Blob([content], { type: mimeType }); | |
| const url = URL.createObjectURL(blob); | |
| const link = document.createElement('a'); | |
| link.href = url; | |
| link.download = filename; | |
| document.body.appendChild(link); | |
| link.click(); | |
| document.body.removeChild(link); | |
| URL.revokeObjectURL(url); | |
| } | |
| // Generate print-friendly HTML for PDF export | |
| function generatePrintHTML(noteText: string): string { | |
| return ` | |
| <!DOCTYPE html> | |
| <html> | |
| <head> | |
| <meta charset="utf-8"> | |
| <title>Clinical Note</title> | |
| <style> | |
| * { margin: 0; padding: 0; box-sizing: border-box; } | |
| @page { | |
| size: letter; | |
| margin: 1in; | |
| } | |
| body { | |
| font-family: Arial, Helvetica, sans-serif; | |
| line-height: 1.6; | |
| color: #000; | |
| padding: 2rem; | |
| max-width: 8.5in; | |
| margin: 0 auto; | |
| } | |
| .header { | |
| text-align: center; | |
| font-size: 14pt; | |
| font-weight: bold; | |
| color: #000; | |
| margin-bottom: 2rem; | |
| padding-bottom: 1rem; | |
| border-bottom: 2px solid #ccc; | |
| } | |
| .note-content { | |
| white-space: pre-wrap; | |
| word-wrap: break-word; | |
| font-family: Arial, Helvetica, sans-serif; | |
| font-size: 11pt; | |
| line-height: 1.6; | |
| } | |
| .footer { | |
| margin-top: 3rem; | |
| padding-top: 1rem; | |
| border-top: 1px solid #e5e7eb; | |
| text-align: center; | |
| color: #9ca3af; | |
| font-size: 0.875rem; | |
| } | |
| @media print { | |
| body { padding: 0; } | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="header">Clinical Note</div> | |
| <div class="note-content">${escapeHtml(noteText)}</div> | |
| <div class="footer"> | |
| Generated on ${new Date().toLocaleDateString()} • Clinical Error Detector | |
| </div> | |
| </body> | |
| </html> | |
| `; | |
| } | |
| function escapeHtml(text: string): string { | |
| const div = document.createElement('div'); | |
| div.textContent = text; | |
| return div.innerHTML; | |
| } | |