ot / frontend /src /components /preview /PreviewPanel.jsx
jashdoshi77's picture
OT NoteBuilder - Production deployment
ba95018
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>
);
}