97 lines
No EOL
2.4 KiB
Vue
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> |