Files
pokedexter/backend/app/routers/cards.py
T

170 lines
6.7 KiB
Python
Raw Normal View History

2026-07-01 21:10:06 +02:00
from fastapi import APIRouter, Depends, Request, Query
from fastapi.responses import HTMLResponse
from fastapi.templating import Jinja2Templates
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.orm import selectinload
from ..database import get_db
from ..models import Serie, Set, Card
2026-07-01 21:10:06 +02:00
router = APIRouter()
templates = Jinja2Templates(directory="app/templates")
@router.get("/", response_class=HTMLResponse)
async def index(request: Request, db: AsyncSession = Depends(get_db)):
result = await db.execute(
select(Serie).options(selectinload(Serie.sets).selectinload(Set.cards)).order_by(Serie.name)
)
series = result.scalars().all()
return templates.TemplateResponse("index.html", {"request": request, "series": series})
@router.get("/series", response_class=HTMLResponse)
async def list_series(request: Request, db: AsyncSession = Depends(get_db)):
result = await db.execute(
select(Serie).options(selectinload(Serie.sets).selectinload(Set.cards)).order_by(Serie.name)
)
series = result.scalars().all()
return templates.TemplateResponse("series.html", {"request": request, "series": series})
@router.get("/series/{serie_name}", response_class=HTMLResponse)
async def serie_detail(request: Request, serie_name: str, db: AsyncSession = Depends(get_db)):
result = await db.execute(
select(Serie).where(Serie.name == serie_name).options(
selectinload(Serie.sets).selectinload(Set.cards)
)
)
serie = result.scalar_one_or_none()
if not serie:
return templates.TemplateResponse("404.html", {"request": request}, status_code=404)
return templates.TemplateResponse("serie_detail.html", {"request": request, "serie": serie})
2026-07-01 21:10:06 +02:00
@router.get("/sets", response_class=HTMLResponse)
async def list_sets(request: Request, db: AsyncSession = Depends(get_db)):
result = await db.execute(
select(Set).options(selectinload(Set.serie), selectinload(Set.cards)).order_by(Set.code)
)
2026-07-01 21:10:06 +02:00
sets = result.scalars().all()
return templates.TemplateResponse("sets.html", {"request": request, "sets": sets})
@router.get("/sets/{set_code}", response_class=HTMLResponse)
async def set_detail(request: Request, set_code: str, db: AsyncSession = Depends(get_db)):
result = await db.execute(
select(Set).where(Set.code == set_code.upper()).options(
selectinload(Set.cards), selectinload(Set.serie)
)
2026-07-01 21:10:06 +02:00
)
s = result.scalar_one_or_none()
if not s:
return templates.TemplateResponse("404.html", {"request": request}, status_code=404)
return templates.TemplateResponse("set_detail.html", {"request": request, "set": s})
@router.get("/card/{set_code}/{number}", response_class=HTMLResponse)
async def card_detail(request: Request, set_code: str, number: str,
db: AsyncSession = Depends(get_db)):
# Prøv med og uden leading zero (robust overfor "50" vs "050")
candidates = set([number, number.zfill(3), number.lstrip("0")])
for num in candidates:
result = await db.execute(
select(Card)
.join(Card.set)
.where(Set.code == set_code.upper(), Card.number == num)
.options(selectinload(Card.set).selectinload(Set.serie))
)
card = result.scalar_one_or_none()
if card:
return templates.TemplateResponse("card_detail.html", {"request": request, "card": card})
return templates.TemplateResponse("404.html", {"request": request}, status_code=404)
2026-07-01 21:10:06 +02:00
@router.get("/search", response_class=HTMLResponse)
async def search_page(request: Request):
return templates.TemplateResponse("search.html", {"request": request})
# ─── JSON API ───────────────────────────────────────────────────────
2026-07-01 21:10:06 +02:00
@router.get("/api/series")
async def api_list_series(db: AsyncSession = Depends(get_db)):
result = await db.execute(
select(Serie).options(selectinload(Serie.sets)).order_by(Serie.name)
)
return [{"id": s.id, "name": s.name, "description": s.description or "",
"set_count": len(s.sets)} for s in result.scalars().all()]
2026-07-01 21:10:06 +02:00
@router.get("/api/series/{serie_name}/sets")
async def api_series_sets(serie_name: str, db: AsyncSession = Depends(get_db)):
result = await db.execute(
select(Serie).where(Serie.name == serie_name).options(
selectinload(Serie.sets).selectinload(Set.cards)
)
)
serie = result.scalar_one_or_none()
if not serie:
return {"error": "Serie ikke fundet"}
return [{"code": s.code, "name": s.name, "card_count": len(s.cards)} for s in serie.sets]
2026-07-01 21:10:06 +02:00
@router.get("/api/sets")
async def api_list_sets(db: AsyncSession = Depends(get_db)):
result = await db.execute(
select(Set).options(selectinload(Set.serie), selectinload(Set.cards)).order_by(Set.code)
)
return [{"code": s.code, "name": s.name, "serie": s.serie.name,
"card_count": len(s.cards)} for s in result.scalars().all()]
2026-07-01 21:10:06 +02:00
@router.get("/api/sets/{set_code}/cards")
async def api_set_cards(set_code: str, db: AsyncSession = Depends(get_db)):
result = await db.execute(
select(Set).where(Set.code == set_code.upper()).options(selectinload(Set.cards))
)
s = result.scalar_one_or_none()
if not s:
return []
return [{"id": c.id, "number": c.number, "name": c.name,
"full_code": c.full_code, "image_url": c.image_url} for c in s.cards]
@router.get("/api/search")
async def search_cards(q: str = Query(""), db: AsyncSession = Depends(get_db)):
"""Search cards by full code (CRI-068) or by name."""
q = q.strip()
if not q:
return []
if "\u002D" in q or " " in q or "=" in q:
# Split på bindestreg, mellemrum eller =: "CRI-068" eller "CRI 068"
sep = "\u002D" if "\u002D" in q else (" " if " " in q else "=")
parts = q.split(sep, 1)
code_part = parts[0].strip().upper()
num_part = parts[1].strip()
candidates = set([num_part, num_part.zfill(3), num_part.lstrip("0")])
stmt = select(Card).join(Card.set).where(
Set.code == code_part, Card.number.in_(list(candidates))
).options(selectinload(Card.set).selectinload(Set.serie))
else:
stmt = (
select(Card)
.join(Card.set)
.where(Card.name.ilike(f"%{q}%"))
.options(selectinload(Card.set).selectinload(Set.serie))
.limit(50)
)
result = await db.execute(stmt)
cards = result.scalars().all()
return [{
"id": c.id, "full_code": c.full_code, "name": c.name,
"set_name": c.set.name, "set_code": c.set.code,
"serie_name": c.set.serie.name,
"image_url": c.image_url,
} for c in cards]