285 lines
8.4 KiB
Python
285 lines
8.4 KiB
Python
from fastapi import APIRouter, Depends, HTTPException
|
|
from sqlmodel import Session, select
|
|
from typing import List
|
|
from database import get_session
|
|
from models import User, Vertical, UserVerticalPreference
|
|
from auth import get_current_user
|
|
from pydantic import BaseModel
|
|
from datetime import datetime
|
|
|
|
router = APIRouter(prefix="/verticals", tags=["verticals"])
|
|
|
|
|
|
class VerticalRead(BaseModel):
|
|
id: int
|
|
name: str
|
|
slug: str
|
|
description: str | None = None
|
|
|
|
|
|
class UserVerticalPreferenceRead(BaseModel):
|
|
vertical_id: int
|
|
vertical: VerticalRead
|
|
display_mode: str
|
|
priority: int
|
|
tier: str = "main_stage"
|
|
notify_on_show: bool
|
|
|
|
|
|
class UserVerticalPreferenceCreate(BaseModel):
|
|
vertical_id: int
|
|
display_mode: str = "primary" # primary, secondary, attribution_only, hidden
|
|
priority: int = 0
|
|
tier: str = "main_stage"
|
|
notify_on_show: bool = True
|
|
|
|
|
|
class UserVerticalPreferenceUpdate(BaseModel):
|
|
display_mode: str | None = None
|
|
priority: int | None = None
|
|
tier: str | None = None
|
|
notify_on_show: bool | None = None
|
|
|
|
|
|
class BulkVerticalPreferencesCreate(BaseModel):
|
|
"""For onboarding - set multiple band preferences at once"""
|
|
vertical_ids: List[int]
|
|
display_mode: str = "primary"
|
|
|
|
|
|
# --- Public endpoints ---
|
|
|
|
@router.get("/", response_model=List[VerticalRead])
|
|
def list_verticals(
|
|
scene: str | None = None,
|
|
session: Session = Depends(get_session)
|
|
):
|
|
"""List all available verticals (bands), optionally filtered by scene"""
|
|
from models import Scene, VerticalScene
|
|
|
|
if scene:
|
|
# Filter by scene
|
|
scene_obj = session.exec(select(Scene).where(Scene.slug == scene)).first()
|
|
if not scene_obj:
|
|
raise HTTPException(status_code=404, detail="Scene not found")
|
|
|
|
vertical_ids = session.exec(
|
|
select(VerticalScene.vertical_id).where(VerticalScene.scene_id == scene_obj.id)
|
|
).all()
|
|
|
|
verticals = session.exec(
|
|
select(Vertical)
|
|
.where(Vertical.id.in_(vertical_ids))
|
|
.where(Vertical.is_active == True)
|
|
).all()
|
|
else:
|
|
verticals = session.exec(
|
|
select(Vertical).where(Vertical.is_active == True)
|
|
).all()
|
|
|
|
return verticals
|
|
|
|
|
|
class SceneRead(BaseModel):
|
|
id: int
|
|
name: str
|
|
slug: str
|
|
description: str | None = None
|
|
|
|
|
|
@router.get("/scenes", response_model=List[SceneRead])
|
|
def list_scenes(session: Session = Depends(get_session)):
|
|
"""List all scenes (genres)"""
|
|
from models import Scene
|
|
scenes = session.exec(select(Scene)).all()
|
|
return scenes
|
|
|
|
|
|
@router.get("/{slug}", response_model=VerticalRead)
|
|
def get_vertical(slug: str, session: Session = Depends(get_session)):
|
|
"""Get a specific vertical by slug"""
|
|
vertical = session.exec(select(Vertical).where(Vertical.slug == slug)).first()
|
|
if not vertical:
|
|
raise HTTPException(status_code=404, detail="Vertical not found")
|
|
return vertical
|
|
|
|
|
|
# --- User preference endpoints ---
|
|
|
|
@router.get("/preferences/me", response_model=List[UserVerticalPreferenceRead])
|
|
def get_my_vertical_preferences(
|
|
session: Session = Depends(get_session),
|
|
current_user: User = Depends(get_current_user)
|
|
):
|
|
"""Get current user's band preferences"""
|
|
prefs = session.exec(
|
|
select(UserVerticalPreference)
|
|
.where(UserVerticalPreference.user_id == current_user.id)
|
|
.order_by(UserVerticalPreference.priority)
|
|
).all()
|
|
|
|
# Enrich with vertical data
|
|
result = []
|
|
for pref in prefs:
|
|
vertical = session.get(Vertical, pref.vertical_id)
|
|
if vertical:
|
|
result.append({
|
|
"vertical_id": pref.vertical_id,
|
|
"vertical": vertical,
|
|
"display_mode": pref.display_mode,
|
|
"priority": pref.priority,
|
|
"tier": pref.tier,
|
|
"notify_on_show": pref.notify_on_show
|
|
})
|
|
return result
|
|
|
|
|
|
@router.post("/preferences", response_model=UserVerticalPreferenceRead)
|
|
def add_vertical_preference(
|
|
pref: UserVerticalPreferenceCreate,
|
|
session: Session = Depends(get_session),
|
|
current_user: User = Depends(get_current_user)
|
|
):
|
|
"""Add a band to user's preferences"""
|
|
# Check vertical exists
|
|
vertical = session.get(Vertical, pref.vertical_id)
|
|
if not vertical:
|
|
raise HTTPException(status_code=404, detail="Vertical not found")
|
|
|
|
# Check if already exists
|
|
existing = session.exec(
|
|
select(UserVerticalPreference)
|
|
.where(UserVerticalPreference.user_id == current_user.id)
|
|
.where(UserVerticalPreference.vertical_id == pref.vertical_id)
|
|
).first()
|
|
|
|
if existing:
|
|
raise HTTPException(status_code=400, detail="Preference already exists")
|
|
|
|
db_pref = UserVerticalPreference(
|
|
user_id=current_user.id,
|
|
vertical_id=pref.vertical_id,
|
|
display_mode=pref.display_mode,
|
|
priority=pref.priority,
|
|
tier=pref.tier,
|
|
notify_on_show=pref.notify_on_show
|
|
)
|
|
session.add(db_pref)
|
|
session.commit()
|
|
session.refresh(db_pref)
|
|
|
|
return {
|
|
"vertical_id": db_pref.vertical_id,
|
|
"vertical": vertical,
|
|
"display_mode": db_pref.display_mode,
|
|
"priority": db_pref.priority,
|
|
"tier": db_pref.tier,
|
|
"notify_on_show": db_pref.notify_on_show
|
|
}
|
|
|
|
|
|
@router.post("/preferences/bulk", response_model=List[UserVerticalPreferenceRead])
|
|
def set_vertical_preferences_bulk(
|
|
data: BulkVerticalPreferencesCreate,
|
|
session: Session = Depends(get_session),
|
|
current_user: User = Depends(get_current_user)
|
|
):
|
|
"""Set multiple band preferences at once (for onboarding)"""
|
|
result = []
|
|
|
|
for idx, vid in enumerate(data.vertical_ids):
|
|
vertical = session.get(Vertical, vid)
|
|
if not vertical:
|
|
continue
|
|
|
|
# Upsert
|
|
existing = session.exec(
|
|
select(UserVerticalPreference)
|
|
.where(UserVerticalPreference.user_id == current_user.id)
|
|
.where(UserVerticalPreference.vertical_id == vid)
|
|
).first()
|
|
|
|
if existing:
|
|
existing.display_mode = data.display_mode
|
|
existing.priority = idx
|
|
session.add(existing)
|
|
pref = existing
|
|
else:
|
|
pref = UserVerticalPreference(
|
|
user_id=current_user.id,
|
|
vertical_id=vid,
|
|
display_mode=data.display_mode,
|
|
priority=idx,
|
|
notify_on_show=True
|
|
)
|
|
session.add(pref)
|
|
|
|
result.append({
|
|
"vertical_id": vid,
|
|
"vertical": vertical,
|
|
"display_mode": data.display_mode,
|
|
"priority": idx,
|
|
"notify_on_show": True
|
|
})
|
|
|
|
session.commit()
|
|
return result
|
|
|
|
|
|
@router.put("/preferences/{vertical_id}", response_model=UserVerticalPreferenceRead)
|
|
def update_vertical_preference(
|
|
vertical_id: int,
|
|
data: UserVerticalPreferenceUpdate,
|
|
session: Session = Depends(get_session),
|
|
current_user: User = Depends(get_current_user)
|
|
):
|
|
"""Update a specific band preference"""
|
|
pref = session.exec(
|
|
select(UserVerticalPreference)
|
|
.where(UserVerticalPreference.user_id == current_user.id)
|
|
.where(UserVerticalPreference.vertical_id == vertical_id)
|
|
).first()
|
|
|
|
if not pref:
|
|
raise HTTPException(status_code=404, detail="Preference not found")
|
|
|
|
vertical = session.get(Vertical, vertical_id)
|
|
|
|
update_data = data.model_dump(exclude_unset=True)
|
|
for key, value in update_data.items():
|
|
setattr(pref, key, value)
|
|
|
|
session.add(pref)
|
|
session.commit()
|
|
session.refresh(pref)
|
|
|
|
return {
|
|
"vertical_id": pref.vertical_id,
|
|
"vertical": vertical,
|
|
"display_mode": pref.display_mode,
|
|
"priority": pref.priority,
|
|
"tier": pref.tier,
|
|
"notify_on_show": pref.notify_on_show
|
|
}
|
|
|
|
|
|
@router.delete("/preferences/{vertical_id}")
|
|
def delete_vertical_preference(
|
|
vertical_id: int,
|
|
session: Session = Depends(get_session),
|
|
current_user: User = Depends(get_current_user)
|
|
):
|
|
"""Remove a band from user's preferences"""
|
|
pref = session.exec(
|
|
select(UserVerticalPreference)
|
|
.where(UserVerticalPreference.user_id == current_user.id)
|
|
.where(UserVerticalPreference.vertical_id == vertical_id)
|
|
).first()
|
|
|
|
if not pref:
|
|
raise HTTPException(status_code=404, detail="Preference not found")
|
|
|
|
session.delete(pref)
|
|
session.commit()
|
|
|
|
return {"ok": True}
|