Add an option to view Splatfest history for all regions

This also changes the region selector so it's based on routes.
This commit is contained in:
Matt Isenhower
2018-08-30 15:46:01 -07:00
parent fa037453fc
commit 5ece45a457
4 changed files with 105 additions and 51 deletions

View File

@@ -0,0 +1,39 @@
<template>
<div class="dropdown" :class="{ 'is-active': isActive }">
<div class="dropdown-trigger">
<a :class="triggerClass" @click="isActive = !isActive" v-click-outside="hide">
<slot name="trigger">
<span>{{ label }}</span>
<span class="icon is-small">
<span class="chevron bottom"></span>
</span>
</slot>
</a>
</div>
<div class="dropdown-menu" role="menu">
<div class="dropdown-content">
<slot />
</div>
</div>
</div>
</template>
<script>
export default {
props: {
label: null,
triggerClass: null,
contentClass: null,
},
data() {
return {
isActive: false,
};
},
methods: {
hide() {
this.isActive = false;
},
},
}
</script>

View File

@@ -1,5 +1,5 @@
<template>
<Modal @close="$emit('close')" class="is-wide splatfest-history-dialog modal-rounded-box" v-if="allSplatfests">
<Modal @close="$emit('close')" class="is-wide splatfest-history-dialog modal-rounded-box" v-if="festivals">
<div class="modal-card">
<div class="modal-card-head">
<div class="level">
@@ -8,11 +8,16 @@
</div>
<div class="level-right">
<Dropdown
:options="regions"
v-model="region"
style="margin: 0 -12px" class="font-splatoon2 is-right-tablet"
/>
<DropdownBase
:label="selectedRegion.name"
style="margin: 0 -12px"
class="font-splatoon2 is-right-tablet"
trigger-class="button is-clear font-splatoon2"
>
<router-link v-for="region in regions" class="dropdown-item" :key="region.key" :to="region.route">
{{ region.name }}
</router-link>
</DropdownBase>
</div>
</div>
</div>
@@ -54,40 +59,35 @@ import Vue from 'vue';
import { mapGetters } from 'vuex';
import analytics from '@/web/support/analytics';
import Modal from '@/web/components/Modal.vue';
import Dropdown from '@/web/components/Dropdown.vue';
import DropdownBase from '@/web/components/DropdownBase.vue';
import SplatfestBox from './SplatfestBox.vue';
import SplatfestResultsBox from './SplatfestResultsBox.vue';
export default {
components: { Modal, Dropdown, SplatfestBox, SplatfestResultsBox },
components: { Modal, DropdownBase, SplatfestBox, SplatfestResultsBox },
filters: {
resultsIn(time) {
return Vue.i18n.translate('splatfest.results_in', { time });
},
},
data() {
return {
region: 'na',
};
},
props: ['region'],
computed: {
...mapGetters('splatoon', ['now']),
...mapGetters('splatoon/regions', { initialRegion: 'selectedKey' }),
allSplatfests() {
return {
na: this.$store.getters['splatoon/splatfests/na/allSplatfests'],
eu: this.$store.getters['splatoon/splatfests/eu/allSplatfests'],
jp: this.$store.getters['splatoon/splatfests/jp/allSplatfests'],
};
},
regions() {
return this.$store.state.splatoon.regions.all.map(({ key }) => {
let name = (key) ? this.$t(`regions.${key}.name`) : this.$t('regions.global.name');
return { key, name };
let route = (key) ? `/splatfests/${key}` : '/splatfests';
return { key, name, route };
});
},
selectedRegion() {
let key = this.region || null;
return this.regions.find(r => r.key === key);
},
festivals() {
return this.allSplatfests[this.region];
if (this.region)
return this.$store.getters[`splatoon/splatfests/${this.region}/allSplatfests`];
return this.$store.getters['splatoon/splatfests/allSplatfests'];
},
},
watch: {
@@ -95,10 +95,6 @@ export default {
this.scrollToTop();
},
},
created() {
if (this.initialRegion)
this.region = this.initialRegion;
},
mounted() {
analytics.event('Splatfest History', 'Open');
},

View File

@@ -37,8 +37,9 @@ const routes = [
// Splatfests
{
path: 'splatfests',
path: 'splatfests/:region(na|eu|jp)?',
component: require('./components/splatoon/SplatfestHistoryDialog.vue').default,
props: true,
},
// Other/misc

View File

@@ -1,6 +1,44 @@
export const namespaced = true;
export const getters = {
allSplatfests(state, getters, { splatoon }) {
let now = splatoon.now;
let data = splatoon.data.festivals;
if (now && data) {
let splatfests = { };
for (let region of ['na', 'eu', 'jp']) {
let { festivals, results } = data[region];
for (let festival of festivals) {
if (splatfests[festival.festival_id]) {
splatfests[festival.festival_id].regions.push(region);
continue;
}
let state;
if (festival.times.start > now)
state = 'upcoming';
else if (festival.times.end > now)
state = 'active';
else
state = 'past';
splatfests[festival.festival_id] = {
...festival,
regions: [region],
state,
results: results.find(r => r.festival_id === festival.festival_id),
};
}
}
return Object.values(splatfests)
.sort((a, b) => b.times.start - a.times.start);
}
},
anyRegionHasCurrentSplatfest(state, getters, rootState, rootGetters) {
return rootGetters['splatoon/splatfests/na/currentSplatfest']
|| rootGetters['splatoon/splatfests/eu/currentSplatfest']
@@ -21,29 +59,9 @@ function generateModule(region) {
return {
namespaced: true,
getters: {
allSplatfests(state, getters, { splatoon }) {
let now = splatoon.now;
let data = splatoon.data.festivals && splatoon.data.festivals[region];
if (now && data) {
let { festivals, results } = data;
return festivals.map(festival => {
let state;
if (festival.times.start > now)
state = 'upcoming';
else if (festival.times.end > now)
state = 'active';
else
state = 'past';
return {
...festival,
state,
results: results.find(r => r.festival_id === festival.festival_id),
};
});
}
allSplatfests(state, getters, rootState, rootGetters) {
return rootGetters['splatoon/splatfests/allSplatfests']
&& rootGetters['splatoon/splatfests/allSplatfests'].filter(s => s.regions.includes(region));
},
currentSplatfest(state, getters, { splatoon }) {
let now = splatoon.now;