Pediatric discharge card

Asking for Preferences
Asking for Preferences
Reading File
Reading File
Finding Sources
Finding Sources
Finding Sources
Reading File
Reading File
Finding Sources
Finding Sources
Reading File
Reading File
Loading Image
Running Command

mkdir -p /home/daytona/workspace/pediatric-discharge && ls /home/daytona/workspace/pediatric-discharge/

Writing File

~/pediatric-discharge/generate_card.py

"""
Pediatric Respiratory Discharge Card
Covers: Asthma, Bronchiolitis, Croup
Based on Tintinalli's EM & Rosen's EM clinical guidelines
"""
from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.lib.units import mm, cm
from reportlab.platypus import (
    SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
    HRFlowable, KeepTogether
)
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_RIGHT
from reportlab.platypus import Flowable

OUTPUT = "/home/daytona/workspace/pediatric-discharge/Pediatric_Respiratory_Discharge_Card.pdf"

# ── Colours ──────────────────────────────────────────────────────────────────
TEAL       = colors.HexColor("#006E7F")
GREEN      = colors.HexColor("#2E7D32")
GREEN_BG   = colors.HexColor("#E8F5E9")
YELLOW     = colors.HexColor("#F57F17")
YELLOW_BG  = colors.HexColor("#FFFDE7")
RED        = colors.HexColor("#C62828")
RED_BG     = colors.HexColor("#FFEBEE")
BLUE       = colors.HexColor("#1565C0")
BLUE_BG    = colors.HexColor("#E3F2FD")
ORANGE     = colors.HexColor("#E65100")
ORANGE_BG  = colors.HexColor("#FFF3E0")
GREY_BG    = colors.HexColor("#F5F5F5")
DARK_GREY  = colors.HexColor("#37474F")
WHITE      = colors.white
BLACK      = colors.black
LIGHT_TEAL = colors.HexColor("#E0F4F7")

# ── Document setup ─────────────────────────────────────────────────────────
doc = SimpleDocTemplate(
    OUTPUT,
    pagesize=A4,
    rightMargin=14*mm,
    leftMargin=14*mm,
    topMargin=12*mm,
    bottomMargin=12*mm,
)
W = A4[0] - 28*mm   # usable width

# ── Styles ─────────────────────────────────────────────────────────────────
ss = getSampleStyleSheet()

def S(name, **kw):
    base = ss["Normal"]
    return ParagraphStyle(name, parent=base, **kw)

HEADER_TITLE = S("HT", fontSize=20, textColor=WHITE, fontName="Helvetica-Bold",
                 alignment=TA_CENTER, spaceAfter=0)
HEADER_SUB   = S("HS", fontSize=10, textColor=WHITE, fontName="Helvetica",
                 alignment=TA_CENTER, spaceAfter=0)
SECTION_TTL  = S("ST", fontSize=13, textColor=WHITE, fontName="Helvetica-Bold",
                 alignment=TA_LEFT, spaceAfter=0, leftPadding=6)
ZONE_TITLE   = S("ZT", fontSize=12, fontName="Helvetica-Bold",
                 alignment=TA_LEFT, spaceAfter=2)
BODY         = S("BD", fontSize=9, fontName="Helvetica",
                 leading=13, spaceAfter=2)
BODY_BOLD    = S("BB", fontSize=9, fontName="Helvetica-Bold", leading=13)
SMALL        = S("SM", fontSize=8, fontName="Helvetica", leading=11,
                 textColor=DARK_GREY)
LABEL        = S("LB", fontSize=8.5, fontName="Helvetica-Bold",
                 textColor=DARK_GREY)
WARNING      = S("WN", fontSize=9, fontName="Helvetica-Bold",
                 textColor=RED, leading=13)
FIELD_LABEL  = S("FL", fontSize=8.5, fontName="Helvetica",
                 textColor=DARK_GREY)
