- Add `timezone` column to User model (VARCHAR 64, default UTC) with idempotent startup migration - Expose and persist timezone via PATCH /api/users/me - Fix TimerEvent.occurred_at serialization to include UTC offset marker (+00:00) so JavaScript correctly parses timestamps as UTC - Add frontend utility (src/utils/time.js) with timezone-aware formatTime, getHHMM, getDateInTZ, tzDateTimeToUTC helpers and a curated IANA timezone list - Add Settings section to Admin page with timezone dropdown; saves to both the API and localStorage for the unauthenticated TV view - Update Activity Log to display and edit times in the user's timezone - Update TV dashboard clock to respect the saved timezone - Update README: features, setup steps, usage table, WebSocket events Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
54 lines
1.3 KiB
Python
54 lines
1.3 KiB
Python
from datetime import date, datetime, timezone
|
|
from pydantic import BaseModel, 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()
|