feat: add create team dialog

This commit is contained in:
Settel 2022-09-09 12:50:05 +02:00
parent 2fb3833dd8
commit c6f09831e3
7 changed files with 119 additions and 42 deletions

View File

@ -1,28 +1,41 @@
<template>
<ModalDialog @close="closeModalDialog" :title="$t('create-team')">
<div class="create-team-dialog__description">{{ $t('description') }}</div>
<div class="create-team-dialog__form">
<label class="create-team-dialog__label">{{ $t('your-name') }}</label>
<input id="create-team-dialog-name" class="create-team-dialog__input" v-model="playerName" size="40"/>
<label class="create-team-dialog__label">{{ $t('team-name') }}</label>
<input class="create-team-dialog__input" v-model="teamName" size="40"/>
<label class="create-team-dialog__label">{{ $t('language') }}</label>
<select class="create-team-dialog__select" v-model="lang">
<option value="en">EN</option>
<option value="de">DE</option>
</select>
</div>
<template v-slot:footer>
<Button class="create-team-dialog__button" :border="true" @click="createTeam">{{ $t('create-team') }}</Button>
<Button class="create-team-dialog__button" :border="false" @click="closeModalDialog">{{ $t('cancel') }}</Button>
</template>
</ModalDialog>
<template v-if="authcode">
<ModalDialog :no-close-button="true" @close="closeModalDialog">
<div class="create-team-dialog__auth-message">{{ $t('pin') }}</div>
<div class="create-team-dialog__pin">{{ authcode }}</div>
<div class="create-team-dialog__auth-message">{{ $t('remember-and-log-in') }}</div>
<div class="create-team-dialog__login-box">
<LoginBox />
</div>
</ModalDialog>
</template>
<template v-else>
<ModalDialog @close="closeModalDialog" :title="$t('create-team')">
<div class="create-team-dialog__description">{{ $t('description') }}</div>
<div class="create-team-dialog__form">
<label class="create-team-dialog__label">{{ $t('your-name') }}</label>
<input id="create-team-dialog-name" class="create-team-dialog__input" v-model="playerName" size="40" />
<label class="create-team-dialog__label">{{ $t('team-name') }}</label>
<input class="create-team-dialog__input" v-model="teamName" size="40" />
<label class="create-team-dialog__label">{{ $t('language') }}</label>
<select class="create-team-dialog__select" v-model="lang">
<option value="en">EN</option>
<option value="de">DE</option>
</select>
</div>
<template v-slot:footer>
<Button class="create-team-dialog__button" :border="true" @click="createTeam">{{ $t('create-team') }}</Button>
<Button class="create-team-dialog__button" :border="false" @click="closeModalDialog">{{ $t('cancel') }}</Button>
</template>
</ModalDialog>
</template>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue'
import useI18n from '@/composables/useI18n'
import useEngine from '../composables/useEngine';
import LoginBox from './LoginBox.vue';
const emit = defineEmits(['close'])
@ -34,19 +47,35 @@ const { $t, getLang } = useI18n({
'team-name': { en: 'Team name', de: 'Teamname' },
'language': { en: 'Language', de: 'Sprache' },
'names-missing': { en: 'Please enter a user name and a team name.', de: 'Bitte wähle einen Benutzernamen und Teamnamen.' },
'failed-to-create': { en: 'Failed to create team, sorry. Please contact Settel to investigate.', de: 'Team konnte nicht angelegt werden. Bitte kontaktiere Settel zur genaueren Untersuchung.' },
'pin': { en: 'Your pin code is:', de: 'Deine PIN lautet:' },
'remember-and-log-in': { en: 'Write it down now, then log in with your pin code.', de: 'Schreibe sie Dir gleich auf und logge dich anschließend damit ein.' },
})
const closeModalDialog = () => { emit('close') }
const playerName = ref('')
const teamName = ref('')
const lang = ref(getLang())
const authcode = ref('')
const createTeam = () => {
const createTeam = async (): Promise<void> => {
if (playerName.value.length == 0 || teamName.value.length == 0) {
alert($t('names-missing'))
return
}
alert('not yet implemented')
const status = await useEngine().createGame(
playerName.value,
teamName.value,
lang.value,
)
if (status.status !== 'ok') {
alert($t('failed-to-create'))
return
}
authcode.value = status.authcode
}
onMounted(() => {
@ -90,5 +119,25 @@ onMounted(() => {
&__button~&__button {
margin-left: 16px;
}
&__auth-message {
font-family: $font-secondary;
font-size: 24px;
text-align: center;
margin: 32px;
}
&__pin {
font-family: $font-secondary;
font-size: 32px;
font-weight: 800;
text-align: center;
}
&__login-box {
display: flex;
margin-top: 96px;
justify-content: center;
}
}
</style>
</style>

View File

@ -3,7 +3,7 @@
<div class="modal-dialog__box">
<div class="modal-dialog__header">
<div class="modal-dialog__title">{{ title }}</div>
<Button :border="false" @click="emit('close')">x</Button>
<Button v-if="!noCloseButton" :border="false" @click="emit('close')">x</Button>
</div>
<div class="modal-dialog__body">
<slot />
@ -19,6 +19,7 @@
<script setup lang="ts">
defineProps<{
title?: string
noCloseButton?: boolean
}>()
const emit = defineEmits(['close'])
</script>
@ -55,21 +56,21 @@ const emit = defineEmits(['close'])
&__title {
flex-grow: 1;
margin: 16px 16px 8px 16px;
margin: 36px 36px 8px 36px;
font-family: $font-primary;
font-size: 24px;
}
&__body {
flex-grow: 1;
margin: 16px;
margin: 36px;
font-family: $font-secondary;
}
&__footer {
display: flex;
// justify-content: end;
margin: 24px 16px;
margin: 24px 36px;
}
&__backdrop {

View File

@ -1,21 +1,21 @@
<template>
<ModalDialog :title="title" @close="emit('close')">
<label class="player-dialog__label">Name</label>
<input id="player-dialog-name" class="player-dialog__input" v-model="player.name" size="40"/>
<input id="player-dialog-name" class="player-dialog__input" v-model="player.name" size="60" />
<label class="player-dialog__label">Score</label>
<input class="player-dialog__input" v-model="player.score" size="40" maxlength="4" />
<input class="player-dialog__input" v-model="player.score" size="60" maxlength="4" />
<label class="player-dialog__label">Authcode</label>
<div class="player-dialog__input-box">
<input class="player-dialog__input" v-model="player.authcode" size="10" maxlength="6" />
<Button :border="false" css-class="mini" @click="generate">generate</Button>
<input class="player-dialog__input" v-model="player.authcode" size="40" maxlength="6" />
<Button class="player-dialog__generate" :border="false" css-class="mini" @click="generate">generate</Button>
</div>
<div class="player-dialog__id-container" @click="showId = true">
<span class="player-dialog__id" :class="{ 'player-dialog__id__show': showId }">{{ player.id }}</span>
</div>
<template v-slot:footer>
<Button v-for="button in buttons" :key="button.id" class="player-dialog__button"
:css-class="button.type === 'caution' ? button.type : ''" :border="['primary', 'caution'].indexOf(button.type) >= 0"
@click="emit('submit', button.id)">{{ button.name
:css-class="button.type === 'caution' ? button.type : ''"
:border="['primary', 'caution'].indexOf(button.type) >= 0" @click="emit('submit', button.id)">{{ button.name
}}</Button>
</template>
</ModalDialog>
@ -34,7 +34,7 @@ const props = defineProps<{
const emit = defineEmits(['close', 'submit'])
const showId = ref(false)
onMounted(() => {
onMounted(() => {
window.setTimeout(() => {
document.getElementById('player-dialog-name')?.focus()
}, 0)
@ -76,6 +76,14 @@ const generate = () => {
}
}
&__input-box {
display: flex;
}
&__generate {
margin-left: auto;
}
&__button~&__button {
margin-left: 16px;
}

View File

@ -29,8 +29,9 @@
<script setup lang="ts">
import { computed, ref } from 'vue'
import useI18n from '@/composables/useI18n'
import useDateFormatter from '@/composables/useDateFormatter';
import useEngine from '@/composables/useEngine';
import useDateFormatter from '@/composables/useDateFormatter'
import useEngine from '@/composables/useEngine'
import { useUserinfoStore } from "@/stores/UserinfoStore"
import type { GameInfo, PlayerEdit } from '@/composables/engine.d'
import type { Button, ButtonAction } from '@/components/admin/PlayerModal'
@ -70,13 +71,17 @@ const addPlayer = () => {
}
}
const user = useUserinfoStore()
const editPlayer = async (player: PlayerEdit): Promise<void> => {
showPlayerDialog.value = true
playerDialogTitle.value = 'Edit player'
playerDialogButtons.value =[
playerDialogButtons.value = [
{ id: 'edit', name: 'Save', type: 'primary' },
{ id: 'delete', name: 'Delete', type: 'caution' },
]
if (player.id != user.id) {
playerDialogButtons.value.push({ id: 'delete', name: 'Delete', type: 'caution' })
}
playerDialogPlayer.value = {
...player,
}

View File

@ -74,4 +74,9 @@ export type GameInfo = {
players: Array<PlayersExtended>
numQuotesLeft: number
numQuotesTotal: number
}
}
export type CreateGameStatus = {
status: string
authcode: string
}

View File

@ -1,6 +1,6 @@
import { EngineContext } from '@/composables/useEngine'
import type { GameInfo, PlayerEdit } from '@/composables/engine.d'
import { useUserinfoStore } from "@/stores/UserinfoStore"
import type { GameInfo, PlayerEdit, Lang, CreateGameStatus } from '@/composables/engine.d'
export async function fetchGameInfo(this: EngineContext): Promise<GameInfo> {
const userInfoStore = useUserinfoStore()
@ -44,3 +44,10 @@ export async function deletePlayer(this: EngineContext, id: string): Promise<voi
})
}
export async function createGame(this: EngineContext, name: string, teamname: string, lang: Lang): Promise<CreateGameStatus> {
return await this.callApi('/api/createGame', {
name,
teamname,
lang,
}) as CreateGameStatus
}

View File

@ -3,10 +3,10 @@ import { callApi, QueryParams } from '@/composables/engine/callApi'
import { start, stop } from '@/composables/engine/startStop'
import { fetchUpdate } from '@/composables/engine/fetchUpdate'
import { loadQuotes, getQuotesRef, deleteQuote, saveQuote } from '@/composables/engine/quotes'
import { fetchGameInfo, setGameLang, setGameName, savePlayer, deletePlayer } from '@/composables/engine/gamemaster'
import { fetchGameInfo, setGameLang, setGameName, savePlayer, deletePlayer, createGame } from '@/composables/engine/gameManagement'
import { collectQuotes, startGame, continueGame, resetGame, finishGame } from '@/composables/engine/gameState'
import { saveSelection } from '@/composables/engine/play'
import type { Quotes, GameInfo, PlayerEdit } from '@/composables/engine.d'
import type { Quotes, GameInfo, PlayerEdit, Lang, CreateGameStatus } from '@/composables/engine.d'
export interface EngineContext {
isActive: boolean
@ -42,6 +42,7 @@ export interface useEngine {
setGameName: (name: string) => Promise<void>
savePlayer: (player: PlayerEdit) => Promise<void>
deletePlayer: (id: string) => Promise<void>
createGame: (name: string, teamname: string, lang: Lang) => Promise<CreateGameStatus>
}
export default (): useEngine => {
@ -80,5 +81,6 @@ export default (): useEngine => {
setGameName: (name: string) => setGameName.apply(context, [name]),
savePlayer: (player: PlayerEdit) => savePlayer.apply(context, [player]),
deletePlayer: (id: string) => deletePlayer.apply(context, [id]),
createGame: (name: string, teamname: string, lang: Lang) => createGame.apply(context, [name, teamname, lang]),
}
}
}