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

<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">&nbsp;</div>
</template>