Industry Applications
legal
How to Build a Legal Case Management Dashboard
Track all cases in one dashboard with status, deadlines, and billing.
Jay Banlasan
The AI Systems Guy
A legal case management dashboard brings every active case, deadline, and billing metric into one view. I built this for a firm where partners were asking "what's the status?" ten times a day because information lived in three different systems. Now they open one page and see everything.
What You Need Before Starting
- Python 3.8+ with FastAPI
- SQLite databases from previous legal systems
- Basic HTML/CSS for the dashboard interface
Step 1: Create the Unified Case Database
import sqlite3
from datetime import datetime
def init_case_db(db_path="case_management.db"):
conn = sqlite3.connect(db_path)
conn.execute("""
CREATE TABLE IF NOT EXISTS cases (
id INTEGER PRIMARY KEY AUTOINCREMENT,
case_number TEXT UNIQUE,
case_name TEXT,
client_name TEXT,
practice_area TEXT,
assigned_attorney TEXT,
status TEXT DEFAULT 'active',
opened_date TEXT,
closed_date TEXT,
case_value REAL,
notes TEXT
)
""")
conn.commit()
conn.close()
Step 2: Build the Dashboard API
from fastapi import FastAPI
from fastapi.responses import HTMLResponse
app = FastAPI()
@app.get("/dashboard/overview")
def dashboard_overview():
conn = sqlite3.connect("case_management.db")
active_count = conn.execute("SELECT COUNT(*) FROM cases WHERE status = 'active'").fetchone()[0]
by_attorney = conn.execute("""
SELECT assigned_attorney, COUNT(*) as count FROM cases WHERE status = 'active'
GROUP BY assigned_attorney ORDER BY count DESC
""").fetchall()
by_area = conn.execute("""
SELECT practice_area, COUNT(*) as count FROM cases WHERE status = 'active'
GROUP BY practice_area ORDER BY count DESC
""").fetchall()
conn.close()
deadline_conn = sqlite3.connect("legal_deadlines.db")
overdue = deadline_conn.execute(
"SELECT COUNT(*) FROM deadlines WHERE status = 'active' AND due_date < date('now')"
).fetchone()[0]
upcoming_week = deadline_conn.execute(
"SELECT COUNT(*) FROM deadlines WHERE status = 'active' AND due_date BETWEEN date('now') AND date('now', '+7 days')"
).fetchone()[0]
deadline_conn.close()
return {
"active_cases": active_count,
"overdue_deadlines": overdue,
"deadlines_this_week": upcoming_week,
"by_attorney": [{"attorney": a[0], "cases": a[1]} for a in by_attorney],
"by_practice_area": [{"area": a[0], "cases": a[1]} for a in by_area]
}
@app.get("/dashboard/cases")
def list_cases(status: str = "active", attorney: str = None):
conn = sqlite3.connect("case_management.db")
sql = "SELECT * FROM cases WHERE status = ?"
params = [status]
if attorney:
sql += " AND assigned_attorney = ?"
params.append(attorney)
sql += " ORDER BY opened_date DESC"
rows = conn.execute(sql, params).fetchall()
conn.close()
columns = ["id", "case_number", "case_name", "client_name", "practice_area",
"assigned_attorney", "status", "opened_date", "closed_date", "case_value", "notes"]
return [dict(zip(columns, row)) for row in rows]
Step 3: Add Case Detail with Timeline
@app.get("/dashboard/case/{case_number}")
def case_detail(case_number: str):
conn = sqlite3.connect("case_management.db")
case = conn.execute("SELECT * FROM cases WHERE case_number = ?", (case_number,)).fetchone()
conn.close()
if not case:
return {"error": "Case not found"}
columns = ["id", "case_number", "case_name", "client_name", "practice_area",
"assigned_attorney", "status", "opened_date", "closed_date", "case_value", "notes"]
case_dict = dict(zip(columns, case))
dl_conn = sqlite3.connect("legal_deadlines.db")
deadlines = dl_conn.execute(
"SELECT deadline_type, description, due_date, status FROM deadlines WHERE case_id = ? ORDER BY due_date",
(case_number,)
).fetchall()
dl_conn.close()
billing_conn = sqlite3.connect("legal_billing.db")
billing = billing_conn.execute("""
SELECT SUM(hours), SUM(amount) FROM time_entries WHERE client_id = ? AND status != 'void'
""", (case[0],)).fetchone()
billing_conn.close()
case_dict["deadlines"] = [{"type": d[0], "description": d[1], "due": d[2], "status": d[3]} for d in deadlines]
case_dict["total_hours"] = billing[0] or 0
case_dict["total_billed"] = billing[1] or 0
return case_dict
Step 4: Build the HTML Dashboard
@app.get("/", response_class=HTMLResponse)
def dashboard_page():
overview = dashboard_overview()
cases = list_cases()
case_rows = ""
for c in cases[:20]:
case_rows += f"""<tr>
<td><a href="/dashboard/case/{c['case_number']}">{c['case_number']}</a></td>
<td>{c['case_name']}</td>
<td>{c['client_name']}</td>
<td>{c['assigned_attorney']}</td>
<td>{c['practice_area']}</td>
<td>{c['opened_date']}</td>
</tr>"""
return f"""<!DOCTYPE html>
<html><head><title>Case Management</title>
<style>
body {{ font-family: sans-serif; margin: 20px; }}
.stats {{ display: flex; gap: 20px; margin-bottom: 20px; }}
.stat {{ background: #f5f5f5; padding: 15px 25px; border-radius: 8px; }}
.stat h3 {{ margin: 0; font-size: 28px; }}
.stat p {{ margin: 5px 0 0; color: #666; }}
.overdue {{ background: #fee; }}
table {{ border-collapse: collapse; width: 100%; }}
th, td {{ padding: 8px 12px; text-align: left; border-bottom: 1px solid #eee; }}
th {{ background: #f9f9f9; }}
a {{ color: #2563eb; text-decoration: none; }}
</style></head>
<body>
<h1>Case Management Dashboard</h1>
<div class="stats">
<div class="stat"><h3>{overview['active_cases']}</h3><p>Active Cases</p></div>
<div class="stat overdue"><h3>{overview['overdue_deadlines']}</h3><p>Overdue Deadlines</p></div>
<div class="stat"><h3>{overview['deadlines_this_week']}</h3><p>Due This Week</p></div>
</div>
<h2>Active Cases</h2>
<table><tr><th>Case #</th><th>Name</th><th>Client</th><th>Attorney</th><th>Area</th><th>Opened</th></tr>
{case_rows}</table>
</body></html>"""
Step 5: Run the Dashboard
pip install fastapi uvicorn
uvicorn case_dashboard:app --port 8080 --reload
What to Build Next
Add a Slack integration that sends each attorney their personal daily brief: their active cases, upcoming deadlines, and unbilled time from yesterday.
Related Reading
- Building a Reporting Dashboard from Scratch - dashboard design
- AI in Legal and Compliance - legal tech
- AI for Workflow Optimization - workflow management
Want this system built for your business?
Get a free assessment. We will map every system your business needs and show you the ROI.
Get Your Free Assessment