Ejercicio
tv-shows # Carpeta del proyecto
├──
src # Código editable y ficheros relacionados
│ ├──
index.html # HTML principal
│ ├──
index.css # CSS global
│ └──
index.js # Javascript principal
├──
README.md # Instrucciones o presentación del proyecto
├──
.gitignore # Ficheros o carpetas a ignorar para git
└──
package.json # Fichero de información del proyecto
Obtener datos de una serie por su ID
const ID = "2993";
const PLACEHOLDER_IMAGE = "https://placehold.co/210x295";
const getShowData = async (id) => {
const URL = `https://api.tvmaze.com/shows/${id}`;
const data = await fetch(URL).then(res => res.json());
return {
name: data.name,
rating: data.rating,
image: data.image?.medium ?? PLACEHOLDER_IMAGE
}
}
Obtener episodios por temporada
const getEpisodeList = async (id) => {
const URL = `https://api.tvmaze.com/shows/${id}/episodes`;
const episodes = await fetch(URL).then(res => res.json());
const episodeList = episodes.map(episode => ({
number: episode.number,
season: episode.season,
rating: episode.rating.average
}));
const episodesBySeason = Object.groupBy(episodeList, (episode) => episode.season);
return episodesBySeason;
}
Página principal (HTML)
<div class="content">
<header></header>
<article class="episodes"></article>
</div>
<script type="module">
import { getShowData, getEpisodeList } from "./services/tvmaze.js";
const show = await getShowData(ID);
const seasons = await getEpisodeList(ID);
</script>
Prototipo del HTML de los componentes
<header>
<img class="poster" src="...">
<h1>...</h1>
</header>
<article class="episodes">
<article class="season"> </article>
<article class="season"> </article>
</article>
.episodes {
display: grid;
place-items: start;
place-content: center;
}
.season {
display: flex;
}
Estilos CSS
<article class="season">
<header class="season-header">T##</header>
<div class="episode episode-## rating-##">##</div>
<div class="episode episode-## rating-##">##</div>
</article>
.season-header,
.episode {
--size: 2rem;
width: var(--size);
height: var(--size);
background: var(--color);
display: grid;
place-items: center;
margin: 2px;
border-radius: 25px;
corner-shape: squircle;
color: #fff;
}
Colores para las valoraciones (rating)
.rating-0 { --color: #2b0a27 }
.rating-1 { --color: #451010 }
.rating-2 { --color: #922323 }
.rating-3 { --color: #c53030 }
.rating-4 { --color: #c53030 }
.rating-5 { --color: #c53030 }
.rating-6 { --color: #dd6b20 }
.rating-7 { --color: #f6e05e; color: #333 }
.rating-8 { --color: #48bb78 }
.rating-9 { --color: #2f855a }
.rating-10 { --color: #4CAF50 }
Renderizar DOM
const $header = document.querySelector("header");
const $episodes = document.querySelector(".episodes");
$header.setHTMLUnsafe();
const createEpisodeHTML = (episode) => ;
const createSeasonHTML = (data, number) => ;
const list = Object.values(seasons).map((season, index) => createSeasonHTML(season, index + 1));
$episodes.setHTMLUnsafe(list.join(""));
Resultado