├── .gitignore
├── .vscode
└── settings.json
├── LICENSE
├── README.md
├── index.html
├── package.json
├── src
├── main.js
├── navigation.js
├── nodes.js
└── secrets.example.js
└── styles
└── app.css
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | lerna-debug.log*
8 |
9 | # Diagnostic reports (https://nodejs.org/api/report.html)
10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
11 |
12 | # Runtime data
13 | pids
14 | *.pid
15 | *.seed
16 | *.pid.lock
17 |
18 | # Directory for instrumented libs generated by jscoverage/JSCover
19 | lib-cov
20 |
21 | # Coverage directory used by tools like istanbul
22 | coverage
23 | *.lcov
24 |
25 | # nyc test coverage
26 | .nyc_output
27 |
28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
29 | .grunt
30 |
31 | # Bower dependency directory (https://bower.io/)
32 | bower_components
33 |
34 | # node-waf configuration
35 | .lock-wscript
36 |
37 | # Compiled binary addons (https://nodejs.org/api/addons.html)
38 | build/Release
39 |
40 | # Dependency directories
41 | node_modules/
42 | jspm_packages/
43 |
44 | # TypeScript v1 declaration files
45 | typings/
46 |
47 | # TypeScript cache
48 | *.tsbuildinfo
49 |
50 | # Optional npm cache directory
51 | .npm
52 |
53 | # Optional eslint cache
54 | .eslintcache
55 |
56 | # Microbundle cache
57 | .rpt2_cache/
58 | .rts2_cache_cjs/
59 | .rts2_cache_es/
60 | .rts2_cache_umd/
61 |
62 | # Optional REPL history
63 | .node_repl_history
64 |
65 | # Output of 'npm pack'
66 | *.tgz
67 |
68 | # Yarn Integrity file
69 | .yarn-integrity
70 |
71 | # dotenv environment variables file
72 | .env
73 | .env.test
74 |
75 | # parcel-bundler cache (https://parceljs.org/)
76 | .cache
77 |
78 | # Next.js build output
79 | .next
80 |
81 | # Nuxt.js build / generate output
82 | .nuxt
83 | dist
84 |
85 | # Gatsby files
86 | .cache/
87 | # Comment in the public line in if your project uses Gatsby and *not* Next.js
88 | # https://nextjs.org/blog/next-9-1#public-directory-support
89 | # public
90 |
91 | # vuepress build output
92 | .vuepress/dist
93 |
94 | # Serverless directories
95 | .serverless/
96 |
97 | # FuseBox cache
98 | .fusebox/
99 |
100 | # DynamoDB Local files
101 | .dynamodb/
102 |
103 | # TernJS port file
104 | .tern-port
105 |
106 | # Secrets.js (API KEY)
107 | src/secrets.js
108 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "workbench.colorCustomizations": {
3 | "activityBar.activeBackground": "#b1c827",
4 | "activityBar.activeBorder": "#1f8ea0",
5 | "activityBar.background": "#b1c827",
6 | "activityBar.foreground": "#15202b",
7 | "activityBar.inactiveForeground": "#15202b99",
8 | "activityBarBadge.background": "#1f8ea0",
9 | "activityBarBadge.foreground": "#e7e7e7",
10 | "sash.hoverBorder": "#b1c827",
11 | "statusBar.background": "#8b9d1f",
12 | "statusBar.foreground": "#15202b",
13 | "statusBarItem.hoverBackground": "#657217",
14 | "statusBarItem.remoteBackground": "#8b9d1f",
15 | "statusBarItem.remoteForeground": "#15202b",
16 | "tab.activeBorder": "#b1c827",
17 | "titleBar.activeBackground": "#8b9d1f",
18 | "titleBar.activeForeground": "#15202b",
19 | "titleBar.inactiveBackground": "#8b9d1f99",
20 | "titleBar.inactiveForeground": "#15202b99"
21 | },
22 | "peacock.color": "#8b9d1f"
23 | }
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 Comunidad Platzi
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # curso-api-rest-javascript-practico
2 | Curso Práctico de Consumo de API REST con JavaScript
3 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | PlatziMovies
14 |
15 |
16 |
26 |
27 |
28 |
32 |
33 |
34 |
41 |
42 |
43 |
44 |
45 | Categorías
46 |
47 |
48 |
51 |
52 |
53 |
54 |
55 |
56 |

