feat: implement movie listing functionality with pagination and search

This commit is contained in:
2026-05-12 13:57:55 +02:00
parent fb81aa10c1
commit 4269eca582
17 changed files with 239 additions and 64 deletions

View File

@@ -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,
[

View File

@@ -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,