Open app/main.py and replace its entire contents with: from fastapi import FastAPI, Request, UploadFile, File, HTTPException from fastapi.responses import HTMLResponse from fastapi.staticfiles import StaticFiles from fastapi.templating import Jinja2Templates from app.db import fetch_monthly_summary, fetch_retention_pen, fetch_campaigns app = FastAPI() app.mount("/static", StaticFiles(directory="app/static"), name="static") templates = Jinja2Templates(directory="app/templates") @app.get("/", response_class=HTMLResponse) async def dashboard(request: Request): data = await fetch_monthly_summary() latest = data[-1] if data else None return templates.TemplateResponse( "dashboard.html", {"request": request, "latest": latest}, ) @app.get("/api/monthly-summary") async def api_monthly_summary(): data = await fetch_monthly_summary() return {"data": data} @app.get("/api/retention-pen") async def api_retention_pen(): data = await fetch_retention_pen() return {"data": data} @app.get("/api/campaigns") async def api_campaigns(): data = await fetch_campaigns() return {"data": data} # --- Data upload stub (CSV -> storage path placeholder) --- from uuid import uuid4 async def upload_to_supabase_storage(file: UploadFile) -> str: """ Stub implementation: in future this should upload to Supabase Storage. For now we just pretend and return a generated path. """ return f"books/{uuid4()}-{file.filename}" @app.post("/upload-book") async def upload_book(file: UploadFile = File(...)): if not file.filename.endswith(".csv"): raise HTTPException(status_code=400, detail="Only CSV files are allowed") storage_path = await upload_to_supabase_storage(file) return {"message": "Upload complete", "path": storage_path} # --- WhatsApp automation stub --- from pydantic import BaseModel class WhatsAppMessage(BaseModel): contact_id: str phone_number: str | None = None campaign_id: str | None = None message_preview: str @app.post("/api/whatsapp/send") async def send_whatsapp_stub(payload: WhatsAppMessage): # Later: push to Make/n8n or another service. print("WhatsApp stub queued:", payload.dict()) return { "status": "queued", "detail": "WhatsApp message queued for external automation (stub).", }