feat: add gamemaster page (WIP)

This commit is contained in:
Settel 2022-09-03 21:41:30 +02:00
parent 6b1316d3ef
commit cab1a91cc2
10 changed files with 138 additions and 24 deletions

View File

@ -6,9 +6,6 @@
</div> </div>
</template> </template>
<script setup>
</script>
<style lang="scss"> <style lang="scss">
@import '~/assets/css/components'; @import '~/assets/css/components';
@ -31,6 +28,7 @@
border-radius: 10px; border-radius: 10px;
background-color: $alert-background-color; background-color: $alert-background-color;
font-size: 24px; font-size: 24px;
color: $text-primary-color;
} }
} }
</style> </style>

View File

@ -18,7 +18,7 @@ defineProps<{
.admin-tile { .admin-tile {
&__container { &__container {
width: 360px; width: 300px;
margin: 40px; margin: 40px;
padding: 16px 30px; padding: 16px 30px;
background-color: $admin-tile-background-color; background-color: $admin-tile-background-color;

View File

@ -0,0 +1,45 @@
<template>
<AdminTile title="Game">
<table>
<tr>
<td>{{ $t('name') }}:</td>
<td>{{ game.name }}</td>
<td>
<div class="gameinfo-tile__edit-game-name" @click="editName"></div>
</td>
</tr>
<tr>
<td>{{ $t('language') }}:</td>
<td>{{ user.lang }}</td>
<td>
<div class="gameinfo-tile__edit-lang" @click="editLang"></div>
</td>
</tr>
</table>
</AdminTile>
</template>
<script setup lang="ts">
import useI18n from '@/composables/useI18n'
import { useUserinfoStore } from "@/stores/UserinfoStore"
import { useGameinfoStore } from "@/stores/GameinfoStore"
const { $t } = useI18n({
name: { en: 'Name', de: 'Name' },
language: { en: 'Language', de: 'Sprache' },
})
const game = useGameinfoStore()
const user = useUserinfoStore()
const editName = () => { alert('not yet implemented') }
const editLang = () => { alert('not yet implemented') }
</script>
<style lang="scss">
.gameinfo-tile {
&__container {
width: 100%;
height: 100%;
}
}
</style>

View File

@ -0,0 +1,33 @@
<template>
<AdminTile title="Players">
<table>
<tr>
<th>{{ $t('name') }}:</th>
<th>{{ $t('num-quotes') }}</th>
<th>{{ $t('score') }}</th>
<th>{{ $t('last-logged-in') }}</th>
</tr>
</table>
</AdminTile>
</template>
<script setup lang="ts">
import useI18n from '@/composables/useI18n'
const { $t } = useI18n({
name: { en: 'Name', de: 'Name' },
'num-quotes': { en: '# quotes', de: '# Quotes' },
'score': { en: 'Score', de: 'Score' },
'last-logged-in': { en: 'last logged in', de: 'zuletzt eingeloggt' },
})
</script>
<style lang="scss">
.gameinfo-tile {
&__container {
width: 100%;
height: 100%;
}
}
</style>

View File

@ -4,6 +4,8 @@ import { useGameinfoStore } from "@/stores/GameinfoStore"
import { useRoundStore } from "@/stores/RoundStore" import { useRoundStore } from "@/stores/RoundStore"
import { usePlayersStore } from "@/stores/PlayersStore" import { usePlayersStore } from "@/stores/PlayersStore"
import { EngineContext } from '@/composables/useEngine' import { EngineContext } from '@/composables/useEngine'
import useAlert from '@/composables/useAlert'
import useI18n from '@/composables/useI18n'
type EngineResponse = { type EngineResponse = {
version: string, version: string,
@ -17,8 +19,14 @@ type EngineResponse = {
}, },
} }
const { $t } = useI18n({
'connection-broken': { en: 'connection to server broken.', de: 'Verbindung zum Server ist unterbrochen.' },
'retrying': { en: 'retrying', de: 'verbinde erneut'},
})
export async function fetchUpdate(this: EngineContext) { export async function fetchUpdate(this: EngineContext) {
if (this.shouldStop || !this.isActive) { if (this.shouldStop || !this.isActive) {
useAlert().clearAlert()
this.isActive = false this.isActive = false
this.shouldStop = false this.shouldStop = false
console.debug('engine stopped') console.debug('engine stopped')
@ -41,6 +49,7 @@ export async function fetchUpdate(this: EngineContext) {
this.isConnected.value = true this.isConnected.value = true
this.retry.value = 0 this.retry.value = 0
useAlert().clearAlert()
useEngineStore().setJson(response) useEngineStore().setJson(response)
useGameinfoStore().setGameinfo(response.game) useGameinfoStore().setGameinfo(response.game)
useRoundStore().setRound(response.game.round) useRoundStore().setRound(response.game.round)
@ -57,6 +66,10 @@ export async function fetchUpdate(this: EngineContext) {
} catch (e: any) { } catch (e: any) {
this.isConnected.value = false this.isConnected.value = false
this.retry.value++ this.retry.value++
useAlert().setAlert([
$t('connection-broken'),
this.retry.value > 0 ? $t('retrying') + '...'.slice(0, this.retry.value % 4) : ''
])
if (e.response) { if (e.response) {
// callApi() threw an exception // callApi() threw an exception

View File

@ -1,5 +1,6 @@
import { useUserinfoStore } from "@/stores/UserinfoStore" import { useUserinfoStore } from "@/stores/UserinfoStore"
import { EngineContext } from '@/composables/useEngine' import { EngineContext } from '@/composables/useEngine'
import useAlert from '@/composables/useAlert'
export function start(this: EngineContext): void { export function start(this: EngineContext): void {
if (this.isActive && !this.shouldStop) { if (this.isActive && !this.shouldStop) {
@ -11,6 +12,7 @@ export function start(this: EngineContext): void {
return return
} }
useAlert().clearAlert()
this.isActive = true this.isActive = true
this.shouldStop = false this.shouldStop = false
this.isConnected.value = true this.isConnected.value = true
@ -21,6 +23,7 @@ export function start(this: EngineContext): void {
export function stop(this: EngineContext): void { export function stop(this: EngineContext): void {
if (this.isActive) { if (this.isActive) {
useAlert().clearAlert()
this.shouldStop = true this.shouldStop = true
this.isConnected.value = true this.isConnected.value = true
console.log('shut down engine') console.log('shut down engine')

View File

@ -0,0 +1,23 @@
import { Ref, ref } from 'vue'
export type AlertMessages = Array<string>
export interface useAlert {
setAlert(message: AlertMessages): void
clearAlert(): void
getAlertMessagesRef(): Ref<AlertMessages>
}
const alertMessages = ref([] as AlertMessages)
export default (): useAlert => {
return {
setAlert: (message: AlertMessages): void => {
alertMessages.value = message
},
clearAlert: ():void => {
alertMessages.value = []
},
getAlertMessagesRef: (): Ref<AlertMessages> => alertMessages
}
}

View File

@ -1,16 +1,22 @@
<template> <template>
<div class="layout-default"> <div class="layout-default">
<AlertBox v-if="alertMessages.length > 0">
<div v-for="msg in alertMessages" :key="msg">{{ msg }}</div>
</AlertBox>
<slot /> <slot />
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { useHead } from '#app' import { useHead } from '#app'
import useAlert from '@/composables/useAlert'
useHead({ useHead({
title: 'Know Your Teammates!', title: 'Know Your Teammates!',
charset: 'utf-8', charset: 'utf-8',
}) })
const alertMessages = useAlert().getAlertMessagesRef()
</script> </script>
<style lang="scss"> <style lang="scss">

View File

@ -1,16 +1,15 @@
<template> <template>
<div class="gamemaster__container"> <div class="gamemaster__container">
<TopBar /> <TopBar />
<AdminTile title="Info"> <AdminGameInfoTile />
<div class="gamemaster__info">... info ...</div>
</AdminTile>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { navigateTo } from '#app' import { navigateTo } from '#app'
import useAuth from '@/composables/useAuth'; import { onMounted, onBeforeUnmount } from 'vue'
import TopBar from '../components/TopBar.vue'; import useAuth from '@/composables/useAuth'
import useEngine from '@/composables/useEngine'
// ensure user is authenticated // ensure user is authenticated
const { authenticateAndLoadUserInfo } = useAuth() const { authenticateAndLoadUserInfo } = useAuth()
@ -19,6 +18,10 @@ try {
} catch (e) { } catch (e) {
navigateTo('/', { replace: true }) navigateTo('/', { replace: true })
} }
const { start: startEngine, stop: stopEngine } = useEngine()
onMounted(() => startEngine())
onBeforeUnmount(() => stopEngine())
</script> </script>
<style lang="scss"> <style lang="scss">

View File

@ -1,10 +1,6 @@
<template> <template>
<div class="page-play__container"> <div class="page-play__container">
<TopBar /> <TopBar />
<AlertBox v-if="!isConnected" mode="alert">
{{ $t('connection-broken') }}
<div v-if="retry >= 0">{{ $t('retrying') }} {{ '...'.slice(0, retry % 4) }}</div>
</AlertBox>
<div class="page-play__playfield-container"> <div class="page-play__playfield-container">
<div class="page-play__playfield-content"> <div class="page-play__playfield-content">
<Lobby v-if="game.state === 'idle'" /> <Lobby v-if="game.state === 'idle'" />
@ -20,17 +16,11 @@
<script setup lang="ts"> <script setup lang="ts">
import { navigateTo, useRoute } from '#app' import { navigateTo, useRoute } from '#app'
import { computed, onMounted, onBeforeUnmount } from 'vue'; import { computed, onMounted, onBeforeUnmount, watch } from 'vue';
import useAuth from '@/composables/useAuth'; import useAuth from '@/composables/useAuth';
import useEngine from '@/composables/useEngine'; import useEngine from '@/composables/useEngine';
import { useGameinfoStore } from "@/stores/GameinfoStore"
import useI18n from '@/composables/useI18n' import useI18n from '@/composables/useI18n'
import { useGameinfoStore } from "@/stores/GameinfoStore"
const { $t } = useI18n({
'connection-broken': { en: 'connection to server broken.', de: 'Verbindung zum Server ist unterbrochen.' },
'retrying': { en: 'retrying', de: 'verbinde erneut'},
})
// ensure user is authenticated // ensure user is authenticated
const { authenticateAndLoadUserInfo } = useAuth() const { authenticateAndLoadUserInfo } = useAuth()
@ -40,7 +30,7 @@ try {
navigateTo('/', { replace: true }) navigateTo('/', { replace: true })
} }
const { start: startEngine, stop: stopEngine, isConnected, retry } = useEngine() const { start: startEngine, stop: stopEngine } = useEngine()
onMounted(() => startEngine()) onMounted(() => startEngine())
onBeforeUnmount(() => stopEngine()) onBeforeUnmount(() => stopEngine())