Building TVFlixx
Tags: typescript, vue, javascript, webdev
Published: 2022-08-13 10:49:21

Hiya!

A little over two years ago, I [started my journey](https://dev.to/benneee_/learning-vue-js-5bjg) into the world of Vue.js after a long and probably-never-ending stint with Angular. Working with Vue.js has been rewarding and there are more things to uncover even as work continues on the amazing framework and its libraries, e.g Nuxt.js.

Working with Angular gave me working TypeScript knowledge, but I (have) never tried to build anything with TypeScript outside Angular. I had to do a quick [refresh on TypeScript](https://github.com/Benneee/ts-play) with a [scrimba course](https://scrimba.com/learn/typescript) and [toe-dipping](https://github.com/Benneee/vue-ts-play) into the Vue.js<>TypeScript world with this [amazing YouTube playlist](https://www.youtube.com/watch?v=JfI5PISLr9w).

I am a huge TV shows fan, and I [tweet](https://twitter.com/search?q=(series%2C%20OR%20TV%20shows)%20(from%3Abenneee_)&src=typed_query&f=top) a lot about my current favorites (follow me 🤩!), but I never thought about building an app to play around with TV shows data until now. 
I built [Moflixx](https://github.com/Benneee/moflixx) with Angular sometime in 2019 but It was based on a Movies API. I wanted to build an application that would help me work with Vue.js (Composition API) and TypeScript and now felt like a great time to play around with some TV shows data.


### The User Interface

Like [Moflixx](https://github.com/Benneee/moflixx), I needed an API to fetch TV shows data from. It took a few days, but I found [Episodate](https://episodate.com) surprisingly off a series of GitHub search. I explored the data, it wasn't super robust in terms of endpoints available but It had everything I needed for `TVFlixx`.

I needed some inspiration for the UI, but I did not also want to stray too far away from what my datasource website looked like, [Episodate](https//episodate.com)'s interface pretty much did it for me, so I borrowed a few UI tips.

Next, I needed a structure for `TVFlixx`. I wrote down a list of components and pages I felt I would need and sketched a few things as well for the components. A regular for me in this type of application is the `Favorites` page.

Pages                      |   Components
:-------------------------:|:-------------------------:
- `TVShows`                |  - `Episodes`
- `NotFound` / `404`       |  - `Pagination`
- `TVShowDetails`          |  - `Header`
- `Favorites`              |  - `TVShow`
                           |  - `TVShowList`
                           |  - `Loading` component
                           |  - `Carousel`
                           | - `CarouselItem` component

With the help of a few resources, I built some components I could have easily installed a few packages for.
For the next few paragraphs, I will explain the reasoning behind the choice of some components.

The `TVShows` page is a simple page that shows a paginated list of TV shows from the API, 20 items are shown on each page depending on the items available from the API.

The `TVShowDetails` page employs more of the other components.
For instance, I use the `Carousel` and `CarouselItem` components to show a list of images that comes with each TV show item - this helps any prospective user view the images one at a time or select any image from the preview.

![Carousel component](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yhh5k8p8if8ttabtvrdz.png)

I also use the `Episodes` component in the `TVShowDetails` page, the component takes an `episodes` prop which is an `array` of all the episodes contained in `objects` for a particular TV show. This component filters each item in the array by their season and creates a view that enable users view list of episodes per season by selecting a button showing the season they are interested in.
![Episodes component UI](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nxseum3vaj1f8pfj8n8g.png)

The `TVShow` component needed a few iterations before I could get what I wanted.

![Sketch](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9hd0501swmx25hm1hx4v.jpg)

I wanted an hover effect to cause the card to flip to the other side to show some details and allow a user "see more details" about the TV show, took a while but I achieved it.

Front of card            |  Flip side
:-------------------------:|:-------------------------:
![Front](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1v1ki3usdjyluncaa70q.png)  |  ![Flip side](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/940woyt6gbc3zm2zuwul.png)

The other components are pretty much self-explanatory.



### The TypeScript Part

I use the `Volar` extension in my VS Code, so I had to enable the `Template Interpolation Service` to do some validation and code completion in the template. I also wanted to explore the Composition API more and using the `defineComponent` method from `vue` was a good decision.

First, I knew I had to define the structure for the objects I would be using within the app. I created some interfaces to handle the data coming into each page and component and tried really hard to avoid the `any` type 😅.

The `Episodes` component required a special custom type different from the other interfaces I created, because it eventually provided an `object of arrays` and the type for the `key` for the items in the object weren't exactly known or constant before runtime as they were the values of the `season` field for the episodes. 
This [extract](https://www.typescriptlang.org/docs/handbook/2/objects.html#index-signatures) from the TypeScript docs came in handy:

```
import Episode from "./Episode"

interface SeasonEpisodes { 
    [index: string]: Episode[]
}

export default SeasonEpisodes;
```

I also needed to handle issues around passing props to the components and ensuring the right type was enforced for the objects using type assertion with `PropType` imported from `vue`.



### Conclusion

I use the composition API extensively at work, but using it with TypeScript encourages a bit more sanity within the codebase and data flow across components.
I will probably do some tweaks in the application (especially the UI) in the future but I really just wanted to focus on how I could work with the composition API and TypeScript.

I wanted to share my thoughts around working with TypeScript and Vue.js, this article mostly captures the parts I thought were worth talking about. 

[The Repository on GitHub](https://github.com/Benneee/tvflixx) - star the repo if you enjoyed this!

Thank you for reading.



### References
- [TypeScript docs excerpt](https://www.typescriptlang.org/docs/handbook/2/objects.html#index-signatures)
- [The UI inspiration](https://episodate.com)
- [API resource](https://episodate.com/api)
- [The Carousel component](https://www.youtube.com/watch?v=6-JEiEfkluc)
- [The Pagination component](https://www.digitalocean.com/community/tutorials/vuejs-vue-pagination-component)