docs: add survey invite tracking design and implementation plan
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
76
docs/plans/2026-03-04-survey-invite-tracking-design.md
Normal file
76
docs/plans/2026-03-04-survey-invite-tracking-design.md
Normal file
@@ -0,0 +1,76 @@
|
||||
# Survey Invite Tracking — Design
|
||||
|
||||
> **Date:** 2026-03-04
|
||||
> **Status:** Approved
|
||||
|
||||
## Goal
|
||||
|
||||
Add invite tracking to the FlowPilot survey so Michael can create personalized links, optionally email them, and see who has/hasn't responded. Each invite token is single-use — one submission per token.
|
||||
|
||||
## Data Model
|
||||
|
||||
### New table: `survey_invites`
|
||||
|
||||
| Column | Type | Notes |
|
||||
|--------|------|-------|
|
||||
| `id` | UUID PK | |
|
||||
| `token` | VARCHAR(32) UNIQUE | Random URL-safe token |
|
||||
| `recipient_name` | VARCHAR(255) NOT NULL | Who it's for |
|
||||
| `recipient_email` | VARCHAR(255) NULL | Only if emailing |
|
||||
| `status` | VARCHAR(20) DEFAULT 'pending' | `pending` or `completed` |
|
||||
| `email_sent` | BOOLEAN DEFAULT false | Whether Resend email was sent |
|
||||
| `created_at` | TIMESTAMPTZ NOT NULL | |
|
||||
| `completed_at` | TIMESTAMPTZ NULL | Set on submission |
|
||||
|
||||
### Modified table: `survey_responses`
|
||||
|
||||
Add `invite_id` UUID FK nullable → `survey_invites.id`. Responses from tokenless `/survey` have `invite_id = NULL`.
|
||||
|
||||
## API Endpoints
|
||||
|
||||
### Public (no auth)
|
||||
|
||||
- `GET /api/v1/survey/invite/{token}` — Returns invite status (`{ name, status }`). If `completed`, frontend shows "already submitted" screen. Returns 404 for invalid tokens.
|
||||
- `POST /api/v1/survey/submit` — Modified: accepts optional `token` field. If token provided, validates it's `pending`, links the response, and marks invite as `completed`. Returns 409 if token already used.
|
||||
|
||||
### Admin (super_admin auth)
|
||||
|
||||
- `POST /api/v1/admin/survey-invites` — Create invite. Body: `{ recipient_name, recipient_email?, send_email? }`. Generates token, optionally sends email. Returns the invite with the full survey URL.
|
||||
- `GET /api/v1/admin/survey-invites` — List all invites with status.
|
||||
|
||||
## Frontend
|
||||
|
||||
### Survey page changes (`/survey`)
|
||||
|
||||
- On load, reads `?t=<token>` from URL params
|
||||
- If token present: calls `GET /survey/invite/{token}`
|
||||
- If `completed` → show "already submitted" screen
|
||||
- If `pending` → show survey, include token in submission payload
|
||||
- If 404 → show survey without token (treat as open link)
|
||||
- If no token: show survey as-is (open access)
|
||||
|
||||
### Admin page (`/admin/survey-invites`)
|
||||
|
||||
**Top section: Create Invite**
|
||||
- Name input (required) + Email input (optional)
|
||||
- "Generate Link" button → creates invite, shows URL with copy button
|
||||
- "Send Email" button → creates invite with `send_email: true`, shows confirmation toast
|
||||
- "Send Email" only enabled when email field is filled
|
||||
|
||||
**Bottom section: Invite Table**
|
||||
- Columns: Name, Email, Status badge (pending amber / completed green), Sent (email icon or dash), Created date, Completed date
|
||||
- Sorted by created_at descending
|
||||
|
||||
## Email Template
|
||||
|
||||
Uses existing `EmailService` + Resend pattern. Dark-themed email matching Slate & Ice aesthetic:
|
||||
- Subject: "FlowPilot Survey — Your expertise matters"
|
||||
- Body: Brief intro, CTA button linking to `/survey?t=<token>`, ~5 minutes note
|
||||
- From: existing `FROM_EMAIL` config
|
||||
|
||||
## Constraints
|
||||
|
||||
- No token expiration
|
||||
- No reminder/resend (keep it simple)
|
||||
- Tokenless survey still works for open sharing
|
||||
- One submission per invite token (enforced backend + frontend)
|
||||
Reference in New Issue
Block a user