Spaces:
Running
Running
| import { X, Copy, Download } from 'lucide-react'; | |
| import { useForm } from '../../context/FormContext'; | |
| import { getTemplateData } from '../../data/templateData'; | |
| import toast from 'react-hot-toast'; | |
| export default function PreviewPanel({ isOpen, onClose }) { | |
| const { formState } = useForm(); | |
| if (!isOpen) return null; | |
| const buildPreviewText = () => { | |
| const TEMPLATE_SECTIONS = getTemplateData()?.sections || []; | |
| const lines = []; | |
| // Header | |
| lines.push('SNF OCCUPATIONAL THERAPY \u2014 DAILY PROGRESS NOTE'); | |
| lines.push('='.repeat(50)); | |
| const pInfo = formState.patientInfo; | |
| if (pInfo.pt_name) lines.push(`Pt: ${pInfo.pt_name}`); | |
| if (pInfo.dos) lines.push(`DOS: ${pInfo.dos}`); | |
| if (pInfo.dx) lines.push(`Dx: ${pInfo.dx}`); | |
| if (pInfo.precautions) lines.push(`Precautions: ${pInfo.precautions}`); | |
| if (pInfo.visit_number || pInfo.frequency) lines.push(`Visit #: ${pInfo.visit_number || '___'} Freq: ${pInfo.frequency || '___'}`); | |
| if (pInfo.tx_time || pInfo.cpt_codes) lines.push(`Tx Time: ${pInfo.tx_time || '___'} min CPT: ${pInfo.cpt_codes || '___'}`); | |
| lines.push(''); | |
| TEMPLATE_SECTIONS.forEach(section => { | |
| if (formState.enabledSections[section.id] === false) return; | |
| const sectionState = formState.sections[section.id]; | |
| if (!sectionState) return; | |
| let hasContent = false; | |
| const sectionLines = [`\n${'—'.repeat(50)}`, section.title, '—'.repeat(50)]; | |
| section.subsections.forEach(sub => { | |
| sub.fields.forEach(field => { | |
| const val = sectionState[field.id]; | |
| if (!val) return; | |
| if (field.type === 'fill-blank' && val.selected?.length > 0) { | |
| hasContent = true; | |
| let sentence = field.sentence || ''; | |
| sentence = sentence.replace('____________', val.selected.join(' / ')); | |
| sectionLines.push(` ${sentence}`); | |
| } else if (field.type === 'checkbox-group' && val.checked?.length > 0) { | |
| hasContent = true; | |
| sectionLines.push(` ${field.label}:`); | |
| val.checked.forEach(c => sectionLines.push(` \u2611 ${c}`)); | |
| } else if (field.type === 'exercise-list') { | |
| const enabled = []; | |
| Object.entries(val.exercises || {}).forEach(([exId, exState]) => { | |
| if (exState.enabled) { | |
| const ex = field.exercises.find(e => e.id === exId); | |
| if (ex) { | |
| let desc = ex.name; | |
| if (exState.sets && exState.reps) desc += ` \u2014 ${exState.sets} \u00d7 ${exState.reps}`; | |
| else if (exState.minutes) desc += ` \u2014 ${exState.minutes} min`; | |
| else if (exState.seconds) desc += ` \u2014 ${exState.seconds} sec`; | |
| else if (exState.trials) desc += ` \u2014 ${exState.trials} trials`; | |
| enabled.push(desc); | |
| } | |
| } | |
| }); | |
| if (enabled.length > 0) { | |
| hasContent = true; | |
| sectionLines.push(` ${field.label}: ${enabled.join(', ')}`); | |
| } | |
| } else if ((field.type === 'text' || field.type === 'number') && val) { | |
| hasContent = true; | |
| sectionLines.push(` ${field.label}: ${val}`); | |
| } | |
| }); | |
| }); | |
| if (hasContent) { | |
| lines.push(...sectionLines); | |
| } | |
| }); | |
| return lines.join('\n'); | |
| }; | |
| const previewText = buildPreviewText(); | |
| const handleCopy = () => { | |
| navigator.clipboard.writeText(previewText).then(() => { | |
| toast.success('Preview copied to clipboard'); | |
| }); | |
| }; | |
| const handleDownload = () => { | |
| const blob = new Blob([previewText], { type: 'text/plain' }); | |
| const url = URL.createObjectURL(blob); | |
| const a = document.createElement('a'); | |
| a.href = url; | |
| a.download = `OT_Preview_${new Date().toISOString().slice(0, 10)}.txt`; | |
| a.click(); | |
| URL.revokeObjectURL(url); | |
| }; | |
| return ( | |
| <div className="preview-overlay" onClick={onClose}> | |
| <div className="preview-panel" onClick={e => e.stopPropagation()}> | |
| <div className="preview-panel__header"> | |
| <h3 className="preview-panel__title">Template Preview</h3> | |
| <button className="preview-panel__close" onClick={onClose}> | |
| <X size={16} /> | |
| </button> | |
| </div> | |
| <div className="preview-panel__body"> | |
| <pre className="preview-panel__content" style={{ fontFamily: 'var(--font-family)', whiteSpace: 'pre-wrap' }}> | |
| {previewText} | |
| </pre> | |
| </div> | |
| <div className="preview-panel__footer"> | |
| <button className="navbar__btn" onClick={handleCopy}> | |
| <Copy size={16} /> | |
| Copy | |
| </button> | |
| <button className="navbar__btn" onClick={handleDownload}> | |
| <Download size={16} /> | |
| Download | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| ); | |
| } | |