mirror of
https://github.com/Pandipipas/scoreko-dev.git
synced 2026-06-06 03:32:06 +00:00
Add player filtering to scoreboard selects (#25)
* Add player filtering to scoreboard selects * Hide selected player while typing * Avoid duplicated text in player selects * Show selected player only when not typing
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue';
|
||||
import { computed, ref, watchEffect } from 'vue';
|
||||
import type { Schemas } from '../../../types';
|
||||
import { usePlayersStore } from '../stores/players';
|
||||
import { useScoreboardStore } from '../stores/scoreboard';
|
||||
@@ -7,6 +7,24 @@ import { useScoreboardStore } from '../stores/scoreboard';
|
||||
const playersStore = usePlayersStore();
|
||||
const scoreboardStore = useScoreboardStore();
|
||||
|
||||
const leftFilter = ref('');
|
||||
const rightFilter = ref('');
|
||||
const leftInput = ref('');
|
||||
const rightInput = ref('');
|
||||
const leftFocused = ref(false);
|
||||
const rightFocused = ref(false);
|
||||
|
||||
const filterOptions = (
|
||||
options: { label: string; value: string }[],
|
||||
needle: string,
|
||||
) => {
|
||||
if (!needle) {
|
||||
return options;
|
||||
}
|
||||
const lowerNeedle = needle.toLowerCase();
|
||||
return options.filter((option) => option.label.toLowerCase().includes(lowerNeedle));
|
||||
};
|
||||
|
||||
const playerOptions = computed(() => {
|
||||
const base = [{ label: '(Sin asignar)', value: '' }];
|
||||
const entries = Object.entries(playersStore.players) as [string, Schemas.Players[string]][];
|
||||
@@ -16,6 +34,73 @@ const playerOptions = computed(() => {
|
||||
}));
|
||||
return base.concat(options);
|
||||
});
|
||||
|
||||
const getPlayerLabel = (playerId: string) => {
|
||||
const match = playerOptions.value.find((option) => option.value === playerId);
|
||||
return match ? match.label : '';
|
||||
};
|
||||
|
||||
const leftPlayerOptions = computed(() => filterOptions(playerOptions.value, leftFilter.value));
|
||||
const rightPlayerOptions = computed(() => filterOptions(playerOptions.value, rightFilter.value));
|
||||
|
||||
const onLeftFilter = (val: string, update: (fn: () => void) => void) => {
|
||||
update(() => {
|
||||
leftFilter.value = val;
|
||||
leftInput.value = val;
|
||||
});
|
||||
};
|
||||
|
||||
const onRightFilter = (val: string, update: (fn: () => void) => void) => {
|
||||
update(() => {
|
||||
rightFilter.value = val;
|
||||
rightInput.value = val;
|
||||
});
|
||||
};
|
||||
|
||||
const onLeftFocus = () => {
|
||||
leftFocused.value = true;
|
||||
leftInput.value = '';
|
||||
};
|
||||
|
||||
const onLeftBlur = () => {
|
||||
leftFocused.value = false;
|
||||
leftFilter.value = '';
|
||||
leftInput.value = getPlayerLabel(scoreboardStore.scoreboard.leftPlayerId);
|
||||
};
|
||||
|
||||
const onRightFocus = () => {
|
||||
rightFocused.value = true;
|
||||
rightInput.value = '';
|
||||
};
|
||||
|
||||
const onRightBlur = () => {
|
||||
rightFocused.value = false;
|
||||
rightFilter.value = '';
|
||||
rightInput.value = getPlayerLabel(scoreboardStore.scoreboard.rightPlayerId);
|
||||
};
|
||||
|
||||
const onLeftSelect = () => {
|
||||
leftFilter.value = '';
|
||||
leftInput.value = getPlayerLabel(scoreboardStore.scoreboard.leftPlayerId);
|
||||
};
|
||||
|
||||
const onRightSelect = () => {
|
||||
rightFilter.value = '';
|
||||
rightInput.value = getPlayerLabel(scoreboardStore.scoreboard.rightPlayerId);
|
||||
};
|
||||
|
||||
watchEffect(() => {
|
||||
if (!leftFocused.value) {
|
||||
leftInput.value = getPlayerLabel(scoreboardStore.scoreboard.leftPlayerId);
|
||||
}
|
||||
});
|
||||
|
||||
watchEffect(() => {
|
||||
if (!rightFocused.value) {
|
||||
rightInput.value = getPlayerLabel(scoreboardStore.scoreboard.rightPlayerId);
|
||||
}
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -50,12 +135,21 @@ const playerOptions = computed(() => {
|
||||
<QCardSection>
|
||||
<QSelect
|
||||
v-model="scoreboardStore.scoreboard.leftPlayerId"
|
||||
:options="playerOptions"
|
||||
:options="leftPlayerOptions"
|
||||
label="Jugador"
|
||||
dense
|
||||
outlined
|
||||
emit-value
|
||||
map-options
|
||||
use-input
|
||||
input-debounce="0"
|
||||
hide-selected
|
||||
fill-input
|
||||
v-model:input-value="leftInput"
|
||||
@filter="onLeftFilter"
|
||||
@focus="onLeftFocus"
|
||||
@blur="onLeftBlur"
|
||||
@update:model-value="onLeftSelect"
|
||||
/>
|
||||
<QInput
|
||||
v-model="scoreboardStore.scoreboard.leftNameOverride"
|
||||
@@ -86,12 +180,21 @@ const playerOptions = computed(() => {
|
||||
<QCardSection>
|
||||
<QSelect
|
||||
v-model="scoreboardStore.scoreboard.rightPlayerId"
|
||||
:options="playerOptions"
|
||||
:options="rightPlayerOptions"
|
||||
label="Jugador"
|
||||
dense
|
||||
outlined
|
||||
emit-value
|
||||
map-options
|
||||
use-input
|
||||
input-debounce="0"
|
||||
hide-selected
|
||||
fill-input
|
||||
v-model:input-value="rightInput"
|
||||
@filter="onRightFilter"
|
||||
@focus="onRightFocus"
|
||||
@blur="onRightBlur"
|
||||
@update:model-value="onRightSelect"
|
||||
/>
|
||||
<QInput
|
||||
v-model="scoreboardStore.scoreboard.rightNameOverride"
|
||||
|
||||
Reference in New Issue
Block a user