Initial project commit
This commit is contained in:
@@ -0,0 +1,112 @@
|
||||
from fastapi import APIRouter, Depends, HTTPException, Query, status
|
||||
from sqlalchemy import func, select
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from app.core.deps import get_current_active_user, get_db
|
||||
from app.models.favorite import Favorite
|
||||
from app.models.spot import Spot
|
||||
from app.models.user import User
|
||||
from app.schemas.common import PageResponse
|
||||
from app.schemas.spot import SpotBrief
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
def _spot_to_brief(spot: Spot) -> SpotBrief:
|
||||
cover = next((img for img in spot.images if img.is_cover), None)
|
||||
if cover is None and spot.images:
|
||||
cover = spot.images[0]
|
||||
return SpotBrief(
|
||||
id=spot.id,
|
||||
title=spot.title,
|
||||
city=spot.city,
|
||||
longitude=spot.longitude,
|
||||
latitude=spot.latitude,
|
||||
cover_image_url=cover.image_url if cover else None,
|
||||
audit_status=spot.audit_status,
|
||||
created_at=spot.created_at,
|
||||
)
|
||||
|
||||
|
||||
@router.post("/{spot_id}", status_code=status.HTTP_201_CREATED)
|
||||
async def add_favorite(
|
||||
spot_id: int,
|
||||
current_user: User = Depends(get_current_active_user),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
result = await db.execute(select(Spot).where(Spot.id == spot_id))
|
||||
if not result.scalar_one_or_none():
|
||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Spot not found")
|
||||
|
||||
existing = await db.execute(
|
||||
select(Favorite).where(
|
||||
Favorite.user_id == current_user.id, Favorite.spot_id == spot_id
|
||||
)
|
||||
)
|
||||
if existing.scalar_one_or_none():
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_409_CONFLICT, detail="Already favorited"
|
||||
)
|
||||
|
||||
fav = Favorite(user_id=current_user.id, spot_id=spot_id)
|
||||
db.add(fav)
|
||||
await db.execute(
|
||||
select(Spot).where(Spot.id == spot_id)
|
||||
)
|
||||
spot_obj = (await db.execute(select(Spot).where(Spot.id == spot_id))).scalar_one()
|
||||
spot_obj.favorite_count = (spot_obj.favorite_count or 0) + 1
|
||||
await db.commit()
|
||||
return {"code": 0, "message": "success"}
|
||||
|
||||
|
||||
@router.delete("/{spot_id}", status_code=status.HTTP_204_NO_CONTENT)
|
||||
async def remove_favorite(
|
||||
spot_id: int,
|
||||
current_user: User = Depends(get_current_active_user),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
result = await db.execute(
|
||||
select(Favorite).where(
|
||||
Favorite.user_id == current_user.id, Favorite.spot_id == spot_id
|
||||
)
|
||||
)
|
||||
fav = result.scalar_one_or_none()
|
||||
if not fav:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_404_NOT_FOUND, detail="Favorite not found"
|
||||
)
|
||||
spot_obj = (await db.execute(select(Spot).where(Spot.id == spot_id))).scalar_one_or_none()
|
||||
if spot_obj:
|
||||
spot_obj.favorite_count = max((spot_obj.favorite_count or 0) - 1, 0)
|
||||
await db.delete(fav)
|
||||
await db.commit()
|
||||
|
||||
|
||||
@router.get("/", response_model=PageResponse[SpotBrief])
|
||||
async def list_favorites(
|
||||
page: int = Query(default=1, ge=1),
|
||||
page_size: int = Query(default=20, ge=1, le=100),
|
||||
current_user: User = Depends(get_current_active_user),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
count_query = select(func.count(Favorite.id)).where(
|
||||
Favorite.user_id == current_user.id
|
||||
)
|
||||
total_result = await db.execute(count_query)
|
||||
total = total_result.scalar() or 0
|
||||
|
||||
offset = (page - 1) * page_size
|
||||
query = (
|
||||
select(Favorite)
|
||||
.where(Favorite.user_id == current_user.id)
|
||||
.order_by(Favorite.created_at.desc())
|
||||
.offset(offset)
|
||||
.limit(page_size)
|
||||
)
|
||||
result = await db.execute(query)
|
||||
favorites = result.scalars().all()
|
||||
|
||||
return PageResponse(
|
||||
total=total,
|
||||
items=[_spot_to_brief(f.spot) for f in favorites],
|
||||
)
|
||||
Reference in New Issue
Block a user