Full-stack implementation of event invitations allowing users to invite connected contacts to calendar events. Invitees can respond Going/Tentative/Declined, with per-occurrence overrides for recurring series. Invited events appear on the invitee's calendar with a Users icon indicator. LeaveEventDialog replaces delete for invited events. Backend: Migration 054 (2 tables + notification types), EventInvitation model with lazy="raise", service layer, dual-router (events + event-invitations), cascade on disconnect, events/dashboard queries extended with OR for invited events. Frontend: Types, useEventInvitations hook, InviteeSection (view list + RSVP buttons + invite search), LeaveEventDialog, event invite toast with 3 response buttons, calendar eventContent render with Users icon for invited events. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
32 lines
906 B
Python
32 lines
906 B
Python
from pydantic import BaseModel, ConfigDict, Field
|
|
from typing import Literal, Optional
|
|
from datetime import datetime
|
|
|
|
|
|
class EventInvitationCreate(BaseModel):
|
|
model_config = ConfigDict(extra="forbid")
|
|
user_ids: list[int] = Field(..., min_length=1, max_length=20)
|
|
|
|
|
|
class EventInvitationRespond(BaseModel):
|
|
model_config = ConfigDict(extra="forbid")
|
|
status: Literal["accepted", "tentative", "declined"]
|
|
|
|
|
|
class EventInvitationOverrideCreate(BaseModel):
|
|
model_config = ConfigDict(extra="forbid")
|
|
status: Literal["accepted", "tentative", "declined"]
|
|
|
|
|
|
class EventInvitationResponse(BaseModel):
|
|
model_config = ConfigDict(from_attributes=True)
|
|
id: int
|
|
event_id: int
|
|
user_id: int
|
|
invited_by: Optional[int]
|
|
status: str
|
|
invited_at: datetime
|
|
responded_at: Optional[datetime]
|
|
invitee_name: Optional[str] = None
|
|
invitee_umbral_name: Optional[str] = None
|