twenty-one/src/components/JoinScreen.vue
2023-04-23 16:36:31 +02:00

97 lines
No EOL
2.4 KiB
Vue

<template>
<div class="flex flex-col h-full justify-center items-center gap-8 text-8xl">
<input
v-model="lobbyCodeInput"
class="uppercase bg-transparent text-white text-center font-fat tracking-wider focus:outline-none pb-2 rounded-lg transition"
:class="isUnknown ? 'bg-red-800' : ''"
:maxlength="LOBBY_CODE_LENGTH"
:placeholder="'X'.repeat(LOBBY_CODE_LENGTH)"
:style="{ width: `${LOBBY_CODE_LENGTH * 0.95}em` }"
@keypress="onKeypress"
/>
<button
class="uppercase font-bold text-4xl border border-white rounded-md bg-white bg-opacity-0 transition px-10 py-4"
:class="$style.button"
:disabled="lobbyCodeInput.length !== LOBBY_CODE_LENGTH"
@click="join()"
>
Join
</button>
<button
class="font-bold text-2xl border border-white rounded-md bg-white bg-opacity-0 transition px-6 py-2"
:class="$style.button"
@click="create()"
>
Create game
</button>
</div>
</template>
<style module lang="scss">
.button {
&:disabled {
cursor: not-allowed;
}
&:not(:disabled) {
@apply hover:bg-opacity-20;
}
}
</style>
<script setup lang="ts">
import { computed, ref, watch, watchEffect } from "vue"
import { useGame } from "../clientGame"
import { LOBBY_CODE_LENGTH } from "../shared/constants"
import { useBrowserLocation } from "@vueuse/core"
const location = useBrowserLocation()
const REGEX = new RegExp("^[a-zA-Z]*$")
const game = useGame()
const lobbyCodeInput = ref("")
const normalizedLobbyCode = computed(() => lobbyCodeInput.value.toUpperCase())
const isLoading = ref(false)
const isUnknown = ref(false)
watchEffect(() => {
const hash = (location.value.hash ?? "").slice(1)
if (REGEX.test(hash) && hash.length === LOBBY_CODE_LENGTH) {
lobbyCodeInput.value = hash
}
})
watch(lobbyCodeInput, () => {
isUnknown.value = false
})
function onKeypress(e: KeyboardEvent) {
if (e.key.length !== 1 || !REGEX.test(e.key)) {
e.preventDefault()
e.stopImmediatePropagation()
}
}
async function join() {
if (isLoading.value) return
isLoading.value = true
try {
await game.join(normalizedLobbyCode.value)
window.location.hash = normalizedLobbyCode.value
} catch (e: unknown) {
isUnknown.value = true
}
isLoading.value = false
}
async function create() {
if (isLoading.value) return
isLoading.value = true
const { lobbyCode } = await game.create()
lobbyCodeInput.value = lobbyCode
isLoading.value = false
await join()
}
</script>