Add first test web design for p2 rerun

This commit is contained in:
Trenton Zimmer
2026-08-11 14:40:39 -04:00
parent 2f3e42823f
commit fc09ed65ea
15 changed files with 1073 additions and 5 deletions

View File

@@ -33,6 +33,10 @@ const props = defineProps({
type: Boolean,
default: false,
},
disableHover: {
type: Boolean,
default: false,
},
});
const tag = computed(() => {
@@ -72,11 +76,16 @@ const cardStyle = `
background-size: cover;
background-repeat: no-repeat;
`;
const hoverClass = props.disableHover
? null
: "hover:cursor-pointer hover:outline outline-blue-500/50";
</script>
<template>
<button
class="flex rounded-2xl hover:scale-[1.01] hover:shadow-xl hover:outline outline-blue-500/50 hover:bg-slate-500 hover:dark:bg-slate-950 hover:cursor-pointer transition-all duration-100"
class="flex rounded-2xl hover:scale-[1.01] hover:shadow-xl hover:bg-slate-500 hover:dark:bg-slate-950 transition-all duration-100"
:class="hoverClass"
:style="cardStyle"
@click="loadGamePage()"
>

View File

@@ -0,0 +1,56 @@
import { chartColors } from "@/components/Charts/chart.config";
const createDataset = (color, label, data) => ({
fill: false,
borderColor: chartColors.default[color],
borderWidth: 2,
pointBackgroundColor: chartColors.default[color],
pointBorderColor: "rgba(255,255,255,0)",
pointHoverBackgroundColor: chartColors.default[color],
pointBorderWidth: 20,
pointHoverRadius: 4,
pointHoverBorderWidth: 15,
pointRadius: 4,
tension: 0.5,
cubicInterpolationMode: "default",
label,
data,
});
export const generateMonthlyChartData = () => {
const labels = [
"Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun",
"Jul",
"Aug",
"Sep",
"Oct",
"Nov",
"Dec",
];
return {
labels,
datasets: [
createDataset(
"info",
"Plays",
[145, 168, 192, 210, 185, 230, 244, 267, 289, 301, 315, 338],
),
createDataset(
"danger",
"Attempts",
[85, 92, 108, 115, 101, 128, 132, 140, 156, 170, 181, 194],
),
createDataset(
"primary",
"Records",
[14, 17, 13, 19, 16, 22, 24, 28, 26, 31, 35, 39],
),
],
};
};

View File

@@ -0,0 +1,142 @@
<script setup>
import { ref, onMounted } from "vue";
import { PhCalendar, PhChartLine } from "@phosphor-icons/vue";
import SectionTitleLine from "@/components/SectionTitleLine.vue";
import CardBox from "@/components/CardBox.vue";
import LineChart from "@/components/Charts/LineChart.vue";
import RerunLogo from "@/components/Rerun/RerunLogo.vue";
import StatsBox from "@/components/Rerun/StatsBox.vue";
import { generateMonthlyChartData } from "@/components/Charts/monthly";
defineProps({
data: {
type: Object,
},
});
const show = ref(false);
const chartData = generateMonthlyChartData();
onMounted(() => {
requestAnimationFrame(() => {
show.value = true;
});
});
</script>
<template>
<div class="relative flex h-full flex-col px-4 py-8 max-w-3xl md:min-w-lg">
<div class="absolute left-4 top-4">
<RerunLogo small :year="data.year" />
</div>
<Transition
enter-active-class="transition-all duration-700 delay-50 ease-out"
enter-from-class="opacity-0 translate-y-4"
enter-to-class="opacity-100 translate-y-0"
>
<div v-if="show" class="mt-12 -mb-6">
<SectionTitleLine
:icon="PhCalendar"
color="text-orange-300"
title="Notable Dates"
main
/>
</div>
</Transition>
<div class="mt-6 grid w-full gap-5">
<Transition
enter-active-class="transition-all duration-700 delay-[200ms]"
enter-from-class="opacity-0 translate-y-6"
enter-to-class="opacity-100 translate-y-0"
>
<div v-if="show">
<StatsBox
header="Your first play..."
footer="Started with DDR, and you never stopped."
suffix="(14 plays, 30 scores, 10 records)"
>
1/1/2026
</StatsBox>
</div>
</Transition>
<Transition
enter-active-class="transition-all duration-700 delay-[300ms]"
enter-from-class="opacity-0 translate-y-6"
enter-to-class="opacity-100 translate-y-0"
>
<div v-if="show">
<StatsBox
header="Your best day..."
footer="What a day!"
suffix="(14 plays, 30 scores, 10 records)"
>
3/3/2026
</StatsBox>
</div>
</Transition>
<Transition
enter-active-class="transition-all duration-700 delay-[300ms]"
enter-from-class="opacity-0 translate-y-6"
enter-to-class="opacity-100 translate-y-0"
>
<div v-if="show">
<StatsBox
header="Your best month..."
footer="You're truly dedicated."
suffix="(14 plays, 30 scores, 10 records)"
>
December
</StatsBox>
</div>
</Transition>
<Transition
enter-active-class="transition-all duration-700 delay-[400ms]"
enter-from-class="opacity-0 translate-y-6"
enter-to-class="opacity-100 translate-y-0"
>
<div v-if="show">
<StatsBox
header="Your latest play..."
footer="Wrapping it up with IIDX."
suffix="(14 plays, 30 scores, 10 records)"
>
12/25/2026
</StatsBox>
</div>
</Transition>
</div>
<Transition
enter-active-class="transition-all duration-700 delay-[700ms] ease-out"
enter-from-class="opacity-0 translate-y-4"
enter-to-class="opacity-100 translate-y-0"
>
<div v-if="show" class="mt-6">
<SectionTitleLine
:icon="PhChartLine"
color="text-sky-300"
title="Monthly Breakdown"
main
/>
</div>
</Transition>
<Transition
enter-active-class="transition-all duration-700 delay-[800ms] ease-out"
enter-from-class="opacity-0 translate-y-4"
enter-to-class="opacity-100 translate-y-0"
>
<div v-if="show">
<CardBox>
<LineChart :data="chartData" class="h-50" />
</CardBox>
</div>
</Transition>
</div>
</template>

View File

@@ -0,0 +1,113 @@
<script setup>
import { PhCalendar, PhJoystick, PhTrendUp } from "@phosphor-icons/vue";
import SectionTitleLine from "@/components/SectionTitleLine.vue";
import CardBoxWidget from "@/components/CardBoxWidget.vue";
import GameTitleLine from "@/components/GameTitleLine.vue";
import { GameConstants, getGameInfo } from "@/constants";
defineProps({
data: {
type: Object,
},
});
const gameInfo = getGameInfo(GameConstants.DDR);
</script>
<template>
<div>
<div>
<SectionTitleLine
:icon="PhTrendUp"
color="text-emerald-300"
title="Overall Stats"
main
/>
<div
class="grid grid-cols-2 sm:grid-cols-3 gap-6 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 3xl:grid-cols-5 mb-6"
>
<CardBoxWidget label="Yearly Plays" :number="100" />
<CardBoxWidget label="Unique Games" :number="3" />
<CardBoxWidget label="Top Game">DDR</CardBoxWidget>
<CardBoxWidget label="Top Song">Din Don Dan</CardBoxWidget>
<CardBoxWidget label="Yearly Records" :number="3" />
<CardBoxWidget label="Yearly Attempts" :number="3" />
</div>
</div>
<div>
<SectionTitleLine
:icon="PhCalendar"
color="text-orange-300"
title="Notable Days"
main
/>
<div
class="grid grid-cols-2 sm:grid-cols-3 gap-6 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 3xl:grid-cols-5 mb-6"
>
<CardBoxWidget label="Most Played Day">
1/1/2026, with 30 plays
</CardBoxWidget>
<CardBoxWidget label="Most Games Day">
1/1/2026, with 3 games
</CardBoxWidget>
</div>
</div>
<div>
<SectionTitleLine
:icon="PhCalendar"
color="text-rose-300"
title="Monthly Breakdown"
main
/>
<div
class="grid grid-cols-2 sm:grid-cols-3 gap-6 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 3xl:grid-cols-5 mb-6"
>
<CardBoxWidget label="Most Played Month">
January, with 300 plays
</CardBoxWidget>
</div>
</div>
<div>
<SectionTitleLine
:icon="PhJoystick"
color="text-cyan-300"
title="Game Breakdown"
main
/>
<GameTitleLine :title="gameInfo.name" :path="gameInfo.icon" />
<div
class="grid grid-cols-2 sm:grid-cols-3 gap-6 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 3xl:grid-cols-5 mb-6"
>
<CardBoxWidget label="Most Played Song"> Din Don Dan </CardBoxWidget>
<CardBoxWidget label="Yearly Plays" :number="25" />
<CardBoxWidget label="Yearly Records" :number="3" />
<CardBoxWidget label="Yearly Attempts" :number="3" />
</div>
</div>
<div>
<SectionTitleLine
:icon="PhJoystick"
color="text-fuchsia-300"
title="Location Statistics"
main
/>
<div
class="grid grid-cols-2 sm:grid-cols-3 gap-6 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 3xl:grid-cols-5 mb-6"
>
<CardBoxWidget label="Most Visited Arcade">
Boss Battle Games
</CardBoxWidget>
</div>
</div>
</div>
</template>

View File

@@ -0,0 +1,128 @@
<script setup>
import { ref, onMounted } from "vue";
import { PhJoystick, PhPlus } from "@phosphor-icons/vue";
import SectionTitleLine from "@/components/SectionTitleLine.vue";
import CardBoxGameStat from "@/components/CardBoxGameStat.vue";
import RerunLogo from "@/components/Rerun/RerunLogo.vue";
import StatsBox from "@/components/Rerun/StatsBox.vue";
const props = defineProps({
data: {
type: Object,
},
});
const show = ref(false);
onMounted(() => {
requestAnimationFrame(() => {
show.value = true;
});
});
</script>
<template>
<div class="relative flex h-full flex-col px-4 py-8 max-w-3xl md:min-w-lg">
<div class="absolute left-4 top-4">
<RerunLogo small :year="data.year" />
</div>
<Transition
enter-active-class="transition-all duration-700 delay-50 ease-out"
enter-from-class="opacity-0 translate-y-4"
enter-to-class="opacity-100 translate-y-0"
>
<div v-if="show" class="mt-12 -mb-6">
<SectionTitleLine
:icon="PhJoystick"
color="text-sky-300"
title="Game Breakdowns"
main
/>
<p class="mb-4 text-lg text-slate-300">
Let's go through what had you hooked.
</p>
</div>
</Transition>
<div class="mt-6 grid w-full gap-5">
<Transition
enter-active-class="transition-all duration-700 delay-[200ms]"
enter-from-class="opacity-0 translate-y-6"
enter-to-class="opacity-100 translate-y-0"
>
<div v-if="show">
<StatsBox
header="You played..."
footer="We're impressed!"
suffix="unique games"
:number="props.data.profiles?.length ?? 0"
/>
</div>
</Transition>
</div>
<Transition
enter-active-class="transition-all duration-700 delay-[400ms] ease-out"
enter-from-class="opacity-0 translate-y-4"
enter-to-class="opacity-100 translate-y-0"
>
<div
v-if="show"
class="grid grid-flow-row auto-rows-auto grid-cols-2 md:grid-cols-2 gap-5 my-6"
>
<CardBoxGameStat
v-for="profile of props.data.profiles"
:key="profile.game"
:game="profile.game"
:value="profile.data.total_plays"
:profile-name="profile?.username"
disable-local-click
disable-hover
type="plays"
/>
</div>
</Transition>
<Transition
enter-active-class="transition-all duration-700 delay-[500ms] ease-out"
enter-from-class="opacity-0 translate-y-4"
enter-to-class="opacity-100 translate-y-0"
>
<div v-if="show" class="mt-2 -mb-6">
<SectionTitleLine
:icon="PhPlus"
color="text-red-300"
title="New Games"
main
/>
<p class="mb-4 text-lg text-slate-300">
These games were new to you this year.
</p>
</div>
</Transition>
<Transition
enter-active-class="transition-all duration-700 delay-[700ms] ease-out"
enter-from-class="opacity-0 translate-y-4"
enter-to-class="opacity-100 translate-y-0"
>
<div
v-if="show"
class="grid grid-flow-row auto-rows-auto grid-cols-2 md:grid-cols-2 gap-5 my-6"
>
<template v-for="profile of props.data.profiles" :key="profile.game">
<CardBoxGameStat
v-if="profile.data?.new"
:game="profile.game"
:value="profile.data.total_plays"
:profile-name="profile?.username"
disable-local-click
disable-hover
type="plays"
/>
</template>
</div>
</Transition>
</div>
</template>

View File

@@ -0,0 +1,134 @@
<script setup>
import { ref, onMounted } from "vue";
import NumberDynamic from "@/components/NumberDynamic.vue";
import RerunLogo from "@/components/Rerun/RerunLogo.vue";
import StatsBox from "@/components/Rerun/StatsBox.vue";
import GameTitleLine from "@/components/GameTitleLine.vue";
import { getGameInfo } from "@/constants";
const props = defineProps({
data: {
type: Object,
},
});
const profile = props.data?.profile ?? {};
const show = ref(false);
const gameInfo = getGameInfo(profile?.game);
onMounted(() => {
requestAnimationFrame(() => {
show.value = true;
});
});
</script>
<template>
<div class="relative flex h-full flex-col px-4 py-8 max-w-3xl md:min-w-lg">
<div class="absolute left-4 top-4">
<RerunLogo small :year="data.year" />
</div>
<Transition
enter-active-class="transition-all duration-700 delay-150 ease-out"
enter-from-class="opacity-0 translate-y-8 scale-95"
enter-to-class="opacity-100 translate-y-0 scale-100"
>
<GameTitleLine
v-if="show"
:title="gameInfo.name"
:path="gameInfo.icon"
class="mt-12 -mb-6"
/>
</Transition>
<Transition
enter-active-class="transition-all duration-700 delay-300 ease-out"
enter-from-class="opacity-0 translate-y-4"
enter-to-class="opacity-100 translate-y-0"
>
<div v-if="show">
<div class="text-center">
<div class="">
<p class="mb-4 text-lg text-slate-300">Your #1 game this year</p>
<h1 class="text-2xl">You had...</h1>
<NumberDynamic
class="text-8xl mb-2 font-black text-emerald-600"
:value="1000"
/>
<h1 class="text-3xl font-bold">plays</h1>
</div>
<hr class="border-t my-4 w-full" />
<div class="flex gap-4 w-full justify-center my-4">
<div>
<NumberDynamic
class="text-4xl mb-2 font-black text-pink-300"
:value="4000"
/>
<h1 class="text-3xl font-bold">scores</h1>
</div>
<div class="md:border-r" />
<div>
<NumberDynamic
class="text-4xl mb-2 font-black text-amber-400"
:value="1000"
/>
<h1 class="text-3xl font-bold">records</h1>
</div>
</div>
</div>
</div>
</Transition>
<div class="mt-6 grid w-full gap-5">
<Transition
enter-active-class="transition-all duration-700 delay-[500ms]"
enter-from-class="opacity-0 translate-y-6"
enter-to-class="opacity-100 translate-y-0"
>
<div v-if="show">
<StatsBox
header="You played..."
footer="You were quite diverse!"
suffix="unique games"
:number="6"
/>
</div>
</Transition>
<Transition
enter-active-class="transition-all duration-700 delay-[700ms]"
enter-from-class="opacity-0 translate-y-6"
enter-to-class="opacity-100 translate-y-0"
>
<div v-if="show">
<StatsBox
header="Your favorite was..."
footer="You just kept coming back for more."
suffix="(400 plays)"
>
DanceDanceRevolution
</StatsBox>
</div>
</Transition>
<Transition
enter-active-class="transition-all duration-700 delay-[800ms]"
enter-from-class="opacity-0 translate-y-6"
enter-to-class="opacity-100 translate-y-0"
>
<div v-if="show">
<StatsBox
header="One song to rule them all..."
footer="It must've been stuck in your head."
suffix="(100 plays)"
>
Din Don Dan
</StatsBox>
</div>
</Transition>
</div>
</div>
</template>

View File

@@ -0,0 +1,135 @@
<script setup>
import { ref, onMounted } from "vue";
import NumberDynamic from "@/components/NumberDynamic.vue";
import UserCard from "@/components/UserCard.vue";
import RerunLogo from "@/components/Rerun/RerunLogo.vue";
import StatsBox from "@/components/Rerun/StatsBox.vue";
defineProps({
data: {
type: Object,
},
});
const show = ref(false);
onMounted(() => {
requestAnimationFrame(() => {
show.value = true;
});
});
</script>
<template>
<div class="relative flex h-full flex-col px-4 py-8 max-w-3xl md:min-w-lg">
<Transition
enter-active-class="transition-all duration-700 ease-out"
enter-from-class="opacity-0 -translate-y-6"
enter-to-class="opacity-100 translate-y-0"
>
<div v-if="show" class="absolute left-4 top-4">
<RerunLogo small :year="data.year" />
</div>
</Transition>
<Transition
enter-active-class="transition-all duration-700 delay-150 ease-out"
enter-from-class="opacity-0 translate-y-8 scale-95"
enter-to-class="opacity-100 translate-y-0 scale-100"
>
<UserCard v-if="show" class="mt-10 scale-[90%]" use-small even-smaller />
</Transition>
<Transition
enter-active-class="transition-all duration-700 delay-300 ease-out"
enter-from-class="opacity-0 translate-y-4"
enter-to-class="opacity-100 translate-y-0"
>
<div v-if="show">
<div class="text-center">
<div class="mt-4">
<p class="mb-4 text-lg text-slate-300">
From the first play on 1/1/2026, this is what your year looked
like.
</p>
<h1 class="text-2xl">You had...</h1>
<NumberDynamic
class="text-8xl mb-2 font-black text-emerald-600"
:value="1000"
/>
<h1 class="text-3xl font-bold">plays</h1>
</div>
<hr class="border-t my-4 w-full" />
<div class="flex gap-4 w-full justify-center my-4">
<div>
<NumberDynamic
class="text-4xl mb-2 font-black text-pink-300"
:value="4000"
/>
<h1 class="text-3xl font-bold">scores</h1>
</div>
<div class="md:border-r" />
<div>
<NumberDynamic
class="text-4xl mb-2 font-black text-amber-400"
:value="1000"
/>
<h1 class="text-3xl font-bold">records</h1>
</div>
</div>
</div>
</div>
</Transition>
<div class="mt-6 grid w-full gap-5">
<Transition
enter-active-class="transition-all duration-700 delay-[500ms]"
enter-from-class="opacity-0 translate-y-6"
enter-to-class="opacity-100 translate-y-0"
>
<div v-if="show">
<StatsBox
header="You played..."
footer="You were quite diverse!"
suffix="unique games"
:number="6"
/>
</div>
</Transition>
<Transition
enter-active-class="transition-all duration-700 delay-[700ms]"
enter-from-class="opacity-0 translate-y-6"
enter-to-class="opacity-100 translate-y-0"
>
<div v-if="show">
<StatsBox
header="Your favorite was..."
footer="You just kept coming back for more."
suffix="(400 plays)"
>
DanceDanceRevolution
</StatsBox>
</div>
</Transition>
<Transition
enter-active-class="transition-all duration-700 delay-[800ms]"
enter-from-class="opacity-0 translate-y-6"
enter-to-class="opacity-100 translate-y-0"
>
<div v-if="show">
<StatsBox
header="One song to rule them all..."
footer="It must've been stuck in your head."
suffix="(100 plays)"
>
Din Don Dan
</StatsBox>
</div>
</Transition>
</div>
</div>
</template>

View File

@@ -0,0 +1,19 @@
<script setup>
import RerunLogo from "@/components/Rerun/RerunLogo.vue";
defineProps({
data: {
type: Object,
},
});
</script>
<template>
<RerunLogo />
<p class="text-lg">Let's run back your {{ data.year }}.</p>
<hr class="border-t mt-6 w-full" />
<p class="my-2 font-light tracking-wide italic">
You can navigate with your arrow keys
</p>
</template>

View File

@@ -0,0 +1,37 @@
<script setup>
import { computed } from "vue";
import { PhRewind } from "@phosphor-icons/vue";
import BaseIcon from "@/components/BaseIcon.vue";
const props = defineProps({
small: {
type: Boolean,
default: false,
},
year: {
type: Number,
default: null,
},
});
const iconWidth = computed(() => (props.small ? "w-8" : "w-20"));
const iconSize = computed(() => (props.small ? 24 : 45));
const titleClass = computed(() =>
props.small ? "text-xl font-bold" : "text-3xl font-bold",
);
const wrapperClass = computed(() =>
props.small ? "flex items-center gap-2" : "text-center space-y-2",
);
</script>
<template>
<div :class="wrapperClass">
<BaseIcon
:icon="PhRewind"
color="text-amber-400"
:w="iconWidth"
:size="iconSize"
/>
<h1 :class="titleClass"><samp>PhaseII</samp> Rerun {{ year }}</h1>
</div>
</template>

View File

@@ -0,0 +1,68 @@
<script setup>
import NumberDynamic from "@/components/NumberDynamic.vue";
const props = defineProps({
header: {
type: String,
},
footer: {
type: String,
},
number: {
type: Number,
default: null,
},
icon: {
type: Object,
default: null,
},
prefix: {
type: String,
default: null,
},
suffix: {
type: String,
default: null,
},
color: {
type: String,
default: "text-gray-500 dark:text-slate-400",
},
numColor: {
type: String,
default: "",
},
iconColor: {
type: String,
default: "",
},
});
</script>
<template>
<div
class="rounded-2xl border border-slate-400/10 bg-slate-400/5 hover:bg-slate-400/10 transition-colors px-6 py-5"
>
<div class="text-sm tracking-wider text-slate-400">
{{ props.header }}
</div>
<div class="text-2xl font-bold">
<NumberDynamic
v-if="props.number !== null"
:value="props.number"
:prefix="props.prefix"
:suffix="props.suffix"
/>
<div v-else class="grid md:flex gap-x-2 items-baseline">
<slot />
<div class="text-sm text-slate-300">
{{ suffix }}
</div>
</div>
</div>
<div class="text-slate-400">{{ props.footer }}</div>
</div>
</template>

View File

@@ -0,0 +1,82 @@
<script setup>
import { computed, onMounted, onUnmounted } from "vue";
import CardBox from "@/components/CardBox.vue";
import BaseButton from "@/components/BaseButton.vue";
import BaseButtons from "@/components/BaseButtons.vue";
import { PhArrowLeft, PhArrowRight } from "@phosphor-icons/vue";
const props = defineProps({
current: Number,
total: Number,
});
const emit = defineEmits(["next", "previous"]);
const progress = computed(() => {
return (props.current / (props.total - 1)) * 100;
});
function onKeyDown(event) {
switch (event.key) {
case "ArrowRight":
case " ":
case "Enter":
emit("next");
break;
case "ArrowLeft":
emit("previous");
break;
}
}
onMounted(() => {
window.addEventListener("keydown", onKeyDown);
});
onUnmounted(() => {
window.removeEventListener("keydown", onKeyDown);
});
</script>
<template>
<CardBox
class="w-full md:w-auto rounded-none md:rounded-xl p-4"
color-prop="bg-slate-800 dark:bg-slate-800"
has-table
>
<div class="flex flex-col items-center justify-center">
<slot />
</div>
<template v-if="current">
<div class="space-y-2 mt-8">
<p class="text-sm opacity-70">{{ current }} / {{ total - 1 }}</p>
<div class="h-1 bg-gray-700">
<div
class="h-full bg-emerald-400 transition-all duration-500"
:style="{ width: `${progress}%` }"
/>
</div>
</div>
</template>
<BaseButtons type="justify-center gap-4" class-addon="my-6">
<BaseButton
v-if="current"
label="Back"
color="info"
:icon="PhArrowLeft"
@click="$emit('previous')"
/>
<BaseButton
v-if="progress !== 100"
:label="current ? 'Next' : `Here we go!`"
color="success"
:icon="current ? PhArrowRight : null"
@click="$emit('next')"
/>
</BaseButtons>
</CardBox>
</template>

View File

@@ -1,11 +1,14 @@
<script setup></script>
<template>
<div class="bg-gray-950 dark:text-slate-100">
<div
class="relative min-h-screen bg-slate-800 md:bg-slate-950 dark:text-slate-100"
>
<div
class="hidden md:block absolute inset-0 z-0 bg-[radial-gradient(125%_125%_at_50%_10%,#000000_40%,#0d1a36_100%)]"
class="pointer-events-none absolute inset-0 hidden md:block z-0 md:bg-[radial-gradient(125%_125%_at_50%_10%,#000000_40%,#0d1a36_100%)]"
/>
<div class="animated animatedFadeInUp fadeInUp">
<div class="relative z-10 animated animatedFadeInUp fadeInUp">
<slot />
</div>
</div>

View File

@@ -41,6 +41,7 @@ const routes = [
},
{
meta: {
requiresGuest: true,
title: "Login",
},
path: "/auth/login",
@@ -49,6 +50,7 @@ const routes = [
},
{
meta: {
requiresGuest: true,
title: "Register",
},
path: "/auth/register",
@@ -57,6 +59,7 @@ const routes = [
},
{
meta: {
requiresGuest: true,
title: "Reset Password",
},
path: "/auth/reset",
@@ -182,6 +185,19 @@ const routes = [
hotReload: true, // disables Hot Reload
},
},
{
meta: {
requiresAuth: true,
requiresAdmin: true,
title: "Profile Rerun",
},
path: "/profile/rerun",
name: "profile_rerun",
component: () => import("@/views/Profile/RerunView.vue"),
options: {
hotReload: true, // disables Hot Reload
},
},
{
meta: {
requiresAuth: true,
@@ -488,6 +504,16 @@ router.beforeEach(async (to) => {
}
}
if (to.meta.requiresGuest) {
const validSession = await mainStore.loadUser();
if (validSession) {
return {
name: "dashboard",
};
}
}
if (to.meta.requiresAdmin) {
const validSession = await mainStore.loadUser();

View File

@@ -240,7 +240,12 @@ const cardBoxes = ref([
</div>
<CardBoxComponentEmpty v-if="!newsData || !newsData.length" />
<SectionTitleLine :icon="PhTrendUp" title="Quick Stats" main />
<SectionTitleLine
:icon="PhTrendUp"
title="Quick Stats"
color="text-emerald-300"
main
/>
<div
class="grid grid-cols-2 sm:grid-cols-3 gap-6 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 3xl:grid-cols-5 mb-6"
>

View File

@@ -0,0 +1,111 @@
<script setup>
import { ref, computed } from "vue";
import LayoutGuest from "@/layouts/LayoutGuest.vue";
import StoryCard from "@/components/Rerun/StoryCard.vue";
import IntroStory from "@/components/Rerun/IntroStory.vue";
import GeneralStory from "@/components/Rerun/GeneralStory.vue";
import DatesStory from "@/components/Rerun/DatesStory.vue";
import GameIntroStory from "@/components/Rerun/GameIntroStory.vue";
import GameStory from "@/components/Rerun/GameStory.vue";
import FinalStory from "@/components/Rerun/FinalStory.vue";
import { GameConstants } from "@/constants";
const ReRunYear = 2049;
const current = ref(0);
const profiles = [
{
game: GameConstants.DDR,
username: "TRMAZI",
data: {
new: true,
total_plays: 100,
},
},
{
game: GameConstants.DDROMNI,
username: "TRMAZI",
data: {
total_plays: 100,
},
},
{
game: GameConstants.IIDX,
username: "TRMAZI",
data: {
total_plays: 100,
},
},
{
game: GameConstants.SDVX,
username: "TRMAZI",
data: {
total_plays: 100,
},
},
{
game: GameConstants.TSUMTSUM,
username: "TRMAZI",
data: {
total_plays: 100,
},
},
{
game: GameConstants.REFLEC_BEAT,
username: "TRMAZI",
data: {
total_plays: 100,
},
},
];
const baseData = {
year: ReRunYear,
};
var cards = [
{ card: IntroStory },
{ card: GeneralStory },
{ card: DatesStory },
{
card: GameIntroStory,
data: {
...baseData,
profiles: profiles,
},
},
];
for (const profile of profiles) {
cards.push({
card: GameStory,
data: {
...baseData,
profile,
},
});
}
cards.push({ card: FinalStory });
const CurrentStory = computed(() => cards[current.value].card);
const CurrentData = computed(() => cards[current.value].data ?? baseData);
function next() {
if (current.value < cards.length - 1) current.value++;
}
function previous() {
if (current.value > 0) current.value--;
}
</script>
<template>
<LayoutGuest>
<div class="flex md:min-h-screen md:items-center md:justify-center md:p-6">
<StoryCard
:current="current"
:total="cards.length"
@next="next"
@previous="previous"
>
<component :is="CurrentStory" :key="current" :data="CurrentData" />
</StoryCard>
</div>
</LayoutGuest>
</template>