Last post, I worked on making a call to the IGDB API and rendering a processed response in the UI.
For the past week and a half, I’ve been working on filtering functionality. A philosophy I’ve adopted from some developers I respect “get all the data from the server, then filter on the front end.” (This works for many cases, but where the data set is quite large, tools like graphql can really help)
At the moment, I’m accounting for two filter criteria: platform and genre. The gif below shows the results.

Backend
Thankfully I had done groundwork up front when I was working on handling the API response. In an earlier commit, I included handling platforms for a game. From there, adding in genre was fairly straightforward, with one caveat: not all games have genres defined. I only found this out when I was looking through a few example response objects. The genres field is slightly different from the platforms field, where all games have platforms defined.
Here is an example of raw response data (edited to make a point):
{
"id": 29914,
"name": "Animality",
"release_dates": [
{
"id": 72645,
"date": 1485993600,
"human": "Feb 02, 2017",
"platform": {
"id": 6,
"name": "PC (Microsoft Windows)"
}
},
{
"id": 471833,
"date": 1684972800,
"human": "May 25, 2023",
"platform": {
"id": 130,
"name": "Nintendo Switch"
}
}
],
"genres": [
"Role-playing (RPG)",
"Adventure"
],
}
I take that response object and map the game to a given date, adding in fields for a list of platforms and a list of genres. Here is what an example of the mapped data looks like:
[
{
"date": "Jun 01, 2023",
"games": [
{
"name": "Etrian Odyssey: Origins Collection",
"platforms": [
"Nintendo Switch",
"PC (Microsoft Windows)"
],
"genres": [
"Role-playing (RPG)",
"Adventure"
],
},
}
]
Side note: list comprehension in Python
Python has really powerful methods for working with lists. List comprehension, once you get the hang of the syntax, offers concise statements for what would otherwise be verbose declarations. To deal with nested objects and lists, some that contained ‘null’ data, I started off with nested for loops. Once I got used to the structure, I worked my backwards into list comprehension, eventually producing the following statement:
genres = [genre['name'] for genre in res['genres']] if res.get('genres') else []
Frontend
A user chooses a combination of platforms and/or genres they want to see releases for and when the filter button is clicked, the set of games matching the selected criteria are shown. This is my filtering function:
const applyFilters = game_data => {
// 1. check for filter criteria
let hasFilters = consoleFilters.length > 0 || genreFilters.length > 0;
// 2. set a variable we're going to manipulate and return
let filtered_games = game_data;
// 3. do filtering based on selected filter criteria
if (hasFilters) {
if (consoleFilters.length > 0 && genreFilters.length > 0) {
filtered_games = game_data.filter(
game => game.platforms.some(
console => consoleFilters.includes(console)
)
&& game.genres.some(genre => genreFilters.includes(genre))
);
} else if (consoleFilters.length > 0) {
filtered_games = game_data.filter(
game => game.platforms.some(
platform => consoleFilters.includes(platform)
));
} else {
filtered_games = game_data.filter(
game => game.genres.some(
genre => genreFilters.includes(genre)
));
}
}
// 4. return filtered list
return filtered_games;
}
This function is invoked in two cases, 1. when a user clicks the filter button and 2. when a user goes to the next or previous month. In both cases, I’m calling this on the full list of game data returned from the server call. This ensures that I’m able to return to the full list of games if I’ve already applied multiple filters.
In my next post, I’ll get into hover and click functionality for the games.
Thanks for reading.