shotgun/site/src/App.vue

117 lines
3.0 KiB
Vue
Raw Normal View History

2024-01-27 21:36:41 -06:00
<template>
2024-01-28 10:42:05 -06:00
<v-app :theme="theme">
2024-01-29 07:09:59 -06:00
<v-app-bar :elevation="2">
2024-01-31 06:42:35 -06:00
<v-app-bar-title>SHOTGUN</v-app-bar-title>
2024-01-29 07:09:59 -06:00
<template #append>
<v-btn :icon="themeIcon" @click="toggleDark()"></v-btn>
</template>
</v-app-bar>
2024-01-28 10:42:05 -06:00
<v-main>
2024-02-02 19:42:43 -06:00
<Game v-if="playing" :game="game" :dealer="dealer" @action="action" />
2024-02-02 18:19:25 -06:00
<v-container v-else-if="loading" class="fill-height">
<v-row class="d-flex justify-center">
<v-progress-circular class="pa-8" indeterminate size="128"></v-progress-circular>
</v-row>
</v-container>
<v-container v-else>
2024-02-02 08:28:36 -06:00
<TheLanding />
<v-row v-if="!loadingMe && !me" class="d-flex justify-center">
<TheLogin />
</v-row>
<v-row v-else-if="!loadingMe" class="d-flex justify-center">
2024-02-02 17:30:35 -06:00
<v-btn @click="clickPlay" class="mx-4" color="primary">Play</v-btn>
<v-btn class="mx-4">Log Out</v-btn>
2024-02-02 08:28:36 -06:00
</v-row>
</v-container>
2024-01-28 10:42:05 -06:00
</v-main>
</v-app>
2024-01-27 21:36:41 -06:00
</template>
<script setup lang="ts">
2024-02-02 18:19:25 -06:00
import { useDark, useToggle, useWebSocket } from '@vueuse/core';
import { computed, onMounted, ref, watchEffect } from 'vue';
import type { Action, Game, GameStart } from '@/lib/game';
2024-01-28 10:42:05 -06:00
const dark = useDark();
const toggleDark = useToggle(dark);
2024-01-29 07:19:25 -06:00
const theme = computed(() => dark.value ? 'dark' : 'light');
const themeIcon = computed(() => dark.value ? 'mdi-moon-waxing-crescent' : 'mdi-white-balance-sunny');
2024-01-28 10:42:05 -06:00
2024-02-02 19:01:19 -06:00
const { status, data, send, open } = useWebSocket<string>(`wss://${window.location.host}/queue`, {
immediate: false,
heartbeat: {
interval: 5000,
message: '{"action":"ping"}',
},
});
2024-02-02 18:19:25 -06:00
const game = ref<Game | null>(null);
const dealer = ref<boolean | null>(null);
watchEffect(() => {
2024-02-02 18:49:43 -06:00
console.log('data', data.value);
2024-02-02 18:19:25 -06:00
if (data.value == null) {
game.value = null;
dealer.value = null;
2024-02-02 18:54:10 -06:00
if (window.location.pathname.includes('game/')) {
history.replaceState(null, '', window.origin);
}
2024-02-02 18:19:25 -06:00
return;
}
2024-02-02 18:25:33 -06:00
const m = JSON.parse(data.value) as Game | GameStart;
if ('id' in m) {
2024-02-02 18:19:25 -06:00
// Game start.
2024-02-02 18:25:33 -06:00
dealer.value = m.dealer;
history.replaceState(null, '', `${window.origin}/game/${m.id}`);
2024-02-02 18:19:25 -06:00
return;
}
// Game state update.
2024-02-02 18:25:33 -06:00
game.value = m as Game;
2024-02-02 18:19:25 -06:00
});
const playing = computed(() => game.value != null);
const loading = computed(() => status.value === 'CONNECTING' || status.value === 'OPEN' && !playing.value);
2024-01-31 06:42:35 -06:00
function clickPlay() {
2024-02-02 18:19:25 -06:00
open();
2024-01-31 06:42:35 -06:00
}
2024-01-30 21:14:11 -06:00
const testGame = ref<Game>({
2024-01-30 21:14:11 -06:00
players: [
{ hp: 4, items: ['🔍', '🔪', '', '', '', '', '', ''] },
{ hp: 3, items: ['👮', '🚬', '', '', '', '', '', ''] },
2024-01-30 21:14:11 -06:00
],
round: 1,
dealer: true,
damage: 1,
previous: null,
live: 3,
blank: 4,
});
2024-01-31 07:05:33 -06:00
function action(evt: Action) {
2024-02-02 18:19:25 -06:00
console.log('send action', evt);
send(JSON.stringify(action));
2024-01-31 07:05:33 -06:00
}
2024-02-02 08:28:36 -06:00
const loadingMe = ref(true);
const me = ref<string | null>(null);
onMounted(async () => {
loadingMe.value = true;
try {
const resp = await fetch('/user/me', {
method: 'GET',
mode: 'same-origin',
credentials: 'same-origin',
})
loadingMe.value = false;
if (!resp.ok) {
me.value = null;
return;
}
const { id } = await resp.json();
me.value = id as string;
} catch {
me.value = null;
}
});
2024-01-27 21:36:41 -06:00
</script>