119 lines
3.8 KiB
Python
119 lines
3.8 KiB
Python
"""Challenge endpoints for API v1."""
|
|
from fastapi import APIRouter, Depends, HTTPException, status
|
|
from sqlalchemy.orm import Session
|
|
from sqlalchemy import func
|
|
from typing import List, Optional
|
|
import datetime
|
|
|
|
from backend.models.challenge import Challenge
|
|
from backend.models.tracking import Tracking
|
|
from backend.models.user import User
|
|
from backend import auth
|
|
from backend.schemas.challenge import ChallengeCreate, ChallengeResponse
|
|
from backend.schemas.tracking import TrackingCreate, TrackingResponse
|
|
from backend.database import get_db
|
|
|
|
router = APIRouter(prefix="/api/challenges", tags=["challenges"])
|
|
|
|
|
|
@router.post("", response_model=ChallengeResponse, status_code=status.HTTP_201_CREATED)
|
|
def create_challenge(
|
|
challenge: ChallengeCreate,
|
|
db: Session = Depends(get_db),
|
|
current_user: User = Depends(auth.get_current_user)
|
|
):
|
|
"""Create a new challenge."""
|
|
# Calculate next display_order for THIS user
|
|
max_order = db.query(func.max(Challenge.display_order)).filter(
|
|
Challenge.user_id == current_user.id
|
|
).scalar()
|
|
new_order = (max_order if max_order is not None else -1) + 1
|
|
|
|
db_challenge = Challenge(**challenge.dict(), display_order=new_order, user_id=current_user.id)
|
|
db.add(db_challenge)
|
|
db.commit()
|
|
db.refresh(db_challenge)
|
|
return db_challenge
|
|
|
|
|
|
@router.get("", response_model=List[ChallengeResponse])
|
|
def read_challenges(
|
|
db: Session = Depends(get_db),
|
|
current_user: User = Depends(auth.get_current_user)
|
|
):
|
|
"""Get all challenges for the current user."""
|
|
challenges = db.query(Challenge).filter(
|
|
Challenge.user_id == current_user.id
|
|
).order_by(Challenge.display_order.asc()).all()
|
|
return challenges
|
|
|
|
|
|
@router.put("/reorder", status_code=status.HTTP_204_NO_CONTENT)
|
|
def reorder_challenges(
|
|
ordered_ids: List[int],
|
|
db: Session = Depends(get_db),
|
|
current_user: User = Depends(auth.get_current_user)
|
|
):
|
|
"""Reorder challenges."""
|
|
# Sanity check: ensure these challenges belong to user
|
|
for index, challenge_id in enumerate(ordered_ids):
|
|
db.query(Challenge).filter(
|
|
Challenge.id == challenge_id,
|
|
Challenge.user_id == current_user.id
|
|
).update({"display_order": index})
|
|
db.commit()
|
|
return None
|
|
|
|
|
|
@router.delete("/{challenge_id}", status_code=status.HTTP_204_NO_CONTENT)
|
|
def delete_challenge(
|
|
challenge_id: int,
|
|
db: Session = Depends(get_db),
|
|
current_user: User = Depends(auth.get_current_user)
|
|
):
|
|
"""Delete a challenge."""
|
|
db_challenge = db.query(Challenge).filter(
|
|
Challenge.id == challenge_id,
|
|
Challenge.user_id == current_user.id
|
|
).first()
|
|
if not db_challenge:
|
|
raise HTTPException(status_code=404, detail="Challenge not found")
|
|
db.delete(db_challenge)
|
|
db.commit()
|
|
return None
|
|
|
|
|
|
@router.post("/{challenge_id}/tracking", response_model=TrackingResponse)
|
|
def log_tracking(
|
|
challenge_id: int,
|
|
tracking: TrackingCreate,
|
|
db: Session = Depends(get_db),
|
|
current_user: User = Depends(auth.get_current_user)
|
|
):
|
|
"""Log tracking for a challenge."""
|
|
# Verify challenge belongs to user
|
|
challenge = db.query(Challenge).filter(
|
|
Challenge.id == challenge_id,
|
|
Challenge.user_id == current_user.id
|
|
).first()
|
|
if not challenge:
|
|
raise HTTPException(status_code=404, detail="Challenge not found")
|
|
|
|
# Check if tracking exists for this date and challenge
|
|
db_tracking = db.query(Tracking).filter(
|
|
Tracking.challenge_id == challenge_id,
|
|
Tracking.date == tracking.date
|
|
).first()
|
|
|
|
if db_tracking:
|
|
db_tracking.reps = tracking.reps
|
|
db_tracking.completed = tracking.completed
|
|
db_tracking.notes = tracking.notes
|
|
else:
|
|
db_tracking = Tracking(**tracking.dict())
|
|
db.add(db_tracking)
|
|
|
|
db.commit()
|
|
db.refresh(db_tracking)
|
|
return db_tracking
|