BULLET       = S("BU", fontSize=9, fontName="Helvetica", leading=13,
                 leftIndent=10, spaceAfter=1,
                 bulletIndent=2, bulletFontName="Helvetica")

def bullet_para(text, color=BLACK):
    return Paragraph(f"• {text}", S("b_", fontSize=9, fontName="Helvetica",
                                    leading=13, leftIndent=8,
                                    spaceAfter=1, textColor=color))

def field_line(label, width=55*mm):
    return f'<font name="Helvetica-Bold">{label}:</font> ' \
           f'<u>{"_" * 32}</u>'

# ── Helper: coloured section header ───────────────────────────────────────
def section_header(title, bg_color):
    data = [[Paragraph(title, SECTION_TTL)]]
    t = Table(data, colWidths=[W])
    t.setStyle(TableStyle([
        ("BACKGROUND", (0,0), (-1,-1), bg_color),
        ("TOPPADDING",    (0,0), (-1,-1), 5),
        ("BOTTOMPADDING", (0,0), (-1,-1), 5),
        ("LEFTPADDING",   (0,0), (-1,-1), 8),
        ("RIGHTPADDING",  (0,0), (-1,-1), 8),
        ("ROUNDEDCORNERS", [4,4,4,4]),
    ]))
    return t

# ── Helper: two-column info box ─────────────────────────────────────────────
def info_box(rows, bg=GREY_BG, col_widths=None):
    if col_widths is None:
        col_widths = [W*0.35, W*0.65]
    data = []
    for left, right in rows:
        data.append([
            Paragraph(left,  LABEL),
            Paragraph(right, BODY),
        ])
    t = Table(data, colWidths=col_widths)
    t.setStyle(TableStyle([
        ("BACKGROUND",    (0,0), (-1,-1), bg),
        ("TOPPADDING",    (0,0), (-1,-1), 3),
        ("BOTTOMPADDING", (0,0), (-1,-1), 3),
        ("LEFTPADDING",   (0,0), (-1,-1), 6),
        ("RIGHTPADDING",  (0,0), (-1,-1), 6),
        ("VALIGN",        (0,0), (-1,-1), "TOP"),
        ("LINEBELOW",     (0,0), (-1,-2), 0.3, colors.HexColor("#DDDDDD")),
    ]))
    return t

# ── Helper: zone table (Green / Yellow / Red) ──────────────────────────────
def zone_table(zone_color, zone_bg, zone_name, signs, actions):
    left_items = [Paragraph(f"<b>{zone_name}</b>", S("zt",fontSize=10,
                             fontName="Helvetica-Bold", textColor=zone_color))]
    for s in signs:
        left_items.append(bullet_para(s, BLACK))
    right_items = []
    for a in actions:
        right_items.append(bullet_para(a, BLACK))

    left_col  = [i for pair in [(x, Spacer(1,1)) for x in left_items] for i in pair]
    right_col = [i for pair in [(x, Spacer(1,1)) for x in right_items] for i in pair]

    from reportlab.platypus import ListFlowable, ListItem
    # build inner tables
    def stack(items):
        d = [[i] for i in items]
        t = Table(d, colWidths=[W*0.46 - 8])
        t.setStyle(TableStyle([
            ("TOPPADDING",    (0,0), (-1,-1), 1),
            ("BOTTOMPADDING", (0,0), (-1,-1), 1),
            ("LEFTPADDING",   (0,0), (-1,-1), 2),
            ("RIGHTPADDING",  (0,0), (-1,-1), 2),
        ]))
        return t

    outer = Table([[stack(left_items), stack(right_items)]],
                  colWidths=[W*0.46, W*0.54])
    outer.setStyle(TableStyle([
        ("BACKGROUND",    (0,0), (-1,-1), zone_bg),
        ("TOPPADDING",    (0,0), (-1,-1), 6),
        ("BOTTOMPADDING", (0,0), (-1,-1), 6),
        ("LEFTPADDING",   (0,0), (-1,-1), 6),
        ("RIGHTPADDING",  (0,0), (-1,-1), 6),
        ("VALIGN",        (0,0), (-1,-1), "TOP"),
        ("LINEAFTER",     (0,0), (0,-1), 0.5, zone_color),
        ("BOX",           (0,0), (-1,-1), 1, zone_color),
    ]))
    return outer

