feat: Rebuild as Court Manager Dashboard v2
- Complete rewrite for single Court Manager user - Feature 1: Player Management (CRUD, ELO, skill level) - Feature 2: Court Reservation (timeline, override) - Feature 3: Match Event Builder (3-step wizard) - Step 1: Event setup with player selection + stage calculator - Step 2: Stage configurator (Open/Skill/RR/Tournament) - Step 3: Auto bracket generation - Feature 4: Live Court View (main dashboard, 2x2 grid) - Event Control: score entry, bracket advancement, court assignment - Screen view: TV display per court (/screen/:id) - Seed: 8 players, 4 courts, 1 completed + 1 active event - Routes: / players courts events events/new events/:id screen/:id
This commit is contained in:
81
backend/app/routers/courts.py
Normal file
81
backend/app/routers/courts.py
Normal file
@@ -0,0 +1,81 @@
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
from sqlalchemy.orm import Session, joinedload
|
||||
from typing import List
|
||||
from datetime import datetime
|
||||
from ..database import get_db
|
||||
from ..models import Court, CourtReservation
|
||||
from ..schemas import CourtCreate, CourtStatusUpdate, ReservationCreate, ReservationOut, CourtOut
|
||||
|
||||
router = APIRouter(prefix="/api/courts", tags=["courts"])
|
||||
|
||||
|
||||
@router.get("/", response_model=List[CourtOut])
|
||||
def list_courts(db: Session = Depends(get_db)):
|
||||
courts = db.query(Court).options(joinedload(Court.reservations).joinedload(CourtReservation.player)).all()
|
||||
return courts
|
||||
|
||||
|
||||
@router.post("/", response_model=CourtOut)
|
||||
def create_court(data: CourtCreate, db: Session = Depends(get_db)):
|
||||
court = Court(**data.model_dump())
|
||||
db.add(court)
|
||||
db.commit()
|
||||
db.refresh(court)
|
||||
return court
|
||||
|
||||
|
||||
@router.get("/{court_id}", response_model=CourtOut)
|
||||
def get_court(court_id: int, db: Session = Depends(get_db)):
|
||||
court = db.query(Court).options(joinedload(Court.reservations).joinedload(CourtReservation.player)).filter(Court.id == court_id).first()
|
||||
if not court:
|
||||
raise HTTPException(status_code=404, detail="Court not found")
|
||||
return court
|
||||
|
||||
|
||||
@router.patch("/{court_id}/status")
|
||||
def update_court_status(court_id: int, data: CourtStatusUpdate, db: Session = Depends(get_db)):
|
||||
court = db.query(Court).filter(Court.id == court_id).first()
|
||||
if not court:
|
||||
raise HTTPException(status_code=404, detail="Court not found")
|
||||
valid_statuses = ["available", "in_use", "reserved", "maintenance"]
|
||||
if data.status not in valid_statuses:
|
||||
raise HTTPException(status_code=400, detail=f"Status must be one of {valid_statuses}")
|
||||
court.status = data.status
|
||||
db.commit()
|
||||
return {"ok": True, "status": data.status}
|
||||
|
||||
|
||||
@router.get("/{court_id}/reservations", response_model=List[ReservationOut])
|
||||
def list_reservations(court_id: int, db: Session = Depends(get_db)):
|
||||
return db.query(CourtReservation).filter(CourtReservation.court_id == court_id).order_by(CourtReservation.start_time).all()
|
||||
|
||||
|
||||
@router.post("/{court_id}/reservations", response_model=ReservationOut)
|
||||
def create_reservation(court_id: int, data: ReservationCreate, db: Session = Depends(get_db)):
|
||||
court = db.query(Court).filter(Court.id == court_id).first()
|
||||
if not court:
|
||||
raise HTTPException(status_code=404, detail="Court not found")
|
||||
reservation = CourtReservation(court_id=court_id, **data.model_dump())
|
||||
db.add(reservation)
|
||||
# Update court status to reserved if it's currently available
|
||||
if court.status == "available":
|
||||
court.status = "reserved"
|
||||
db.commit()
|
||||
db.refresh(reservation)
|
||||
return reservation
|
||||
|
||||
|
||||
@router.delete("/reservations/{reservation_id}")
|
||||
def delete_reservation(reservation_id: int, db: Session = Depends(get_db)):
|
||||
reservation = db.query(CourtReservation).filter(CourtReservation.id == reservation_id).first()
|
||||
if not reservation:
|
||||
raise HTTPException(status_code=404, detail="Reservation not found")
|
||||
court = db.query(Court).filter(Court.id == reservation.court_id).first()
|
||||
db.delete(reservation)
|
||||
db.commit()
|
||||
# Check if court has any remaining reservations
|
||||
remaining = db.query(CourtReservation).filter(CourtReservation.court_id == reservation.court_id).count()
|
||||
if remaining == 0 and court and court.status == "reserved":
|
||||
court.status = "available"
|
||||
db.commit()
|
||||
return {"ok": True}
|
||||
Reference in New Issue
Block a user