diff --git a/src/containers/Movie/dtos/index.ts b/src/components/Movie/dtos/index.ts similarity index 100% rename from src/containers/Movie/dtos/index.ts rename to src/components/Movie/dtos/index.ts diff --git a/src/containers/Movie/index.tsx b/src/components/Movie/index.tsx similarity index 100% rename from src/containers/Movie/index.tsx rename to src/components/Movie/index.tsx diff --git a/src/containers/Movie/styles.ts b/src/components/Movie/styles.ts similarity index 100% rename from src/containers/Movie/styles.ts rename to src/components/Movie/styles.ts diff --git a/src/containers/MovieList/index.tsx b/src/containers/MovieList/index.tsx index b354df4..f611ab0 100644 --- a/src/containers/MovieList/index.tsx +++ b/src/containers/MovieList/index.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { Wrapper } from 'components/Layout'; -import Movie from 'containers/Movie'; +import Movie from 'components/Movie'; import { Container, Title, ListContainer, ListContent } from './styles'; import Props from './dtos'; diff --git a/src/containers/index.ts b/src/containers/index.ts index ad4923d..1f35ed1 100644 --- a/src/containers/index.ts +++ b/src/containers/index.ts @@ -1,5 +1,5 @@ export { default as Footer } from './Footer'; export { default as Header } from './Header'; export { default as Highlights } from './Highlights'; -export { default as Movie } from './Movie'; +export { default as Movie } from '../components/Movie'; export { default as MovieList } from './MovieList'; diff --git a/src/domains/Favorites/api/List/RawResponse.ts b/src/domains/Favorites/api/List/RawResponse.ts new file mode 100644 index 0000000..adb1f95 --- /dev/null +++ b/src/domains/Favorites/api/List/RawResponse.ts @@ -0,0 +1,7 @@ +export default interface RawResponse { + id: string; + user_id: string; + movie_id: number; + created_at: string; + updated_at: string; +} diff --git a/src/domains/Favorites/api/List/Response.ts b/src/domains/Favorites/api/List/Response.ts new file mode 100644 index 0000000..b7a4954 --- /dev/null +++ b/src/domains/Favorites/api/List/Response.ts @@ -0,0 +1,7 @@ +import DetailsResponse from 'domains/Movie/api/Details/Response'; + +export default interface Response extends Omit { + id: string; + userId: string; + movieId: number; +} diff --git a/src/domains/Favorites/api/List/index.ts b/src/domains/Favorites/api/List/index.ts new file mode 100644 index 0000000..0241318 --- /dev/null +++ b/src/domains/Favorites/api/List/index.ts @@ -0,0 +1,41 @@ +import api from 'services/api'; + +import RawResponse from 'domains/Favorites/api/List/RawResponse'; +import Response from 'domains/Favorites/api/List/Response'; +import { Details } from 'domains/Movie/api'; + +const Favorites = async (): Promise => { + const response = await rawFavorites(); + + return parseResponse(response); +}; + +export const rawFavorites = async (): Promise => { + const response = await api.get('/favorites'); + + return response.data; +}; + +const parseResponse = async ( + rawResponse: RawResponse[], +): Promise => { + const response = rawResponse.map(async (favorite: RawResponse) => { + // Get favorites details from TMDB API and merge + const details = await Details(favorite.movie_id); + + // Merge API and TMDB results + return { + ...details, + id: favorite.id, + userId: favorite.user_id, + movieId: favorite.movie_id, + }; + }); + + // Resolve async requests and promises + const resolvedResponse = Promise.all(response); + + return resolvedResponse; +}; + +export default Favorites; diff --git a/src/domains/Favorites/api/index.ts b/src/domains/Favorites/api/index.ts new file mode 100644 index 0000000..6a0f2da --- /dev/null +++ b/src/domains/Favorites/api/index.ts @@ -0,0 +1 @@ +export { default as Favorites } from './List'; diff --git a/src/domains/Movie/api/Details/RawResponse.ts b/src/domains/Movie/api/Details/RawResponse.ts new file mode 100644 index 0000000..91f6e41 --- /dev/null +++ b/src/domains/Movie/api/Details/RawResponse.ts @@ -0,0 +1,21 @@ +export default interface RawResponse { + poster_path?: string; + budget: number; + overview: string; + release_date: string; + genres: [ + { + id: number; + name: string; + }, + ]; + id: number; + original_title: string; + original_language: string; + title: string; + backdrop_path?: string; + popularity: number; + vote_count: number; + video: boolean; + vote_average: number; +} diff --git a/src/domains/Movie/api/Details/Response.ts b/src/domains/Movie/api/Details/Response.ts new file mode 100644 index 0000000..7f186ac --- /dev/null +++ b/src/domains/Movie/api/Details/Response.ts @@ -0,0 +1,19 @@ +export default interface Response { + poster?: string; + backdrop?: string; + budget: number; + overview: string; + releaseDate: string; + genres: [ + { + id: number; + name: string; + }, + ]; + id: number; + originalTitle: string; + title: string; + popularity: number; + voteCount: number; + voteAverage: number; +} diff --git a/src/domains/Movie/api/Details/index.ts b/src/domains/Movie/api/Details/index.ts new file mode 100644 index 0000000..b1b092a --- /dev/null +++ b/src/domains/Movie/api/Details/index.ts @@ -0,0 +1,40 @@ +import tmdb from 'services/api/tmdb'; + +import RawResponse from 'domains/Movie/api/Details/RawResponse'; +import Response from 'domains/Movie/api/Details/Response'; +import formatDate from 'shared/utils/formatDate'; +import formatTmdbImage from 'shared/utils/formatTmdbImage'; + +const Details = async (movieId: number): Promise => { + const response = await rawPopular(movieId); + + return parseResponse(response); +}; + +export const rawPopular = async (movieId: number): Promise => { + const response = await tmdb.get(`/movie/${movieId}`); + + return response.data; +}; + +const parseResponse = (movie: RawResponse): Response => { + const parsedMovie = { + overview: movie.overview, + budget: movie.budget, + genres: movie.genres, + id: movie.id, + originalTitle: movie.original_title, + title: movie.title, + popularity: movie.popularity, + voteCount: movie.vote_count, + voteAverage: movie.vote_average, + + releaseDate: formatDate({ value: movie.release_date }), + poster: formatTmdbImage({ value: movie.poster_path }), + backdrop: formatTmdbImage({ value: movie.backdrop_path }), + } as Response; + + return parsedMovie; +}; + +export default Details; diff --git a/src/domains/Movie/api/index.ts b/src/domains/Movie/api/index.ts index 76a96a2..aeebfaa 100644 --- a/src/domains/Movie/api/index.ts +++ b/src/domains/Movie/api/index.ts @@ -1,2 +1,3 @@ +export { default as Details } from './Details'; export { default as NowPlaying } from './NowPlaying'; export { default as Popular } from './Popular'; diff --git a/src/screens/Home/index.tsx b/src/screens/Home/index.tsx index 3ef1786..d4f3b5b 100644 --- a/src/screens/Home/index.tsx +++ b/src/screens/Home/index.tsx @@ -1,7 +1,9 @@ import React, { useEffect, useState } from 'react'; import { NowPlaying, Popular } from 'domains/Movie/api'; +import { Favorites } from 'domains/Favorites/api'; import MovieResponse from 'domains/Movie/api/Popular/Response'; +import FavoriteResponse from 'domains/Favorites/api/List/Response'; import { ColumnLayout } from 'components/Layout'; import { Footer, Header, Highlights, MovieList } from 'containers'; @@ -10,10 +12,14 @@ import { HeaderBackground, ContentContainer } from './styles'; const Home: React.FC = () => { const [popularList, setPopularList] = useState([] as MovieResponse[]); const [nowPlayingList, setNowPlayingList] = useState([] as MovieResponse[]); + const [favoriteList, setFavoriteList] = useState([] as FavoriteResponse[]); useEffect(() => { NowPlaying().then(response => setNowPlayingList(response)); Popular().then(response => setPopularList(response)); + Favorites().then(response => { + setFavoriteList(response); + }); }, []); return ( @@ -23,6 +29,7 @@ const Home: React.FC = () => { +