Fix : switch to state based shuffle animation
This commit is contained in:
@@ -0,0 +1,3 @@
|
|||||||
|
<html>
|
||||||
|
I LOVE LOADING SCREENS
|
||||||
|
</html>
|
||||||
@@ -161,7 +161,7 @@ onUnmounted(() => {
|
|||||||
<style scoped>
|
<style scoped>
|
||||||
#background {
|
#background {
|
||||||
left: 0;
|
left: 0;
|
||||||
position: absolute;
|
position: fixed;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -129,14 +129,12 @@ onMounted(() => {
|
|||||||
.card {
|
.card {
|
||||||
--max-height: 250px;
|
--max-height: 250px;
|
||||||
--margin-bottom: calc(var(--max-height) * 0.05);
|
--margin-bottom: calc(var(--max-height) * 0.05);
|
||||||
/* max-width: 256px; */
|
|
||||||
position: relative;
|
position: relative;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
margin-bottom: 0px;
|
margin-bottom: 0px;
|
||||||
margin-top: var(--margin-bottom);
|
margin-top: var(--margin-bottom);
|
||||||
transition: all 0.075s cubic-bezier(1, 1.81, 0.59, 1.42);
|
transition: all 0.075s cubic-bezier(1, 1.81, 0.59, 1.42);
|
||||||
isolation: isolate;
|
|
||||||
pointer-events: all;
|
pointer-events: all;
|
||||||
max-height: var(--max-height);
|
max-height: var(--max-height);
|
||||||
}
|
}
|
||||||
|
|||||||
+45
-41
@@ -1,5 +1,5 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { containerEvents, delay } from "~/netcode/events";
|
import { delay } from "~/netcode/events";
|
||||||
import type { Container, PlayingTurn } from "~/netcode/interfaces";
|
import type { Container, PlayingTurn } from "~/netcode/interfaces";
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
@@ -34,13 +34,13 @@ const shuffleAnimationSpeed = computed(
|
|||||||
);
|
);
|
||||||
function populateContainer() {}
|
function populateContainer() {}
|
||||||
|
|
||||||
const rotate = ref(false);
|
// const rotate = ref(false);
|
||||||
async function shuffleContainer() {
|
// async function shuffleContainer() {
|
||||||
rotate.value = true;
|
// rotate.value = true;
|
||||||
await delay(settingsStore.animationSpeed * 2);
|
// await delay(settingsStore.animationSpeed * 2);
|
||||||
rotate.value = false;
|
// rotate.value = false;
|
||||||
await delay(settingsStore.animationSpeed * 2);
|
// await delay(settingsStore.animationSpeed * 2);
|
||||||
}
|
// }
|
||||||
|
|
||||||
function getCardsPosition(cards: string) {}
|
function getCardsPosition(cards: string) {}
|
||||||
|
|
||||||
@@ -55,47 +55,44 @@ function endAnimation() {
|
|||||||
animationCallbacks.value.forEach((p) => p());
|
animationCallbacks.value.forEach((p) => p());
|
||||||
}
|
}
|
||||||
|
|
||||||
watch(
|
// watch(
|
||||||
props.container,
|
// props.container,
|
||||||
(newValue, oldValue) => {
|
// (newValue, oldValue) => {
|
||||||
if (oldValue) {
|
// if (oldValue) {
|
||||||
containerEvents.delete(oldValue._id);
|
// containerEvents.delete(oldValue._id);
|
||||||
}
|
// }
|
||||||
if (newValue) {
|
// if (newValue) {
|
||||||
containerEvents.set(newValue._id, {
|
// containerEvents.set(newValue._id, {
|
||||||
populateContainer,
|
// populateContainer,
|
||||||
shuffleContainer,
|
// shuffleContainer,
|
||||||
getCardsPosition,
|
// getCardsPosition,
|
||||||
startAnimation,
|
// startAnimation,
|
||||||
endAnimation,
|
// endAnimation,
|
||||||
});
|
// });
|
||||||
}
|
// }
|
||||||
},
|
// },
|
||||||
{ immediate: true }
|
// { immediate: true }
|
||||||
);
|
// );
|
||||||
|
|
||||||
async function onEnter(_el: any, done: () => void) {
|
// async function onEnter(_el: any, done: () => void) {
|
||||||
animationCallbacks.value.push(done);
|
// animationCallbacks.value.push(done);
|
||||||
}
|
// }
|
||||||
|
|
||||||
|
// async function onLeave(_el: any, done: () => void) {
|
||||||
|
// animationCallbacks.value.push(done);
|
||||||
|
// }
|
||||||
|
|
||||||
async function onLeave(_el: any, done: () => void) {
|
|
||||||
animationCallbacks.value.push(done);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function onBeforeEnter() {}
|
|
||||||
|
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
containerEvents.delete(props.container._id);
|
// containerEvents.delete(props.container._id);
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="cards_container" :class="{ wrapped, rotate }">
|
<div class="cards_container" :class="{ wrapped, rotate:container.shuffling }">
|
||||||
<TransitionGroup
|
<TransitionGroup
|
||||||
name="list"
|
name="list"
|
||||||
@enter="onEnter"
|
|
||||||
@leave="onLeave"
|
|
||||||
@before-enter="onBeforeEnter"
|
|
||||||
>
|
>
|
||||||
<CardPreview
|
<CardPreview
|
||||||
@click="$emit('cardClick', c._id)"
|
@click="$emit('cardClick', c._id)"
|
||||||
@@ -115,15 +112,21 @@ onUnmounted(() => {
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
.list-move,
|
||||||
.list-enter-active,
|
.list-enter-active,
|
||||||
.list-leave-active {
|
.list-leave-active {
|
||||||
transition: all v-bind("animationSpeed") ease;
|
transition: all v-bind("animationSpeed") ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.list-leave-to,
|
/* .list-leave-to, */
|
||||||
.list-enter-from {
|
.list-enter-from {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transform: translateX(30px);
|
/* transform: translateX(30px); */
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-leave-active {
|
||||||
|
position: absolute;
|
||||||
|
height:unset;
|
||||||
}
|
}
|
||||||
|
|
||||||
.rotate {
|
.rotate {
|
||||||
@@ -133,13 +136,14 @@ onUnmounted(() => {
|
|||||||
.cards_container {
|
.cards_container {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
justify-content: center;
|
justify-content: space-evenly;
|
||||||
min-width: 200px;
|
min-width: 200px;
|
||||||
transition: rotate v-bind("shuffleAnimationSpeed") ease;
|
transition: rotate v-bind("shuffleAnimationSpeed") ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cards_container.wrapped {
|
.cards_container.wrapped {
|
||||||
flex-direction: column-reverse;
|
flex-direction: column-reverse;
|
||||||
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cards_container.wrapped:before {
|
.cards_container.wrapped:before {
|
||||||
|
|||||||
+10
-31
@@ -258,10 +258,7 @@ function boardCardClick(cardUUID: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#turn_buttons {
|
#turn_buttons {
|
||||||
position: absolute;
|
grid-area: turn_buttons;
|
||||||
bottom: 0;
|
|
||||||
left: 50%;
|
|
||||||
transform: translateX(-50%);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#end_turn {
|
#end_turn {
|
||||||
@@ -273,32 +270,6 @@ function boardCardClick(cardUUID: string) {
|
|||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.stack,
|
|
||||||
.discard,
|
|
||||||
.cards_container {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: center;
|
|
||||||
flex-wrap: wrap-reverse;
|
|
||||||
}
|
|
||||||
|
|
||||||
.stack {
|
|
||||||
grid-area: stack;
|
|
||||||
margin-left: 75px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.discard {
|
|
||||||
margin-top: 40px;
|
|
||||||
grid-area: discard;
|
|
||||||
justify-content: start;
|
|
||||||
cursor: pointer;
|
|
||||||
pointer-events: none;
|
|
||||||
margin-left: 75px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.discard.invisible {
|
|
||||||
visibility: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.player {
|
.player {
|
||||||
display: grid;
|
display: grid;
|
||||||
@@ -307,12 +278,20 @@ function boardCardClick(cardUUID: string) {
|
|||||||
/* border-top: 5px solid black; */
|
/* border-top: 5px solid black; */
|
||||||
grid-template-areas:
|
grid-template-areas:
|
||||||
"player_stats"
|
"player_stats"
|
||||||
"player";
|
"player"
|
||||||
|
"turn_buttons";
|
||||||
|
justify-items: center;
|
||||||
transition: all 1s;
|
transition: all 1s;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#current_player_board {
|
#current_player_board {
|
||||||
grid-area: player;
|
grid-area: player;
|
||||||
|
display:flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
max-width: 1200px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.damage_button {
|
.damage_button {
|
||||||
|
|||||||
+13
-10
@@ -2,21 +2,23 @@ import { useAuthStore } from "#imports";
|
|||||||
|
|
||||||
export default defineNuxtRouteMiddleware(async (to, from) => {
|
export default defineNuxtRouteMiddleware(async (to, from) => {
|
||||||
const authStore = useAuthStore();
|
const authStore = useAuthStore();
|
||||||
|
const config = useRuntimeConfig();
|
||||||
if (to.path == "/login") {
|
if (to.path == "/login") {
|
||||||
const code = to.query.code;
|
const code = to.query.code;
|
||||||
if (code) {
|
if (!code) {
|
||||||
if (!Array.isArray(code)) {
|
return navigateTo(config.public.discordLoginEndpoint, { external: true });
|
||||||
try {
|
}
|
||||||
await authStore.whoami();
|
|
||||||
return navigateTo("/lobby");
|
if (!Array.isArray(code)) {
|
||||||
} catch {
|
try {
|
||||||
return navigateTo("/login");
|
await authStore.whoami();
|
||||||
}
|
return navigateTo("/lobby");
|
||||||
} else {
|
} catch {
|
||||||
return navigateTo("/login");
|
return navigateTo("/login");
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
return navigateTo("/login");
|
||||||
}
|
}
|
||||||
return navigateTo("/lobby");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// if (to.path == '/') {
|
// if (to.path == '/') {
|
||||||
@@ -69,4 +71,5 @@ export default defineNuxtRouteMiddleware(async (to, from) => {
|
|||||||
if (to.path !== "/") {
|
if (to.path !== "/") {
|
||||||
return navigateTo("/");
|
return navigateTo("/");
|
||||||
}
|
}
|
||||||
|
return navigateTo("/lobby");
|
||||||
});
|
});
|
||||||
|
|||||||
+8
-8
@@ -4,12 +4,12 @@ export function delay(delay: number) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ContainerHandler = {
|
// export type ContainerHandler = {
|
||||||
populateContainer: () => void;
|
// populateContainer: () => void;
|
||||||
shuffleContainer: () => void;
|
// shuffleContainer: () => void;
|
||||||
getCardsPosition: (cards: string) => any;
|
// getCardsPosition: (cards: string) => any;
|
||||||
startAnimation: () => void;
|
// startAnimation: () => void;
|
||||||
endAnimation: () => void;
|
// endAnimation: () => void;
|
||||||
};
|
// };
|
||||||
|
|
||||||
export const containerEvents = reactive(new Map<string, ContainerHandler>());
|
// export const containerEvents = reactive(new Map<string, ContainerHandler>());
|
||||||
|
|||||||
@@ -16,8 +16,8 @@ export interface Game extends GameObject {
|
|||||||
marketStack: Container;
|
marketStack: Container;
|
||||||
teams: Team[];
|
teams: Team[];
|
||||||
currentTurn: PlayingTurn;
|
currentTurn: PlayingTurn;
|
||||||
started: boolean
|
started: boolean;
|
||||||
owner: User
|
owner: User;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Team extends GameObject {
|
export interface Team extends GameObject {
|
||||||
@@ -31,8 +31,8 @@ export interface Player extends GameObject {
|
|||||||
hand: Container;
|
hand: Container;
|
||||||
stack: Container;
|
stack: Container;
|
||||||
user: User;
|
user: User;
|
||||||
discardMarkers: number
|
discardMarkers: number;
|
||||||
fuckUMarkers: number
|
fuckUMarkers: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface User extends GameObject {
|
export interface User extends GameObject {
|
||||||
@@ -43,6 +43,7 @@ export interface User extends GameObject {
|
|||||||
|
|
||||||
export interface Container extends GameObject {
|
export interface Container extends GameObject {
|
||||||
cards: Card[];
|
cards: Card[];
|
||||||
|
shuffling?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Card extends GameObject {
|
export interface Card extends GameObject {
|
||||||
|
|||||||
+12
-12
@@ -1,7 +1,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import LoadingScreen from "~/components/LoadingScreen.vue";
|
import LoadingScreen from "~/components/LoadingScreen.vue";
|
||||||
import { subscribe } from "~/netcode";
|
import { subscribe } from "~/netcode";
|
||||||
import { containerEvents, delay } from "~/netcode/events";
|
import { delay } from "~/netcode/events";
|
||||||
import { type Container, type Game, type Player } from "~/netcode/interfaces";
|
import { type Container, type Game, type Player } from "~/netcode/interfaces";
|
||||||
import { playSound } from "~/helpers/audioHelpers";
|
import { playSound } from "~/helpers/audioHelpers";
|
||||||
|
|
||||||
@@ -76,7 +76,7 @@ eventSource.addEventListener("message", async (message) => {
|
|||||||
throw new Error("not implemented");
|
throw new Error("not implemented");
|
||||||
} else if (data.type == "populateContainer") {
|
} else if (data.type == "populateContainer") {
|
||||||
queueAction(async () => {
|
queueAction(async () => {
|
||||||
await containerEvents.get(data.container)?.startAnimation();
|
// await containerEvents.get(data.container)?.startAnimation();
|
||||||
});
|
});
|
||||||
const fromContainer = containers.value[data.container._id as string];
|
const fromContainer = containers.value[data.container._id as string];
|
||||||
queueAction(async () => {
|
queueAction(async () => {
|
||||||
@@ -87,20 +87,23 @@ eventSource.addEventListener("message", async (message) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
queueAction(async () => {
|
queueAction(async () => {
|
||||||
await containerEvents.get(data.container)?.endAnimation();
|
// await containerEvents.get(data.container)?.endAnimation();
|
||||||
});
|
});
|
||||||
} else if (data.type == "shuffleContainer") {
|
} else if (data.type == "shuffleContainer") {
|
||||||
queueAction(async () => {
|
queueAction(async () => {
|
||||||
playSound("/sounds/shuffle.mp3");
|
playSound("/sounds/shuffle.mp3");
|
||||||
// TODO : IMPORTANT : find a better way than containerEvents
|
const container = containers.value[data.container as string];
|
||||||
await containerEvents.get(data.container)?.shuffleContainer();
|
container.shuffling = true
|
||||||
|
await delay(settingsStore.animationSpeed *2)
|
||||||
|
container.shuffling = false
|
||||||
|
await delay(settingsStore.animationSpeed *2)
|
||||||
});
|
});
|
||||||
} else if (data.type == "distributeCards") {
|
} else if (data.type == "distributeCards") {
|
||||||
// containerEvents.get(data.from)?.getCardsPosition(data.cards)
|
// containerEvents.get(data.from)?.getCardsPosition(data.cards)
|
||||||
|
|
||||||
queueAction(async () => {
|
queueAction(async () => {
|
||||||
containerEvents.get(data.from)?.startAnimation();
|
// containerEvents.get(data.from)?.startAnimation();
|
||||||
containerEvents.get(data.to)?.startAnimation();
|
// containerEvents.get(data.to)?.startAnimation();
|
||||||
});
|
});
|
||||||
|
|
||||||
const fromContainer = containers.value[data.from as string];
|
const fromContainer = containers.value[data.from as string];
|
||||||
@@ -119,8 +122,8 @@ eventSource.addEventListener("message", async (message) => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
queueAction(async () => {
|
queueAction(async () => {
|
||||||
containerEvents.get(data.from)?.endAnimation();
|
// containerEvents.get(data.from)?.endAnimation();
|
||||||
containerEvents.get(data.to)?.endAnimation();
|
// containerEvents.get(data.to)?.endAnimation();
|
||||||
await delay(settingsStore.animationSpeed * 2);
|
await delay(settingsStore.animationSpeed * 2);
|
||||||
});
|
});
|
||||||
} else if (data.type == "endTurn") {
|
} else if (data.type == "endTurn") {
|
||||||
@@ -315,9 +318,6 @@ onUnmounted(() => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#current_player {
|
#current_player {
|
||||||
overflow: auto;
|
|
||||||
position: relative;
|
|
||||||
isolation: isolate;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
|||||||
@@ -1,16 +0,0 @@
|
|||||||
<script setup lang="ts">
|
|
||||||
|
|
||||||
// import goStore, { setReady } from "@/netcode";
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<div class="root_page_div">
|
|
||||||
tehe
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.root_page_div {
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
-107
@@ -1,107 +0,0 @@
|
|||||||
<script setup lang="ts">
|
|
||||||
// import { navigateTo, useRuntimeConfig } from 'nuxt/app';
|
|
||||||
// import goStore, { netcode_create_game, join_game } from '../netcode';
|
|
||||||
|
|
||||||
const config = useRuntimeConfig()
|
|
||||||
|
|
||||||
|
|
||||||
async function discordLogin() {
|
|
||||||
await navigateTo(config.public.discordLoginEndpoint, {
|
|
||||||
external: true
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<div class="background">
|
|
||||||
<div class="title">
|
|
||||||
Entrez dans le Royaume de Héron !
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="middle-row">
|
|
||||||
<div class="icon">
|
|
||||||
<CardPreview :card_id="undefined"></CardPreview>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- <div v-if="goStore.current_game?.started">
|
|
||||||
<b>Mode spectateur</b>
|
|
||||||
</div> -->
|
|
||||||
|
|
||||||
<!-- <template v-if="!goStore.current_game?.started"> -->
|
|
||||||
<!-- <input type="text" v-model="username" />
|
|
||||||
<button @click="register(username)">LOGIN</button> -->
|
|
||||||
<!-- <button class="menu-button" @click="discordLogin()">Se connecter via Discord</button>
|
|
||||||
</template> -->
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<footer>
|
|
||||||
<p>
|
|
||||||
Héron Realms n'est en aucun cas affilié à Hero Realms.<br>
|
|
||||||
Le concept et certains noms de cartes sont la propriété de Wise Wizard Games.<br>
|
|
||||||
Les illustrations sont la propriété de leurs auteurs respectifs (il y en a plein).<br>
|
|
||||||
Ce magnifique fond d'écran est tiré de Fire Emblem: Engage.<br>
|
|
||||||
Programmeur principal, owner du projet: Legonzaur
|
|
||||||
</p>
|
|
||||||
</footer>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.background {
|
|
||||||
background-color: #f0f0f0;
|
|
||||||
background-image: url('https://www.pockettactics.com/wp-content/sites/pockettactics/2023/01/fire-emblem-engage-review-29.jpg');
|
|
||||||
background-size: cover;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
height: 100vh;
|
|
||||||
width: 100vw;
|
|
||||||
}
|
|
||||||
|
|
||||||
.title {
|
|
||||||
font-family: 'Kanit', 'Roboto', sans-serif;
|
|
||||||
font-size: 64px;
|
|
||||||
color: white;
|
|
||||||
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.2);
|
|
||||||
margin-bottom: 100px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.middle-row {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
gap: 100px;
|
|
||||||
margin-bottom: 100px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.menu-button {
|
|
||||||
background-color: #4CAF50;
|
|
||||||
border: none;
|
|
||||||
color: white;
|
|
||||||
text-align: center;
|
|
||||||
text-decoration: none;
|
|
||||||
display: inline-block;
|
|
||||||
font-family: 'Roboto', sans-serif;
|
|
||||||
font-size: 16px;
|
|
||||||
margin: auto;
|
|
||||||
cursor: pointer;
|
|
||||||
border-radius: 12px;
|
|
||||||
padding: 20px 24px;
|
|
||||||
height: 120px;
|
|
||||||
transition-duration: 0.4s;
|
|
||||||
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.2);
|
|
||||||
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
|
|
||||||
}
|
|
||||||
|
|
||||||
footer {
|
|
||||||
position: absolute;
|
|
||||||
bottom: 0;
|
|
||||||
background-color: rgba(0, 0, 0, 0.5);
|
|
||||||
color: white;
|
|
||||||
width: 100%;
|
|
||||||
font-family: 'Roboto', sans-serif;
|
|
||||||
font-size: 12px;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
</style>import { useRuntimeConfig, navigateTo } from 'nuxt/app';
|
|
||||||
Reference in New Issue
Block a user