diff --git a/src/domains/Favorites/api/List/types/Response.ts b/src/domains/Favorites/api/List/types/Response.ts index 4e28d91..5031644 100644 --- a/src/domains/Favorites/api/List/types/Response.ts +++ b/src/domains/Favorites/api/List/types/Response.ts @@ -1,9 +1,11 @@ import MovieResponse from 'domains/Movie/api/Details/types/Response'; import PersonResponse from 'domains/Person/api/Details/types/Response'; +import TvResponse from 'domains/Tv/api/Details/types/Response'; export default interface Response extends Omit, - Omit { + Omit, + Omit { favoriteId: string; userId: string; entityId: number; diff --git a/src/domains/Movie/api/Details/index.ts b/src/domains/Movie/api/Details/index.ts index 95912be..36c26f5 100644 --- a/src/domains/Movie/api/Details/index.ts +++ b/src/domains/Movie/api/Details/index.ts @@ -1,6 +1,6 @@ import tmdb from 'services/api/tmdb'; -import { arrayToString } from 'shared/helpers'; +import { arrayToString, randomInteger } from 'shared/helpers'; import { getBackdrop, getFeaturedImage, @@ -19,6 +19,7 @@ import Credits from 'domains/Movie/api/Credits/types/Response'; import Crew from 'domains/Movie/api/Credits/types/Crew'; import Cast from 'domains/Movie/api/Credits/types/Cast'; +import Image from 'shared/types/Image'; const Details = async (movieId: number, params?: Params): Promise => { const response = await rawPopular(movieId, params); @@ -41,33 +42,25 @@ export const rawPopular = async ( }; const parseResponse = (movie: RawResponse): Response => { - let parsedMovie = { - overview: movie.overview, - budget: movie.budget, - genres: movie.genres, - genresNames: arrayToString(movie.genres, 'name'), - id: movie.id, - originalTitle: movie.original_title, - popularity: movie.popularity, - voteCount: movie.vote_count, - voteAverage: movie.vote_average, - runtime: `${movie.runtime} min`, - tagline: movie.tagline, - - directorName: movie.credits?.crew.find( - person => person.job.toUpperCase() === 'DIRECTOR', - )?.name, - - releaseDate: getReleaseDate(movie), - backdrop: getBackdrop(movie), - - featuredImage: getFeaturedImage(movie), - releaseYear: getReleaseYear(movie), - subtitle: getReleaseDate(movie), - title: getTitle(movie), - favorite: false, - mediaType: EntityType.MOVIE, - } as Response; + const posters = movie.images?.posters.map(poster => ({ + aspectRatio: poster.aspect_ratio, + height: poster.height, + width: poster.width, + voteAverage: poster.vote_average, + voteCount: poster.vote_count, + featuredImage: getFeaturedImage(poster), + })) as Image[]; + + const backdrops = movie.images?.backdrops.map(backdrop => ({ + aspectRatio: backdrop.aspect_ratio, + height: backdrop.height, + width: backdrop.width, + voteAverage: backdrop.vote_average, + voteCount: backdrop.vote_count, + featuredImage: getFeaturedImage(backdrop), + })) as Image[]; + + const images = { posters, backdrops }; const recommendations = movie.recommendations?.results.map( recommendation => ({ @@ -118,7 +111,37 @@ const parseResponse = (movie: RawResponse): Response => { const credits = { cast, crew } as Credits; - parsedMovie = { ...parsedMovie, recommendations, credits }; + let parsedMovie = { + overview: movie.overview, + budget: movie.budget, + genres: movie.genres, + genresNames: arrayToString(movie.genres, 'name'), + id: movie.id, + originalTitle: movie.original_title, + popularity: movie.popularity, + voteCount: movie.vote_count, + voteAverage: movie.vote_average, + runtime: `${movie.runtime} min`, + tagline: movie.tagline, + + directorName: movie.credits?.crew.find( + person => person.job.toUpperCase() === 'DIRECTOR', + )?.name, + + releaseDate: getReleaseDate(movie), + backdrop: + backdrops[randomInteger(0, backdrops.length - 1)]?.featuredImage || + getBackdrop(movie), + + featuredImage: getFeaturedImage(movie), + releaseYear: getReleaseYear(movie), + subtitle: getReleaseDate(movie), + title: getTitle(movie), + favorite: false, + mediaType: EntityType.MOVIE, + } as Response; + + parsedMovie = { ...parsedMovie, recommendations, credits, images }; return parsedMovie; }; diff --git a/src/domains/Movie/api/Details/types/RawResponse.ts b/src/domains/Movie/api/Details/types/RawResponse.ts index 5e35edd..3f30fd2 100644 --- a/src/domains/Movie/api/Details/types/RawResponse.ts +++ b/src/domains/Movie/api/Details/types/RawResponse.ts @@ -1,5 +1,6 @@ import Recommendations from 'domains/Movie/api/Recommendations/types/RawResponse'; import Credits from 'domains/Movie/api/Credits/types/RawResponse'; +import RawImage from 'shared/types/Image/RawImage'; export default interface RawResponse { poster_path?: string; @@ -24,9 +25,14 @@ export default interface RawResponse { video: boolean; vote_average: number; tagline: string; + recommendations?: { results: Recommendations[]; }; + images?: { + posters: RawImage[]; + backdrops: RawImage[]; + }; credits?: Credits; mediaType: string; } diff --git a/src/domains/Movie/api/Details/types/Response.ts b/src/domains/Movie/api/Details/types/Response.ts index 686dc32..1dd7883 100644 --- a/src/domains/Movie/api/Details/types/Response.ts +++ b/src/domains/Movie/api/Details/types/Response.ts @@ -1,5 +1,6 @@ import Recommendations from 'domains/Movie/api/Recommendations/types/Response'; import Credits from 'domains/Movie/api/Credits/types/Response'; +import Images from 'shared/types/Images'; export default interface Response { poster?: string; @@ -24,6 +25,7 @@ export default interface Response { tagline: string; recommendations?: Recommendations[]; + images?: Images; credits?: Credits; directorName?: string; diff --git a/src/domains/Person/api/Details/index.ts b/src/domains/Person/api/Details/index.ts index 8b0c597..fcbcc09 100644 --- a/src/domains/Person/api/Details/index.ts +++ b/src/domains/Person/api/Details/index.ts @@ -17,6 +17,7 @@ import Params from 'domains/Person/api/Details/types/Params'; import RawResponse from 'domains/Person/api/Details/types/RawResponse'; import Response from 'domains/Person/api/Details/types/Response'; import Movie from 'domains/Person/api/Details/types/Movie'; +import Image from 'shared/types/Image'; const Details = async ( personId: number, @@ -97,14 +98,16 @@ const parseResponse = (person: RawResponse): Response => { Date.parse(a.originalDate) < Date.parse(b.originalDate) ? 1 : -1, ); - const images = person.images?.profiles.map(image => ({ - aspectRatio: image.aspect_ratio, - featuredImage: getFeaturedImage(image) || undefined, - height: image.height, - voteAverage: image.vote_average, - voteCount: image.vote_count, - width: image.width, - })); + const images = { + profiles: person.images?.profiles.map(profile => ({ + aspectRatio: profile.aspect_ratio, + height: profile.height, + width: profile.width, + voteAverage: profile.vote_average, + voteCount: profile.vote_count, + featuredImage: getFeaturedImage(profile), + })) as Image[], + }; parsedPerson = { ...parsedPerson, knownFor, filmography, images }; diff --git a/src/domains/Person/api/Details/types/RawResponse.ts b/src/domains/Person/api/Details/types/RawResponse.ts index c9896cc..fb5b731 100644 --- a/src/domains/Person/api/Details/types/RawResponse.ts +++ b/src/domains/Person/api/Details/types/RawResponse.ts @@ -1,5 +1,6 @@ // import Recommendations from 'domains/Movie/api/Recommendations/RawResponse'; import RawMovie from 'domains/Person/api/Details/types/RawMovie'; +import RawImage from 'shared/types/Image/RawImage'; export default interface RawResponse { id: number; @@ -21,14 +22,7 @@ export default interface RawResponse { homepage?: string; images?: { - profiles: Array<{ - aspect_ratio: number; - file_path: string; - height: number; - vote_average: number; - vote_count: number; - width: number; - }>; + profiles: RawImage[]; }; combined_credits?: { cast: RawMovie[] }; diff --git a/src/domains/Person/api/Details/types/Response.ts b/src/domains/Person/api/Details/types/Response.ts index 591d3bc..f12a9de 100644 --- a/src/domains/Person/api/Details/types/Response.ts +++ b/src/domains/Person/api/Details/types/Response.ts @@ -1,5 +1,6 @@ // import Recommendations from 'domains/Movie/api/Recommendations/Response'; import Movie from 'domains/Person/api/Details/types/Movie'; +import Images from 'shared/types/Images'; export default interface Response { id: number; @@ -21,14 +22,7 @@ export default interface Response { knownFor?: Movie[]; filmography?: Movie[]; - images?: Array<{ - aspectRatio: number; - featuredImage?: string; - height: number; - voteAverage: number; - voteCount: number; - width: number; - }>; + images?: Images; favorite: boolean; mediaType: number; diff --git a/src/domains/Tv/api/Details/index.ts b/src/domains/Tv/api/Details/index.ts index 86a1f78..082d0fc 100644 --- a/src/domains/Tv/api/Details/index.ts +++ b/src/domains/Tv/api/Details/index.ts @@ -1,6 +1,6 @@ import tmdb from 'services/api/tmdb'; -import { arrayToString } from 'shared/helpers'; +import { arrayToString, randomInteger } from 'shared/helpers'; import { getBackdrop, getFeaturedImage, @@ -19,6 +19,7 @@ import Credits from 'domains/Tv/api/Credits/types/Response'; import Crew from 'domains/Tv/api/Credits/types/Crew'; import Cast from 'domains/Tv/api/Credits/types/Cast'; +import Image from 'shared/types/Image'; const Details = async (tvId: number, params?: Params): Promise => { const response = await rawPopular(tvId, params); @@ -41,31 +42,6 @@ export const rawPopular = async ( }; const parseResponse = (tv: RawResponse): Response => { - let parsedMovie = { - overview: tv.overview, - genres: tv.genres, - genresNames: arrayToString(tv.genres, 'name'), - id: tv.id, - originalTitle: tv.original_name, - popularity: tv.popularity, - voteCount: tv.vote_count, - voteAverage: tv.vote_average, - tagline: tv.tagline, - runtime: `${tv.episode_run_time} min`, - - creatorName: tv.created_by[0]?.name, - - releaseDate: getReleaseDate(tv), - backdrop: getBackdrop(tv), - - featuredImage: getFeaturedImage(tv), - releaseYear: getReleaseYear(tv), - subtitle: getReleaseDate(tv), - title: getTitle(tv), - favorite: false, - mediaType: EntityType.TV, - } as Response; - const recommendations = tv.recommendations?.results.map(recommendation => ({ backdrop: getBackdrop(recommendation), id: recommendation.id, @@ -78,6 +54,26 @@ const parseResponse = (tv: RawResponse): Response => { mediaType: EntityType.TV, })) as Recommendations[]; + const posters = tv.images?.posters.map(poster => ({ + aspectRatio: poster.aspect_ratio, + height: poster.height, + width: poster.width, + voteAverage: poster.vote_average, + voteCount: poster.vote_count, + featuredImage: getFeaturedImage(poster), + })) as Image[]; + + const backdrops = tv.images?.backdrops.map(backdrop => ({ + aspectRatio: backdrop.aspect_ratio, + height: backdrop.height, + width: backdrop.width, + voteAverage: backdrop.vote_average, + voteCount: backdrop.vote_count, + featuredImage: getFeaturedImage(backdrop), + })) as Image[]; + + const images = { posters, backdrops }; + const cast = tv.credits?.cast.slice(0, 15).map(person => ({ order: person.order, id: person.id, @@ -113,7 +109,34 @@ const parseResponse = (tv: RawResponse): Response => { const credits = { cast, crew } as Credits; - parsedMovie = { ...parsedMovie, recommendations, credits }; + let parsedMovie = { + overview: tv.overview, + genres: tv.genres, + genresNames: arrayToString(tv.genres, 'name'), + id: tv.id, + originalTitle: tv.original_name, + popularity: tv.popularity, + voteCount: tv.vote_count, + voteAverage: tv.vote_average, + tagline: tv.tagline, + runtime: `${tv.episode_run_time} min`, + + creatorName: tv.created_by[0]?.name, + + releaseDate: getReleaseDate(tv), + backdrop: + backdrops[randomInteger(0, backdrops.length - 1)]?.featuredImage || + getBackdrop(tv), + + featuredImage: getFeaturedImage(tv), + releaseYear: getReleaseYear(tv), + subtitle: getReleaseDate(tv), + title: getTitle(tv), + favorite: false, + mediaType: EntityType.TV, + } as Response; + + parsedMovie = { ...parsedMovie, recommendations, credits, images }; return parsedMovie; }; diff --git a/src/domains/Tv/api/Details/types/RawResponse.ts b/src/domains/Tv/api/Details/types/RawResponse.ts index 69892cd..63f9275 100644 --- a/src/domains/Tv/api/Details/types/RawResponse.ts +++ b/src/domains/Tv/api/Details/types/RawResponse.ts @@ -1,5 +1,6 @@ import Recommendations from 'domains/Tv/api/Recommendations/types/RawResponse'; import Credits from 'domains/Tv/api/Credits/types/RawResponse'; +import RawImage from 'shared/types/Image/RawImage'; export default interface RawResponse { poster_path?: string; @@ -24,9 +25,13 @@ export default interface RawResponse { vote_average: number; created_by: any[]; + credits?: Credits; recommendations?: { results: Recommendations[]; }; - credits?: Credits; + images?: { + posters: RawImage[]; + backdrops: RawImage[]; + }; mediaType: string; } diff --git a/src/domains/Tv/api/Details/types/Response.ts b/src/domains/Tv/api/Details/types/Response.ts index 446f53e..e4218f0 100644 --- a/src/domains/Tv/api/Details/types/Response.ts +++ b/src/domains/Tv/api/Details/types/Response.ts @@ -1,5 +1,6 @@ import Recommendations from 'domains/Movie/api/Recommendations/types/Response'; import Credits from 'domains/Movie/api/Credits/types/Response'; +import Images from 'shared/types/Images'; export default interface Response { backdrop?: string; @@ -24,6 +25,7 @@ export default interface Response { creatorName: string; recommendations?: Recommendations[]; + images?: Images; credits?: Credits; directorName?: string; diff --git a/src/pages/Person/index.tsx b/src/pages/Person/index.tsx index 3a980f7..aea7c25 100644 --- a/src/pages/Person/index.tsx +++ b/src/pages/Person/index.tsx @@ -122,7 +122,7 @@ const Person: React.FC = () => { {person?.images && ( = () => {
- ${isLoading && backdrop} + {!isLoading && backdrop} diff --git a/src/shared/helpers/Entity/getBackdrop.ts b/src/shared/helpers/Entity/getBackdrop.ts index 835fcb1..4b8e82e 100644 --- a/src/shared/helpers/Entity/getBackdrop.ts +++ b/src/shared/helpers/Entity/getBackdrop.ts @@ -2,7 +2,7 @@ import { formatTmdbImage } from 'shared/helpers'; const getBackdrop = (value: any): string | null => { return formatTmdbImage({ - value: value.backdrop_path || value.profile_path, + value: value.backdrop_path || value.profile_path || value.file_path, }); }; diff --git a/src/shared/helpers/index.ts b/src/shared/helpers/index.ts index 68ead60..e7372ab 100644 --- a/src/shared/helpers/index.ts +++ b/src/shared/helpers/index.ts @@ -8,3 +8,4 @@ export { default as getColorByTheme } from './colors/getColorByTheme'; export { default as getEntityRoute } from './getEntityRoute'; export { default as getMediaTypeId } from './getMediaTypeId'; export { default as getValidationErrors } from './getValidationErrors'; +export { default as randomInteger } from './randomInteger'; diff --git a/src/shared/helpers/randomInteger.ts b/src/shared/helpers/randomInteger.ts new file mode 100644 index 0000000..34a9eaf --- /dev/null +++ b/src/shared/helpers/randomInteger.ts @@ -0,0 +1,5 @@ +const randomInteger = (min = 0, max = 0): number => { + return Math.floor(Math.random() * (max - min)) + min; +}; + +export default randomInteger; diff --git a/src/shared/types/Image/RawImage.ts b/src/shared/types/Image/RawImage.ts new file mode 100644 index 0000000..6dd3e0f --- /dev/null +++ b/src/shared/types/Image/RawImage.ts @@ -0,0 +1,8 @@ +export default interface RawImage { + aspect_ratio: number; + file_path: string; + height: number; + vote_average: number; + vote_count: number; + width: number; +} diff --git a/src/shared/types/Image/index.ts b/src/shared/types/Image/index.ts new file mode 100644 index 0000000..7bd10c5 --- /dev/null +++ b/src/shared/types/Image/index.ts @@ -0,0 +1,8 @@ +export default interface Image { + aspectRatio: number; + height: number; + voteAverage: number; + voteCount: number; + width: number; + featuredImage: string; +} diff --git a/src/shared/types/Images.ts b/src/shared/types/Images.ts new file mode 100644 index 0000000..c60fc3b --- /dev/null +++ b/src/shared/types/Images.ts @@ -0,0 +1,7 @@ +import Image from 'shared/types/Image'; + +export default interface Images { + profiles?: Image[]; + posters?: Image[]; + backdrops?: Image[]; +}