# ═══════════════════════════════════════════════════════════════════════════
# BUILD CONTENT
# ═══════════════════════════════════════════════════════════════════════════
story = []

# ── MAIN HEADER ─────────────────────────────────────────────────────────────
hdr_data = [[
    Paragraph("PEDIATRIC RESPIRATORY DISCHARGE CARD", HEADER_TITLE),
], [
    Paragraph("Asthma · Bronchiolitis · Croup  |  For Parent / Caregiver", HEADER_SUB),
]]
hdr_tbl = Table(hdr_data, colWidths=[W])
hdr_tbl.setStyle(TableStyle([
    ("BACKGROUND",    (0,0), (-1,-1), TEAL),
    ("TOPPADDING",    (0,0), (0,0), 10),
    ("BOTTOMPADDING", (0,1), (0,1), 10),
    ("LEFTPADDING",   (0,0), (-1,-1), 0),
    ("RIGHTPADDING",  (0,0), (-1,-1), 0),
]))
story.append(hdr_tbl)
story.append(Spacer(1, 4*mm))

# ── PATIENT INFO BAR ─────────────────────────────────────────────────────────
patient_fields = [
    ["Patient Name:", "_"*30, "Date of Birth:", "_"*18],
    ["Date:",         "_"*30, "Weight (kg):",   "_"*18],
    ["Diagnosis:",    "_"*30, "Follow-up with:", "_"*18],
    ["ED Physician:", "_"*30, "Follow-up in:",  "______ days"],
]
pf_data = []
for row in patient_fields:
    pf_data.append([
        Paragraph(row[0], LABEL), Paragraph(row[1], BODY),
        Paragraph(row[2], LABEL), Paragraph(row[3], BODY),
    ])
pf_tbl = Table(pf_data, colWidths=[W*0.18, W*0.32, W*0.22, W*0.28])
pf_tbl.setStyle(TableStyle([
    ("BACKGROUND",    (0,0), (-1,-1), LIGHT_TEAL),
    ("TOPPADDING",    (0,0), (-1,-1), 3),
    ("BOTTOMPADDING", (0,0), (-1,-1), 3),
    ("LEFTPADDING",   (0,0), (-1,-1), 5),
    ("RIGHTPADDING",  (0,0), (-1,-1), 5),
    ("LINEBELOW",     (0,0), (-1,-3), 0.3, colors.HexColor("#AACCCC")),
    ("BOX",           (0,0), (-1,-1), 0.8, TEAL),
]))
story.append(pf_tbl)
story.append(Spacer(1, 5*mm))

# ═══════════════════════════════════════════════════════════════════════════════
# SECTION 1 — ASTHMA
# ═══════════════════════════════════════════════════════════════════════════════
story.append(section_header("🫁  ASTHMA", BLUE))
story.append(Spacer(1, 3*mm))

# -- Zone table (Green / Yellow / Red) --
story.append(Paragraph("<b>Asthma Action Plan — Know Your Zone</b>",
                        S("ap", fontSize=10, fontName="Helvetica-Bold",
                          textColor=BLUE, spaceAfter=3)))

gz = zone_table(GREEN, GREEN_BG, "🟢  GREEN ZONE — Asthma Under Control",
    signs=["Breathing is good", "Can run, play normally",
           "Cough or wheeze <4× per week", "Sleeping through the night"],
    actions=["Continue CONTROLLER medicine daily",
             "Use QUICK RELIEF inhaler only if needed",
             "No limitations on activity"])

