Retires Support/donation/tiers page in favor of simple configurable link

This commit is contained in:
2026-06-23 00:30:47 +00:00
parent 86fbfa56bf
commit 9b95bef9c6
34 changed files with 124 additions and 924 deletions
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+1 -2
View File
@@ -2,7 +2,7 @@ from fastapi import APIRouter
from app.config import settings
from app.database import get_session
from app.models import DonationTier, Event, StationConfig, Show, ShowSchedule
from app.models import Event, StationConfig, Show, ShowSchedule
router = APIRouter()
@@ -20,7 +20,6 @@ async def reset_database():
await session.execute(ShowSchedule.__table__.delete())
await session.execute(Show.__table__.delete())
await session.execute(Event.__table__.delete())
await session.execute(DonationTier.__table__.delete())
await session.execute(StationConfig.__table__.delete())
await session.commit()
-73
View File
@@ -1,73 +0,0 @@
from fastapi import APIRouter, Depends
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession
from app.auth import get_current_admin_user
from app.database import get_session
from app.models import DonationTier
from app.schemas import TierCreate, TierUpdate, TierResponse
from app.user_models import User
router = APIRouter()
@router.get("/", response_model=list[TierResponse])
async def list_tiers(session: AsyncSession = Depends(get_session)):
result = await session.execute(
select(DonationTier).order_by(DonationTier.display_order)
)
return list(result.scalars().all())
@router.get("/{tier_id}", response_model=TierResponse)
async def get_tier(tier_id: int, session: AsyncSession = Depends(get_session)):
result = await session.execute(select(DonationTier).where(DonationTier.id == tier_id))
tier = result.scalar_one_or_none()
if not tier:
return {"error": "Tier not found"}
return tier
@router.post("/", response_model=TierResponse, status_code=201)
async def create_tier(
payload: TierCreate,
session: AsyncSession = Depends(get_session),
_: User = Depends(get_current_admin_user),
):
tier = DonationTier(**payload.model_dump())
session.add(tier)
await session.commit()
await session.refresh(tier)
return tier
@router.put("/{tier_id}", response_model=TierResponse)
async def update_tier(
tier_id: int,
payload: TierUpdate,
session: AsyncSession = Depends(get_session),
_: User = Depends(get_current_admin_user),
):
result = await session.execute(select(DonationTier).where(DonationTier.id == tier_id))
tier = result.scalar_one_or_none()
if not tier:
return {"error": "Tier not found"}
for key, value in payload.model_dump(exclude_unset=True).items():
setattr(tier, key, value)
await session.commit()
await session.refresh(tier)
return tier
@router.delete("/{tier_id}", status_code=204)
async def delete_tier(
tier_id: int,
session: AsyncSession = Depends(get_session),
_: User = Depends(get_current_admin_user),
):
result = await session.execute(select(DonationTier).where(DonationTier.id == tier_id))
tier = result.scalar_one_or_none()
if not tier:
return {"error": "Tier not found"}
await session.delete(tier)
await session.commit()
+1 -2
View File
@@ -8,7 +8,7 @@ from app.config import settings
from app.database import async_session, engine
from app.models import Base, Show, StationConfig, HistoryEntry, TeamMember, CommunityHighlight
from app.user_models import User
from app.api import events, tiers, auth, station_config, history, team, community, shows, storage
from app.api import events, auth, station_config, history, team, community, shows, storage
async def _ensure_station_config(session):
@@ -87,7 +87,6 @@ app.add_middleware(
# Register routers
app.include_router(auth.router, prefix="/api/auth", tags=["auth"])
app.include_router(events.router, prefix="/api/events", tags=["events"])
app.include_router(tiers.router, prefix="/api/tiers", tags=["tiers"])
app.include_router(station_config.router, prefix="/api/station-config", tags=["station-config"])
app.include_router(history.router, prefix="/api/history", tags=["history"])
app.include_router(team.router, prefix="/api/team", tags=["team"])
+3 -13
View File
@@ -7,10 +7,8 @@ from sqlalchemy import (
LargeBinary,
String,
Text,
Numeric,
Boolean,
Date,
JSON,
ForeignKey,
UniqueConstraint,
)
@@ -63,17 +61,6 @@ class Event(Base):
active = Column(Boolean, default=True)
class DonationTier(Base):
__tablename__ = "donation_tiers"
id = Column(Integer, primary_key=True, autoincrement=True)
name = Column(String(50), unique=True, nullable=False)
amount = Column(Numeric(10, 2), nullable=False)
icon = Column(String(10), nullable=False)
benefits = Column(JSON, nullable=False)
display_order = Column(Integer, nullable=False)
class StationConfig(Base):
__tablename__ = "station_config"
@@ -104,6 +91,9 @@ class StationConfig(Base):
email = Column(String(100), nullable=False, default="hello@kmountainflower.org")
website = Column(String(200), nullable=False, default="kmountainflower.org")
# Donation
donation_url = Column(String(500), nullable=False, default="")
class HistoryEntry(Base):
__tablename__ = "history_entries"
+2 -29
View File
@@ -51,35 +51,6 @@ class EventResponse(BaseModel):
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):
@@ -101,6 +72,7 @@ class StationConfigResponse(BaseModel):
phone: str
email: str
website: str
donation_url: str
model_config = {"from_attributes": True}
@@ -122,6 +94,7 @@ class StationConfigUpdate(BaseModel):
phone: Optional[str] = None
email: Optional[str] = None
website: Optional[str] = None
donation_url: Optional[str] = None
# ── HistoryEntry ──────────────────────────────────────────
+2 -51
View File
@@ -14,7 +14,7 @@ from datetime import date
from sqlalchemy import select
from app.database import async_session
from app.models import Show, ShowSchedule, Event, DonationTier, StationConfig
from app.models import Show, ShowSchedule, Event, StationConfig
from app.models import HistoryEntry, TeamMember, CommunityHighlight
# ── Seed data ──────────────────────────────────────────────
@@ -193,37 +193,6 @@ EVENTS: list[dict] = [
},
]
TIERS: list[dict] = [
{
"name": "Seed",
"amount": 5.00,
"icon": "🌱",
"benefits": ["Digital thank-you card", "Name listed on our website", "Quarterly newsletter"],
"display_order": 1,
},
{
"name": "Stream",
"amount": 15.00,
"icon": "🎵",
"benefits": ["All Seed benefits", "KMountain Flower pin", "Priority show-request line", "Annual station update call"],
"display_order": 2,
},
{
"name": "Ridge",
"amount": 30.00,
"icon": "🏔️",
"benefits": ["All Stream benefits", "Official member patch", "Exclusive show invitations", "Annual station tour"],
"display_order": 3,
},
{
"name": "Summit",
"amount": 60.00,
"icon": "",
"benefits": ["All Ridge benefits", "Featured on the Summit Wall", "Name on-air during anniversary special", "Lifetime patron recognition"],
"display_order": 4,
},
]
STATION_CONFIG: dict = {
"key": "default",
"callsign": "KMTN",
@@ -242,6 +211,7 @@ STATION_CONFIG: dict = {
"phone": "(970) 555-0198",
"email": "hello@kmountainflower.org",
"website": "kmountainflower.org",
"donation_url": "",
}
HISTORY_ENTRIES: list[dict] = [
@@ -348,19 +318,6 @@ async def _upsert_event(session, data: dict) -> None:
session.add(Event(**data, active=True))
async def _upsert_tier(session, data: dict) -> None:
"""Get-or-create a donation tier matched on name."""
existing = await session.execute(
select(DonationTier).where(DonationTier.name == data["name"])
)
tier = existing.scalar_one_or_none()
if tier:
for key, value in data.items():
setattr(tier, key, value)
else:
session.add(DonationTier(**data))
async def _upsert_station_config(session, data: dict) -> None:
"""Get-or-create the singleton station config (key='default')."""
existing = await session.execute(
@@ -452,11 +409,6 @@ async def seed() -> None:
await session.commit()
print(f" ✓ Seeded {len(EVENTS)} events")
for data in TIERS:
await _upsert_tier(session, data)
await session.commit()
print(f" ✓ Seeded {len(TIERS)} donation tiers")
await _upsert_station_config(session, STATION_CONFIG)
await session.commit()
print(" ✓ Seeded station config")
@@ -491,7 +443,6 @@ async def truncate_all() -> None:
await session.execute(ShowSchedule.__table__.delete())
await session.execute(Show.__table__.delete())
await session.execute(Event.__table__.delete())
await session.execute(DonationTier.__table__.delete())
await session.execute(StationConfig.__table__.delete())
await session.execute(HistoryEntry.__table__.delete())
await session.execute(TeamMember.__table__.delete())