Backend: Include overdue todos and snoozed reminders in /upcoming response, add end_datetime/snoozed_until/is_overdue fields, widen snooze schema to accept 1-1440 minutes for 1h/3h/tomorrow options. Frontend: Full UpcomingWidget rewrite with sticky day separators (Today highlighted in accent), collapsible groups, past-event toggle, focus mode (Today + Tomorrow), color-coded left borders, compact type pills, relative time for today's items, item count badge, and inline quick actions (complete todo, snooze/dismiss reminder on hover). Card fills available height with no dead space. DashboardPage always renders widget (no duplicate empty state). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
47 lines
1.4 KiB
Python
47 lines
1.4 KiB
Python
from pydantic import BaseModel, ConfigDict, Field
|
|
from datetime import datetime
|
|
from typing import Literal, Optional
|
|
|
|
|
|
class ReminderCreate(BaseModel):
|
|
model_config = ConfigDict(extra="forbid")
|
|
|
|
title: str = Field(min_length=1, max_length=255)
|
|
description: Optional[str] = Field(None, max_length=5000)
|
|
remind_at: Optional[datetime] = None
|
|
is_active: bool = True
|
|
recurrence_rule: Optional[Literal['daily', 'weekly', 'monthly']] = None
|
|
|
|
|
|
class ReminderUpdate(BaseModel):
|
|
model_config = ConfigDict(extra="forbid")
|
|
|
|
title: Optional[str] = Field(None, min_length=1, max_length=255)
|
|
description: Optional[str] = Field(None, max_length=5000)
|
|
remind_at: Optional[datetime] = None
|
|
is_active: Optional[bool] = None
|
|
is_dismissed: Optional[bool] = None
|
|
recurrence_rule: Optional[Literal['daily', 'weekly', 'monthly']] = None
|
|
|
|
|
|
class ReminderSnooze(BaseModel):
|
|
model_config = ConfigDict(extra="forbid")
|
|
|
|
minutes: int = Field(ge=1, le=1440)
|
|
client_now: Optional[datetime] = None
|
|
|
|
|
|
class ReminderResponse(BaseModel):
|
|
id: int
|
|
title: str
|
|
description: Optional[str]
|
|
remind_at: Optional[datetime]
|
|
is_active: bool
|
|
is_dismissed: bool
|
|
snoozed_until: Optional[datetime] = None
|
|
recurrence_rule: Optional[str]
|
|
created_at: datetime
|
|
updated_at: datetime
|
|
|
|
model_config = ConfigDict(from_attributes=True)
|