mirror of
https://github.com/misenhower/splatoon2.ink.git
synced 2026-08-22 02:14:21 -05:00
Layout overhaul, add popups to view all upcoming stages
This commit is contained in:
@@ -5,6 +5,46 @@
|
||||
padding-top: 35px;
|
||||
}
|
||||
|
||||
.modal-card-product-box {
|
||||
.modal-card-head {
|
||||
@extend .bg-mask-product;
|
||||
-webkit-mask-size: 730px 1168px;
|
||||
mask-size: 730px 1168px;
|
||||
background-position-y: bottom;
|
||||
|
||||
border: none;
|
||||
|
||||
border-top-left-radius: 32px;
|
||||
border-top-right-radius: 32px;
|
||||
|
||||
padding-top: 45px;
|
||||
|
||||
display: block; // Fixes issues with .level
|
||||
}
|
||||
.modal-card-body {
|
||||
@extend .bg-stripes;
|
||||
|
||||
border-bottom-left-radius: 32px;
|
||||
border-bottom-right-radius: 32px;
|
||||
|
||||
padding-bottom: 32px;
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
}
|
||||
&::-webkit-scrollbar-track {
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
&::-webkit-scrollbar-thumb {
|
||||
border-radius: 10px;
|
||||
background: rgba($white, 0.6);
|
||||
&:hover {
|
||||
background: rgba($white-ter, 0.8);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.hook-box {
|
||||
border-radius: 32px;
|
||||
padding: 10px;
|
||||
|
||||
@@ -32,6 +32,26 @@
|
||||
}
|
||||
}
|
||||
|
||||
.button.is-clear {
|
||||
@extend .text-shadow;
|
||||
|
||||
background: rgba($white-ter, 0.4);
|
||||
border: rgba($white-ter, 0.9);
|
||||
color: $white-ter;
|
||||
|
||||
&:hover {
|
||||
background: rgba($white, 0.5);
|
||||
border: rgba($white, 1.0);
|
||||
color: $white;
|
||||
}
|
||||
}
|
||||
|
||||
.button.is-rounded {
|
||||
border-radius: 100px;
|
||||
padding-left: 12px;
|
||||
padding-right: 12px;
|
||||
}
|
||||
|
||||
.hand {
|
||||
cursor: pointer;
|
||||
}
|
||||
@@ -57,11 +77,21 @@
|
||||
transform: rotate(1.4deg);
|
||||
}
|
||||
|
||||
.tilt-right-slight {
|
||||
-webkit-transform: rotate(1.2deg);
|
||||
transform: rotate(1.2deg);
|
||||
}
|
||||
|
||||
.tilt-left {
|
||||
-webkit-transform: rotate(-1.4deg);
|
||||
transform: rotate(-1.4deg);
|
||||
}
|
||||
|
||||
.tilt-left-slight {
|
||||
-webkit-transform: rotate(-1.2deg);
|
||||
transform: rotate(-1.2deg);
|
||||
}
|
||||
|
||||
.columns.is-slim {
|
||||
margin-left: -0.4rem;
|
||||
margin-right: -0.4rem;
|
||||
|
||||
@@ -10,17 +10,34 @@ html {
|
||||
background-color: #191919;
|
||||
}
|
||||
|
||||
.squid-refresh {
|
||||
.fa {
|
||||
&:before {
|
||||
display: inline-block;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
}
|
||||
|
||||
.squid-refresh {
|
||||
&:before {
|
||||
@extend .font-splatoon2;
|
||||
content: "\e066";
|
||||
}
|
||||
}
|
||||
|
||||
.schedule-box {
|
||||
.squid-squid {
|
||||
&:before {
|
||||
@extend .font-splatoon2;
|
||||
content: "\e065";
|
||||
}
|
||||
}
|
||||
|
||||
.squid-icon-tilt {
|
||||
-webkit-transform: rotate(25deg);
|
||||
transform: rotate(25deg);
|
||||
}
|
||||
|
||||
.main-schedule-box {
|
||||
@extend .product-box;
|
||||
@extend .bg-stripes;
|
||||
@extend .text-shadow;
|
||||
@@ -42,6 +59,47 @@ html {
|
||||
}
|
||||
}
|
||||
|
||||
.modal-card.schedule-box {
|
||||
@extend .modal-card-product-box;
|
||||
@extend .text-shadow;
|
||||
|
||||
.modal-card-head {
|
||||
@extend .bg-spots-dots;
|
||||
}
|
||||
.modal-card-body {
|
||||
@extend .bg-stripes;
|
||||
}
|
||||
|
||||
&.regular {
|
||||
.modal-card-head {
|
||||
background-color: darken($bg-battle-regular, 30%);
|
||||
}
|
||||
.modal-card-body {
|
||||
background-color: $bg-battle-regular;
|
||||
}
|
||||
}
|
||||
|
||||
&.ranked {
|
||||
.modal-card-head {
|
||||
background-color: darken($bg-battle-ranked, 30%);
|
||||
// background-color: $grey-darker;
|
||||
background-color: mix($bg-battle-ranked, $black-ter, 25%);
|
||||
}
|
||||
.modal-card-body {
|
||||
background-color: $bg-battle-ranked;
|
||||
}
|
||||
}
|
||||
|
||||
&.league {
|
||||
.modal-card-head {
|
||||
background-color: darken($bg-battle-league, 30%);
|
||||
}
|
||||
.modal-card-body {
|
||||
background-color: $bg-battle-league;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.salmon-run {
|
||||
@extend .text-shadow;
|
||||
max-width: 600px;
|
||||
|
||||
@@ -27,13 +27,13 @@
|
||||
<div v-else>
|
||||
<div class="columns is-desktop">
|
||||
<div class="column">
|
||||
<ScheduleBox class="schedule-box tilt-left regular" :schedules="regular" :now="now"></ScheduleBox>
|
||||
<ScheduleBox class="main-schedule-box tilt-left" cssClass="regular" :schedules="regular" :now="now"></ScheduleBox>
|
||||
</div>
|
||||
<div class="column">
|
||||
<ScheduleBox class="schedule-box tilt-right ranked" :schedules="ranked" :now="now"></ScheduleBox>
|
||||
<ScheduleBox class="main-schedule-box tilt-right" cssClass="ranked" :schedules="ranked" :now="now"></ScheduleBox>
|
||||
</div>
|
||||
<div class="column">
|
||||
<ScheduleBox class="schedule-box tilt-left league" :schedules="league" :now="now"></ScheduleBox>
|
||||
<ScheduleBox class="main-schedule-box tilt-left" cssClass="league" :schedules="league" :now="now"></ScheduleBox>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
24
src/js/components/GameModeHeader.vue
Normal file
24
src/js/components/GameModeHeader.vue
Normal file
@@ -0,0 +1,24 @@
|
||||
<template>
|
||||
<div class="level">
|
||||
<div class="level-left">
|
||||
<div class="level-item">
|
||||
<div class="image is-48x48" style="margin-bottom: -6px">
|
||||
<img v-if="gameMode.key == 'regular'" src="../../img/battle-regular.png" />
|
||||
<img v-if="gameMode.key == 'gachi'" src="../../img/battle-ranked.png" />
|
||||
<img v-if="gameMode.key == 'league'" src="../../img/battle-league.png" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="level-item">
|
||||
<h2 class="title is-3 is-size-2-fullhd is-size-4-mobile font-splatoon1">
|
||||
{{ gameMode.name }}
|
||||
</h2>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: ['gameMode'],
|
||||
}
|
||||
</script>
|
||||
@@ -48,26 +48,10 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import moment from 'moment';
|
||||
|
||||
export default {
|
||||
props: ['coop', 'now'],
|
||||
computed: {
|
||||
isOpen() { return this.coop.schedule.start_time <= this.now; },
|
||||
},
|
||||
filters: {
|
||||
time(value) {
|
||||
return moment.unix(value).local().format('ha');
|
||||
},
|
||||
duration(value) {
|
||||
let duration = moment.duration(value, 'seconds');
|
||||
let hours = Math.floor(duration.asHours());
|
||||
let minutes = ('0' + duration.minutes()).substr(-2);
|
||||
let seconds = ('0' + duration.seconds()).substr(-2);
|
||||
if (hours)
|
||||
return `${hours}h ${minutes}m ${seconds}s`;
|
||||
return `${minutes}m ${seconds}s`;
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -1,124 +1,82 @@
|
||||
<template>
|
||||
<div class="font-splatoon2" v-if="firstSchedule">
|
||||
<div class="level">
|
||||
<div class="level-left">
|
||||
<div class="level-item">
|
||||
<div class="image is-48x48" style="margin-bottom: -6px">
|
||||
<img v-if="firstSchedule.game_mode.key == 'regular'" src="../../img/battle-regular.png" />
|
||||
<img v-if="firstSchedule.game_mode.key == 'gachi'" src="../../img/battle-ranked.png" />
|
||||
<img v-if="firstSchedule.game_mode.key == 'league'" src="../../img/battle-league.png" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="level-item">
|
||||
<h2 class="title is-3 is-size-2-fullhd font-splatoon1">
|
||||
{{ firstSchedule.game_mode.name }}
|
||||
</h2>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="font-splatoon2" :class="cssClass" v-if="gameMode">
|
||||
<GameModeHeader :gameMode="gameMode"></GameModeHeader>
|
||||
|
||||
<div class="main-schedule">
|
||||
<div class="main-schedule" v-if="currentSchedule">
|
||||
<div class="level is-mobile top-bar">
|
||||
<div class="level-left">
|
||||
<div class="level-item title-color is-size-5">{{ firstSchedule.rule.name }}</div>
|
||||
<div class="level-item title-color is-size-5">{{ currentSchedule.rule.name }}</div>
|
||||
</div>
|
||||
<div class="level-right">
|
||||
<div class="level-item">
|
||||
{{ firstSchedule.start_time | time }} –
|
||||
{{ firstSchedule.end_time | time }}
|
||||
{{ currentSchedule.start_time | time }} –
|
||||
{{ currentSchedule.end_time | time }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="is-clearfix"></div>
|
||||
<div class="columns is-mobile is-slim">
|
||||
<div class="column"><Stage :stage="firstSchedule.stage_a"></Stage></div>
|
||||
<div class="column"><Stage :stage="firstSchedule.stage_b"></Stage></div>
|
||||
<div class="column"><Stage :stage="currentSchedule.stage_a"></Stage></div>
|
||||
<div class="column"><Stage :stage="currentSchedule.stage_b"></Stage></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="upcoming-schedule" v-if="upcomingSchedule">
|
||||
<div class="is-size-5 title-squid font-splatoon1">
|
||||
Next
|
||||
</div>
|
||||
<div class="level is-mobile is-marginless is-hidden-tablet">
|
||||
<div class="level-left">
|
||||
<div class="level-item title-color is-size-5">{{ upcomingSchedule.rule.name }}</div>
|
||||
</div>
|
||||
<div class="level-right">
|
||||
<div class="level-item">
|
||||
in {{ upcomingSchedule.start_time - now | duration }},
|
||||
{{ upcomingSchedule.start_time | time }} –
|
||||
{{ upcomingSchedule.end_time | time }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<ScheduleList :schedules="upcomingSchedules" :now="now" :onlyFirst="true"></ScheduleList>
|
||||
|
||||
<div class="columns is-slim" v-if="upcomingSchedule">
|
||||
<div class="column has-text-centered is-hidden-mobile" style="margin-top: auto; margin-bottom: auto;">
|
||||
<div class="title is-6 is-size-5-fullhd">{{ upcomingSchedule.rule.name }}</div>
|
||||
<div class="subtitle is-7 is-size-6-fullhd ">
|
||||
in {{ upcomingSchedule.start_time - now | duration }}
|
||||
<br />
|
||||
{{ upcomingSchedule.start_time | time }} –
|
||||
{{ upcomingSchedule.end_time | time }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="column is-8">
|
||||
<div class="columns is-mobile is-slim">
|
||||
<div class="column"><Stage :stage="upcomingSchedule.stage_a"></Stage></div>
|
||||
<div class="column"><Stage :stage="upcomingSchedule.stage_b"></Stage></div>
|
||||
</div>
|
||||
</div>
|
||||
<p class="has-text-centered" style="margin-top: 10px">
|
||||
<button class="button is-smallZ is-clear is-rounded" @click="isOpen=true">
|
||||
<span class="icon is-smallZ squid-icon-tilt">
|
||||
<span class="fa squid-squid"></span>
|
||||
</span>
|
||||
<span class="font-splatoon2">All Upcoming Stages</span>
|
||||
</button>
|
||||
</p>
|
||||
|
||||
<div class="modal is-active font-splatoon2" v-if="isOpen" v-portal>
|
||||
<div class="modal-background" @click="isOpen = false"></div>
|
||||
<div class="modal-card schedule-box tilt-left-slight" :class="cssClass">
|
||||
<header class="modal-card-head">
|
||||
|
||||
<GameModeHeader :gameMode="gameMode"></GameModeHeader>
|
||||
</header>
|
||||
<section class="modal-card-body">
|
||||
<ScheduleList :schedules="schedules" :now="now" :onlyFirst="false"></ScheduleList>
|
||||
</section>
|
||||
</div>
|
||||
<button class="modal-close is-large" @click="isOpen = false"></button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import moment from 'moment';
|
||||
import GameModeHeader from './GameModeHeader.vue';
|
||||
import Stage from './Stage.vue';
|
||||
import ScheduleList from './ScheduleList.vue';
|
||||
|
||||
export default {
|
||||
components: { Stage },
|
||||
props: ['schedules', 'now'],
|
||||
components: { GameModeHeader, Stage, ScheduleList },
|
||||
props: ['schedules', 'cssClass', 'now'],
|
||||
data() {
|
||||
return {
|
||||
upcomingScheduleIndex: 0,
|
||||
isOpen: false,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
firstSchedule() { return this.schedules && this.schedules[0]; },
|
||||
upcomingSchedules() { return this.schedules && this.schedules.slice(1); },
|
||||
upcomingSchedule() { return this.upcomingSchedules && this.upcomingSchedules[this.upcomingScheduleIndex]; },
|
||||
},
|
||||
watch: {
|
||||
firstSchedule(newSchedule, oldSchedule) { if (oldSchedule != newSchedule) this.upcomingScheduleIndex = 0; },
|
||||
},
|
||||
filters: {
|
||||
time(value) {
|
||||
return moment.unix(value).local().format('ha');
|
||||
gameMode() {
|
||||
if (this.schedules && this.schedules[0])
|
||||
return this.schedules[0].game_mode;
|
||||
},
|
||||
duration(value) {
|
||||
let duration = moment.duration(value, 'seconds');
|
||||
let hours = Math.floor(duration.asHours());
|
||||
let minutes = ('0' + duration.minutes()).substr(-2);
|
||||
let seconds = ('0' + duration.seconds()).substr(-2);
|
||||
if (hours)
|
||||
return `${hours}h ${minutes}m ${seconds}s`;
|
||||
return `${minutes}m ${seconds}s`;
|
||||
currentSchedule() {
|
||||
if (this.schedules && this.schedules[0] && this.schedules[0].start_time <= this.now)
|
||||
return this.schedules[0];
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
// nextSchedule() {
|
||||
// this.upcomingScheduleIndex++;
|
||||
// if (this.upcomingScheduleIndex >= this.upcomingSchedules.length)
|
||||
// this.upcomingScheduleIndex = 0;
|
||||
// },
|
||||
// previousSchedule() {
|
||||
// this.upcomingScheduleIndex--;
|
||||
// if (this.upcomingScheduleIndex < 0)
|
||||
// this.upcomingScheduleIndex = this.upcomingSchedules.length - 1;
|
||||
// },
|
||||
upcomingSchedules() {
|
||||
if (this.schedules) {
|
||||
if (this.currentSchedule)
|
||||
return this.schedules.slice(1);
|
||||
return this.schedules;
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
50
src/js/components/ScheduleList.vue
Normal file
50
src/js/components/ScheduleList.vue
Normal file
@@ -0,0 +1,50 @@
|
||||
<template>
|
||||
<div>
|
||||
<div v-if="first">
|
||||
<div class="is-size-5 title-squid font-splatoon1">
|
||||
<span v-if="first.start_time <= this.now">Now</span>
|
||||
<span v-else-if="onlyFirst">Next</span>
|
||||
<span v-else>Soon!</span>
|
||||
</div>
|
||||
|
||||
<ScheduleRow :schedule="first" :now="now"></ScheduleRow>
|
||||
</div>
|
||||
<template v-if="!onlyFirst">
|
||||
<div v-if="second">
|
||||
<div class="is-size-5 title-squid font-splatoon1">
|
||||
Next
|
||||
</div>
|
||||
|
||||
<ScheduleRow :schedule="second" :now="now"></ScheduleRow>
|
||||
</div>
|
||||
|
||||
<div v-if="others && others.length">
|
||||
<div class="is-size-5 title-squid font-splatoon1">
|
||||
Future
|
||||
</div>
|
||||
|
||||
<ScheduleRow
|
||||
v-for="schedule in others"
|
||||
:key="schedule.id"
|
||||
:schedule="schedule"
|
||||
:now="now"
|
||||
></ScheduleRow>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ScheduleRow from './ScheduleRow.vue';
|
||||
|
||||
export default {
|
||||
components: { ScheduleRow },
|
||||
props: ['schedules', 'now', 'onlyFirst'],
|
||||
computed: {
|
||||
first() { return this.schedules && this.schedules[0]; },
|
||||
second() { return this.schedules && this.schedules[1]; },
|
||||
others() { return this.schedules && this.schedules.splice(2); },
|
||||
},
|
||||
}
|
||||
</script>
|
||||
47
src/js/components/ScheduleRow.vue
Normal file
47
src/js/components/ScheduleRow.vue
Normal file
@@ -0,0 +1,47 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="level is-mobile is-marginless is-hidden-tablet">
|
||||
<div class="level-left">
|
||||
<div class="level-item title-color is-size-5">{{ schedule.rule.name }}</div>
|
||||
</div>
|
||||
<div class="level-right">
|
||||
<div class="level-item">
|
||||
<template v-if="schedule.start_time > now">
|
||||
in {{ schedule.start_time - now | duration }},
|
||||
</template>
|
||||
{{ schedule.start_time | time }} –
|
||||
{{ schedule.end_time | time }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="columns is-slim" v-if="schedule">
|
||||
<div class="column has-text-centered is-hidden-mobile" style="margin-top: auto; margin-bottom: auto;">
|
||||
<div class="title is-6 is-size-5-fullhd is-size-5-touch">{{ schedule.rule.name }}</div>
|
||||
<div class="subtitle is-7 is-size-6-fullhd is-size-6-touch">
|
||||
<template v-if="schedule.start_time > now">
|
||||
in {{ schedule.start_time - now | duration }}
|
||||
<br />
|
||||
</template>
|
||||
{{ schedule.start_time | time }} –
|
||||
{{ schedule.end_time | time }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="column is-8">
|
||||
<div class="columns is-mobile is-slim">
|
||||
<div class="column"><Stage :stage="schedule.stage_a"></Stage></div>
|
||||
<div class="column"><Stage :stage="schedule.stage_b"></Stage></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Stage from './Stage.vue';
|
||||
|
||||
export default {
|
||||
components: { Stage },
|
||||
props: ['schedule', 'now'],
|
||||
}
|
||||
</script>
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
<div class="modal is-active" v-if="isOpen" v-portal>
|
||||
<div class="modal-background" @click="isOpen = false"></div>
|
||||
<div class="modal-content">
|
||||
<div class="modal-content tilt-right-slight">
|
||||
<p class="image is-16by9">
|
||||
<img :src="image" />
|
||||
</p>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import Vue from 'vue';
|
||||
import App from './components/App.vue';
|
||||
import moment from 'moment';
|
||||
|
||||
Vue.directive('portal', {
|
||||
inserted(el) {
|
||||
@@ -7,4 +8,18 @@ Vue.directive('portal', {
|
||||
}
|
||||
});
|
||||
|
||||
Vue.filter('time', function(value) {
|
||||
return moment.unix(value).local().format('ha');
|
||||
});
|
||||
|
||||
Vue.filter('duration', function(value) {
|
||||
let duration = moment.duration(value, 'seconds');
|
||||
let hours = Math.floor(duration.asHours());
|
||||
let minutes = ('0' + duration.minutes()).substr(-2);
|
||||
let seconds = ('0' + duration.seconds()).substr(-2);
|
||||
if (hours)
|
||||
return `${hours}h ${minutes}m ${seconds}s`;
|
||||
return `${minutes}m ${seconds}s`;
|
||||
});
|
||||
|
||||
new Vue(App).$mount('#app');
|
||||
|
||||
Reference in New Issue
Block a user