82 lines
2.6 KiB
Python
82 lines
2.6 KiB
Python
from __future__ import annotations
|
|
|
|
from pathlib import Path
|
|
|
|
from fastapi import FastAPI, HTTPException
|
|
from pydantic import BaseModel, Field
|
|
|
|
from .service import CivicSwarmService
|
|
|
|
|
|
class ProposalCreate(BaseModel):
|
|
city: str
|
|
title: str
|
|
body: str
|
|
geography: str = ""
|
|
tags: list[str] = Field(default_factory=list)
|
|
|
|
|
|
class ResidentCreate(BaseModel):
|
|
resident_key: str
|
|
geography: str = ""
|
|
interests: list[str] = Field(default_factory=list)
|
|
lived_experience: list[str] = Field(default_factory=list)
|
|
languages: list[str] = Field(default_factory=list)
|
|
|
|
|
|
class CommentCreate(BaseModel):
|
|
text: str
|
|
channel: str = "mobile"
|
|
resident_key: str | None = None
|
|
geography: str = ""
|
|
metadata: dict = Field(default_factory=dict)
|
|
|
|
|
|
class PreferenceCreate(BaseModel):
|
|
resident_key: str
|
|
score: float
|
|
channel: str = "mobile"
|
|
|
|
|
|
def create_app(db_path: str | Path = ":memory:") -> FastAPI:
|
|
service = CivicSwarmService.from_path(db_path)
|
|
app = FastAPI(title="CivicSwarm", version="0.1.0")
|
|
app.state.service = service
|
|
|
|
@app.post("/proposals")
|
|
def create_proposal(payload: ProposalCreate):
|
|
return service.create_proposal(payload.city, payload.title, payload.body, payload.geography, payload.tags)
|
|
|
|
@app.post("/residents")
|
|
def create_resident(payload: ResidentCreate):
|
|
return service.register_resident(payload.resident_key, payload.geography, payload.interests, payload.lived_experience, payload.languages)
|
|
|
|
@app.post("/proposals/{proposal_id}/comments")
|
|
def create_comment(proposal_id: int, payload: CommentCreate):
|
|
try:
|
|
return service.add_comment(proposal_id, payload.text, payload.channel, payload.resident_key, payload.geography, payload.metadata)
|
|
except KeyError as exc:
|
|
raise HTTPException(status_code=404, detail=str(exc)) from exc
|
|
|
|
@app.post("/proposals/{proposal_id}/preferences")
|
|
def create_preference(proposal_id: int, payload: PreferenceCreate):
|
|
return service.submit_preference(proposal_id, payload.resident_key, payload.score, payload.channel)
|
|
|
|
@app.get("/proposals/{proposal_id}/route")
|
|
def route_proposal(proposal_id: int, top_n: int = 3):
|
|
return service.route_proposal(proposal_id, top_n=top_n)
|
|
|
|
@app.get("/proposals/{proposal_id}/dashboard")
|
|
def dashboard(proposal_id: int):
|
|
return service.build_dashboard(proposal_id)
|
|
|
|
@app.get("/proposals/{proposal_id}/brief")
|
|
def brief(proposal_id: int):
|
|
return service.export_brief(proposal_id)
|
|
|
|
@app.get("/proposals/{proposal_id}/ledger")
|
|
def ledger(proposal_id: int):
|
|
return service.list_ledger(proposal_id)
|
|
|
|
return app
|