mirror of
https://github.com/misenhower/splatoon3.ink.git
synced 2026-07-11 15:25:30 -05:00
Add a Splatfest results box
This commit is contained in:
parent
5264884e3f
commit
9f3fb1dbff
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<div class="relative">
|
||||
<div class="absolute inset-0 product-mask rounded-2xl -z-10" :class="props.bg"></div>
|
||||
<div class="absolute inset-0 product-mask rounded-2xl -z-10" :class="props.bg" :style="bgStyle"></div>
|
||||
<slot />
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -11,6 +11,7 @@ const props = defineProps({
|
|||
type: String,
|
||||
default: 'bg-splatoon-blue',
|
||||
},
|
||||
bgStyle: String,
|
||||
})
|
||||
</script>
|
||||
|
||||
|
|
|
|||
90
src/components/SplatfestResultsBox.vue
Normal file
90
src/components/SplatfestResultsBox.vue
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
<template>
|
||||
<ProductContainer class="pt-10 pb-4" bg="bg-camo-purple" :bgStyle="`background-color: ${toRgba(winner.color)};`">
|
||||
<div class="space-y-2">
|
||||
<div class="font-splatoon1 text-3xl mx-2">
|
||||
Results!
|
||||
</div>
|
||||
|
||||
<div class="mx-2 px-1 bg-zinc-700 bg-opacity-50 backdrop-blur-sm rounded-lg">
|
||||
<div class="flex justify-end py-2">
|
||||
<template v-for="team in festival.teams" :key="team.id">
|
||||
<div class="w-20 mx-2 flex justify-center py-1 rounded" :style="`background-color: ${toRgba(team.color)};`">
|
||||
<img :src="team.image.url" class="w-6 h-6" />
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<template v-for="row in resultRows" :key="row.title">
|
||||
<div class="flex font-splatoon2 text-shadow text-center py-1 items-center">
|
||||
<div class="w-36 mx-2">
|
||||
{{ row.title }}
|
||||
</div>
|
||||
|
||||
<div class="flex bg-zinc-700 bg-opacity-70 rounded-full py-1">
|
||||
<div class="w-20 mx-2" v-for="(result, i) in row.results" :key="i">
|
||||
<div :class="result.isTop ? 'text-splatoon-yellow' : 'text-zinc-300'">
|
||||
{{ (result.ratio * 100).toFixed(2) }}%
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<div class="font-splatoon2 text-splatoon-yellow text-center mx-2 ss:hidden">
|
||||
Team {{ winner.teamName }} Wins!
|
||||
</div>
|
||||
</div>
|
||||
</ProductContainer>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed } from 'vue';
|
||||
import ProductContainer from './ProductContainer.vue';
|
||||
|
||||
const props = defineProps({
|
||||
festival: Object,
|
||||
});
|
||||
|
||||
function toRgba(color) {
|
||||
return `rgba(${color.r * 255}, ${color.g * 255}, ${color.b * 255}, ${color.a})`;
|
||||
}
|
||||
|
||||
function results(ratioKey, topKey) {
|
||||
return props.festival.teams.map(team => ({
|
||||
ratio: team.result[ratioKey],
|
||||
isTop: team.result[topKey],
|
||||
}));
|
||||
}
|
||||
|
||||
const resultRows = computed(() => {
|
||||
return [
|
||||
{
|
||||
title: 'Conch Shells',
|
||||
results: results('horagaiRatio', 'isHoragaiRatioTop'),
|
||||
},
|
||||
{
|
||||
title: 'Votes',
|
||||
results: results('voteRatio', 'isVoteRatioTop'),
|
||||
},
|
||||
{
|
||||
title: 'Open',
|
||||
results: results('regularContributionRatio', 'isRegularContributionRatioTop'),
|
||||
},
|
||||
{
|
||||
title: 'Pro',
|
||||
results: results('challengeContributionRatio', 'isChallengeContributionRatioTop'),
|
||||
},
|
||||
];
|
||||
});
|
||||
|
||||
const winner = computed(() => props.festival.teams.find(t => t.result.isWinner));
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
:deep(.bg-camo-purple) {
|
||||
background-image: url('@/assets/img/camo-transparent-bg.png'),
|
||||
linear-gradient(180deg, rgba(2, 0, 36, 0.10) 0%, rgba(0, 0, 0, 0) 35%, rgba(0, 0, 0, 0.25) 100%);
|
||||
background-size: cover;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -27,6 +27,7 @@ function defineSplatfestRegionStore(region) {
|
|||
return {
|
||||
...node,
|
||||
status: getStatus(node),
|
||||
hasResults: node.teams.some(t => t.result),
|
||||
};
|
||||
}));
|
||||
|
||||
|
|
@ -34,6 +35,12 @@ function defineSplatfestRegionStore(region) {
|
|||
const activeFestival = computed(() => festivals.value?.find(f => f.status === STATUS_ACTIVE));
|
||||
const upcomingFestival = computed(() => festivals.value?.find(f => f.status === STATUS_UPCOMING));
|
||||
|
||||
// A "recent festival" is one that ended within the past 3 days
|
||||
const recentFestival = computed(() => festivals.value?.find(f =>
|
||||
f.status === STATUS_PAST &&
|
||||
time.now - Date.parse(f.endTime) < 3 * 24 * 60 * 60 * 1000
|
||||
));
|
||||
|
||||
// TODO: Eventually this needs to be handled on a per-region basis.
|
||||
const tricolor = computed(() => {
|
||||
let fest = useSchedulesDataStore().data?.currentFest;
|
||||
|
|
@ -48,7 +55,7 @@ function defineSplatfestRegionStore(region) {
|
|||
};
|
||||
});
|
||||
|
||||
return { festivals, previousFestivals, activeFestival, upcomingFestival, tricolor };
|
||||
return { festivals, previousFestivals, activeFestival, upcomingFestival, recentFestival, tricolor };
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,6 +20,19 @@
|
|||
class="flex-1 max-w-md md:-rotate-1"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center justify-center flex-col space-y-6 md:flex-row md:space-x-6 md:space-y-0" v-if="usSplatfests.recentFestival">
|
||||
<SplatfestBox
|
||||
:festival="usSplatfests.recentFestival"
|
||||
class="max-w-md md:-rotate-1"
|
||||
/>
|
||||
|
||||
<SplatfestResultsBox
|
||||
v-if="usSplatfests.recentFestival.hasResults"
|
||||
:festival="usSplatfests.recentFestival"
|
||||
class="max-w-md md:rotate-1"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</MainLayout>
|
||||
|
|
@ -31,5 +44,6 @@ import ScheduleBox from '../components/ScheduleBox.vue';
|
|||
|
||||
import { useUSSplatfestsStore } from '@/stores/splatfests';
|
||||
import SplatfestBox from '../components/SplatfestBox.vue';
|
||||
import SplatfestResultsBox from '../components/SplatfestResultsBox.vue';
|
||||
const usSplatfests = useUSSplatfestsStore();
|
||||
</script>
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user