Skip to content

Commit

Permalink
Merge pull request #35 from f-lab-edu/feature/34-all-now-playing-movi…
Browse files Browse the repository at this point in the history
…e-list

[FEATURE] 영화 필터 API 라우트 추가
  • Loading branch information
ag502 authored Dec 7, 2024
2 parents 4b25879 + 4af5f79 commit a40e264
Show file tree
Hide file tree
Showing 15 changed files with 173 additions and 0 deletions.
41 changes: 41 additions & 0 deletions apps/web/pages/api/filter/movie.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { tmdbHttpServer, withCommonRoute } from "@/shared/api";
import { camelCaseObjMapper } from "@/shared/lib";

import {
FilteredMovieList,
filteredMovieListQuerySchema,
SFilteredMovieListReqParams,
} from "../../../src/entities/filter";

export default withCommonRoute(
async (req, res) => {
const queries = req.query as unknown as SFilteredMovieListReqParams;

const result = await tmdbHttpServer.get<FilteredMovieList>("discover/movie", {
params: {
certification_country: queries.certificationCountry,
include_adult: queries.includeAdult,
include_video: queries.includeVideo,
language: queries.language,
page: queries.page,
"release_date.gte": queries.releaseDateGte,
"release_date.lte": queries.releaseDateLte,
sort_by: queries.sortBy,
"vote_average.gte": queries.voteAverageGte,
"vote_average.lte": queries.voteAverageLte,
"vote_count.gte": queries.voteCountGte,
"vote_count.lte": queries.voteCountLte,
watch_region: queries.watchRegion,
with_genre: queries.withGenre,
with_release_type: queries.withReleaseType && queries.withReleaseType.join("|"),
"with_run_time.gte": queries.withRunTimeGte,
"with_run_time.lte": queries.withRunTimeLte,
},
});
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
return res.status(200).send(camelCaseObjMapper(result.data));
},
["GET"],
filteredMovieListQuerySchema,
);
24 changes: 24 additions & 0 deletions apps/web/src/entities/filter/api/filter-api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { AxiosRequestConfig } from "axios";

import { FilteredMovieListDTO } from "@/entities/filter";
import { FilteredMovieListReqParams } from "@/entities/filter/api/request-types/movie";
import { localHttp } from "@/shared/api";

const discoverBaseURL = "filter";

export default class FilterApi {
/**
* 영화 필터
*/
static async getFilterMovies(
args: FilteredMovieListReqParams,
axiosRequestConfig?: AxiosRequestConfig,
): Promise<FilteredMovieListDTO> {
return localHttp
.get(`${discoverBaseURL}/movie`, {
params: args,
...axiosRequestConfig,
})
.then((res) => res.data);
}
}
3 changes: 3 additions & 0 deletions apps/web/src/entities/filter/api/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from "./request-types";
export * from "./response-types";
export * from "./filter-api";
2 changes: 2 additions & 0 deletions apps/web/src/entities/filter/api/queries/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from "./query-keys";
export * from "./use-filtered-movie-list";
6 changes: 6 additions & 0 deletions apps/web/src/entities/filter/api/queries/query-keys.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { FilteredMovieListReqParams } from "@/entities/filter/api/request-types/movie";

export const filteredMediaListQueryKeys = {
all: ["filter"] as const,
filteredMovieList: (args: FilteredMovieListReqParams) => ["filtered-movie-list", { ...args }] as const,
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { useQuery } from "@tanstack/react-query";

import FilterApi from "@/entities/filter/api/filter-api";
import { filteredMediaListQueryKeys } from "@/entities/filter/api/queries/query-keys";
import { FilteredMovieListReqParams } from "@/entities/filter/api/request-types/movie";
import FilteredMovieListModel from "@/entities/filter/model/filtered-movie-list";

export const useFilteredMovieList = (args: FilteredMovieListReqParams = {}) => {
const { page = 1, watchRegion = "KR", certificationCountry = "KR", language = "ko-KR", ...restArgs } = args;

const reqArgs = {
page,
watchRegion,
certificationCountry,
language,
...restArgs,
};

return useQuery({
queryKey: [...filteredMediaListQueryKeys.all, ...filteredMediaListQueryKeys.filteredMovieList(reqArgs)],
queryFn: () => FilterApi.getFilterMovies(reqArgs),
select: (data) => new FilteredMovieListModel(data),
});
};
1 change: 1 addition & 0 deletions apps/web/src/entities/filter/api/request-types/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./movie.server";
49 changes: 49 additions & 0 deletions apps/web/src/entities/filter/api/request-types/movie.server.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { z } from "zod";

export const filteredMovieListQuerySchema = z.object({
certificationCountry: z.string().optional(),
includeAdult: z.coerce.boolean().optional(),
includeVideo: z.coerce.boolean().optional(),
language: z.string().optional(),
page: z.coerce.number().optional(),
releaseDateGte: z.coerce.date().optional(),
releaseDateLte: z.coerce.date().optional(),
sortBy: z
.enum([
"original_title.asc",
"original_title_desc",
"popularity.asc",
"popularity.desc",
"title.asc",
"title.desc",
"vote_average.asc",
"vote_average.desc",
"vote_count.asc",
"vote_count.desc",
])
.optional(),
voteAverageGte: z.coerce.number().optional(),
voteAverageLte: z.coerce.number().optional(),
voteCountGte: z.coerce.number().optional(),
voteCountLte: z.coerce.number().optional(),
watchRegion: z.string().optional(),
withGenre: z.string().optional(),
withReleaseType: z.enum(["1", "2", "3", "4", "5"]).array().optional(),
withRunTimeGte: z.coerce.number().optional(),
withRunTimeLte: z.coerce.number().optional(),
});

/**
* ```
* voteAverage - 사용자 점수
* voteCount - 투표수
* withReleaseType
* 1 - Premiere
* 2 - Theatrical (limited)
* 3 - Theatrical
* 4 - Digital
* 5 - Physical
* 6 - TV
* ```
*/
export type SFilteredMovieListReqParams = z.infer<typeof filteredMovieListQuerySchema>;
3 changes: 3 additions & 0 deletions apps/web/src/entities/filter/api/request-types/movie.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { SFilteredMovieListReqParams } from "../.";

export interface FilteredMovieListReqParams extends SFilteredMovieListReqParams {}
5 changes: 5 additions & 0 deletions apps/web/src/entities/filter/api/response-types/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// server
export * from "./movie.server";

// client
export * from "./movie";
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { MovieList } from "@/entities/movie-list/api/response-types/movie-list.server";

export interface FilteredMovieList extends MovieList {}
3 changes: 3 additions & 0 deletions apps/web/src/entities/filter/api/response-types/movie.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { MovieListDTO } from "@/entities/movie-list";

export interface FilteredMovieListDTO extends MovieListDTO {}
2 changes: 2 additions & 0 deletions apps/web/src/entities/filter/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from "./api";
export * from "./model";
7 changes: 7 additions & 0 deletions apps/web/src/entities/filter/model/filtered-movie-list.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { MovieListDTO, MovieListModel } from "@/entities/movie-list";

export default class FilteredMovieListModel extends MovieListModel {
constructor(data: MovieListDTO) {
super(data);
}
}
Empty file.

0 comments on commit a40e264

Please sign in to comment.