yz = zone_table(YELLOW, YELLOW_BG, "🟡  YELLOW ZONE — Asthma Not Well Controlled",
    signs=["Signs of a cold or mild illness",
           "Mild to moderate cough or wheeze",
           "Waking up at night due to asthma",
           "Some limitation on activity"],
    actions=["Continue GREEN ZONE controller medicine",
             "Take QUICK RELIEF inhaler every 4 hours",
             "If relief medicine does not last 4 hours → see a doctor",
             "If symptoms worsen → move to RED ZONE"])

rz = zone_table(RED, RED_BG, "🔴  RED ZONE — Asthma Out of Control",
    signs=["Very short of breath, severe wheeze",
           "Skin pulling in between ribs (retractions)",
           "Cannot do usual activities",
           "Blue tinge to lips or fingernails",
           "Rescue inhaler not helping"],
    actions=["Give QUICK RELIEF inhaler every 10–20 min if needed",
             "Take oral steroid if prescribed",
             "Call your doctor NOW",
             "If no improvement in 15 min OR cannot reach doctor → call 911 or go to ED IMMEDIATELY"])

story.append(gz)
story.append(Spacer(1, 2*mm))
story.append(yz)
story.append(Spacer(1, 2*mm))
story.append(rz)
story.append(Spacer(1, 3*mm))

# -- Medications prescribed --
story.append(Paragraph("<b>Medications Prescribed at Discharge</b>",
                        S("mp", fontSize=10, fontName="Helvetica-Bold",
                          textColor=BLUE, spaceAfter=3)))
med_rows = [
    ["QUICK RELIEF (Rescue) Inhaler\ne.g. Salbutamol (Ventolin®)",
     "Name: _______________    Dose: _____ mcg × _____ puffs\n"
     "Frequency: Every 4–6 h as needed\n"
     "Spacer / AeroChamber®: □ with mask   □ with mouthpiece"],
    ["CONTROLLER Inhaler\ne.g. Budesonide, Fluticasone",
     "Name: _______________    Dose: _____ mcg × _____ puffs\n"
     "Frequency: Twice daily for 3 months   Refill: 3"],
    ["ORAL STEROID\ne.g. Prednisolone / Dexamethasone",
     "Name: _______________    Dose: _____ mg\n"
     "Duration: _____ days   (If single-dose dexamethasone given in ED, no course needed)"],
]
md_data = []
for row in med_rows:
    md_data.append([
        Paragraph(row[0], LABEL),
        Paragraph(row[1], BODY),
    ])
md_tbl = Table(md_data, colWidths=[W*0.28, W*0.72])
md_tbl.setStyle(TableStyle([
    ("BACKGROUND",    (0,0), (0,-1), BLUE_BG),
    ("BACKGROUND",    (1,0), (1,-1), WHITE),
    ("TOPPADDING",    (0,0), (-1,-1), 5),
    ("BOTTOMPADDING", (0,0), (-1,-1), 5),
    ("LEFTPADDING",   (0,0), (-1,-1), 6),
    ("RIGHTPADDING",  (0,0), (-1,-1), 6),
    ("VALIGN",        (0,0), (-1,-1), "TOP"),
    ("LINEBELOW",     (0,0), (-1,-2), 0.4, colors.HexColor("#BBBBBB")),
    ("BOX",           (0,0), (-1,-1), 0.8, BLUE),
]))
story.append(md_tbl)
story.append(Spacer(1, 3*mm))

# -- Inhaler technique reminder --
story.append(Paragraph("<b>Inhaler Technique (MDI + Spacer):</b> "
    "Shake inhaler → attach to spacer → breathe out gently → seal lips around spacer → "
    "press inhaler once → breathe in slowly for 3–5 sec → hold breath 10 sec → wait 30 sec between puffs.",
    SMALL))
story.append(Spacer(1, 5*mm))

