feat(annotations): comments, threads, voting system with review mode

Backend:
- comment_threads + comments + object_votes tables with indexes
- Thread/comment CRUD endpoints with socket broadcast
- Vote toggle endpoint with socket broadcast

Frontend:
- AnnotationStore for reactive thread/comment/vote state
- FeedbackPanel with thread list, expanded view, replies, filtering
- Vote toggle buttons in panel
- PinOverlay for canvas pin markers + vote badges
- Review Mode toggle in toolbar (comment bubble icon)
- Jump-to-object from thread view
- Orphaned thread detection for deleted objects
- New comment creation from panel when object selected
- Socket event wiring for real-time sync
This commit is contained in:
Hiren Kangad
2026-03-10 21:04:38 +05:30
parent b6b615957b
commit 303124f518
10 changed files with 1365 additions and 2 deletions
+13
View File
@@ -34,6 +34,8 @@ interface ToolbarProps {
onToggleHelp?: () => void;
onMmImport?: () => void;
onExport?: () => void;
onToggleReview?: () => void;
reviewMode?: boolean;
boardName?: string;
}
@@ -150,6 +152,8 @@ export default function Toolbar({
onToggleHelp,
onMmImport,
onExport,
onToggleReview,
reviewMode,
}: ToolbarProps) {
const showStroke = activeTool === ToolType.PEN;
const showFontSize = activeTool === ToolType.TEXT;
@@ -309,6 +313,15 @@ export default function Toolbar({
</ActionBtn>
)}
{/* Review / Feedback */}
{onToggleReview && (
<ActionBtn onClick={onToggleReview} title="Review Mode (R)" active={reviewMode}>
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" stroke="currentColor" strokeWidth="1.3">
<path d="M2 2.5A1.5 1.5 0 013.5 1h7A1.5 1.5 0 0112 2.5v6A1.5 1.5 0 0110.5 10H6l-3 3v-3H3.5A1.5 1.5 0 012 8.5v-6z" />
</svg>
</ActionBtn>
)}
{/* Spacer */}
<div style={{ flex: 1 }} />