feat: add create team dialog
This commit is contained in:
parent
2fb3833dd8
commit
c6f09831e3
@ -1,4 +1,15 @@
|
|||||||
<template>
|
<template>
|
||||||
|
<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')">
|
<ModalDialog @close="closeModalDialog" :title="$t('create-team')">
|
||||||
<div class="create-team-dialog__description">{{ $t('description') }}</div>
|
<div class="create-team-dialog__description">{{ $t('description') }}</div>
|
||||||
<div class="create-team-dialog__form">
|
<div class="create-team-dialog__form">
|
||||||
@ -11,7 +22,6 @@
|
|||||||
<option value="en">EN</option>
|
<option value="en">EN</option>
|
||||||
<option value="de">DE</option>
|
<option value="de">DE</option>
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<template v-slot:footer>
|
<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="true" @click="createTeam">{{ $t('create-team') }}</Button>
|
||||||
@ -19,10 +29,13 @@
|
|||||||
</template>
|
</template>
|
||||||
</ModalDialog>
|
</ModalDialog>
|
||||||
</template>
|
</template>
|
||||||
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, onMounted } from 'vue'
|
import { ref, onMounted } from 'vue'
|
||||||
import useI18n from '@/composables/useI18n'
|
import useI18n from '@/composables/useI18n'
|
||||||
|
import useEngine from '../composables/useEngine';
|
||||||
|
import LoginBox from './LoginBox.vue';
|
||||||
|
|
||||||
const emit = defineEmits(['close'])
|
const emit = defineEmits(['close'])
|
||||||
|
|
||||||
@ -34,19 +47,35 @@ const { $t, getLang } = useI18n({
|
|||||||
'team-name': { en: 'Team name', de: 'Teamname' },
|
'team-name': { en: 'Team name', de: 'Teamname' },
|
||||||
'language': { en: 'Language', de: 'Sprache' },
|
'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.' },
|
'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 closeModalDialog = () => { emit('close') }
|
||||||
const playerName = ref('')
|
const playerName = ref('')
|
||||||
const teamName = ref('')
|
const teamName = ref('')
|
||||||
const lang = ref(getLang())
|
const lang = ref(getLang())
|
||||||
|
const authcode = ref('')
|
||||||
|
|
||||||
const createTeam = () => {
|
const createTeam = async (): Promise<void> => {
|
||||||
if (playerName.value.length == 0 || teamName.value.length == 0) {
|
if (playerName.value.length == 0 || teamName.value.length == 0) {
|
||||||
alert($t('names-missing'))
|
alert($t('names-missing'))
|
||||||
return
|
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(() => {
|
onMounted(() => {
|
||||||
@ -90,5 +119,25 @@ onMounted(() => {
|
|||||||
&__button~&__button {
|
&__button~&__button {
|
||||||
margin-left: 16px;
|
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>
|
@ -3,7 +3,7 @@
|
|||||||
<div class="modal-dialog__box">
|
<div class="modal-dialog__box">
|
||||||
<div class="modal-dialog__header">
|
<div class="modal-dialog__header">
|
||||||
<div class="modal-dialog__title">{{ title }}</div>
|
<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>
|
||||||
<div class="modal-dialog__body">
|
<div class="modal-dialog__body">
|
||||||
<slot />
|
<slot />
|
||||||
@ -19,6 +19,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
defineProps<{
|
defineProps<{
|
||||||
title?: string
|
title?: string
|
||||||
|
noCloseButton?: boolean
|
||||||
}>()
|
}>()
|
||||||
const emit = defineEmits(['close'])
|
const emit = defineEmits(['close'])
|
||||||
</script>
|
</script>
|
||||||
@ -55,21 +56,21 @@ const emit = defineEmits(['close'])
|
|||||||
|
|
||||||
&__title {
|
&__title {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
margin: 16px 16px 8px 16px;
|
margin: 36px 36px 8px 36px;
|
||||||
font-family: $font-primary;
|
font-family: $font-primary;
|
||||||
font-size: 24px;
|
font-size: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__body {
|
&__body {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
margin: 16px;
|
margin: 36px;
|
||||||
font-family: $font-secondary;
|
font-family: $font-secondary;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__footer {
|
&__footer {
|
||||||
display: flex;
|
display: flex;
|
||||||
// justify-content: end;
|
// justify-content: end;
|
||||||
margin: 24px 16px;
|
margin: 24px 36px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__backdrop {
|
&__backdrop {
|
||||||
|
@ -1,21 +1,21 @@
|
|||||||
<template>
|
<template>
|
||||||
<ModalDialog :title="title" @close="emit('close')">
|
<ModalDialog :title="title" @close="emit('close')">
|
||||||
<label class="player-dialog__label">Name</label>
|
<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>
|
<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>
|
<label class="player-dialog__label">Authcode</label>
|
||||||
<div class="player-dialog__input-box">
|
<div class="player-dialog__input-box">
|
||||||
<input class="player-dialog__input" v-model="player.authcode" size="10" maxlength="6" />
|
<input class="player-dialog__input" v-model="player.authcode" size="40" maxlength="6" />
|
||||||
<Button :border="false" css-class="mini" @click="generate">generate</Button>
|
<Button class="player-dialog__generate" :border="false" css-class="mini" @click="generate">generate</Button>
|
||||||
</div>
|
</div>
|
||||||
<div class="player-dialog__id-container" @click="showId = true">
|
<div class="player-dialog__id-container" @click="showId = true">
|
||||||
<span class="player-dialog__id" :class="{ 'player-dialog__id__show': showId }">{{ player.id }}</span>
|
<span class="player-dialog__id" :class="{ 'player-dialog__id__show': showId }">{{ player.id }}</span>
|
||||||
</div>
|
</div>
|
||||||
<template v-slot:footer>
|
<template v-slot:footer>
|
||||||
<Button v-for="button in buttons" :key="button.id" class="player-dialog__button"
|
<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"
|
:css-class="button.type === 'caution' ? button.type : ''"
|
||||||
@click="emit('submit', button.id)">{{ button.name
|
:border="['primary', 'caution'].indexOf(button.type) >= 0" @click="emit('submit', button.id)">{{ button.name
|
||||||
}}</Button>
|
}}</Button>
|
||||||
</template>
|
</template>
|
||||||
</ModalDialog>
|
</ModalDialog>
|
||||||
@ -76,6 +76,14 @@ const generate = () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&__input-box {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__generate {
|
||||||
|
margin-left: auto;
|
||||||
|
}
|
||||||
|
|
||||||
&__button~&__button {
|
&__button~&__button {
|
||||||
margin-left: 16px;
|
margin-left: 16px;
|
||||||
}
|
}
|
||||||
|
@ -29,8 +29,9 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, ref } from 'vue'
|
import { computed, ref } from 'vue'
|
||||||
import useI18n from '@/composables/useI18n'
|
import useI18n from '@/composables/useI18n'
|
||||||
import useDateFormatter from '@/composables/useDateFormatter';
|
import useDateFormatter from '@/composables/useDateFormatter'
|
||||||
import useEngine from '@/composables/useEngine';
|
import useEngine from '@/composables/useEngine'
|
||||||
|
import { useUserinfoStore } from "@/stores/UserinfoStore"
|
||||||
import type { GameInfo, PlayerEdit } from '@/composables/engine.d'
|
import type { GameInfo, PlayerEdit } from '@/composables/engine.d'
|
||||||
import type { Button, ButtonAction } from '@/components/admin/PlayerModal'
|
import type { Button, ButtonAction } from '@/components/admin/PlayerModal'
|
||||||
|
|
||||||
@ -70,13 +71,17 @@ const addPlayer = () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const user = useUserinfoStore()
|
||||||
|
|
||||||
const editPlayer = async (player: PlayerEdit): Promise<void> => {
|
const editPlayer = async (player: PlayerEdit): Promise<void> => {
|
||||||
showPlayerDialog.value = true
|
showPlayerDialog.value = true
|
||||||
playerDialogTitle.value = 'Edit player'
|
playerDialogTitle.value = 'Edit player'
|
||||||
playerDialogButtons.value = [
|
playerDialogButtons.value = [
|
||||||
{ id: 'edit', name: 'Save', type: 'primary' },
|
{ 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 = {
|
playerDialogPlayer.value = {
|
||||||
...player,
|
...player,
|
||||||
}
|
}
|
||||||
|
5
client/src/composables/engine.d.ts
vendored
5
client/src/composables/engine.d.ts
vendored
@ -75,3 +75,8 @@ export type GameInfo = {
|
|||||||
numQuotesLeft: number
|
numQuotesLeft: number
|
||||||
numQuotesTotal: number
|
numQuotesTotal: number
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type CreateGameStatus = {
|
||||||
|
status: string
|
||||||
|
authcode: string
|
||||||
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { EngineContext } from '@/composables/useEngine'
|
import { EngineContext } from '@/composables/useEngine'
|
||||||
import type { GameInfo, PlayerEdit } from '@/composables/engine.d'
|
|
||||||
import { useUserinfoStore } from "@/stores/UserinfoStore"
|
import { useUserinfoStore } from "@/stores/UserinfoStore"
|
||||||
|
import type { GameInfo, PlayerEdit, Lang, CreateGameStatus } from '@/composables/engine.d'
|
||||||
|
|
||||||
export async function fetchGameInfo(this: EngineContext): Promise<GameInfo> {
|
export async function fetchGameInfo(this: EngineContext): Promise<GameInfo> {
|
||||||
const userInfoStore = useUserinfoStore()
|
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
|
||||||
|
}
|
@ -3,10 +3,10 @@ import { callApi, QueryParams } from '@/composables/engine/callApi'
|
|||||||
import { start, stop } from '@/composables/engine/startStop'
|
import { start, stop } from '@/composables/engine/startStop'
|
||||||
import { fetchUpdate } from '@/composables/engine/fetchUpdate'
|
import { fetchUpdate } from '@/composables/engine/fetchUpdate'
|
||||||
import { loadQuotes, getQuotesRef, deleteQuote, saveQuote } from '@/composables/engine/quotes'
|
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 { collectQuotes, startGame, continueGame, resetGame, finishGame } from '@/composables/engine/gameState'
|
||||||
import { saveSelection } from '@/composables/engine/play'
|
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 {
|
export interface EngineContext {
|
||||||
isActive: boolean
|
isActive: boolean
|
||||||
@ -42,6 +42,7 @@ export interface useEngine {
|
|||||||
setGameName: (name: string) => Promise<void>
|
setGameName: (name: string) => Promise<void>
|
||||||
savePlayer: (player: PlayerEdit) => Promise<void>
|
savePlayer: (player: PlayerEdit) => Promise<void>
|
||||||
deletePlayer: (id: string) => Promise<void>
|
deletePlayer: (id: string) => Promise<void>
|
||||||
|
createGame: (name: string, teamname: string, lang: Lang) => Promise<CreateGameStatus>
|
||||||
}
|
}
|
||||||
|
|
||||||
export default (): useEngine => {
|
export default (): useEngine => {
|
||||||
@ -80,5 +81,6 @@ export default (): useEngine => {
|
|||||||
setGameName: (name: string) => setGameName.apply(context, [name]),
|
setGameName: (name: string) => setGameName.apply(context, [name]),
|
||||||
savePlayer: (player: PlayerEdit) => savePlayer.apply(context, [player]),
|
savePlayer: (player: PlayerEdit) => savePlayer.apply(context, [player]),
|
||||||
deletePlayer: (id: string) => deletePlayer.apply(context, [id]),
|
deletePlayer: (id: string) => deletePlayer.apply(context, [id]),
|
||||||
|
createGame: (name: string, teamname: string, lang: Lang) => createGame.apply(context, [name, teamname, lang]),
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user