# ═══════════════════════════════════════════════════════════════════════════════
# SECTION 2 — BRONCHIOLITIS
# ═══════════════════════════════════════════════════════════════════════════════
story.append(section_header("👶  BRONCHIOLITIS", ORANGE))
story.append(Spacer(1, 3*mm))

story.append(Paragraph(
    "<b>What is bronchiolitis?</b>  A viral infection (most often RSV) causing swelling "
    "of the small breathing tubes in babies and young children.  It usually peaks at "
    "<b>days 3–5</b> and most children improve by <b>7–10 days</b>.",
    BODY))
story.append(Spacer(1, 3*mm))

# Two-column: home care | return precautions
home_care = [
    "Offer small, frequent feeds (breast or bottle) — fluids prevent dehydration",
    "Use a bulb/nasal-aspirator to clear blocked nostrils before feeds",
    "Elevate head of cot slightly (place towel under mattress — not a pillow)",
    "Keep the room smoke-free; avoid exposure to cigarette smoke entirely",
    "Paracetamol/ibuprofen for comfort only — not for the bronchiolitis itself",
    "Salbutamol only if prescribed; continue every 4 h as needed if a response was seen in ED",
]
return_signs = [
    "Breathing faster or harder than usual",
    "Nostrils flaring or ribs visibly pulling in",
    "Pale, mottled, or blue-tinged skin",
    "High fever or temp <36 °C",
    "Too tired to feed or taking <50% of normal feeds",
    "Not passing urine (>8 h in infant, >12 h in older child)",
    "Lethargy, difficult to wake, or inconsolable crying",
]

def two_col_box(title_l, items_l, color_l, bg_l,
                title_r, items_r, color_r, bg_r):
    def col(title, items, c, bg):
        cells = [[Paragraph(f"<b>{title}</b>",
                             S("ch", fontSize=9, fontName="Helvetica-Bold",
                               textColor=c))]]
        for item in items:
            cells.append([bullet_para(item)])
        t = Table(cells, colWidths=[(W-4)/2 - 6])
        t.setStyle(TableStyle([
            ("BACKGROUND",    (0,0), (-1,-1), bg),
            ("TOPPADDING",    (0,0), (-1,-1), 3),
            ("BOTTOMPADDING", (0,0), (-1,-1), 2),
            ("LEFTPADDING",   (0,0), (-1,-1), 5),
            ("RIGHTPADDING",  (0,0), (-1,-1), 5),
        ]))
        return t
    outer = Table([[col(title_l, items_l, color_l, bg_l),
                    col(title_r, items_r, color_r, bg_r)]],
                  colWidths=[(W)/2, (W)/2])
    outer.setStyle(TableStyle([
        ("TOPPADDING",    (0,0), (-1,-1), 0),
        ("BOTTOMPADDING", (0,0), (-1,-1), 0),
        ("LEFTPADDING",   (0,0), (-1,-1), 0),
        ("RIGHTPADDING",  (0,0), (-1,-1), 0),
        ("LINEAFTER",     (0,0), (0,-1), 0.8, ORANGE),
        ("BOX",           (0,0), (-1,-1), 0.8, ORANGE),
    ]))
    return outer

bron_box = two_col_box(
    "Home Care", home_care, ORANGE, ORANGE_BG,
    "⚠️  Return to ED If:", return_signs, RED, RED_BG)
story.append(bron_box)
story.append(Spacer(1, 3*mm))
story.append(Paragraph(
    "<b>Follow-up:</b>  See your family doctor or paediatrician within <b>24 hours</b> for re-evaluation.  "
    "Bronchiolitis is dynamic; a single assessment may not reflect full severity.",
    SMALL))
story.append(Spacer(1, 5*mm))

# ═══════════════════════════════════════════════════════════════════════════════
# SECTION 3 — CROUP
# ═══════════════════════════════════════════════════════════════════════════════
story.append(section_header("🌙  CROUP (Laryngotracheobronchitis)", GREEN))
story.append(Spacer(1, 3*mm))

