Start
This commit is contained in:
108
linedance-api/app/routers/dances.py
Normal file
108
linedance-api/app/routers/dances.py
Normal file
@@ -0,0 +1,108 @@
|
||||
"""
|
||||
dances.py — Endpoints til dans-navne, niveauer og community alternativer.
|
||||
"""
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
from sqlalchemy.orm import Session
|
||||
from sqlalchemy import func
|
||||
from pydantic import BaseModel
|
||||
from app.core.database import get_db
|
||||
from app.core.security import get_current_user
|
||||
from app.models import User
|
||||
|
||||
router = APIRouter(prefix="/dances", tags=["dances"])
|
||||
|
||||
|
||||
# ── Schemas ───────────────────────────────────────────────────────────────────
|
||||
|
||||
class DanceLevelOut(BaseModel):
|
||||
id: int
|
||||
sort_order: int
|
||||
name: str
|
||||
description: str
|
||||
model_config = {"from_attributes": True}
|
||||
|
||||
class DanceNameOut(BaseModel):
|
||||
name: str
|
||||
use_count: int
|
||||
|
||||
class DanceNameSubmit(BaseModel):
|
||||
name: str
|
||||
|
||||
class CommunityDanceOut(BaseModel):
|
||||
id: str
|
||||
song_mbid: str | None
|
||||
dance_name: str
|
||||
level_id: int | None
|
||||
level_name: str | None
|
||||
submitted_by: str
|
||||
use_count: int
|
||||
|
||||
class CommunityAltOut(BaseModel):
|
||||
id: str
|
||||
song_mbid: str | None
|
||||
dance_name: str
|
||||
alt_dance_name: str
|
||||
level_id: int | None
|
||||
level_name: str | None
|
||||
note: str
|
||||
bayesian_score: float
|
||||
rating_count: int
|
||||
my_rating: int | None
|
||||
|
||||
|
||||
# ── Dans-niveauer ─────────────────────────────────────────────────────────────
|
||||
|
||||
@router.get("/levels", response_model=list[DanceLevelOut])
|
||||
def get_levels(db: Session = Depends(get_db)):
|
||||
"""Hent alle dans-niveauer — bruges til synkronisering i appen."""
|
||||
from sqlalchemy import text
|
||||
rows = db.execute(text(
|
||||
"SELECT id, sort_order, name, description FROM dance_levels ORDER BY sort_order"
|
||||
)).fetchall()
|
||||
return [{"id": r[0], "sort_order": r[1], "name": r[2], "description": r[3]} for r in rows]
|
||||
|
||||
|
||||
# ── Dans-navne ────────────────────────────────────────────────────────────────
|
||||
|
||||
@router.get("/names", response_model=list[DanceNameOut])
|
||||
def get_dance_names(prefix: str = "", limit: int = 50, db: Session = Depends(get_db)):
|
||||
"""Hent kendte dans-navne — bruges til autoudfyld og synkronisering."""
|
||||
from sqlalchemy import text
|
||||
pattern = f"{prefix}%"
|
||||
rows = db.execute(text(
|
||||
"SELECT name, use_count FROM dance_names "
|
||||
"WHERE name LIKE :pattern "
|
||||
"ORDER BY use_count DESC, name "
|
||||
"LIMIT :limit"
|
||||
), {"pattern": pattern, "limit": limit}).fetchall()
|
||||
return [{"name": r[0], "use_count": r[1]} for r in rows]
|
||||
|
||||
|
||||
@router.post("/names", status_code=201)
|
||||
def submit_dance_name(
|
||||
data: DanceNameSubmit,
|
||||
db: Session = Depends(get_db),
|
||||
me: User = Depends(get_current_user),
|
||||
):
|
||||
"""Indsend et dans-navn — opretter eller tæller op."""
|
||||
from sqlalchemy import text
|
||||
name = data.name.strip()
|
||||
if not name:
|
||||
raise HTTPException(400, "Navn må ikke være tomt")
|
||||
existing = db.execute(
|
||||
text("SELECT id FROM dance_names WHERE name = :name COLLATE NOCASE"),
|
||||
{"name": name}
|
||||
).fetchone()
|
||||
if existing:
|
||||
db.execute(
|
||||
text("UPDATE dance_names SET use_count = use_count + 1 WHERE id = :id"),
|
||||
{"id": existing[0]}
|
||||
)
|
||||
else:
|
||||
db.execute(
|
||||
text("INSERT INTO dance_names (name, use_count) VALUES (:name, 1)"),
|
||||
{"name": name}
|
||||
)
|
||||
db.commit()
|
||||
return {"detail": "ok"}
|
||||
Reference in New Issue
Block a user