diff --git a/docs/plans/2026-02-18-feedback-form-design.md b/docs/plans/2026-02-18-feedback-form-design.md index d59b6ea5..e61fccf9 100644 --- a/docs/plans/2026-02-18-feedback-form-design.md +++ b/docs/plans/2026-02-18-feedback-form-design.md @@ -1,21 +1,26 @@ # Feedback Form — Design Document > **Date:** 2026-02-18 +> **Revised:** 2026-02-18 — added DB persistence, feedback type helper text, confirmation email, future TODO notes ## Overview -A feedback form page where logged-in users can submit bug reports, feature requests, and general feedback. Submissions are emailed to a configurable address via the existing Resend infrastructure. No database storage. +A feedback form page where logged-in users can submit bug reports, feature requests, and general feedback. Submissions are persisted to a `feedback` database table and emailed to a configurable address via the existing Resend infrastructure. A confirmation email is sent back to the submitter. ## Feedback Types -1. Bug Report -2. Feature Request -3. Usability Issue -4. Documentation -5. General Feedback +| Type | Helper Text | +|------|-------------| +| Bug Report | Something is broken or not working as expected | +| Feature Request | An idea for something new you'd like to see | +| Usability Issue | Something works but is confusing or hard to use | +| Documentation | Feedback on help docs, tooltips, or in-app guidance | +| General Feedback | Anything else — thoughts, impressions, suggestions | ## Email Format +### Admin Notification Email + **Subject:** ``` [ResolutionFlow Feedback] Bug Report — 2026-02-18 — ACC-7X3K @@ -37,6 +42,34 @@ User's written feedback text goes here... Reply-to is set to the submitter's email for direct replies. +### Confirmation Email (to submitter) + +**Subject:** `Thanks for your feedback — ResolutionFlow` + +**Body:** Brief thank you, echoes back the feedback type and a preview of their message (first ~100 chars). Dark-themed HTML matching existing email templates. + +Fire-and-forget: if this email fails, it's logged but doesn't affect the user's submission response. + +## Database + +### `feedback` table + +| Column | Type | Notes | +|--------|------|-------| +| `id` | UUID | PK | +| `account_id` | UUID | FK to `accounts`, nullable, SET NULL on delete | +| `user_id` | UUID | FK to `users`, SET NULL on delete | +| `email` | String(255) | The reply-to email submitted | +| `feedback_type` | String(50) | Enum value | +| `message` | Text | Full feedback text | +| `created_at` | DateTime(tz) | Timestamp | + +Indexes on `account_id`, `user_id`, `created_at`. + +No admin view or API read endpoints — queryable directly in the DB when needed. + +**Important:** DB write happens *before* email sending. Email failure does NOT prevent the feedback from being saved. + ## Frontend ### Page @@ -57,17 +90,18 @@ Reply-to is set to the submitter's email for direct replies. | Field | Details | |-------|---------| | Email | Auto-filled from logged-in user, editable | -| Feedback Type | Dropdown select (5 types) | +| Feedback Type | Custom dropdown with description text per option | | Message | Textarea, required, min 10 chars | | Submit | `bg-gradient-brand`, disabled while submitting | ### UX Flow 1. Form loads with email pre-filled -2. User selects type, writes message, submits -3. Button shows loading state during submission -4. On success: success message, form resets -5. On error: inline error, form stays populated for retry +2. User opens feedback type dropdown — sees label + helper description for each option +3. User selects type, writes message, submits +4. Button shows loading state during submission +5. On success: success message with confirmation email note, form resets +6. On error: inline error, form stays populated for retry ### Styling @@ -75,7 +109,7 @@ Standard page layout — `container mx-auto`, `bg-card border border-border roun ### API Client -`feedbackApi.submitFeedback()` in a new `api/feedback.ts` module. +`feedbackApi.submit()` in a new `api/feedback.ts` module. ## Backend @@ -86,9 +120,9 @@ Standard page layout — `container mx-auto`, `bg-card border border-border roun ### Schema `FeedbackSubmission` in `schemas/feedback.py`: -- `email: str` — validated as email -- `feedback_type: str` — enum-validated against the 5 types -- `message: str` — min 10 chars +- `email: EmailStr` — validated as email +- `feedback_type: FeedbackType` — enum-validated against the 5 types +- `message: str` — min 10 chars, max 5000 chars ### Auth @@ -100,18 +134,22 @@ Requires `get_current_active_user`. Account display code pulled from user's acco ### Email Service -New `EmailService.send_feedback_email()` static method: -- Uses existing Resend client -- Sets `reply_to` to submitter's email -- Dark-themed HTML matching existing email templates +Two new static methods on `EmailService`: +- `send_feedback_email()` — admin notification with reply-to +- `send_feedback_confirmation_email()` — thank-you to submitter (fire-and-forget) + +Both use existing Resend client and dark-themed HTML matching existing email templates. ### Rate Limiting One submission per minute per user. +## Future Consideration + +**Post-session contextual feedback prompt** — do NOT build now. TODO comments in `FeedbackPage.tsx` and `endpoints/feedback.py` serve as breadcrumbs. Concept: after completing a troubleshooting session, show a subtle inline prompt that opens a lightweight version of the feedback form pre-tagged with tree/session context. The feedback infrastructure (DB table, email service, API endpoint) built here should be directly reusable. + ## Not Included (YAGNI) -- No DB persistence -- No admin view +- No admin view for feedback - No file attachments - No public (unauthenticated) access