Doctor Who Database
Published: 2021-12-22 02:10:53

My phase 1 project is a visual database of Doctor Who episodes. To view my website [click here](https://joe1350.github.io/phase-1-project/). Information about episodes can be retrieved by season, Doctor, director, or writer This could be considered a companion app to the Doctor Who Series. While working on this project I had to come up with some creative solutions to a couple challenges I was facing.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/titzceh68m5rkp9ulk8e.png)
The first challenge was to prevent having to scroll to see information. For example, when you first click on a category; season, Doctor, director, or writer(in the example above we are looking at seasons); it fetches the endpoint for that category, and renders all items for that category(all of the seasons for this example) to the page. Since there's over 39 seasons the list can be long. When you click on a season you see all the episodes for that season. Now, lets say you want to see the episodes for the very last season. You click on that season, and nothing happens... That's because you have to scroll all the way back up to the top to see that information. So, I wanted to make the information display on screen no matter where I was on the page. I fixed this in CSS by setting `position: fixed;` on the container that holds the list of episodes. Now, this made the information stay fixed in place on the screen, but it was overlapping with the list of seasons. To fix this I moved the container. The final CSS looked like:

```
#episodes-container {
    position: fixed;
    top: 260px;
    left: 25%;
}
```
The `top: 260px;` made the container display 10 pixels beneath my 250 pixel header, and the `left: 25%;` made the container display 25% of the way across from the left side of the window.

The second challenge was more difficult to solve. The structure of the API  did not easily allow episode details to be displayed. Each category has it's own endpoint within the API that I used, [catalogopolis](https://api.catalogopolis.xyz/docs/restapi/index.html). While the endpoint had a way to see what episodes pertained to each item in the category, it did not show the episode details. To see the episode details you had to find it within the episodes endpoint. The two endpoints did not share any data except the episode name. So, I had to come up with a way to take the episode name, fetch the episodes endpoint, and find where the episode names matched. I'm going to break the code down for you. First I saved my endpoint to a variable: `const allEpisodesURL = 'https://api.catalogopolis.xyz/v1/episodes'` from there I ran a fetch on the endpoint: 

```
function fetchAllEpisodes(episodeName) {
    fetch(allEpisodesURL)
    .then(r => r.json())
    .then(episodes => findEpisode(episodes, episodeName))
}
```
in `fetchAllEpisodes` I passed in the `episodeName` so it would be available to pass on to `findEpisode`. In `findEpisode`,

```
function findEpisode(episodes, episodeName) {
    for (let episode of episodes) {
        if(episode.title === episodeName) {
            renderEpisodeDetails(episode)
            break;
        } else {
            renderNoEpisodeDetails(episodeName)
        }
    }
}
```
I am iterating through the array of episodes. I am looking at each episode and checking if the `episodeName` strictly equals the `episode.title`. If we find the matching episode we pass it to `renderEpisodeDetails`. If we don't find the matching episode we pass it to `renderNoEpisodeDetails`. In render episode details, 

```
function renderEpisodeDetails(episode) {
    episodeDetailsContainer.innerText = ''
    let title = create('p')
    let airDate = create('p')
    let runtime = create('p')
    let viewers = create('p')
    let rating = create('p')
    title.innerText = episode.title
    airDate.innerText = `Aired: ${episode.originalAirDate.slice(5)}-${episode.originalAirDate.slice(0, 4)}`
    runtime.innerText = `Runtime: ${episode.runtime}`
    viewers.innerText = `Viewers: ${episode.ukViewersMM} million `
    rating.innerText = `Rating: ${episode.appreciationIndex} / 100`
    episodeDetailsContainer.append(title, airDate, runtime, viewers, rating)
}
```
I create a `p` tag for each detail, fill in the `innerText` of each detail with data returned from the API, and append it all to the container that holds the episode details. A quick side note, `create` is a helper function I added to the top of my file, 

```
const create = el => document.createElement(el)
```
And now, if we back up a little, if no episode details were found in `findEpisode` we pass the `episodeName` to `renderNoEpisodeDetails`,

```
function renderNoEpisodeDetails(episodeName) {
    episodeDetailsContainer.innerText = `${episodeName} is not in the database`
}
```
in `renderNoEpisodeDetails` I am setting the `innerText` of the `episodeDetailsContainer` to say, `episodeName` is not in the database.

Finding solutions to these two challenges made the project easier to navigate and provided additional information.