Questions Addressed:
${formatList(data.questions)}
SUMMARY OF OPINION:
${escapeHTML(data.summaryOpinion)}
DAUBERT CHECKLIST (Reliability Assessment)
${DaubertChecklistHTML}
`;
};
const downloadTxt = () => {
const data = getReportData();
let content = `EXPERT WITNESS REPORT OUTLINE\n`;
content += `Case: ${data.caseName} | Jurisdiction: ${data.jurisdiction}\n`;
content += "========================================\n\n";
content += `I. INTRODUCTION AND QUALIFICATIONS\n`;
content += `Expert: ${data.expertName}\n`;
content += `Area of Expertise: ${data.field}\n\n`;
content += `II. FACTS AND DATA CONSIDERED\n`;
data.factsData.split('\n').filter(l => l.trim().length > 0).forEach(l => content += ` - ${l.trim()}\n`);
content += `\nIII. METHODOLOGY AND PRINCIPLES\n`;
content += `Method: ${data.methodology}\n\n`;
content += `IV. QUESTIONS PRESENTED & OPINION\n`;
content += `Questions:\n`;
data.questions.split('\n').filter(l => l.trim().length > 0).forEach(l => content += ` - ${l.trim()}\n`);
content += `\nSUMMARY OF OPINION:\n${data.summaryOpinion}\n\n`;
content += `========================================\n`;
content += `DAUBERT CHECKLIST (Reliability Assessment)\n`;
content += `========================================\n`;
content += `1. Has the theory/technique been Tested?\nRESPONSE: ${data.tested}\n\n`;
content += `2. Peer Review and Publication?\nRESPONSE: ${data.peer}\n\n`;
content += `3. Known or potential Rate of Error?\nRESPONSE: ${data.error}\n\n`;
content += `4. General Acceptance in the relevant community?\nRESPONSE: ${data.acceptance}\n\n`;
content += `5. Prepared for Litigation or developed independently?\nRESPONSE: ${data.litigation}\n\n`;
const blob = new Blob([content], { type: 'text/plain;charset=utf-8' });
const a = document.createElement('a');
a.href = URL.createObjectURL(blob);
a.download = `${data.caseName.replace(/ /g, '_')}_expert_report.txt`;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(a.href);
};
const downloadPDF = () => {
if (typeof window.jspdf === 'undefined' || typeof window.jspdf.jsPDF === 'undefined') {
alert('Error: jsPDF library not loaded.');
return;
}
const { jsPDF } = window.jspdf;
const doc = new jsPDF('p', 'mm', 'a4');
const data = getReportData();
const margin = 15;
const pageWidth = doc.internal.pageSize.getWidth();
const usableWidth = pageWidth - margin * 2;
let yPos = 20;
const addWrappedText = (text, size, style, color = [52, 73, 94], align = 'left', indent = 0) => {
doc.setFontSize(size);
doc.setFont(undefined, style);
doc.setTextColor(color[0], color[1], color[2]);
const splitText = doc.splitTextToSize(text, usableWidth - indent);
if (yPos + (splitText.length * 5) > 280) { doc.addPage(); yPos = 20; }
doc.text(splitText, margin + indent, yPos);
yPos += (splitText.length * 5) + 3;
};
const addSectionHeader = (title) => {
yPos += 5;
addWrappedText(title.toUpperCase(), 14, 'bold', [44, 62, 80]);
doc.setDrawColor(155, 89, 182); // Purple Line
doc.line(margin, yPos, pageWidth - margin, yPos);
yPos += 5;
};
const addSubHeader = (title) => {
addWrappedText(title, 11, 'bold', [155, 89, 182]);
yPos -= 2;
};
// --- Build PDF Document ---
// 1. Title Page Header
doc.setFontSize(18);
doc.setFont(undefined, 'bold');
doc.setTextColor(155, 89, 182);
doc.text(`EXPERT WITNESS REPORT`, pageWidth / 2, yPos, { align: 'center' });
yPos += 8;
doc.setFontSize(12);
doc.setTextColor(44, 62, 80);
doc.text(`Case: ${data.caseName}`, pageWidth / 2, yPos, { align: 'center' });
yPos += 5;
doc.text(`Jurisdiction: ${data.jurisdiction}`, pageWidth / 2, yPos, { align: 'center' });
yPos += 15;
// 2. Report Outline
addSectionHeader("I. Introduction and Qualifications");
addWrappedText(`Expert: ${data.expertName} | Field: ${data.field}`, 10, 'normal');
yPos += 5;
addSectionHeader("II. Facts and Data Considered");
data.factsData.split('\n').filter(l => l.trim().length > 0).forEach(l => addWrappedText(`• ${l.trim()}`, 10, 'normal', [52, 73, 94], 'left', 5));
yPos += 5;
addSectionHeader("III. Methodology and Principles");
addWrappedText(data.methodology, 10, 'normal');
yPos += 5;
addSectionHeader("IV. Questions Presented & Opinion");
addSubHeader("Questions Addressed:");
data.questions.split('\n').filter(l => l.trim().length > 0).forEach(l => addWrappedText(`- ${l.trim()}`, 10, 'normal', [52, 73, 94], 'left', 5));
yPos += 5;
addSubHeader("SUMMARY OF OPINION:");
yPos -= 2;
addWrappedText(data.summaryOpinion, 11, 'bold', [155, 89, 182]);
yPos += 5;
// 3. Daubert Checklist (Starts on new section)
yPos = 15;
doc.addPage();
doc.setFontSize(16);
doc.setFont(undefined, 'bold');
doc.setTextColor(155, 89, 182);
doc.text(`DAUBERT CHECKLIST (Reliability Assessment)`, pageWidth / 2, yPos, { align: 'center' });
yPos += 10;
const daubertQuestions = [
{ q: "1. Has the theory/technique been Tested?", a: data.tested },
{ q: "2. Peer Review and Publication?", a: data.peer },
{ q: "3. Known or potential Rate of Error?", a: data.error },
{ q: "4. General Acceptance in the relevant community?", a: data.acceptance },
{ q: "5. Prepared for Litigation or developed independently?", a: data.litigation }
];
daubertQuestions.forEach(item => {
addSubHeader(item.q);
yPos -= 2;
addWrappedText(item.a, 10, 'normal', [52, 73, 94], 'left', 5);
yPos += 5;
});
doc.save('expert_witness_report.pdf');
};
// --- Event Listeners ---
// Tab Buttons
tabButtons.forEach((btn, index) => {
btn.addEventListener('click', () => showTab(index + 1));
});
// Next/Prev Navigation
nextBtn.addEventListener('click', () => showTab(currentTab + 1));
prevBtn.addEventListener('click', () => showTab(currentTab - 1));
// Tab 4 Actions
refreshBtn.addEventListener('click', generatePreview);
downloadPdfBtn.addEventListener('click', downloadPDF);
downloadTxtBtn.addEventListener('click', downloadTxt);
// --- Initialization ---
showTab(1); // Set initial state
});