83 lines
1.8 KiB
TypeScript
83 lines
1.8 KiB
TypeScript
/**
|
|
* rChoices Automerge document schemas.
|
|
*
|
|
* Stores collaborative voting sessions with real-time vote sync.
|
|
* Canvas-based choice shapes remain in community-store; this doc
|
|
* handles standalone multiplayer sessions via the dashboard.
|
|
*
|
|
* DocId format: {space}:choices:sessions
|
|
*/
|
|
|
|
import type { DocSchema } from '../../shared/local-first/document';
|
|
|
|
// ── Document types ──
|
|
|
|
export interface ChoiceOption {
|
|
id: string;
|
|
label: string;
|
|
color: string;
|
|
}
|
|
|
|
export interface ChoiceSession {
|
|
id: string;
|
|
title: string;
|
|
type: 'vote' | 'rank' | 'score';
|
|
/** 'vote' mode: plurality, approval, or single */
|
|
mode?: 'plurality' | 'approval' | 'single';
|
|
options: ChoiceOption[];
|
|
createdBy: string | null;
|
|
createdAt: number;
|
|
closed: boolean;
|
|
}
|
|
|
|
export interface ChoiceVote {
|
|
participantDid: string;
|
|
/** For 'vote': optionId → 1 (selected). For 'rank': optionId → rank position. For 'score': optionId → 0-100. */
|
|
choices: Record<string, number>;
|
|
updatedAt: number;
|
|
}
|
|
|
|
export interface ChoicesDoc {
|
|
meta: {
|
|
module: string;
|
|
collection: string;
|
|
version: number;
|
|
spaceSlug: string;
|
|
createdAt: number;
|
|
};
|
|
sessions: Record<string, ChoiceSession>;
|
|
/** Keyed by `${sessionId}:${participantDid}` */
|
|
votes: Record<string, ChoiceVote>;
|
|
}
|
|
|
|
// ── Schema registration ──
|
|
|
|
export const choicesSchema: DocSchema<ChoicesDoc> = {
|
|
module: 'choices',
|
|
collection: 'sessions',
|
|
version: 1,
|
|
init: (): ChoicesDoc => ({
|
|
meta: {
|
|
module: 'choices',
|
|
collection: 'sessions',
|
|
version: 1,
|
|
spaceSlug: '',
|
|
createdAt: Date.now(),
|
|
},
|
|
sessions: {},
|
|
votes: {},
|
|
}),
|
|
migrate: (doc: any, _fromVersion: number) => {
|
|
if (!doc.sessions) doc.sessions = {};
|
|
if (!doc.votes) doc.votes = {};
|
|
doc.meta.version = 1;
|
|
return doc;
|
|
},
|
|
};
|
|
|
|
// ── Helpers ──
|
|
|
|
export function choicesDocId(space: string) {
|
|
return `${space}:choices:sessions` as const;
|
|
}
|