You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
81 lines
1.9 KiB
Vue
81 lines
1.9 KiB
Vue
<script setup lang="ts">
|
|
import { ref, computed } from 'vue'
|
|
|
|
export interface Props {
|
|
solution: string
|
|
}
|
|
type Status = 'red' | 'yellow' | 'green'
|
|
|
|
const props = defineProps<Props>()
|
|
const emit = defineEmits<{
|
|
(e: 'success'): void
|
|
}>()
|
|
const scrollElement = ref<null | HTMLDivElement>(null)
|
|
|
|
const history = ref<{ status: Status, letter: string }[][]>([])
|
|
const input = ref<string>('')
|
|
let success = false
|
|
|
|
function addInput(key: string) {
|
|
if (input.value.length < props.solution.length) {
|
|
input.value = `${input.value}${event.key}`
|
|
}
|
|
}
|
|
|
|
function removeInput() {
|
|
if (input.value.length === 0) return
|
|
input.value = input.value.slice(0, -1)
|
|
}
|
|
|
|
function submit() {
|
|
if (input.value.length < props.solution.length) return
|
|
|
|
if (input.value.toLowerCase() === props.solution) {
|
|
success = true
|
|
emit('success')
|
|
return
|
|
}
|
|
|
|
const letters = input.value.split('')
|
|
const newHistoryEntry = letters.map((letter, i) => {
|
|
letter = letter.toLowerCase()
|
|
const entry = { status: 'red', letter }
|
|
|
|
if (props.solution.indexOf(letter) === i) entry.status = 'green'
|
|
else if (props.solution.indexOf(letter) >= 0) entry.status = 'yellow'
|
|
|
|
return entry
|
|
})
|
|
|
|
history.value.push(newHistoryEntry)
|
|
input.value = ''
|
|
if (scrollElement.value) scrollElement.value.scrollIntoView()
|
|
}
|
|
|
|
function keyHandler ({ key }) {
|
|
if (success) return
|
|
if (key === 'Enter') submit()
|
|
else if (key === 'Backspace') removeInput()
|
|
else if (key.toLowerCase().match(/^[a-z0-9]$/)) addInput(key)
|
|
}
|
|
|
|
document.removeEventListener('keydown', keyHandler)
|
|
document.addEventListener('keydown', keyHandler)
|
|
|
|
</script>
|
|
|
|
<template>
|
|
<div class="history" v-for="word in history">
|
|
<div v-for="{ letter, status } in word" :class="['letter', status]">
|
|
{{ letter }}
|
|
</div>
|
|
</div>
|
|
|
|
<div class="input">
|
|
<div v-for="(_, i) in solution.length" class="letter">
|
|
{{ input[i] ?? '' }}
|
|
</div>
|
|
</div>
|
|
<div ref="scrollElement"> </div>
|
|
</template>
|