story.append(Paragraph(
    "<b>What is croup?</b>  A viral infection causing swelling around the voicebox and windpipe, "
    "producing the characteristic <b>barking cough</b> and <b>stridor</b> (noisy breathing when inhaling).  "
    "Symptoms are often <b>worse at night</b>.  Most children recover fully within <b>3–7 days</b>.",
    BODY))
story.append(Spacer(1, 3*mm))

# Medication given in ED
story.append(Paragraph("<b>Medication Given in the Emergency Department</b>",
                        S("mg", fontSize=9.5, fontName="Helvetica-Bold",
                          textColor=GREEN, spaceAfter=3)))
croup_meds = [
    ["Dexamethasone (Steroid)",
     "Dose given: _____ mg (0.6 mg/kg)  □ Oral   □ IM\n"
     "A single dose; reduces swelling and hospital stay.\n"
     "Effect lasts 24–48 hours.  <b>No further steroid course usually needed.</b>"],
    ["Nebulised Adrenaline (Epinephrine)",
     "□ Given in ED for moderate–severe stridor at rest.\n"
     "Observed for at least <b>2–3 hours</b> post-treatment before discharge.\n"
     "Effect temporary (1–2 h); symptoms may transiently rebound."],
]
cm_data = []
for row in croup_meds:
    cm_data.append([Paragraph(row[0], LABEL), Paragraph(row[1], BODY)])
cm_tbl = Table(cm_data, colWidths=[W*0.28, W*0.72])
cm_tbl.setStyle(TableStyle([
    ("BACKGROUND",    (0,0), (0,-1), GREEN_BG),
    ("BACKGROUND",    (1,0), (1,-1), WHITE),
    ("TOPPADDING",    (0,0), (-1,-1), 5),
    ("BOTTOMPADDING", (0,0), (-1,-1), 5),
    ("LEFTPADDING",   (0,0), (-1,-1), 6),
    ("RIGHTPADDING",  (0,0), (-1,-1), 6),
    ("VALIGN",        (0,0), (-1,-1), "TOP"),
    ("LINEBELOW",     (0,0), (-1,-2), 0.4, colors.HexColor("#AAAAAA")),
    ("BOX",           (0,0), (-1,-1), 0.8, GREEN),
]))
story.append(cm_tbl)
story.append(Spacer(1, 3*mm))

story.append(Paragraph("<b>Home Care for Croup</b>",
                        S("hcc", fontSize=9.5, fontName="Helvetica-Bold",
                          textColor=GREEN, spaceAfter=3)))

croup_care = [
    "Keep the child calm — crying worsens stridor",
    "Cool night air (open window briefly) or cool mist humidifier may ease symptoms",
    "Use paracetamol/ibuprofen for fever and discomfort",
    "Encourage fluids; small frequent offerings",
    "Elevate head of bed slightly",
    "Avoid passive cigarette smoke",
]
croup_return = [
    "<b>Stridor at rest</b> (noisy breathing when calm)",
    "Severe difficulty breathing / marked retractions",
    "Drooling or difficulty swallowing",
    "Child looks very unwell, pale, or blue",
    "Fever persisting beyond 4–5 days (consider bacterial cause)",
    "Symptoms suddenly worsen or do not improve by Day 4",
]

croup_box = two_col_box(
    "Home Care", croup_care, GREEN, GREEN_BG,
    "⚠️  Return to ED Immediately If:", croup_return, RED, RED_BG)
story.append(croup_box)
story.append(Spacer(1, 3*mm))
story.append(Paragraph(
    "<b>Discharge criteria met:</b>  Child discharged with no resting stridor, no significant "
    "distress, and adequate oral intake.  □ Resting stridor resolved  "
    "□ Feeding well  □ Caregiver understands return precautions",
    SMALL))
story.append(Spacer(1, 5*mm))

