diff --git a/src/server/app.ts b/src/server/app.ts index fe28461..9085061 100644 --- a/src/server/app.ts +++ b/src/server/app.ts @@ -1,6 +1,7 @@ import { Hono } from "hono" import { cors } from "hono/cors" import { logger } from "hono/logger" +import { legislationRouter } from "./features/legislation" import { politicianRouter } from "./features/politicians" import { pushRouter } from "./features/push" @@ -17,6 +18,7 @@ app.use( ) app.get("/health", (c) => c.json({ status: "ok" })) +app.route("/legislation", legislationRouter) app.route("/politicians", politicianRouter) app.route("/push", pushRouter) diff --git a/src/server/features/legislation/index.ts b/src/server/features/legislation/index.ts new file mode 100644 index 0000000..55e3d15 --- /dev/null +++ b/src/server/features/legislation/index.ts @@ -0,0 +1 @@ +export { legislationRouter } from "./router" diff --git a/src/server/features/legislation/router.ts b/src/server/features/legislation/router.ts new file mode 100644 index 0000000..11743d7 --- /dev/null +++ b/src/server/features/legislation/router.ts @@ -0,0 +1,60 @@ +import { Hono } from "hono" +import { castVoteSchema } from "./schema" +import { + castVote, + getLegislation, + getLegislationText, + getUpcomingLegislation, + getUserVote, +} from "./service" + +export const legislationRouter = new Hono() + +// static routes FIRST — before /:id param routes +legislationRouter.get("/upcoming", async (c) => { + const items = await getUpcomingLegislation() + return c.json(items) +}) + +legislationRouter.get("/:id", async (c) => { + const id = Number(c.req.param("id")) + if (Number.isNaN(id)) return c.json({ error: "invalid id" }, 400) + + const legislation = await getLegislation(id) + if (!legislation) return c.json({ error: "not found" }, 404) + + return c.json(legislation) +}) + +legislationRouter.get("/:id/text", async (c) => { + const id = Number(c.req.param("id")) + if (Number.isNaN(id)) return c.json({ error: "invalid id" }, 400) + + const text = await getLegislationText(id) + if (text === null) return c.json({ error: "not found" }, 404) + + return c.json({ text }) +}) + +legislationRouter.post("/:id/vote", async (c) => { + const id = Number(c.req.param("id")) + if (Number.isNaN(id)) return c.json({ error: "invalid id" }, 400) + + const body = await c.req.json() + const parsed = castVoteSchema.safeParse(body) + if (!parsed.success) return c.json({ error: parsed.error.flatten() }, 400) + + await castVote(id, parsed.data) + return c.json({ ok: true }, 201) +}) + +legislationRouter.get("/:id/vote/:deviceId", async (c) => { + const id = Number(c.req.param("id")) + const deviceId = c.req.param("deviceId") + if (Number.isNaN(id)) return c.json({ error: "invalid id" }, 400) + + const vote = await getUserVote(id, deviceId) + if (!vote) return c.json({ error: "no vote found" }, 404) + + return c.json(vote) +})