feat: Enhance favorites functionality; add favorites filtering to playlists and sounds, and improve favorite indicators in responses
This commit is contained in:
@@ -3,9 +3,7 @@
|
||||
from typing import Annotated
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException, Query, status
|
||||
from sqlmodel.ext.asyncio.session import AsyncSession
|
||||
|
||||
from app.core.database import get_db
|
||||
from app.core.dependencies import get_current_active_user
|
||||
from app.models.user import User
|
||||
from app.schemas.common import MessageResponse
|
||||
@@ -35,7 +33,7 @@ async def get_user_favorites(
|
||||
) -> FavoritesListResponse:
|
||||
"""Get all favorites for the current user."""
|
||||
favorites = await favorite_service.get_user_favorites(
|
||||
current_user.id, limit, offset
|
||||
current_user.id, limit, offset,
|
||||
)
|
||||
return FavoritesListResponse(favorites=favorites)
|
||||
|
||||
@@ -49,7 +47,7 @@ async def get_user_sound_favorites(
|
||||
) -> FavoritesListResponse:
|
||||
"""Get sound favorites for the current user."""
|
||||
favorites = await favorite_service.get_user_sound_favorites(
|
||||
current_user.id, limit, offset
|
||||
current_user.id, limit, offset,
|
||||
)
|
||||
return FavoritesListResponse(favorites=favorites)
|
||||
|
||||
@@ -63,7 +61,7 @@ async def get_user_playlist_favorites(
|
||||
) -> FavoritesListResponse:
|
||||
"""Get playlist favorites for the current user."""
|
||||
favorites = await favorite_service.get_user_playlist_favorites(
|
||||
current_user.id, limit, offset
|
||||
current_user.id, limit, offset,
|
||||
)
|
||||
return FavoritesListResponse(favorites=favorites)
|
||||
|
||||
@@ -94,16 +92,15 @@ async def add_sound_favorite(
|
||||
status_code=status.HTTP_404_NOT_FOUND,
|
||||
detail=str(e),
|
||||
) from e
|
||||
elif "already favorited" in str(e):
|
||||
if "already favorited" in str(e):
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_409_CONFLICT,
|
||||
detail=str(e),
|
||||
) from e
|
||||
else:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail=str(e),
|
||||
) from e
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail=str(e),
|
||||
) from e
|
||||
|
||||
|
||||
@router.post("/playlists/{playlist_id}", response_model=FavoriteResponse)
|
||||
@@ -115,7 +112,7 @@ async def add_playlist_favorite(
|
||||
"""Add a playlist to favorites."""
|
||||
try:
|
||||
favorite = await favorite_service.add_playlist_favorite(
|
||||
current_user.id, playlist_id
|
||||
current_user.id, playlist_id,
|
||||
)
|
||||
return FavoriteResponse.model_validate(favorite)
|
||||
except ValueError as e:
|
||||
@@ -124,16 +121,15 @@ async def add_playlist_favorite(
|
||||
status_code=status.HTTP_404_NOT_FOUND,
|
||||
detail=str(e),
|
||||
) from e
|
||||
elif "already favorited" in str(e):
|
||||
if "already favorited" in str(e):
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_409_CONFLICT,
|
||||
detail=str(e),
|
||||
) from e
|
||||
else:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail=str(e),
|
||||
) from e
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail=str(e),
|
||||
) from e
|
||||
|
||||
|
||||
@router.delete("/sounds/{sound_id}", response_model=MessageResponse)
|
||||
@@ -189,6 +185,6 @@ async def check_playlist_favorited(
|
||||
) -> dict[str, bool]:
|
||||
"""Check if a playlist is favorited by the current user."""
|
||||
is_favorited = await favorite_service.is_playlist_favorited(
|
||||
current_user.id, playlist_id
|
||||
current_user.id, playlist_id,
|
||||
)
|
||||
return {"is_favorited": is_favorited}
|
||||
|
||||
@@ -40,8 +40,9 @@ def get_favorite_service() -> FavoriteService:
|
||||
|
||||
@router.get("/")
|
||||
async def get_all_playlists( # noqa: PLR0913
|
||||
current_user: Annotated[User, Depends(get_current_active_user_flexible)], # noqa: ARG001
|
||||
current_user: Annotated[User, Depends(get_current_active_user_flexible)],
|
||||
playlist_service: Annotated[PlaylistService, Depends(get_playlist_service)],
|
||||
favorite_service: Annotated[FavoriteService, Depends(get_favorite_service)],
|
||||
search: Annotated[
|
||||
str | None,
|
||||
Query(description="Search playlists by name"),
|
||||
@@ -62,9 +63,13 @@ async def get_all_playlists( # noqa: PLR0913
|
||||
int,
|
||||
Query(description="Number of results to skip", ge=0),
|
||||
] = 0,
|
||||
) -> list[dict]:
|
||||
favorites_only: Annotated[
|
||||
bool,
|
||||
Query(description="Show only favorited playlists"),
|
||||
] = False,
|
||||
) -> list[PlaylistResponse]:
|
||||
"""Get all playlists from all users with search and sorting."""
|
||||
return await playlist_service.search_and_sort_playlists(
|
||||
playlists = await playlist_service.search_and_sort_playlists(
|
||||
search_query=search,
|
||||
sort_by=sort_by,
|
||||
sort_order=sort_order,
|
||||
@@ -72,8 +77,29 @@ async def get_all_playlists( # noqa: PLR0913
|
||||
include_stats=True,
|
||||
limit=limit,
|
||||
offset=offset,
|
||||
favorites_only=favorites_only,
|
||||
current_user_id=current_user.id,
|
||||
)
|
||||
|
||||
# Convert to PlaylistResponse with favorite indicators
|
||||
playlist_responses = []
|
||||
for playlist_dict in playlists:
|
||||
# The playlist service returns dict, need to create playlist object-like structure
|
||||
is_favorited = await favorite_service.is_playlist_favorited(current_user.id, playlist_dict["id"])
|
||||
favorite_count = await favorite_service.get_playlist_favorite_count(playlist_dict["id"])
|
||||
|
||||
# Create a PlaylistResponse-like dict with proper datetime conversion
|
||||
playlist_response = {
|
||||
**playlist_dict,
|
||||
"created_at": playlist_dict["created_at"].isoformat() if playlist_dict["created_at"] else None,
|
||||
"updated_at": playlist_dict["updated_at"].isoformat() if playlist_dict["updated_at"] else None,
|
||||
"is_favorited": is_favorited,
|
||||
"favorite_count": favorite_count,
|
||||
}
|
||||
playlist_responses.append(playlist_response)
|
||||
|
||||
return playlist_responses
|
||||
|
||||
|
||||
@router.get("/user")
|
||||
async def get_user_playlists(
|
||||
@@ -83,7 +109,7 @@ async def get_user_playlists(
|
||||
) -> list[PlaylistResponse]:
|
||||
"""Get playlists for the current user only."""
|
||||
playlists = await playlist_service.get_user_playlists(current_user.id)
|
||||
|
||||
|
||||
# Add favorite indicators for each playlist
|
||||
playlist_responses = []
|
||||
for playlist in playlists:
|
||||
@@ -91,7 +117,7 @@ async def get_user_playlists(
|
||||
favorite_count = await favorite_service.get_playlist_favorite_count(playlist.id)
|
||||
playlist_response = PlaylistResponse.from_playlist(playlist, is_favorited, favorite_count)
|
||||
playlist_responses.append(playlist_response)
|
||||
|
||||
|
||||
return playlist_responses
|
||||
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@ from sqlmodel.ext.asyncio.session import AsyncSession
|
||||
from app.core.database import get_db, get_session_factory
|
||||
from app.core.dependencies import get_current_active_user_flexible
|
||||
from app.models.credit_action import CreditActionType
|
||||
from app.models.sound import Sound
|
||||
from app.models.user import User
|
||||
from app.repositories.sound import SortOrder, SoundRepository, SoundSortField
|
||||
from app.schemas.sound import SoundResponse, SoundsListResponse
|
||||
@@ -87,7 +86,7 @@ async def get_sounds( # noqa: PLR0913
|
||||
favorites_only=favorites_only,
|
||||
user_id=current_user.id,
|
||||
)
|
||||
|
||||
|
||||
# Add favorite indicators for each sound
|
||||
sound_responses = []
|
||||
for sound in sounds:
|
||||
@@ -95,7 +94,7 @@ async def get_sounds( # noqa: PLR0913
|
||||
favorite_count = await favorite_service.get_sound_favorite_count(sound.id)
|
||||
sound_response = SoundResponse.from_sound(sound, is_favorited, favorite_count)
|
||||
sound_responses.append(sound_response)
|
||||
|
||||
|
||||
except Exception as e:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
|
||||
Reference in New Issue
Block a user