Record a StrikeEvent row whenever a strike is added or removed, and surface them in the activity log timeline with timestamp, child name, and whether the strike was added or removed. - New strike_events table (auto-created on startup) - children router records prev/new strikes on every update - GET /api/logs/strikes and DELETE /api/logs/strikes/:id endpoints - Log view merges strike entries into the timeline (red dot, "✕ Strike added (2/3)" / "↩ Strike removed (1/3)") Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
72 lines
1.7 KiB
Python
72 lines
1.7 KiB
Python
from datetime import date, datetime, timezone
|
|
from pydantic import BaseModel, computed_field, field_serializer
|
|
|
|
|
|
class ActivityLogCreate(BaseModel):
|
|
child_id: int
|
|
subject_id: int | None = None
|
|
session_id: int | None = None
|
|
log_date: date
|
|
notes: str | None = None
|
|
duration_minutes: int | None = None
|
|
|
|
|
|
class ActivityLogUpdate(BaseModel):
|
|
notes: str | None = None
|
|
duration_minutes: int | None = None
|
|
subject_id: int | None = None
|
|
|
|
|
|
class ActivityLogOut(BaseModel):
|
|
id: int
|
|
child_id: int
|
|
subject_id: int | None
|
|
session_id: int | None
|
|
log_date: date
|
|
notes: str | None
|
|
duration_minutes: int | None
|
|
|
|
model_config = {"from_attributes": True}
|
|
|
|
|
|
class TimelineEventUpdate(BaseModel):
|
|
event_type: str | None = None
|
|
occurred_at: datetime | None = None
|
|
|
|
|
|
class TimelineEventOut(BaseModel):
|
|
id: int
|
|
event_type: str
|
|
occurred_at: datetime
|
|
session_date: date
|
|
child_id: int
|
|
child_name: str
|
|
block_label: str | None = None
|
|
subject_name: str | None = None
|
|
subject_icon: str | None = None
|
|
subject_color: str | None = None
|
|
|
|
@field_serializer("occurred_at")
|
|
def serialize_occurred_at(self, dt: datetime) -> str:
|
|
if dt.tzinfo is None:
|
|
dt = dt.replace(tzinfo=timezone.utc)
|
|
return dt.isoformat()
|
|
|
|
|
|
class StrikeEventOut(BaseModel):
|
|
id: int
|
|
child_id: int
|
|
child_name: str
|
|
occurred_at: datetime
|
|
log_date: date
|
|
prev_strikes: int
|
|
new_strikes: int
|
|
|
|
model_config = {"from_attributes": True}
|
|
|
|
@field_serializer("occurred_at")
|
|
def serialize_occurred_at(self, dt: datetime) -> str:
|
|
if dt.tzinfo is None:
|
|
dt = dt.replace(tzinfo=timezone.utc)
|
|
return dt.isoformat()
|