forked from quic-issues/427e7578-d7bf-49c8-aee9-2dd999e25316
103 lines
4.7 KiB
Markdown
103 lines
4.7 KiB
Markdown
# Plan: Combined P2P Polling App
|
|
|
|
## Overview
|
|
Merge the three subfolder projects into a single TypeScript + Yjs + Vite application at the repo root, combining the best features from each.
|
|
|
|
## Technology Choices
|
|
- **Language:** TypeScript (from project 3) with strict mode
|
|
- **CRDT:** Yjs + y-webrtc + y-indexeddb (from projects 1 & 3)
|
|
- **Build:** Vite (shared by all)
|
|
- **Package manager:** npm
|
|
|
|
## Feature Superset
|
|
From **project 1** (group-efa16e66):
|
|
- Collaborative title editing via Y.Text (real-time character-level sync)
|
|
- Delete options
|
|
- Diff-rendering for poll list (reuse DOM elements)
|
|
- Peer count display via awareness
|
|
- Share section with copy-to-clipboard
|
|
|
|
From **project 2** (proposal-8835ffc9):
|
|
- Deadline/timer system (2-minute voting window with countdown)
|
|
- Duplicate detection (case-insensitive)
|
|
|
|
From **project 3** (proposal-88461784):
|
|
- TypeScript types & strict mode
|
|
- Modular architecture (state, sync, render, identity, app layers)
|
|
- IndexedDB persistence (offline support)
|
|
- Online/offline connection tracking
|
|
- Input validation (max lengths, empty checks)
|
|
- HTML escaping for XSS prevention
|
|
- ViewModel pattern for clean render layer
|
|
|
|
## Data Model (Yjs)
|
|
```
|
|
Y.Doc
|
|
├── poll-meta (Y.Map<string>)
|
|
│ └── title → Y.Text (collaborative editing from project 1)
|
|
├── poll-options (Y.Map<OptionRecord>)
|
|
│ └── [optionId] → { id, label, createdAt, createdBy }
|
|
├── poll-votes (Y.Map<string>)
|
|
│ └── [userId] → optionId (single vote per user)
|
|
└── poll-deadline (Y.Map<any>)
|
|
└── deadline → number | null (timestamp, from project 2)
|
|
```
|
|
|
|
## Architecture & File Structure
|
|
```
|
|
/
|
|
├── index.html
|
|
├── package.json
|
|
├── tsconfig.json
|
|
├── vite.config.ts (if needed for any plugins)
|
|
├── src/
|
|
│ ├── main.ts (entry: mount app)
|
|
│ ├── app.ts (orchestrator: init sync, bind events, manage state)
|
|
│ ├── identity.ts (getUserId with localStorage persistence)
|
|
│ ├── state.ts (types, pure functions, ViewModel creation)
|
|
│ ├── sync.ts (Yjs doc, WebRTC provider, IndexedDB, connection status)
|
|
│ ├── render.ts (DOM rendering with escapeHtml, diff-rendering for options)
|
|
│ ├── components/
|
|
│ │ ├── PollTitle.ts (collaborative title input bound to Y.Text)
|
|
│ │ ├── PollList.ts (diff-rendered option list with sorting)
|
|
│ │ ├── PollOption.ts (single option: vote bar, vote/delete buttons)
|
|
│ │ ├── AddOption.ts (input + submit with validation & duplicate check)
|
|
│ │ ├── StatusBar.ts (connection status + peer count)
|
|
│ │ ├── ShareSection.ts (copy URL to clipboard)
|
|
│ │ └── DeadlineTimer.ts (set deadline + countdown display, from project 2)
|
|
│ └── styles.css (merged: project 1's design tokens + project 3's glassmorphism)
|
|
```
|
|
|
|
## Implementation Steps
|
|
|
|
### Step 1: Scaffold root project
|
|
- Create `package.json` with dependencies: yjs, y-webrtc, y-indexeddb, vite, typescript
|
|
- Create `tsconfig.json` (strict, ES2022, bundler resolution)
|
|
- Create `index.html` entry point
|
|
- Create `vite.config.ts` if needed
|
|
|
|
### Step 2: Core layer — identity.ts, state.ts, sync.ts
|
|
- `identity.ts`: port from project 3 (getUserId)
|
|
- `state.ts`: port types from project 3, add deadline types, add ViewModel with deadline/timer info, add vote percentage calculation from project 1
|
|
- `sync.ts`: port from project 3, add Y.Text for title (from project 1), add poll-deadline map, add awareness tracking for peer count (from project 1)
|
|
|
|
### Step 3: App orchestrator — app.ts, main.ts
|
|
- `app.ts`: port from project 3, add deadline handlers, add delete option handler, wire up all components
|
|
- `main.ts`: minimal entry that calls initApp
|
|
|
|
### Step 4: Components
|
|
- `PollTitle.ts`: port collaborative Y.Text editing from project 1, add TypeScript types
|
|
- `AddOption.ts`: merge project 1 (UI/animation) + project 2 (duplicate detection) + project 3 (validation)
|
|
- `PollOption.ts`: port from project 1 (vote bar, percentage, delete button), add TypeScript
|
|
- `PollList.ts`: port diff-rendering from project 1, add TypeScript
|
|
- `StatusBar.ts`: merge project 1 (peer count) + project 3 (online/offline status)
|
|
- `ShareSection.ts`: port from project 1, add TypeScript
|
|
- `DeadlineTimer.ts`: new component porting project 2's deadline/countdown logic to Yjs
|
|
|
|
### Step 5: Styling
|
|
- Merge CSS: use project 1's design tokens and typography as base, incorporate project 3's glassmorphism panel effects, add timer-specific styles from project 2
|
|
|
|
### Step 6: Cleanup
|
|
- Remove three subfolders (after confirming with user)
|
|
- Update root README.md
|