Spaces:
Sleeping
Sleeping
frabbani commited on
Commit ·
dc3f8a9
1
Parent(s): 6b833a6
Fix fact extraction - pass raw data for simple tools......
Browse files- report_generator.py +103 -6
- server.py +77 -5
- static/index.html +45 -0
report_generator.py
CHANGED
|
@@ -51,6 +51,12 @@ class PreVisitReport:
|
|
| 51 |
current_medications: List[str] = field(default_factory=list)
|
| 52 |
recent_vitals: Dict[str, str] = field(default_factory=dict)
|
| 53 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 54 |
# Attachments
|
| 55 |
attachments: List[Dict] = field(default_factory=list)
|
| 56 |
|
|
@@ -69,6 +75,10 @@ class PreVisitReport:
|
|
| 69 |
"relevant_conditions": self.relevant_conditions,
|
| 70 |
"current_medications": self.current_medications,
|
| 71 |
"recent_vitals": self.recent_vitals,
|
|
|
|
|
|
|
|
|
|
|
|
|
| 72 |
"attachments": self.attachments,
|
| 73 |
"key_quotes": self.key_quotes
|
| 74 |
}
|
|
@@ -97,7 +107,11 @@ async def generate_report(
|
|
| 97 |
patient_info: Dict,
|
| 98 |
conversation_history: List[Dict],
|
| 99 |
tool_results: List[Dict],
|
| 100 |
-
attachments: List[Dict] = None
|
|
|
|
|
|
|
|
|
|
|
|
|
| 101 |
) -> PreVisitReport:
|
| 102 |
"""
|
| 103 |
Generate a pre-visit report from conversation and medical data.
|
|
@@ -107,6 +121,10 @@ async def generate_report(
|
|
| 107 |
conversation_history: List of {"role": "user"|"assistant", "content": "..."}
|
| 108 |
tool_results: List of {"tool": "...", "facts": "..."}
|
| 109 |
attachments: List of {"type": "audio"|"chart", "title": "...", "summary": "..."}
|
|
|
|
|
|
|
|
|
|
|
|
|
| 110 |
|
| 111 |
Returns:
|
| 112 |
PreVisitReport object
|
|
@@ -207,6 +225,10 @@ Output ONLY the JSON, no other text.
|
|
| 207 |
relevant_conditions=report_data.get('relevant_conditions', []),
|
| 208 |
current_medications=report_data.get('current_medications', []),
|
| 209 |
recent_vitals=report_data.get('recent_vitals', {}),
|
|
|
|
|
|
|
|
|
|
|
|
|
| 210 |
attachments=attachments or [],
|
| 211 |
key_quotes=report_data.get('key_quotes', [])
|
| 212 |
)
|
|
@@ -242,10 +264,64 @@ def format_report_html(report: PreVisitReport) -> str:
|
|
| 242 |
</div>
|
| 243 |
"""
|
| 244 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 245 |
html = f"""
|
| 246 |
<div class="previsit-report">
|
| 247 |
<div class="report-header">
|
| 248 |
-
<h2>Pre-Visit Summary</h2>
|
| 249 |
<div class="report-meta">
|
| 250 |
<div class="patient-info">
|
| 251 |
<strong>{report.patient_name}</strong> · {report.patient_age}y · {report.patient_gender}
|
|
@@ -255,7 +331,7 @@ def format_report_html(report: PreVisitReport) -> str:
|
|
| 255 |
</div>
|
| 256 |
|
| 257 |
<div class="report-section">
|
| 258 |
-
<h3>
|
| 259 |
<ul class="concerns-list">{concerns_html}</ul>
|
| 260 |
</div>
|
| 261 |
|
|
@@ -271,20 +347,41 @@ def format_report_html(report: PreVisitReport) -> str:
|
|
| 271 |
|
| 272 |
<div class="report-columns">
|
| 273 |
<div class="report-section half">
|
| 274 |
-
<h3>📁
|
| 275 |
<ul>{conditions_html}</ul>
|
| 276 |
</div>
|
| 277 |
<div class="report-section half">
|
| 278 |
-
<h3>
|
| 279 |
-
<ul>{
|
| 280 |
</div>
|
| 281 |
</div>
|
| 282 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 283 |
{f'''<div class="report-section">
|
| 284 |
<h3>📊 Recent Vitals</h3>
|
| 285 |
<div class="vitals-grid">{vitals_html}</div>
|
| 286 |
</div>''' if report.recent_vitals else ""}
|
| 287 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 288 |
{f'''<div class="report-section">
|
| 289 |
<h3>💬 Patient Quotes</h3>
|
| 290 |
{quotes_html}
|
|
|
|
| 51 |
current_medications: List[str] = field(default_factory=list)
|
| 52 |
recent_vitals: Dict[str, str] = field(default_factory=dict)
|
| 53 |
|
| 54 |
+
# NEW: Additional medical history
|
| 55 |
+
immunizations: List[Dict] = field(default_factory=list)
|
| 56 |
+
procedures: List[Dict] = field(default_factory=list)
|
| 57 |
+
recent_encounters: List[Dict] = field(default_factory=list)
|
| 58 |
+
allergies: List[Dict] = field(default_factory=list)
|
| 59 |
+
|
| 60 |
# Attachments
|
| 61 |
attachments: List[Dict] = field(default_factory=list)
|
| 62 |
|
|
|
|
| 75 |
"relevant_conditions": self.relevant_conditions,
|
| 76 |
"current_medications": self.current_medications,
|
| 77 |
"recent_vitals": self.recent_vitals,
|
| 78 |
+
"immunizations": self.immunizations,
|
| 79 |
+
"procedures": self.procedures,
|
| 80 |
+
"recent_encounters": self.recent_encounters,
|
| 81 |
+
"allergies": self.allergies,
|
| 82 |
"attachments": self.attachments,
|
| 83 |
"key_quotes": self.key_quotes
|
| 84 |
}
|
|
|
|
| 107 |
patient_info: Dict,
|
| 108 |
conversation_history: List[Dict],
|
| 109 |
tool_results: List[Dict],
|
| 110 |
+
attachments: List[Dict] = None,
|
| 111 |
+
immunizations: List[Dict] = None,
|
| 112 |
+
procedures: List[Dict] = None,
|
| 113 |
+
encounters: List[Dict] = None,
|
| 114 |
+
allergies: List[Dict] = None
|
| 115 |
) -> PreVisitReport:
|
| 116 |
"""
|
| 117 |
Generate a pre-visit report from conversation and medical data.
|
|
|
|
| 121 |
conversation_history: List of {"role": "user"|"assistant", "content": "..."}
|
| 122 |
tool_results: List of {"tool": "...", "facts": "..."}
|
| 123 |
attachments: List of {"type": "audio"|"chart", "title": "...", "summary": "..."}
|
| 124 |
+
immunizations: List of immunization records from DB
|
| 125 |
+
procedures: List of procedure records from DB
|
| 126 |
+
encounters: List of encounter records from DB
|
| 127 |
+
allergies: List of allergy records from DB
|
| 128 |
|
| 129 |
Returns:
|
| 130 |
PreVisitReport object
|
|
|
|
| 225 |
relevant_conditions=report_data.get('relevant_conditions', []),
|
| 226 |
current_medications=report_data.get('current_medications', []),
|
| 227 |
recent_vitals=report_data.get('recent_vitals', {}),
|
| 228 |
+
immunizations=immunizations or [],
|
| 229 |
+
procedures=procedures or [],
|
| 230 |
+
recent_encounters=encounters or [],
|
| 231 |
+
allergies=allergies or [],
|
| 232 |
attachments=attachments or [],
|
| 233 |
key_quotes=report_data.get('key_quotes', [])
|
| 234 |
)
|
|
|
|
| 264 |
</div>
|
| 265 |
"""
|
| 266 |
|
| 267 |
+
# NEW: Format immunizations
|
| 268 |
+
immunizations_html = ""
|
| 269 |
+
if report.immunizations:
|
| 270 |
+
for imm in report.immunizations[:8]: # Limit to 8 most recent
|
| 271 |
+
vaccine_name = imm.get('vaccine_display', 'Unknown vaccine')
|
| 272 |
+
# Truncate long vaccine names
|
| 273 |
+
if len(vaccine_name) > 40:
|
| 274 |
+
vaccine_name = vaccine_name[:37] + "..."
|
| 275 |
+
date = imm.get('occurrence_date', '')[:10] if imm.get('occurrence_date') else 'Unknown'
|
| 276 |
+
immunizations_html += f"<li>{vaccine_name} <span class='date-badge'>({date})</span></li>"
|
| 277 |
+
else:
|
| 278 |
+
immunizations_html = "<li>No immunization records</li>"
|
| 279 |
+
|
| 280 |
+
# NEW: Format procedures (surgical history)
|
| 281 |
+
procedures_html = ""
|
| 282 |
+
if report.procedures:
|
| 283 |
+
for proc in report.procedures[:6]: # Limit to 6 most recent
|
| 284 |
+
proc_name = proc.get('display', 'Unknown procedure')
|
| 285 |
+
if len(proc_name) > 45:
|
| 286 |
+
proc_name = proc_name[:42] + "..."
|
| 287 |
+
date = proc.get('performed_date', '')[:10] if proc.get('performed_date') else 'Unknown'
|
| 288 |
+
procedures_html += f"<li>{proc_name} <span class='date-badge'>({date})</span></li>"
|
| 289 |
+
else:
|
| 290 |
+
procedures_html = "<li>No surgical history</li>"
|
| 291 |
+
|
| 292 |
+
# NEW: Format recent encounters
|
| 293 |
+
encounters_html = ""
|
| 294 |
+
if report.recent_encounters:
|
| 295 |
+
for enc in report.recent_encounters[:5]: # Limit to 5 most recent
|
| 296 |
+
enc_type = enc.get('type_display', enc.get('class_display', 'Visit'))
|
| 297 |
+
if len(enc_type) > 35:
|
| 298 |
+
enc_type = enc_type[:32] + "..."
|
| 299 |
+
reason = enc.get('reason_display', '')
|
| 300 |
+
if reason and len(reason) > 30:
|
| 301 |
+
reason = reason[:27] + "..."
|
| 302 |
+
date = enc.get('period_start', '')[:10] if enc.get('period_start') else 'Unknown'
|
| 303 |
+
reason_text = f" - {reason}" if reason else ""
|
| 304 |
+
encounters_html += f"<li>{enc_type}{reason_text} <span class='date-badge'>({date})</span></li>"
|
| 305 |
+
else:
|
| 306 |
+
encounters_html = "<li>No recent encounters</li>"
|
| 307 |
+
|
| 308 |
+
# NEW: Format allergies with severity
|
| 309 |
+
allergies_html = ""
|
| 310 |
+
if report.allergies:
|
| 311 |
+
for allergy in report.allergies:
|
| 312 |
+
substance = allergy.get('substance', 'Unknown')
|
| 313 |
+
reaction = allergy.get('reaction', allergy.get('reaction_display', ''))
|
| 314 |
+
criticality = allergy.get('criticality', '')
|
| 315 |
+
severity_class = 'allergy-high' if criticality == 'high' else 'allergy-low'
|
| 316 |
+
reaction_text = f" → {reaction}" if reaction else ""
|
| 317 |
+
allergies_html += f"<li class='{severity_class}'><strong>{substance}</strong>{reaction_text}</li>"
|
| 318 |
+
else:
|
| 319 |
+
allergies_html = "<li>No known allergies</li>"
|
| 320 |
+
|
| 321 |
html = f"""
|
| 322 |
<div class="previsit-report">
|
| 323 |
<div class="report-header">
|
| 324 |
+
<h2>📋 Pre-Visit Summary</h2>
|
| 325 |
<div class="report-meta">
|
| 326 |
<div class="patient-info">
|
| 327 |
<strong>{report.patient_name}</strong> · {report.patient_age}y · {report.patient_gender}
|
|
|
|
| 331 |
</div>
|
| 332 |
|
| 333 |
<div class="report-section">
|
| 334 |
+
<h3>🎯 Chief Concerns</h3>
|
| 335 |
<ul class="concerns-list">{concerns_html}</ul>
|
| 336 |
</div>
|
| 337 |
|
|
|
|
| 347 |
|
| 348 |
<div class="report-columns">
|
| 349 |
<div class="report-section half">
|
| 350 |
+
<h3>📁 Active Conditions</h3>
|
| 351 |
<ul>{conditions_html}</ul>
|
| 352 |
</div>
|
| 353 |
<div class="report-section half">
|
| 354 |
+
<h3>⚠️ Allergies</h3>
|
| 355 |
+
<ul class="allergies-list">{allergies_html}</ul>
|
| 356 |
</div>
|
| 357 |
</div>
|
| 358 |
|
| 359 |
+
<div class="report-section">
|
| 360 |
+
<h3>💊 Current Medications</h3>
|
| 361 |
+
<ul>{medications_html}</ul>
|
| 362 |
+
</div>
|
| 363 |
+
|
| 364 |
{f'''<div class="report-section">
|
| 365 |
<h3>📊 Recent Vitals</h3>
|
| 366 |
<div class="vitals-grid">{vitals_html}</div>
|
| 367 |
</div>''' if report.recent_vitals else ""}
|
| 368 |
|
| 369 |
+
<div class="report-columns">
|
| 370 |
+
<div class="report-section half">
|
| 371 |
+
<h3>💉 Immunizations</h3>
|
| 372 |
+
<ul class="compact-list">{immunizations_html}</ul>
|
| 373 |
+
</div>
|
| 374 |
+
<div class="report-section half">
|
| 375 |
+
<h3>🏥 Surgical History</h3>
|
| 376 |
+
<ul class="compact-list">{procedures_html}</ul>
|
| 377 |
+
</div>
|
| 378 |
+
</div>
|
| 379 |
+
|
| 380 |
+
<div class="report-section">
|
| 381 |
+
<h3>📅 Recent Encounters</h3>
|
| 382 |
+
<ul class="compact-list">{encounters_html}</ul>
|
| 383 |
+
</div>
|
| 384 |
+
|
| 385 |
{f'''<div class="report-section">
|
| 386 |
<h3>💬 Patient Quotes</h3>
|
| 387 |
{quotes_html}
|
server.py
CHANGED
|
@@ -167,13 +167,43 @@ async def get_encounters(patient_id: str, limit: int = 10):
|
|
| 167 |
conn = get_db()
|
| 168 |
try:
|
| 169 |
cursor = conn.execute("""
|
| 170 |
-
SELECT
|
| 171 |
-
|
|
|
|
|
|
|
| 172 |
""", (patient_id, limit))
|
| 173 |
encounters = [dict_from_row(row) for row in cursor.fetchall()]
|
| 174 |
return {"encounters": encounters}
|
| 175 |
finally:
|
| 176 |
conn.close()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 177 |
# ============================================================================
|
| 178 |
# LLM Integration
|
| 179 |
# ============================================================================
|
|
@@ -543,9 +573,11 @@ async def generate_report_endpoint(request: ReportRequest):
|
|
| 543 |
conn = get_db()
|
| 544 |
cursor = conn.execute("SELECT * FROM patients WHERE id = ?", (request.patient_id,))
|
| 545 |
patient = cursor.fetchone()
|
| 546 |
-
|
| 547 |
if not patient:
|
|
|
|
| 548 |
raise HTTPException(status_code=404, detail="Patient not found")
|
|
|
|
| 549 |
from datetime import datetime
|
| 550 |
birth = datetime.strptime(patient["birth_date"], "%Y-%m-%d")
|
| 551 |
age = (datetime.now() - birth).days // 365
|
|
@@ -554,13 +586,53 @@ async def generate_report_endpoint(request: ReportRequest):
|
|
| 554 |
"age": age,
|
| 555 |
"gender": patient['gender']
|
| 556 |
}
|
| 557 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 558 |
report = await generate_report(
|
| 559 |
patient_info=patient_info,
|
| 560 |
conversation_history=request.conversation,
|
| 561 |
tool_results=request.tool_results,
|
| 562 |
-
attachments=request.attachments
|
|
|
|
|
|
|
|
|
|
|
|
|
| 563 |
)
|
|
|
|
| 564 |
# Return both structured data and HTML
|
| 565 |
return {
|
| 566 |
"success": True,
|
|
|
|
| 167 |
conn = get_db()
|
| 168 |
try:
|
| 169 |
cursor = conn.execute("""
|
| 170 |
+
SELECT id, status, class_code, class_display, type_code, type_display,
|
| 171 |
+
reason_code, reason_display, period_start, period_end
|
| 172 |
+
FROM encounters WHERE patient_id = ?
|
| 173 |
+
ORDER BY period_start DESC LIMIT ?
|
| 174 |
""", (patient_id, limit))
|
| 175 |
encounters = [dict_from_row(row) for row in cursor.fetchall()]
|
| 176 |
return {"encounters": encounters}
|
| 177 |
finally:
|
| 178 |
conn.close()
|
| 179 |
+
|
| 180 |
+
@app.get("/api/patients/{patient_id}/immunizations")
|
| 181 |
+
async def get_immunizations(patient_id: str):
|
| 182 |
+
conn = get_db()
|
| 183 |
+
try:
|
| 184 |
+
cursor = conn.execute("""
|
| 185 |
+
SELECT id, vaccine_code, vaccine_display, status, occurrence_date
|
| 186 |
+
FROM immunizations WHERE patient_id = ?
|
| 187 |
+
ORDER BY occurrence_date DESC
|
| 188 |
+
""", (patient_id,))
|
| 189 |
+
immunizations = [dict_from_row(row) for row in cursor.fetchall()]
|
| 190 |
+
return {"immunizations": immunizations}
|
| 191 |
+
finally:
|
| 192 |
+
conn.close()
|
| 193 |
+
|
| 194 |
+
@app.get("/api/patients/{patient_id}/procedures")
|
| 195 |
+
async def get_procedures(patient_id: str):
|
| 196 |
+
conn = get_db()
|
| 197 |
+
try:
|
| 198 |
+
cursor = conn.execute("""
|
| 199 |
+
SELECT id, code, display, status, performed_date
|
| 200 |
+
FROM procedures WHERE patient_id = ?
|
| 201 |
+
ORDER BY performed_date DESC
|
| 202 |
+
""", (patient_id,))
|
| 203 |
+
procedures = [dict_from_row(row) for row in cursor.fetchall()]
|
| 204 |
+
return {"procedures": procedures}
|
| 205 |
+
finally:
|
| 206 |
+
conn.close()
|
| 207 |
# ============================================================================
|
| 208 |
# LLM Integration
|
| 209 |
# ============================================================================
|
|
|
|
| 573 |
conn = get_db()
|
| 574 |
cursor = conn.execute("SELECT * FROM patients WHERE id = ?", (request.patient_id,))
|
| 575 |
patient = cursor.fetchone()
|
| 576 |
+
|
| 577 |
if not patient:
|
| 578 |
+
conn.close()
|
| 579 |
raise HTTPException(status_code=404, detail="Patient not found")
|
| 580 |
+
|
| 581 |
from datetime import datetime
|
| 582 |
birth = datetime.strptime(patient["birth_date"], "%Y-%m-%d")
|
| 583 |
age = (datetime.now() - birth).days // 365
|
|
|
|
| 586 |
"age": age,
|
| 587 |
"gender": patient['gender']
|
| 588 |
}
|
| 589 |
+
|
| 590 |
+
# Fetch immunizations
|
| 591 |
+
cursor = conn.execute("""
|
| 592 |
+
SELECT id, vaccine_code, vaccine_display, status, occurrence_date
|
| 593 |
+
FROM immunizations WHERE patient_id = ?
|
| 594 |
+
ORDER BY occurrence_date DESC
|
| 595 |
+
""", (request.patient_id,))
|
| 596 |
+
immunizations = [dict_from_row(row) for row in cursor.fetchall()]
|
| 597 |
+
|
| 598 |
+
# Fetch procedures (surgical history)
|
| 599 |
+
cursor = conn.execute("""
|
| 600 |
+
SELECT id, code, display, status, performed_date
|
| 601 |
+
FROM procedures WHERE patient_id = ?
|
| 602 |
+
ORDER BY performed_date DESC
|
| 603 |
+
""", (request.patient_id,))
|
| 604 |
+
procedures = [dict_from_row(row) for row in cursor.fetchall()]
|
| 605 |
+
|
| 606 |
+
# Fetch recent encounters
|
| 607 |
+
cursor = conn.execute("""
|
| 608 |
+
SELECT id, status, class_code, class_display, type_code, type_display,
|
| 609 |
+
reason_code, reason_display, period_start, period_end
|
| 610 |
+
FROM encounters WHERE patient_id = ?
|
| 611 |
+
ORDER BY period_start DESC LIMIT 10
|
| 612 |
+
""", (request.patient_id,))
|
| 613 |
+
encounters = [dict_from_row(row) for row in cursor.fetchall()]
|
| 614 |
+
|
| 615 |
+
# Fetch allergies
|
| 616 |
+
cursor = conn.execute("""
|
| 617 |
+
SELECT id, substance, reaction_display as reaction, criticality, category
|
| 618 |
+
FROM allergies WHERE patient_id = ?
|
| 619 |
+
""", (request.patient_id,))
|
| 620 |
+
allergies = [dict_from_row(row) for row in cursor.fetchall()]
|
| 621 |
+
|
| 622 |
+
conn.close()
|
| 623 |
+
|
| 624 |
+
# Generate report with all data
|
| 625 |
report = await generate_report(
|
| 626 |
patient_info=patient_info,
|
| 627 |
conversation_history=request.conversation,
|
| 628 |
tool_results=request.tool_results,
|
| 629 |
+
attachments=request.attachments,
|
| 630 |
+
immunizations=immunizations,
|
| 631 |
+
procedures=procedures,
|
| 632 |
+
encounters=encounters,
|
| 633 |
+
allergies=allergies
|
| 634 |
)
|
| 635 |
+
|
| 636 |
# Return both structured data and HTML
|
| 637 |
return {
|
| 638 |
"success": True,
|
static/index.html
CHANGED
|
@@ -929,6 +929,45 @@
|
|
| 929 |
color: var(--text-muted);
|
| 930 |
text-align: center;
|
| 931 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 932 |
</style>
|
| 933 |
</head>
|
| 934 |
<body>
|
|
@@ -1966,6 +2005,12 @@
|
|
| 1966 |
.pdf-report .report-section.half { flex: 1; }
|
| 1967 |
.pdf-report .patient-info { color: #000 !important; }
|
| 1968 |
.pdf-report .report-date { color: #333 !important; }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1969 |
</style>
|
| 1970 |
<div class="pdf-report">
|
| 1971 |
${currentReport.html}
|
|
|
|
| 929 |
color: var(--text-muted);
|
| 930 |
text-align: center;
|
| 931 |
}
|
| 932 |
+
|
| 933 |
+
/* NEW: Compact list styling for immunizations/procedures/encounters */
|
| 934 |
+
.previsit-report .compact-list {
|
| 935 |
+
font-size: 12px;
|
| 936 |
+
margin: 0;
|
| 937 |
+
padding-left: 16px;
|
| 938 |
+
}
|
| 939 |
+
|
| 940 |
+
.previsit-report .compact-list li {
|
| 941 |
+
margin: 3px 0;
|
| 942 |
+
line-height: 1.4;
|
| 943 |
+
}
|
| 944 |
+
|
| 945 |
+
.previsit-report .date-badge {
|
| 946 |
+
color: var(--text-muted);
|
| 947 |
+
font-size: 11px;
|
| 948 |
+
}
|
| 949 |
+
|
| 950 |
+
/* Allergy styling with severity indicators */
|
| 951 |
+
.previsit-report .allergies-list {
|
| 952 |
+
margin: 0;
|
| 953 |
+
padding-left: 16px;
|
| 954 |
+
}
|
| 955 |
+
|
| 956 |
+
.previsit-report .allergies-list li {
|
| 957 |
+
margin: 4px 0;
|
| 958 |
+
}
|
| 959 |
+
|
| 960 |
+
.previsit-report .allergies-list .allergy-high {
|
| 961 |
+
color: #ff6b6b;
|
| 962 |
+
}
|
| 963 |
+
|
| 964 |
+
.previsit-report .allergies-list .allergy-high strong {
|
| 965 |
+
color: #ff4757;
|
| 966 |
+
}
|
| 967 |
+
|
| 968 |
+
.previsit-report .allergies-list .allergy-low {
|
| 969 |
+
color: var(--text-main);
|
| 970 |
+
}
|
| 971 |
</style>
|
| 972 |
</head>
|
| 973 |
<body>
|
|
|
|
| 2005 |
.pdf-report .report-section.half { flex: 1; }
|
| 2006 |
.pdf-report .patient-info { color: #000 !important; }
|
| 2007 |
.pdf-report .report-date { color: #333 !important; }
|
| 2008 |
+
.pdf-report .compact-list { font-size: 12px; padding-left: 16px; }
|
| 2009 |
+
.pdf-report .compact-list li { margin: 3px 0; }
|
| 2010 |
+
.pdf-report .date-badge { color: #666 !important; font-size: 11px; }
|
| 2011 |
+
.pdf-report .allergies-list .allergy-high { color: #c0392b !important; }
|
| 2012 |
+
.pdf-report .allergies-list .allergy-high strong { color: #c0392b !important; }
|
| 2013 |
+
.pdf-report .allergies-list .allergy-low { color: #000 !important; }
|
| 2014 |
</style>
|
| 2015 |
<div class="pdf-report">
|
| 2016 |
${currentReport.html}
|