# ═══════════════════════════════════════════════════════════════════════════════
# GENERAL RETURN PRECAUTIONS
# ═══════════════════════════════════════════════════════════════════════════════
story.append(section_header("⚠️  GENERAL — SEEK EMERGENCY CARE IMMEDIATELY IF:", RED))
story.append(Spacer(1, 2*mm))

gen_warn = [
    "Lips or fingernails turning blue (cyanosis)",
    "Child cannot speak, cry, or make sounds",
    "Chest and neck muscles visibly pulling in with every breath",
    "Child is limp, floppy, or cannot be roused",
    "Breathing rate very fast AND child is in obvious distress",
    "Any concern that your child is getting significantly worse",
]
warn_items = [bullet_para(w, RED) for w in gen_warn]
warn_tbl = Table([[w] for w in warn_items], colWidths=[W])
warn_tbl.setStyle(TableStyle([
    ("BACKGROUND",    (0,0), (-1,-1), RED_BG),
    ("TOPPADDING",    (0,0), (-1,-1), 2),
    ("BOTTOMPADDING", (0,0), (-1,-1), 2),
    ("LEFTPADDING",   (0,0), (-1,-1), 8),
    ("RIGHTPADDING",  (0,0), (-1,-1), 8),
    ("BOX",           (0,0), (-1,-1), 1, RED),
]))
story.append(warn_tbl)
story.append(Spacer(1, 4*mm))

# ═══════════════════════════════════════════════════════════════════════════════
# TRIGGER / PREVENTION
# ═══════════════════════════════════════════════════════════════════════════════
story.append(section_header("💡  PREVENTION & TRIGGER AVOIDANCE", TEAL))
story.append(Spacer(1, 2*mm))

triggers_data = [
    [Paragraph("<b>Common Triggers to Avoid</b>", LABEL),
     Paragraph("<b>Prevention Tips</b>", LABEL)],
    [Paragraph("• Cigarette / e-cigarette smoke\n• Dust mites, pet dander\n"
               "• Mould, pollen, cold air\n• Exercise (in uncontrolled asthma)\n"
               "• Viral URTIs (colds, flu)\n• Strong chemical fumes", BODY),
     Paragraph("• Wash bedding weekly in hot water\n• Keep pets out of bedrooms\n"
               "• Annual influenza vaccine (asthma)\n• Palivizumab (RSV prophylaxis) "
               "for high-risk infants\n• Regular hand washing to prevent viral spread\n"
               "• Do not smoke in the home or car", BODY)],
]
trg_tbl = Table(triggers_data, colWidths=[W*0.5, W*0.5])
trg_tbl.setStyle(TableStyle([
    ("BACKGROUND",    (0,0), (-1,0), LIGHT_TEAL),
    ("BACKGROUND",    (0,1), (-1,-1), WHITE),
    ("TOPPADDING",    (0,0), (-1,-1), 5),
    ("BOTTOMPADDING", (0,0), (-1,-1), 5),
    ("LEFTPADDING",   (0,0), (-1,-1), 6),
    ("RIGHTPADDING",  (0,0), (-1,-1), 6),
    ("VALIGN",        (0,0), (-1,-1), "TOP"),
    ("LINEAFTER",     (0,0), (0,-1), 0.5, TEAL),
    ("BOX",           (0,0), (-1,-1), 0.8, TEAL),
]))
story.append(trg_tbl)
story.append(Spacer(1, 5*mm))

# ═══════════════════════════════════════════════════════════════════════════════
# FOLLOW-UP & SIGNATURE BAR
# ═══════════════════════════════════════════════════════════════════════════════
fu_data = [
    [Paragraph("<b>Schedule follow-up with:</b>  □ Family doctor  "
               "□ Paediatrician  □ Asthma educator  □ Respiratory specialist\n"
               "Within _______ days.   Appointment contact: _______________________",
               SMALL)],
]
fu_tbl = Table(fu_data, colWidths=[W])
fu_tbl.setStyle(TableStyle([
    ("BACKGROUND",    (0,0), (-1,-1), LIGHT_TEAL),
    ("TOPPADDING",    (0,0), (-1,-1), 6),
    ("BOTTOMPADDING", (0,0), (-1,-1), 6),
    ("LEFTPADDING",   (0,0), (-1,-1), 8),
    ("RIGHTPADDING",  (0,0), (-1,-1), 8),
    ("BOX",           (0,0), (-1,-1), 0.8, TEAL),
]))
story.append(fu_tbl)
story.append(Spacer(1, 3*mm))

