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