feat: add gamemaster page (WIP)
This commit is contained in:
parent
6b1316d3ef
commit
cab1a91cc2
@ -6,9 +6,6 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import '~/assets/css/components';
|
||||
|
||||
@ -31,6 +28,7 @@
|
||||
border-radius: 10px;
|
||||
background-color: $alert-background-color;
|
||||
font-size: 24px;
|
||||
color: $text-primary-color;
|
||||
}
|
||||
}
|
||||
</style>
|
@ -18,7 +18,7 @@ defineProps<{
|
||||
|
||||
.admin-tile {
|
||||
&__container {
|
||||
width: 360px;
|
||||
width: 300px;
|
||||
margin: 40px;
|
||||
padding: 16px 30px;
|
||||
background-color: $admin-tile-background-color;
|
45
client/src/components/admin/GameInfoTile.vue
Normal file
45
client/src/components/admin/GameInfoTile.vue
Normal 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>
|
33
client/src/components/admin/PlayersTile.vue
Normal file
33
client/src/components/admin/PlayersTile.vue
Normal 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>
|
@ -4,6 +4,8 @@ import { useGameinfoStore } from "@/stores/GameinfoStore"
|
||||
import { useRoundStore } from "@/stores/RoundStore"
|
||||
import { usePlayersStore } from "@/stores/PlayersStore"
|
||||
import { EngineContext } from '@/composables/useEngine'
|
||||
import useAlert from '@/composables/useAlert'
|
||||
import useI18n from '@/composables/useI18n'
|
||||
|
||||
type EngineResponse = {
|
||||
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) {
|
||||
if (this.shouldStop || !this.isActive) {
|
||||
useAlert().clearAlert()
|
||||
this.isActive = false
|
||||
this.shouldStop = false
|
||||
console.debug('engine stopped')
|
||||
@ -41,6 +49,7 @@ export async function fetchUpdate(this: EngineContext) {
|
||||
this.isConnected.value = true
|
||||
this.retry.value = 0
|
||||
|
||||
useAlert().clearAlert()
|
||||
useEngineStore().setJson(response)
|
||||
useGameinfoStore().setGameinfo(response.game)
|
||||
useRoundStore().setRound(response.game.round)
|
||||
@ -57,6 +66,10 @@ export async function fetchUpdate(this: EngineContext) {
|
||||
} catch (e: any) {
|
||||
this.isConnected.value = false
|
||||
this.retry.value++
|
||||
useAlert().setAlert([
|
||||
$t('connection-broken'),
|
||||
this.retry.value > 0 ? $t('retrying') + '...'.slice(0, this.retry.value % 4) : ''
|
||||
])
|
||||
|
||||
if (e.response) {
|
||||
// callApi() threw an exception
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { useUserinfoStore } from "@/stores/UserinfoStore"
|
||||
import { EngineContext } from '@/composables/useEngine'
|
||||
import useAlert from '@/composables/useAlert'
|
||||
|
||||
export function start(this: EngineContext): void {
|
||||
if (this.isActive && !this.shouldStop) {
|
||||
@ -11,6 +12,7 @@ export function start(this: EngineContext): void {
|
||||
return
|
||||
}
|
||||
|
||||
useAlert().clearAlert()
|
||||
this.isActive = true
|
||||
this.shouldStop = false
|
||||
this.isConnected.value = true
|
||||
@ -21,6 +23,7 @@ export function start(this: EngineContext): void {
|
||||
|
||||
export function stop(this: EngineContext): void {
|
||||
if (this.isActive) {
|
||||
useAlert().clearAlert()
|
||||
this.shouldStop = true
|
||||
this.isConnected.value = true
|
||||
console.log('shut down engine')
|
||||
|
23
client/src/composables/useAlert.ts
Normal file
23
client/src/composables/useAlert.ts
Normal 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
|
||||
}
|
||||
}
|
@ -1,16 +1,22 @@
|
||||
<template>
|
||||
<div class="layout-default">
|
||||
<AlertBox v-if="alertMessages.length > 0">
|
||||
<div v-for="msg in alertMessages" :key="msg">{{ msg }}</div>
|
||||
</AlertBox>
|
||||
<slot />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useHead } from '#app'
|
||||
import useAlert from '@/composables/useAlert'
|
||||
|
||||
useHead({
|
||||
title: 'Know Your Teammates!',
|
||||
charset: 'utf-8',
|
||||
})
|
||||
|
||||
const alertMessages = useAlert().getAlertMessagesRef()
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
|
@ -1,16 +1,15 @@
|
||||
<template>
|
||||
<div class="gamemaster__container">
|
||||
<TopBar />
|
||||
<AdminTile title="Info">
|
||||
<div class="gamemaster__info">... info ...</div>
|
||||
</AdminTile>
|
||||
</div>
|
||||
<AdminGameInfoTile />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { navigateTo } from '#app'
|
||||
import useAuth from '@/composables/useAuth';
|
||||
import TopBar from '../components/TopBar.vue';
|
||||
import { onMounted, onBeforeUnmount } from 'vue'
|
||||
import useAuth from '@/composables/useAuth'
|
||||
import useEngine from '@/composables/useEngine'
|
||||
|
||||
// ensure user is authenticated
|
||||
const { authenticateAndLoadUserInfo } = useAuth()
|
||||
@ -19,6 +18,10 @@ try {
|
||||
} catch (e) {
|
||||
navigateTo('/', { replace: true })
|
||||
}
|
||||
|
||||
const { start: startEngine, stop: stopEngine } = useEngine()
|
||||
onMounted(() => startEngine())
|
||||
onBeforeUnmount(() => stopEngine())
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
|
@ -1,10 +1,6 @@
|
||||
<template>
|
||||
<div class="page-play__container">
|
||||
<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-content">
|
||||
<Lobby v-if="game.state === 'idle'" />
|
||||
@ -20,17 +16,11 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { navigateTo, useRoute } from '#app'
|
||||
import { computed, onMounted, onBeforeUnmount } from 'vue';
|
||||
import { computed, onMounted, onBeforeUnmount, watch } from 'vue';
|
||||
import useAuth from '@/composables/useAuth';
|
||||
import useEngine from '@/composables/useEngine';
|
||||
import { useGameinfoStore } from "@/stores/GameinfoStore"
|
||||
import useI18n from '@/composables/useI18n'
|
||||
|
||||
const { $t } = useI18n({
|
||||
'connection-broken': { en: 'connection to server broken.', de: 'Verbindung zum Server ist unterbrochen.' },
|
||||
'retrying': { en: 'retrying', de: 'verbinde erneut'},
|
||||
})
|
||||
|
||||
import { useGameinfoStore } from "@/stores/GameinfoStore"
|
||||
|
||||
// ensure user is authenticated
|
||||
const { authenticateAndLoadUserInfo } = useAuth()
|
||||
@ -40,7 +30,7 @@ try {
|
||||
navigateTo('/', { replace: true })
|
||||
}
|
||||
|
||||
const { start: startEngine, stop: stopEngine, isConnected, retry } = useEngine()
|
||||
const { start: startEngine, stop: stopEngine } = useEngine()
|
||||
onMounted(() => startEngine())
|
||||
onBeforeUnmount(() => stopEngine())
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user