61 |
62 |
63 |
64 |

69 |
70 |
71 |
72 |

77 |
78 |
79 |
80 |
81 | Deadpool
82 | 7.6
83 |
84 | Wisecracking mercenary Deadpool battles the evil and powerful Cable and other bad guys to save a boy's life.
85 |
86 |
87 |
88 |
89 |
Romance
90 |
91 |
92 |
93 |
Drama
94 |
95 |
96 |
97 |
Acción
98 |
99 |
100 |
101 |
102 |
103 |
104 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "curso-api-rest-javascript-practico",
3 | "version": "1.0.0",
4 | "description": "Curso Práctico de Consumo de API REST con JavaScript",
5 | "main": "index.html",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "repository": {
10 | "type": "git",
11 | "url": "git+https://github.com/platzi/curso-api-rest-javascript-practico.git"
12 | },
13 | "author": "@juandc :)",
14 | "license": "MIT",
15 | "bugs": {
16 | "url": "https://github.com/platzi/curso-api-rest-javascript-practico/issues"
17 | },
18 | "homepage": "https://github.com/platzi/curso-api-rest-javascript-practico#readme"
19 | }
20 |
--------------------------------------------------------------------------------
/src/main.js:
--------------------------------------------------------------------------------
1 | const api = axios.create({
2 | baseURL: 'https://api.themoviedb.org/3/',
3 | headers: {
4 | 'Content-Type': 'application/json;charset=utf-8',
5 | },
6 | params: {
7 | 'api_key': API_KEY,
8 | },
9 | });
10 |
11 |
12 | // Utils
13 |
14 | function createMovies(movies, container) {
15 | container.innerHTML = '';
16 |
17 | movies.forEach(movie => {
18 | const movieContainer = document.createElement('div');
19 | movieContainer.classList.add('movie-container');
20 | movieContainer.addEventListener('click', () => {
21 | location.hash = '#movie=' + movie.id;
22 | });
23 |
24 | const movieImg = document.createElement('img');
25 | movieImg.classList.add('movie-img');
26 | movieImg.setAttribute('alt', movie.title);
27 | movieImg.setAttribute(
28 | 'src',
29 | 'https://image.tmdb.org/t/p/w300' + movie.poster_path,
30 | );
31 |
32 | movieContainer.appendChild(movieImg);
33 | container.appendChild(movieContainer);
34 | });
35 | }
36 |
37 | function createCategories(categories, container) {
38 | container.innerHTML = "";
39 |
40 | categories.forEach(category => {
41 | const categoryContainer = document.createElement('div');
42 | categoryContainer.classList.add('category-container');
43 |
44 | const categoryTitle = document.createElement('h3');
45 | categoryTitle.classList.add('category-title');
46 | categoryTitle.setAttribute('id', 'id' + category.id);
47 | categoryTitle.addEventListener('click', () => {
48 | location.hash = `#category=${category.id}-${category.name}`;
49 | });
50 | const categoryTitleText = document.createTextNode(category.name);
51 |
52 | categoryTitle.appendChild(categoryTitleText);
53 | categoryContainer.appendChild(categoryTitle);
54 | container.appendChild(categoryContainer);
55 | });
56 | }
57 |
58 | // Llamados a la API
59 |
60 | async function getTrendingMoviesPreview() {
61 | const { data } = await api('trending/movie/day');
62 | const movies = data.results;
63 | console.log(movies)
64 |
65 | createMovies(movies, trendingMoviesPreviewList);
66 | }
67 |
68 | async function getCategegoriesPreview() {
69 | const { data } = await api('genre/movie/list');
70 | const categories = data.genres;
71 |
72 | createCategories(categories, categoriesPreviewList) ;
73 | }
74 |
75 | async function getMoviesByCategory(id) {
76 | const { data } = await api('discover/movie', {
77 | params: {
78 | with_genres: id,
79 | },
80 | });
81 | const movies = data.results;
82 |
83 | createMovies(movies, genericSection);
84 | }
85 |
86 | async function getMoviesBySearch(query) {
87 | const { data } = await api('search/movie', {
88 | params: {
89 | query,
90 | },
91 | });
92 | const movies = data.results;
93 |
94 | createMovies(movies, genericSection);
95 | }
96 |
97 | async function getTrendingMovies() {
98 | const { data } = await api('trending/movie/day');
99 | const movies = data.results;
100 |
101 | createMovies(movies, genericSection);
102 | }
103 |
104 | async function getMovieById(id) {
105 | const { data: movie } = await api('movie/' + id);
106 |
107 | const movieImgUrl = 'https://image.tmdb.org/t/p/w500' + movie.poster_path;
108 | console.log(movieImgUrl)
109 | headerSection.style.background = `
110 | linear-gradient(
111 | 180deg,
112 | rgba(0, 0, 0, 0.35) 19.27%,
113 | rgba(0, 0, 0, 0) 29.17%
114 | ),
115 | url(${movieImgUrl})
116 | `;
117 |
118 | movieDetailTitle.textContent = movie.title;
119 | movieDetailDescription.textContent = movie.overview;
120 | movieDetailScore.textContent = movie.vote_average;
121 |
122 | createCategories(movie.genres, movieDetailCategoriesList);
123 |
124 | getRelatedMoviesId(id);
125 | }
126 |
127 | async function getRelatedMoviesId(id) {
128 | const { data } = await api(`movie/${id}/recommendations`);
129 | const relatedMovies = data.results;
130 |
131 | createMovies(relatedMovies, relatedMoviesContainer);
132 | }
133 |
--------------------------------------------------------------------------------
/src/navigation.js:
--------------------------------------------------------------------------------
1 | searchFormBtn.addEventListener('click', () => {
2 | location.hash = '#search=' + searchFormInput.value;
3 | });
4 |
5 | trendingBtn.addEventListener('click', () => {
6 | location.hash = '#trends';
7 | });
8 |
9 | arrowBtn.addEventListener('click', () => {
10 | history.back();
11 | // location.hash = '#home';
12 | });
13 |
14 | window.addEventListener('DOMContentLoaded', navigator, false);
15 | window.addEventListener('hashchange', navigator, false);
16 |
17 | function navigator() {
18 | console.log({ location });
19 |
20 | if (location.hash.startsWith('#trends')) {
21 | trendsPage();
22 | } else if (location.hash.startsWith('#search=')) {
23 | searchPage();
24 | } else if (location.hash.startsWith('#movie=')) {
25 | movieDetailsPage();
26 | } else if (location.hash.startsWith('#category=')) {
27 | categoriesPage();
28 | } else {
29 | homePage();
30 | }
31 |
32 | document.body.scrollTop = 0;
33 | document.documentElement.scrollTop = 0;
34 | }
35 |
36 | function homePage() {
37 | console.log('Home!!');
38 |
39 | headerSection.classList.remove('header-container--long');
40 | headerSection.style.background = '';
41 | arrowBtn.classList.add('inactive');
42 | arrowBtn.classList.remove('header-arrow--white');
43 | headerTitle.classList.remove('inactive');
44 | headerCategoryTitle.classList.add('inactive');
45 | searchForm.classList.remove('inactive');
46 |
47 | trendingPreviewSection.classList.remove('inactive');
48 | categoriesPreviewSection.classList.remove('inactive');
49 | genericSection.classList.add('inactive');
50 | movieDetailSection.classList.add('inactive');
51 |
52 | getTrendingMoviesPreview();
53 | getCategegoriesPreview();
54 | }
55 |
56 | function categoriesPage() {
57 | console.log('categories!!');
58 |
59 | headerSection.classList.remove('header-container--long');
60 | headerSection.style.background = '';
61 | arrowBtn.classList.remove('inactive');
62 | arrowBtn.classList.remove('header-arrow--white');
63 | headerTitle.classList.add('inactive');
64 | headerCategoryTitle.classList.remove('inactive');
65 | searchForm.classList.add('inactive');
66 |
67 | trendingPreviewSection.classList.add('inactive');
68 | categoriesPreviewSection.classList.add('inactive');
69 | genericSection.classList.remove('inactive');
70 | movieDetailSection.classList.add('inactive');
71 |
72 | // ['#category', 'id-name']
73 | const [_, categoryData] = location.hash.split('=');
74 | const [categoryId, categoryName] = categoryData.split('-');
75 |
76 | headerCategoryTitle.innerHTML = categoryName;
77 |
78 | getMoviesByCategory(categoryId);
79 | }
80 |
81 | function movieDetailsPage() {
82 | console.log('Movie!!');
83 |
84 | headerSection.classList.add('header-container--long');
85 | // headerSection.style.background = '';
86 | arrowBtn.classList.remove('inactive');
87 | arrowBtn.classList.add('header-arrow--white');
88 | headerTitle.classList.add('inactive');
89 | headerCategoryTitle.classList.add('inactive');
90 | searchForm.classList.add('inactive');
91 |
92 | trendingPreviewSection.classList.add('inactive');
93 | categoriesPreviewSection.classList.add('inactive');
94 | genericSection.classList.add('inactive');
95 | movieDetailSection.classList.remove('inactive');
96 |
97 | // ['#movie', '234567']
98 | const [_, movieId] = location.hash.split('=');
99 | getMovieById(movieId);
100 | }
101 |
102 | function searchPage() {
103 | console.log('Search!!');
104 |
105 | headerSection.classList.remove('header-container--long');
106 | headerSection.style.background = '';
107 | arrowBtn.classList.remove('inactive');
108 | arrowBtn.classList.remove('header-arrow--white');
109 | headerTitle.classList.add('inactive');
110 | headerCategoryTitle.classList.add('inactive');
111 | searchForm.classList.remove('inactive');
112 |
113 | trendingPreviewSection.classList.add('inactive');
114 | categoriesPreviewSection.classList.add('inactive');
115 | genericSection.classList.remove('inactive');
116 | movieDetailSection.classList.add('inactive');
117 |
118 | // ['#search', 'platzi']
119 | const [_, query] = location.hash.split('=');
120 | getMoviesBySearch(query);
121 | }
122 |
123 | function trendsPage() {
124 | console.log('TRENDS!!');
125 |
126 | headerSection.classList.remove('header-container--long');
127 | headerSection.style.background = '';
128 | arrowBtn.classList.remove('inactive');
129 | arrowBtn.classList.remove('header-arrow--white');
130 | headerTitle.classList.add('inactive');
131 | headerCategoryTitle.classList.remove('inactive');
132 | searchForm.classList.add('inactive');
133 |
134 | trendingPreviewSection.classList.add('inactive');
135 | categoriesPreviewSection.classList.add('inactive');
136 | genericSection.classList.remove('inactive');
137 | movieDetailSection.classList.add('inactive');
138 |
139 | headerCategoryTitle.innerHTML = 'Tendencias';
140 |
141 | getTrendingMovies();
142 | }
143 |
144 |
145 |
--------------------------------------------------------------------------------
/src/nodes.js:
--------------------------------------------------------------------------------
1 | // Sections
2 | const headerSection = document.querySelector('#header');
3 | const trendingPreviewSection = document.querySelector('#trendingPreview');
4 | const categoriesPreviewSection = document.querySelector('#categoriesPreview');
5 | const genericSection = document.querySelector('#genericList');
6 | const movieDetailSection = document.querySelector('#movieDetail');
7 |
8 | // Lists & Containers
9 | const searchForm = document.querySelector('#searchForm');
10 | const trendingMoviesPreviewList = document.querySelector('.trendingPreview-movieList');
11 | const categoriesPreviewList = document.querySelector('.categoriesPreview-list');
12 | const movieDetailCategoriesList = document.querySelector('#movieDetail .categories-list');
13 | const relatedMoviesContainer = document.querySelector('.relatedMovies-scrollContainer');
14 |
15 | // Elements
16 | const headerTitle = document.querySelector('.header-title');
17 | const arrowBtn = document.querySelector('.header-arrow');
18 | const headerCategoryTitle = document.querySelector('.header-title--categoryView');
19 |
20 | const searchFormInput = document.querySelector('#searchForm input');
21 | const searchFormBtn = document.querySelector('#searchBtn');
22 |
23 | const trendingBtn = document.querySelector('.trendingPreview-btn');
24 |
25 | const movieDetailTitle = document.querySelector('.movieDetail-title');
26 | const movieDetailDescription = document.querySelector('.movieDetail-description');
27 | const movieDetailScore = document.querySelector('.movieDetail-score');
28 |
--------------------------------------------------------------------------------
/src/secrets.example.js:
--------------------------------------------------------------------------------
1 | // Crea por favor un archivo secrets.js con tu API KEY
2 | const API_KEY = '';
3 |
--------------------------------------------------------------------------------
/styles/app.css:
--------------------------------------------------------------------------------
1 | /* General */
2 | * { box-sizing: border-box; }
3 |
4 | :root {
5 | --purple-light-1: #FBFAFB;
6 | --purple-light-2: #EEEAF2;
7 | --purple-medium-1: #AA83C8;
8 | --purple-medium-2: #8B48BF;
9 | --purple-medium-3: #5C218A;
10 | --purple-dark-1: #3E0F64;
11 | --purple-dark-2: #2A0646;
12 |
13 | --yellow: #EECC75;
14 | --green: #CAD297;
15 | --aqua: #B7EAC5;
16 | --lightBlue: #A2EEE5;
17 | --darkBlue: #8EA2EA;
18 | --red: #F09D9D;
19 |
20 | --font-family-titles: 'Dosis', sans-serif;
21 | --font-family-text: 'Red Hat Display', sans-serif;
22 | --font-weight-title1: 800;
23 | --font-weight-title2: 700;
24 | --font-weight-text1: 400;
25 | --font-weight-text2: 500;
26 | }
27 |
28 | html {
29 | background-color: var(--purple-medium-3);
30 | }
31 |
32 | body {
33 | background-color: var(--purple-light-1);
34 | color: var(--purple-dark-2);
35 | font-family: var(--font-family-text);
36 | font-weight: var(--font-weight-text1);
37 | font-size: 16px;
38 | margin: 4px 0 0 0;
39 | padding: 0;
40 | }
41 |
42 | h1, h2, h3 {
43 | margin: 0;
44 | padding: 0;
45 | }
46 |
47 | h1, h2 {
48 | font-size: 24px;
49 | color: var(--purple-dark-2);
50 | font-family: var(--font-family-titles);
51 | font-weight: var(--font-weight-title1);
52 | margin: 0;
53 | padding: 0;
54 | }
55 |
56 | h2 {
57 | font-size: 18px;
58 | color: var(--purple-dark-1);
59 | font-weight: var(--font-weight-title2);
60 | }
61 |
62 | h3 {
63 | color: var(--purple-dark-2);
64 | font-weight: var(--font-weight-text2);
65 | font-size: 16px;
66 | }
67 |
68 | input {
69 | background-color: var(--purple-light-2);
70 | color: var(--purple-medium-2);
71 | border: none;
72 | font-size: 18px;
73 | padding-left: 16px;
74 | }
75 |
76 | input::placeholder {
77 | color: var(--purple-medium-1);
78 | font-family: var(--font-family-text);
79 | }
80 |
81 | button {
82 | background-color: var(--purple-dark-1);
83 | border: none;
84 | color: var(--purple-light-2);
85 | font-weight: var(--font-weight-text2);
86 | font-size: 14px;
87 | cursor: pointer;
88 | }
89 |
90 |
91 | /* Shared */
92 | .header-container, .trendingPreview-header, .categoriesPreview-container {
93 | padding: 0 24px;
94 | }
95 |
96 | .trendingPreview-container, .categoriesPreview-container, footer {
97 | margin-top: 48px;
98 | }
99 |
100 | .trendingPreview-header, .categoriesPreview-title {
101 | margin-bottom: 24px;
102 | }
103 |
104 | .movie-container {
105 | cursor: pointer;
106 | }
107 |
108 | .movie-img {
109 | border-radius: 8px;
110 | }
111 |
112 | .categoriesPreview-list, .categories-list {
113 | display: flex;
114 | align-items: center;
115 | justify-content: space-between;
116 | position: relative;
117 | flex-wrap: wrap;
118 | }
119 |
120 |
121 | /* Header */
122 | .header-container {
123 | padding-top: 40px;
124 | }
125 |
126 | .header-container--long {
127 | background-image: url('https://pics.filmaffinity.com/Deadpool-777527803-large.jpg');
128 | background: linear-gradient(180deg, rgba(0, 0, 0, 0.35) 19.27%, rgba(0, 0, 0, 0) 29.17%), url(https://pics.filmaffinity.com/Deadpool-777527803-large.jpg);
129 | background-size: cover !important;
130 | height: 480px;
131 | position: fixed;
132 | top: 0;
133 | width: 100%;
134 | }
135 |
136 | .header-container--categoryView {
137 | background: linear-gradient(180deg, rgba(238, 204, 117, 0.5) 0%, rgba(238, 204, 117, 0) 72.92%);
138 | }
139 |
140 | .header-title {
141 | margin-bottom: 16px;
142 | }
143 |
144 | .header-arrow {
145 | font-weight: var(--font-weight-text2);
146 | font-size: 36px;
147 | margin-bottom: 16px;
148 | cursor: pointer;
149 | display: inline-block;
150 | }
151 | .header-arrow--white {
152 | color: var(--purple-light-1);
153 | }
154 |
155 | .header-searchForm {
156 | display: flex;
157 | align-items: center;
158 | justify-content: center;
159 | width: 100%;
160 | flex-wrap: nowrap;
161 | }
162 |
163 | .header-searchForm input {
164 | height: 48px;
165 | width: 100%;
166 | border-top-left-radius: 8px;
167 | border-bottom-left-radius: 8px;
168 | }
169 | .header-searchForm button {
170 | width: 56px;
171 | height: 48px;
172 | border-top-right-radius: 8px;
173 | border-bottom-right-radius: 8px;
174 | }
175 |
176 |
177 | /* Trending */
178 | .trendingPreview-header {
179 | display: flex;
180 | align-items: center;
181 | justify-content: space-between;
182 | }
183 |
184 | .trendingPreview-btn {
185 | border-radius: 8px;
186 | height: 32px;
187 | width: 72px;
188 | }
189 |
190 | .trendingPreview-movieList {
191 | overflow-x: scroll;
192 | overflow-y: hidden;
193 | white-space: nowrap;
194 | height: 241px;
195 | padding-left: 24px;
196 | padding-bottom: 16px;
197 | }
198 |
199 | .trendingPreview-movieList .movie-container {
200 | display: inline-block;
201 | margin-right: 8px;
202 | }
203 |
204 | .trendingPreview-movieList .movie-container .movie-img {
205 | height: 225px;
206 | min-height: 225px;
207 | max-height: 225px;
208 | width: 150px;
209 | min-width: 150px;
210 | max-width: 150px;
211 | }
212 |
213 |
214 | /* Categories */
215 | .category-container {
216 | width: 45%;
217 | }
218 |
219 | .category-title {
220 | margin-bottom: 8px;
221 | cursor: pointer;
222 | white-space: nowrap;
223 | overflow: hidden;
224 | text-overflow: ellipsis;
225 | }
226 |
227 | .category-title::before {
228 | content: '••••';
229 | color: transparent;
230 | /* TODO: cambiar color por ID de la categoría */
231 | background-color: var(--idColor);
232 | border-radius: 8px;
233 | margin-right: 8px;
234 | width: 8px;
235 | height: 8px;
236 | }
237 | #id28 { --idColor: var(--yellow); }
238 | #id12 { --idColor: var(--red); }
239 | #id16 { --idColor: var(--green); }
240 | #id35 { --idColor: var(--lightBlue); }
241 | #id80 { --idColor: var(--darkBlue); }
242 | #id99 { --idColor: var(--purple-dark-1); }
243 | #id18 { --idColor: var(--purple-medium-1); }
244 | #id10751 { --idColor: var(--yellow); }
245 | #id14 { --idColor: var(--red); }
246 | #id36 { --idColor: var(--green); }
247 | #id27 { --idColor: var(--lightBlue); }
248 | #id10402 { --idColor: var(--darkBlue); }
249 | #id9648 { --idColor: var(--purple-dark-1); }
250 | #id10749 { --idColor: var(--purple-medium-1); }
251 | #id878 { --idColor: var(--yellow); }
252 | #id10770 { --idColor: var(--red); }
253 | #id53 { --idColor: var(--green); }
254 | #id10752 { --idColor: var(--lightBlue); }
255 | #id37 { --idColor: var(--darkBlue); }
256 |
257 |
258 | /* Generic List (search, trending & category) */
259 | .genericList-container {
260 | display: flex;
261 | align-items: center;
262 | justify-content: space-between;
263 | flex-wrap: wrap;
264 | padding: 32px 24px;
265 | }
266 |
267 | .genericList-container .movie-container {
268 | display: inline-block;
269 | width: 47.5%;
270 | }
271 |
272 | .genericList-container .movie-img {
273 | width: 100%;
274 | }
275 |
276 |
277 | /* Movie Detail */
278 | .movieDetail-container {
279 | border-top-left-radius: 16px;
280 | border-top-right-radius: 16px;
281 | padding: 32px 24px;
282 | margin-top: 403px;
283 | z-index: 1;
284 | position: absolute;
285 | background-color: var(--purple-light-1);
286 | }
287 |
288 | .movieDetail-title {
289 | display: inline-block;
290 | width: 80%;
291 | margin: 0 0 16px 0;
292 | padding: 0;
293 | }
294 |
295 | .movieDetail-score {
296 | display: inline-block;
297 | text-align: right;
298 | width: 18%;
299 | font-weight: var(--font-weight-title2);
300 | }
301 | .movieDetail-score::before {
302 | content: '★';
303 | color: var(--yellow);
304 | padding-right: 4px;
305 | }
306 |
307 | .movieDetail-description {
308 | margin: 0 0 24px 0;
309 | }
310 |
311 | .relatedMovies-container {
312 | margin-top: 24px;
313 | height: 216px;
314 | }
315 |
316 | .relatedMovies-title {
317 | margin-bottom: 16px;
318 | }
319 |
320 | .relatedMovies-scrollContainer {
321 | position: absolute;
322 | overflow-x: scroll;
323 | overflow-y: hidden;
324 | white-space: nowrap;
325 | width: calc(100vw - 24px);
326 | padding-bottom: 16px;
327 | }
328 |
329 | .relatedMovies-scrollContainer .movie-container {
330 | display: inline-block;
331 | margin-right: 8px;
332 | }
333 |
334 | .relatedMovies-scrollContainer .movie-img {
335 | width: 125px;
336 | min-width: 125px;
337 | max-width: 125px;
338 | height: 187.5px;
339 | min-height: 187.5px;
340 | max-height: 187.5px;
341 | }
342 |
343 |
344 | /* Footer */
345 | footer {
346 | background-color: var(--purple-medium-3);
347 | color: var(--purple-light-2);
348 | text-align: center;
349 | height: 48px;
350 | display: flex;
351 | justify-content: center;
352 | align-items: center;
353 | }
354 |
355 |
356 | /* Navigation */
357 | .inactive {
358 | display: none;
359 | }
360 |
--------------------------------------------------------------------------------