sig_data = [[
    Paragraph("Physician: ___________________________", FIELD_LABEL),
    Paragraph("Licence #: _______________", FIELD_LABEL),
    Paragraph("Signature: ___________________________", FIELD_LABEL),
    Paragraph("Date: ___________", FIELD_LABEL),
]]
sig_tbl = Table(sig_data, colWidths=[W*0.3, W*0.2, W*0.3, W*0.2])
sig_tbl.setStyle(TableStyle([
    ("TOPPADDING",    (0,0), (-1,-1), 4),
    ("BOTTOMPADDING", (0,0), (-1,-1), 4),
    ("LEFTPADDING",   (0,0), (-1,-1), 4),
    ("RIGHTPADDING",  (0,0), (-1,-1), 4),
    ("LINEABOVE",     (0,0), (-1,0), 0.6, DARK_GREY),
]))
story.append(sig_tbl)
story.append(Spacer(1, 2*mm))

# ── Footer ──────────────────────────────────────────────────────────────────
footer = Paragraph(
    "This discharge card is for informational purposes.  "
    "Based on: Tintinalli's Emergency Medicine (9th ed.) and Rosen's Emergency Medicine (9th ed.).  "
    "If in doubt, always seek medical advice.  |  ORIGINAL – PHARMACY   COPY 1 – CHART   "
    "COPY 2 – FAMILY PHYSICIAN   COPY 3 – PATIENT",
    S("ft", fontSize=7, textColor=DARK_GREY, alignment=TA_CENTER))
story.append(footer)

# ── Build ────────────────────────────────────────────────────────────────────
doc.build(story)
print(f"PDF written → {OUTPUT}")
Running Command

cd /home/daytona/workspace/pediatric-discharge && python generate_card.py 2>&1

The PDF was generated successfully. Here is your download link:

Pediatric Respiratory Discharge Card

PDF Document · PDF


Here's what the card contains, structured across one A4 page:
Patient Info Bar — fillable fields for name, DOB, weight, diagnosis, follow-up physician & timeframe

🫁 ASTHMA
  • Traffic-light action plan (Green / Yellow / Red zones) — signs and corresponding actions for each zone, matching the ED Asthma Clinical Pathway from Tintinalli's (9th ed.)
  • Medications prescribed: Quick relief inhaler (salbutamol + spacer type), controller inhaler (budesonide/fluticasone), oral steroid (prednisolone or dexamethasone course)
  • Spacer/MDI technique reminder
👶 BRONCHIOLITIS
  • Plain-language explanation (RSV, day 3–5 peak, 7–10 day course)
  • Two-column layout: home care vs. return-to-ED signs (feeding, hydration, work of breathing, cyanosis) — per Rosen's EM disposition criteria
  • 24-hour follow-up instruction
🌙 CROUP
  • Barking cough / stridor explanation
  • Medications given in ED: dexamethasone (dose/route) + nebulised epinephrine with post-treatment observation note
  • Home care tips + return signs including drooling/dysphagia (to rule out epiglottitis)
  • Discharge criteria checklist
⚠️ General Emergency Signs — red-flag symptoms triggering immediate ED return for any condition
💡 Prevention & Trigger Avoidance — common triggers and practical prevention tips
Signature bar + copy distribution footer (pharmacy / chart / GP / patient)
This is a shared conversation. Sign in to Orris to start your own chat.