""" HoffDesk Dashboard â Dev Server Serves the static dashboard with mock data for Sprint 1 development. Run: python dev_server.py """ from fastapi import FastAPI from fastapi.responses import HTMLResponse, FileResponse from fastapi.staticfiles import StaticFiles from pathlib import Path from datetime import datetime, timezone, timedelta import json, random app = FastAPI() BASE = Path(__file__).parent CST = timezone(timedelta(hours=-5)) # --- Mock Data Generator --- def mock_today(): now = datetime.now(CST) return { "timestamp": now.isoformat(), "calendar": { "status": "ok", "events_count": 3, "events": [ { "uid": "mock-001", "summary": "Harper's Soccer Practice", "start": now.replace(hour=16, minute=0, second=0).isoformat(), "end": now.replace(hour=17, minute=0, second=0).isoformat(), "is_all_day": False, "location": "Green Bay Community Center", "description": None, "attendees": ["Harper"] }, { "uid": "mock-002", "summary": "Dentist â Sullivan", "start": now.replace(hour=10, minute=30, second=0).isoformat(), "end": now.replace(hour=11, minute=15, second=0).isoformat(), "is_all_day": False, "location": "Dr. Patel, 123 Main St", "description": "Regular checkup", "attendees": None }, { "uid": "mock-003", "summary": "Date Night ð·", "start": now.replace(hour=19, minute=0, second=0).isoformat(), "end": now.replace(hour=21, minute=30, second=0).isoformat(), "is_all_day": False, "location": "KÅv â Ashwaubenon", "description": None, "attendees": ["Matt", "Aundrea"] } ] }, "weather": { "status": "ok", "location": { "name": "Green Bay, WI", "lat": 44.5133, "lon": -88.0133 }, "current": { "temperature_f": 52, "feels_like_f": 49, "condition": "Partly cloudy", "humidity_pct": 62, "wind_mph": 10, "updated_at": now.isoformat() }, "forecast": [ { "hour": f"{(now.hour + i) % 24:02d}:00", "temperature_f": 52 - i + random.randint(-2, 2), "condition": ["Partly cloudy", "Cloudy", "Clear", "Overcast"][i % 4], "precipitation_chance_pct": max(0, 15 - i * 3 + random.randint(0, 10)) } for i in range(1, 7) ] }, "health": { "overall_status": "healthy", "components": { "openclaw_gateway": {"status": "ok", "last_check": now.isoformat(), "latency_ms": 8}, "radicale_caldav": {"status": "ok", "last_check": now.isoformat(), "latency_ms": 14}, "ollama_local": {"status": "ok", "last_check": now.isoformat(), "latency_ms": 45}, "cloudflare_tunnel": {"status": "ok", "last_check": now.isoformat(), "latency_ms": 22} }, "disk_usage": { "total_gb": 476.9, "used_gb": 142.3, "free_gb": 334.6, "usage_pct": 29.8 } }, "meta": { "cache_ttl_seconds": 60, "data_freshness": { "calendar_seconds_ago": 12, "weather_seconds_ago": 180 } } } # --- Routes --- @app.get("/", response_class=HTMLResponse) async def dashboard(): return (BASE / "templates" / "index.html").read_text() @app.get("/api/today") async def api_today(): return mock_today() @app.get("/api/calendar/upcoming") async def api_calendar(hours: int = 24): data = mock_today() return {"status": "ok", "events": data["calendar"]["events"]} @app.get("/api/weather") async def api_weather(): data = mock_today() return {"status": "ok", "data": data["weather"]} @app.get("/api/health") async def api_health(): data = mock_today() return {"status": "ok", "overall": data["health"]} @app.get("/healthz") async def healthz(): return "ok" # --- API Endpoints for Events --- @app.get("/api/events-list", response_class=HTMLResponse) async def api_events_list(): """Return list view HTML fragment for events card.""" data = mock_today() events = data["calendar"]["events"] if not events: return '
No upcoming events
' html = '