feat: personal notes on bill detail pages

- bill_notes table (migration 0014): user_id, bill_id, content, pinned,
  created_at, updated_at; unique constraint (user_id, bill_id)
- BillNote SQLAlchemy model with back-refs on User and Bill
- GET/PUT/DELETE /api/notes/{bill_id} — auth-required, one note per (user, bill)
- NotesPanel component: collapsible, auto-resize textarea, pin toggle,
  save + delete; shows last-saved date and pin indicator in collapsed header
- Pinned notes render above BriefPanel; unpinned render below DraftLetterPanel
- Guests see nothing (token guard in component + query disabled)

Co-Authored-By: Jack Levy
This commit is contained in:
Jack Levy
2026-03-01 22:14:52 -05:00
parent 128c8e9257
commit 62a217cb22
13 changed files with 393 additions and 30 deletions

View File

@@ -4,6 +4,26 @@ from typing import Any, Generic, Optional, TypeVar
from pydantic import BaseModel
# ── Notifications ──────────────────────────────────────────────────────────────
# ── Bill Notes ────────────────────────────────────────────────────────────────
class BillNoteSchema(BaseModel):
id: int
bill_id: str
content: str
pinned: bool
created_at: datetime
updated_at: datetime
model_config = {"from_attributes": True}
class BillNoteUpsert(BaseModel):
content: str
pinned: bool = False
# ── Notifications ──────────────────────────────────────────────────────────────
class NotificationSettingsResponse(BaseModel):