Files
the-office/src/store.js

184 lines
7.3 KiB
JavaScript

import Vue from "vue";
import Vuex from "vuex";
import axios from "axios";
import {types} from "@/mutation_types";
Vue.use(Vuex);
// Generate 'base' representing episode data
const episodeCount = [6, 22, 23, 14, 26, 24, 24, 24, 23];
const baseData = Array.from({length: 9}, (x, season) => {
// Array of null values representing each episode
const episodeData = Array.from({length: episodeCount[season]}, (x, episode) => {
return {episode_id: episode + 1, loaded: false}
})
return {season_id: season + 1, episodes: episodeData};
})
export default new Vuex.Store({
state: {
seasonCount: 9,
episodeCount: episodeCount,
quoteData: baseData,
preloaded: false,
characters: {}
},
mutations: {
// Fully set episode data
[types.SET_EPISODE](state, payload) {
state.quoteData[payload.season - 1].episodes[payload.episode - 1] = payload.episodeData
},
// Merge many episodes data simultaneously
[types.MERGE_EPISODES](state, payload) {
for (const season of payload) {
for (const episode of season) {
if (episode === null) {
console.log(`Missing Episode`)
continue;
}
const s = episode.seasonNumber - 1;
const e = episode.episodeNumber - 1;
state.quoteData[s].episodes[e] = Object.assign(state.quoteData[s].episodes[e], episode);
// If scenes are included for some reason, mark as a fully loaded episode
if (episode.scenes !== undefined)
state.quoteData[s].episodes[e].loaded = true;
}
}
},
// 'Merge' episode data, overwriting existing attributes as needed
[types.MERGE_EPISODE](state, payload) {
const s = payload.season - 1;
const e = payload.episode - 1;
state.quoteData[s].episodes[e] = Object.assign(state.quoteData[s].episodes[e], payload.episodeData);
// If the episodeData has scenes, it means that this is a full episode data merge - mark it as 'loaded'
if (payload.episodeData.scenes !== undefined)
state.quoteData[s].episodes[e].loaded = true;
},
[types.SET_PRELOADED](state, status) {
state.preloaded = status;
},
[types.SET_CHARACTER](state, payload) {
state.characters[payload.id] = payload.characterData
},
[types.MERGE_CHARACTER](state, payload) {
const id = payload.id;
// If character has not been defined in character list yet, simply set the characterData
if (state.characters[id] === undefined)
state.characters[id] = payload.characterData
// Otherwise use intended merge & overwrite effect.
else
state.characters[id] = Object.assign(state.characters[id], payload.characterData)
},
},
actions: {
// Perform async API call to fetch specific Episode data
[types.FETCH_EPISODE](context, payload) {
return new Promise((resolve, reject) => {
// Don't re-fetch API data if it's already loaded
if (context.getters.isFetched(payload.season, payload.episode)) {
resolve()
return
}
const path = `/json/${payload.season.toString().padStart(2, "0")}/${payload.episode.toString().padStart(2, "0")}.json`;
axios.get(path)
.then((res) => {
// Push episode data
context.commit(types.MERGE_EPISODE, {
season: payload.season,
episode: payload.episode,
episodeData: res.data
})
resolve()
})
.catch((error) => {
// eslint-disable-next-line no-console
console.error(error);
reject()
});
})
},
[types.PRELOAD]({commit}) {
const path = `/json/episodes.json`;
axios.get(path)
.then((res) => {
commit(types.MERGE_EPISODES, res.data)
commit(types.SET_PRELOADED, true);
})
.catch((error) => {
// eslint-disable-next-line no-console
console.error(error);
})
},
[types.PRELOAD_CHARACTER]({commit}) {
return new Promise((resolve, reject) => {
const path = `/json/characters.json`;
axios.get(path)
.then((res) => {
for (const [character_id, character_data] of Object.entries(res.data))
commit(types.MERGE_CHARACTER, {id: character_id, characterData: character_data})
resolve();
})
.catch((error) => {
console.error(error);
reject()
})
})
},
[types.FETCH_CHARACTER]({commit}, character_id) {
return new Promise((resolve, reject) => {
const path = `/json/character/${character_id}.json`;
axios.get(path)
.then((res) => {
commit(types.MERGE_CHARACTER, {id: character_id, characterData: res.data})
resolve();
})
.catch((error) => {
reject();
console.error(error);
})
})
}
},
getters: {
// Check whether a episode has been fetched yet
isFetched: (state) => (season, episode) => {
const ep = state.quoteData[season - 1].episodes[episode - 1];
return ep.loaded;
},
// Get the number of episodes present for a given season
getEpisodeCount: (state) => (season) => {
return state.episodeCount[season - 1];
},
// return Episode data if present
getEpisode: (state, getters) => (season, episode) => {
if (getters.isFetched(season, episode)) {
return state.quoteData[season - 1].episodes[episode - 1];
} else
return null
},
// return true if a specific episode is valid
isValidEpisode: (state, getters) => (season, episode = 1) => {
return season >= 1 && season <= 9 && episode >= 1 && episode <= getters.getEpisodeCount(season)
},
getCharacter: (state) => (character_id) => {
return state.characters[character_id];
},
getSortedCharacters: (state) => () => {
let keys = Object.keys(state.characters);
console.log(keys)
keys.sort((a, b) => {
const a_count = state.characters[a].appearances;
const b_count = state.characters[b].appearances
if (a_count < b_count) return 1;
else return -1;
})
return keys;
}
}
});