Full-stack beta feedback system: Backend: - BetaFeedback model with reaction, category, text, page context - POST /feedback/beta (any auth user), GET /feedback/beta (admin, filtered) - Alembic migration 065 with indexes on user_id, reaction, created_at Frontend: - Persistent "Feedback" tab on right edge of all authenticated pages - Slide-out panel: quick reaction (👍😐👎), category pills, optional text - Auto-captures page URL and FlowPilot session ID - Hidden on mobile (<640px), closes on Escape/outside click - Shows "Thanks!" confirmation then auto-closes Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
41 lines
963 B
Python
41 lines
963 B
Python
import uuid
|
|
from datetime import datetime
|
|
from enum import Enum
|
|
from typing import Optional
|
|
|
|
from pydantic import BaseModel, Field
|
|
|
|
|
|
class ReactionType(str, Enum):
|
|
POSITIVE = "positive"
|
|
NEUTRAL = "neutral"
|
|
NEGATIVE = "negative"
|
|
|
|
|
|
class FeedbackCategory(str, Enum):
|
|
BUG = "bug"
|
|
FEATURE = "feature"
|
|
CONFUSING = "confusing"
|
|
PRAISE = "praise"
|
|
|
|
|
|
class BetaFeedbackCreate(BaseModel):
|
|
reaction: ReactionType
|
|
category: Optional[FeedbackCategory] = None
|
|
text: Optional[str] = Field(None, max_length=5000)
|
|
page_url: Optional[str] = Field(None, max_length=500)
|
|
session_id: Optional[str] = Field(None, max_length=100)
|
|
|
|
|
|
class BetaFeedbackResponse(BaseModel):
|
|
id: uuid.UUID
|
|
user_id: uuid.UUID
|
|
reaction: str
|
|
category: Optional[str] = None
|
|
text: Optional[str] = None
|
|
page_url: Optional[str] = None
|
|
session_id: Optional[str] = None
|
|
created_at: datetime
|
|
|
|
model_config = {"from_attributes": True}
|