feat: Phase 2C — notes & todos

- New models: SiteNote, SiteTodo (site_notes, site_todos tables)
- New schemas: NoteOut, TodoOut with creator/done-by name enrichment
- New router: /api/notes/ — full CRUD for notes and todos
  - Notes: create, list (pinned first), update (body + pin), delete
  - Todos: create, list (undone high-priority first), toggle done, edit, delete
  - Marking done records done_at + done_by_id; unchecking clears both
- Migrations: CREATE TABLE IF NOT EXISTS for both tables (additive, safe)
- NotesPage.jsx: two-column layout — notes left, todos right
  - Notes: inline click-to-edit, pin toggle, Ctrl+Enter to save, pinned section on top
  - Todos: inline edit, high-priority flag, completed collapse toggle
- /notes route added to App.jsx
- NotebookPen sidebar entry between Διαχείριση and Ρυθμίσεις

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-06-07 21:34:57 +03:00
parent b15fb27a37
commit cc356077ba
7 changed files with 766 additions and 1 deletions

View File

@@ -0,0 +1,51 @@
from pydantic import BaseModel
from typing import Optional
from datetime import datetime
class NoteCreate(BaseModel):
body: str
is_pinned: bool = False
class NoteUpdate(BaseModel):
body: Optional[str] = None
is_pinned: Optional[bool] = None
class NoteOut(BaseModel):
id: int
body: str
is_pinned: bool
created_by_id: int
created_by_name: Optional[str] = None
created_at: datetime
updated_at: datetime
model_config = {"from_attributes": True}
class TodoCreate(BaseModel):
body: str
priority: str = "normal"
class TodoUpdate(BaseModel):
body: Optional[str] = None
priority: Optional[str] = None
is_done: Optional[bool] = None
class TodoOut(BaseModel):
id: int
body: str
is_done: bool
done_at: Optional[datetime] = None
done_by_id: Optional[int] = None
done_by_name: Optional[str] = None
created_by_id: int
created_by_name: Optional[str] = None
created_at: datetime
priority: str
model_config = {"from_attributes": True}