feat: implement movie listing functionality with pagination and search
This commit is contained in:
@@ -177,6 +177,9 @@ mod tests {
|
||||
async fn delete_movie(&self, _: &MovieId) -> Result<(), DomainError> {
|
||||
panic!()
|
||||
}
|
||||
async fn list_movies(&self, _: &domain::models::collections::PageParams, _: Option<&str>) -> Result<domain::models::collections::Paginated<Movie>, DomainError> {
|
||||
panic!()
|
||||
}
|
||||
}
|
||||
#[async_trait::async_trait]
|
||||
impl ReviewRepository for Panic {
|
||||
|
||||
@@ -10,15 +10,15 @@ use std::str::FromStr;
|
||||
|
||||
use application::{
|
||||
commands::{
|
||||
DeleteReviewCommand, ExportCommand, LoginCommand, RegisterCommand, SyncPosterCommand,
|
||||
DeleteReviewCommand, RegisterCommand, SyncPosterCommand,
|
||||
},
|
||||
queries::{
|
||||
GetActivityFeedQuery, GetMovieSocialPageQuery, GetReviewHistoryQuery, GetUserProfileQuery,
|
||||
GetUsersQuery,
|
||||
ExportQuery, GetActivityFeedQuery, GetMovieSocialPageQuery, GetMoviesQuery,
|
||||
GetReviewHistoryQuery, GetUserProfileQuery, GetUsersQuery, LoginQuery,
|
||||
},
|
||||
use_cases::{
|
||||
delete_review, export_diary as export_diary_uc, get_activity_feed as get_feed_uc,
|
||||
get_diary, get_movie_social_page, get_review_history,
|
||||
get_diary, get_movie_social_page, get_movies, get_review_history,
|
||||
get_user_profile as get_user_profile_uc, get_users, log_review, login as login_uc,
|
||||
register as register_uc, sync_poster, update_profile,
|
||||
},
|
||||
@@ -40,9 +40,9 @@ use api_types::{
|
||||
DiaryQueryParams, DiaryResponse, DirectorStatDto, ExportQueryParams, FeedEntryDto,
|
||||
GenreDto, KeywordDto, LogReviewRequest, LoginRequest, LoginResponse, MonthActivityDto,
|
||||
MonthlyRatingDto, MovieDetailResponse, MovieDto, MovieProfileResponse, MovieStatsDto,
|
||||
PaginationQueryParams, ProfileResponse, RegisterRequest, ReviewDto, ReviewHistoryResponse,
|
||||
SocialFeedResponse, SocialReviewDto, UserProfileQueryParams, UserProfileResponse, UserStatsDto,
|
||||
UserSummaryDto, UserTrendsDto, UsersResponse,
|
||||
MoviesQueryParams, MoviesResponse, PaginationQueryParams, ProfileResponse, RegisterRequest,
|
||||
ReviewDto, ReviewHistoryResponse, SocialFeedResponse, SocialReviewDto, UserProfileQueryParams,
|
||||
UserProfileResponse, UserStatsDto, UserSummaryDto, UserTrendsDto, UsersResponse,
|
||||
};
|
||||
use crate::{
|
||||
errors::ApiError,
|
||||
@@ -74,6 +74,35 @@ pub async fn get_diary(
|
||||
}))
|
||||
}
|
||||
|
||||
#[utoipa::path(
|
||||
get, path = "/api/v1/movies",
|
||||
params(MoviesQueryParams),
|
||||
responses(
|
||||
(status = 200, body = MoviesResponse),
|
||||
)
|
||||
)]
|
||||
pub async fn list_movies(
|
||||
State(state): State<AppState>,
|
||||
Query(params): Query<MoviesQueryParams>,
|
||||
) -> Result<Json<MoviesResponse>, ApiError> {
|
||||
let page = get_movies::execute(
|
||||
&state.app_ctx,
|
||||
GetMoviesQuery {
|
||||
limit: params.limit,
|
||||
offset: params.offset,
|
||||
search: params.search,
|
||||
},
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok(Json(MoviesResponse {
|
||||
items: page.items.iter().map(movie_to_dto).collect(),
|
||||
total_count: page.total_count,
|
||||
limit: page.limit,
|
||||
offset: page.offset,
|
||||
}))
|
||||
}
|
||||
|
||||
#[utoipa::path(
|
||||
get, path = "/api/v1/movies/{id}/history",
|
||||
params(("id" = Uuid, Path, description = "Movie ID")),
|
||||
@@ -179,7 +208,7 @@ pub async fn login(
|
||||
) -> Result<Json<LoginResponse>, ApiError> {
|
||||
let result = login_uc::execute(
|
||||
&state.app_ctx,
|
||||
LoginCommand {
|
||||
LoginQuery {
|
||||
email: req.email,
|
||||
password: req.password,
|
||||
},
|
||||
@@ -415,7 +444,7 @@ pub async fn update_profile_handler(
|
||||
}
|
||||
}
|
||||
|
||||
let cmd = update_profile::UpdateProfileCommand {
|
||||
let cmd = application::commands::UpdateProfileCommand {
|
||||
user_id: user_id.value(),
|
||||
bio,
|
||||
avatar_bytes,
|
||||
@@ -1036,11 +1065,11 @@ pub async fn export_diary(
|
||||
ExportFormat::Csv => ("text/csv; charset=utf-8", "diary.csv"),
|
||||
ExportFormat::Json => ("application/json", "diary.json"),
|
||||
};
|
||||
let cmd = ExportCommand {
|
||||
let query = ExportQuery {
|
||||
user_id: user.0.value(),
|
||||
format,
|
||||
};
|
||||
match export_diary_uc::execute(&state.app_ctx, cmd).await {
|
||||
match export_diary_uc::execute(&state.app_ctx, query).await {
|
||||
Ok(bytes) => (
|
||||
StatusCode::OK,
|
||||
[
|
||||
|
||||
@@ -15,12 +15,12 @@ use application::ports::{
|
||||
FollowersPageData, FollowingPageData,
|
||||
};
|
||||
use application::{
|
||||
commands::{DeleteReviewCommand, ExportCommand, LoginCommand, RegisterCommand},
|
||||
commands::{DeleteReviewCommand, RegisterCommand},
|
||||
queries::{ExportQuery, GetMovieSocialPageQuery, LoginQuery},
|
||||
ports::{
|
||||
HtmlPageContext, LoginPageData, MovieDetailPageData, NewReviewPageData,
|
||||
ProfileSettingsPageData, RegisterPageData, RemoteActorView,
|
||||
},
|
||||
queries::GetMovieSocialPageQuery,
|
||||
use_cases::{
|
||||
delete_review, export_diary as export_diary_uc, get_movie_social_page, log_review,
|
||||
login as login_uc, register as register_uc, update_profile,
|
||||
@@ -133,7 +133,7 @@ pub async fn post_login(
|
||||
}
|
||||
match login_uc::execute(
|
||||
&state.app_ctx,
|
||||
LoginCommand {
|
||||
LoginQuery {
|
||||
email: form.email,
|
||||
password: form.password,
|
||||
},
|
||||
@@ -215,7 +215,7 @@ pub async fn post_register(
|
||||
.await
|
||||
{
|
||||
Ok(_) => {
|
||||
match login_uc::execute(&state.app_ctx, LoginCommand { email, password }).await {
|
||||
match login_uc::execute(&state.app_ctx, LoginQuery { email, password }).await {
|
||||
Ok(result) => {
|
||||
let max_age = (result.expires_at - Utc::now()).num_seconds().max(0);
|
||||
let cookie = set_cookie_header(&result.token, max_age);
|
||||
@@ -320,11 +320,11 @@ pub async fn get_export(
|
||||
ExportFormat::Csv => ("text/csv; charset=utf-8", "diary.csv"),
|
||||
ExportFormat::Json => ("application/json", "diary.json"),
|
||||
};
|
||||
let cmd = ExportCommand {
|
||||
let query = ExportQuery {
|
||||
user_id: user_id.value(),
|
||||
format,
|
||||
};
|
||||
match export_diary_uc::execute(&state.app_ctx, cmd).await {
|
||||
match export_diary_uc::execute(&state.app_ctx, query).await {
|
||||
Ok(bytes) => (
|
||||
StatusCode::OK,
|
||||
[
|
||||
@@ -1230,7 +1230,7 @@ pub async fn post_profile_settings(
|
||||
}
|
||||
}
|
||||
|
||||
let cmd = update_profile::UpdateProfileCommand {
|
||||
let cmd = application::commands::UpdateProfileCommand {
|
||||
user_id: user_id.value(),
|
||||
bio,
|
||||
avatar_bytes,
|
||||
|
||||
@@ -1,20 +1,30 @@
|
||||
use api_types::{
|
||||
DirectorStatDto, MonthActivityDto, MonthlyRatingDto, MovieDetailResponse, MovieDto,
|
||||
MovieStatsDto, ReviewHistoryResponse, SocialFeedResponse, SocialReviewDto, UserTrendsDto,
|
||||
CastMemberDto, CrewMemberDto, DirectorStatDto, GenreDto, KeywordDto, MonthActivityDto,
|
||||
MonthlyRatingDto, MovieDetailResponse, MovieDto, MovieProfileResponse, MovieStatsDto,
|
||||
MoviesQueryParams, MoviesResponse, ReviewHistoryResponse, SocialFeedResponse, SocialReviewDto,
|
||||
UserTrendsDto,
|
||||
};
|
||||
use utoipa::OpenApi;
|
||||
|
||||
#[derive(OpenApi)]
|
||||
#[openapi(
|
||||
paths(
|
||||
crate::handlers::api::list_movies,
|
||||
crate::handlers::api::get_movie_detail,
|
||||
crate::handlers::api::get_review_history,
|
||||
crate::handlers::api::get_movie_profile,
|
||||
crate::handlers::api::sync_poster,
|
||||
),
|
||||
components(schemas(
|
||||
MoviesResponse,
|
||||
MovieDto,
|
||||
MovieDetailResponse,
|
||||
MovieStatsDto,
|
||||
MovieProfileResponse,
|
||||
GenreDto,
|
||||
KeywordDto,
|
||||
CastMemberDto,
|
||||
CrewMemberDto,
|
||||
ReviewHistoryResponse,
|
||||
SocialFeedResponse,
|
||||
SocialReviewDto,
|
||||
|
||||
@@ -177,6 +177,7 @@ fn api_routes(rate_limit: u64) -> Router<AppState> {
|
||||
"/movies/{id}/history",
|
||||
routing::get(handlers::api::get_review_history),
|
||||
)
|
||||
.route("/movies", routing::get(handlers::api::list_movies))
|
||||
.route(
|
||||
"/movies/{id}",
|
||||
routing::get(handlers::api::get_movie_detail),
|
||||
|
||||
Reference in New Issue
Block a user