Files
kmtnflower/backend/app/schemas.py
T
kfj001 9049b066ba Remove Programs tab and all supporting code
The Programs feature is superseded by Shows, which provides a more
flexible model with schedule slots. This commit removes all Programs
code across frontend and backend:

Frontend:
- Delete admin-program-form component (ts/html/scss)
- Delete program.service.ts and program.ts interface
- Remove Programs tab, form modal, and all CRUD logic from admin
  component (ts + html)

Backend:
- Delete programs API router
- Remove Program ORM model and ProgramCreate/Update/Response schemas
- Remove programs router registration from main.py
- Remove Program from seed data, seed helpers, and truncate/reset
2026-06-22 05:42:43 +00:00

273 lines
6.6 KiB
Python

from datetime import date as _date
from typing import Optional
from pydantic import BaseModel, computed_field, field_validator
# ── Shared ───────────────────────────────────────────────
DAY_NAMES = {
1: "Monday",
2: "Tuesday",
3: "Wednesday",
4: "Thursday",
5: "Friday",
6: "Saturday",
7: "Sunday",
}
# ── Event ────────────────────────────────────────────────
class EventCreate(BaseModel):
date: _date
title: str
description: str
location: str
icon: str
rsvp_url: Optional[str] = None
class EventUpdate(BaseModel):
date: Optional[_date] = None
title: Optional[str] = None
description: Optional[str] = None
location: Optional[str] = None
icon: Optional[str] = None
rsvp_url: Optional[str] = None
active: Optional[bool] = None
class EventResponse(BaseModel):
id: int
date: _date
title: str
description: str
location: str
icon: str
rsvp_url: Optional[str]
active: bool
model_config = {"from_attributes": True}
# ── DonationTier ─────────────────────────────────────────
class TierCreate(BaseModel):
name: str
amount: float
icon: str
benefits: list[str]
display_order: int
class TierUpdate(BaseModel):
name: Optional[str] = None
amount: Optional[float] = None
icon: Optional[str] = None
benefits: Optional[list[str]] = None
display_order: Optional[int] = None
class TierResponse(BaseModel):
id: int
name: str
amount: float
icon: str
benefits: list[str]
display_order: int
model_config = {"from_attributes": True}
# ── StationConfig ─────────────────────────────────────────
class StationConfigResponse(BaseModel):
id: int
key: str
callsign: str
name_primary: str
name_secondary: str
tagline: str
frequency: str
founded_year: int
nonprofit_type: str
ein: str
logo_url: str
hero_background_url: str
hero_icon_url: str
hero_divider_url: str
address: str
phone: str
email: str
website: str
model_config = {"from_attributes": True}
class StationConfigUpdate(BaseModel):
callsign: Optional[str] = None
name_primary: Optional[str] = None
name_secondary: Optional[str] = None
tagline: Optional[str] = None
frequency: Optional[str] = None
founded_year: Optional[int] = None
nonprofit_type: Optional[str] = None
ein: Optional[str] = None
logo_url: Optional[str] = None
hero_background_url: Optional[str] = None
hero_icon_url: Optional[str] = None
hero_divider_url: Optional[str] = None
address: Optional[str] = None
phone: Optional[str] = None
email: Optional[str] = None
website: Optional[str] = None
# ── HistoryEntry ──────────────────────────────────────────
class HistoryEntryCreate(BaseModel):
year: int
title: str
body: str
display_order: int
class HistoryEntryUpdate(BaseModel):
year: Optional[int] = None
title: Optional[str] = None
body: Optional[str] = None
display_order: Optional[int] = None
active: Optional[bool] = None
class HistoryEntryResponse(BaseModel):
id: int
year: int
title: str
body: str
display_order: int
active: bool
model_config = {"from_attributes": True}
# ── TeamMember ─────────────────────────────────────────────
class TeamMemberCreate(BaseModel):
name: str
title: str
bio: Optional[str] = None
photo_url: Optional[str] = None
display_order: int
class TeamMemberUpdate(BaseModel):
name: Optional[str] = None
title: Optional[str] = None
bio: Optional[str] = None
photo_url: Optional[str] = None
display_order: Optional[int] = None
active: Optional[bool] = None
class TeamMemberResponse(BaseModel):
id: int
name: str
title: str
bio: Optional[str]
photo_url: Optional[str]
display_order: int
active: bool
model_config = {"from_attributes": True}
# ── CommunityHighlight ─────────────────────────────────────
class CommunityHighlightCreate(BaseModel):
icon: str
title: str
description: str
display_order: int
class CommunityHighlightUpdate(BaseModel):
icon: Optional[str] = None
title: Optional[str] = None
description: Optional[str] = None
display_order: Optional[int] = None
active: Optional[bool] = None
class CommunityHighlightResponse(BaseModel):
id: int
icon: str
title: str
description: str
display_order: int
active: bool
model_config = {"from_attributes": True}
# ── ShowSchedule ──────────────────────────────────────────
class ShowScheduleResponse(BaseModel):
id: int
show_id: int
day_of_week: int
time: str
@computed_field
@property
def day_label(self) -> str:
return DAY_NAMES.get(self.day_of_week, "Unknown")
model_config = {"from_attributes": True}
class ShowScheduleCreate(BaseModel):
day_of_week: int
time: str
# ── Show ────────────────────────────────────────────────────
class ShowResponse(BaseModel):
id: int
title: str
description: str
host: str
genre: str
show_art_url: Optional[str]
hero_image_url: Optional[str]
display_order: int
active: bool
schedules: list[ShowScheduleResponse]
model_config = {"from_attributes": True}
class ShowCreate(BaseModel):
title: str
description: str
host: str
genre: str
show_art_url: Optional[str] = None
hero_image_url: Optional[str] = None
display_order: int = 0
schedules: list[ShowScheduleCreate]
class ShowUpdate(BaseModel):
title: Optional[str] = None
description: Optional[str] = None
host: Optional[str] = None
genre: Optional[str] = None
show_art_url: Optional[str] = None
hero_image_url: Optional[str] = None
display_order: Optional[int] = None
active: Optional[bool] = None
schedules: Optional[list[ShowScheduleCreate]] = None