rspace-online/modules/choices/mod.ts

70 lines
2.2 KiB
TypeScript

/**
* Choices module — voting, ranking, and multi-criteria scoring tools.
*
* The folk-choice-* web components live in lib/ (shared with canvas).
* This module provides:
* - A page listing choice shapes in the current space
* - API to query choice shapes from the Automerge store
* - Links to create new choices on the canvas
*/
import { Hono } from "hono";
import { renderShell } from "../../server/shell";
import type { RSpaceModule } from "../../shared/module";
import { getModuleInfoList } from "../../shared/module";
import { getDocumentData } from "../../server/community-store";
const routes = new Hono();
// GET /api/choices — list choice shapes in the current space
routes.get("/api/choices", async (c) => {
const space = c.req.param("space") || c.req.query("space") || "demo";
const docData = getDocumentData(space);
if (!docData?.shapes) {
return c.json({ choices: [], total: 0 });
}
const choiceTypes = ["folk-choice-vote", "folk-choice-rank", "folk-choice-spider"];
const choices: any[] = [];
for (const [id, shape] of Object.entries(docData.shapes as Record<string, any>)) {
if (shape.forgotten) continue;
if (choiceTypes.includes(shape.type)) {
choices.push({
id,
type: shape.type,
title: shape.title || "Untitled",
mode: shape.mode,
optionCount: (shape.options || []).length,
voteCount: (shape.votes || shape.rankings || shape.scores || []).length,
createdAt: shape.createdAt,
});
}
}
return c.json({ choices, total: choices.length });
});
// GET / — choices page
routes.get("/", (c) => {
const spaceSlug = c.req.param("space") || "demo";
return c.html(renderShell({
title: `${spaceSlug} — Choices | rSpace`,
moduleId: "choices",
spaceSlug,
modules: getModuleInfoList(),
theme: "light",
styles: `<link rel="stylesheet" href="/modules/choices/choices.css">`,
body: `<folk-choices-dashboard space="${spaceSlug}"></folk-choices-dashboard>`,
scripts: `<script type="module" src="/modules/choices/folk-choices-dashboard.js"></script>`,
}));
});
export const choicesModule: RSpaceModule = {
id: "choices",
name: "rChoices",
icon: "☑",
description: "Polls, rankings, and multi-criteria scoring",
routes,
};