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">
|
<script setup lang="ts">
|
||||||
import { computed } from 'vue';
|
import { computed, ref, watchEffect } from 'vue';
|
||||||
import type { Schemas } from '../../../types';
|
import type { Schemas } from '../../../types';
|
||||||
import { usePlayersStore } from '../stores/players';
|
import { usePlayersStore } from '../stores/players';
|
||||||
import { useScoreboardStore } from '../stores/scoreboard';
|
import { useScoreboardStore } from '../stores/scoreboard';
|
||||||
@@ -7,6 +7,24 @@ import { useScoreboardStore } from '../stores/scoreboard';
|
|||||||
const playersStore = usePlayersStore();
|
const playersStore = usePlayersStore();
|
||||||
const scoreboardStore = useScoreboardStore();
|
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 playerOptions = computed(() => {
|
||||||
const base = [{ label: '(Sin asignar)', value: '' }];
|
const base = [{ label: '(Sin asignar)', value: '' }];
|
||||||
const entries = Object.entries(playersStore.players) as [string, Schemas.Players[string]][];
|
const entries = Object.entries(playersStore.players) as [string, Schemas.Players[string]][];
|
||||||
@@ -16,6 +34,73 @@ const playerOptions = computed(() => {
|
|||||||
}));
|
}));
|
||||||
return base.concat(options);
|
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>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -50,12 +135,21 @@ const playerOptions = computed(() => {
|
|||||||
<QCardSection>
|
<QCardSection>
|
||||||
<QSelect
|
<QSelect
|
||||||
v-model="scoreboardStore.scoreboard.leftPlayerId"
|
v-model="scoreboardStore.scoreboard.leftPlayerId"
|
||||||
:options="playerOptions"
|
:options="leftPlayerOptions"
|
||||||
label="Jugador"
|
label="Jugador"
|
||||||
dense
|
dense
|
||||||
outlined
|
outlined
|
||||||
emit-value
|
emit-value
|
||||||
map-options
|
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
|
<QInput
|
||||||
v-model="scoreboardStore.scoreboard.leftNameOverride"
|
v-model="scoreboardStore.scoreboard.leftNameOverride"
|
||||||
@@ -86,12 +180,21 @@ const playerOptions = computed(() => {
|
|||||||
<QCardSection>
|
<QCardSection>
|
||||||
<QSelect
|
<QSelect
|
||||||
v-model="scoreboardStore.scoreboard.rightPlayerId"
|
v-model="scoreboardStore.scoreboard.rightPlayerId"
|
||||||
:options="playerOptions"
|
:options="rightPlayerOptions"
|
||||||
label="Jugador"
|
label="Jugador"
|
||||||
dense
|
dense
|
||||||
outlined
|
outlined
|
||||||
emit-value
|
emit-value
|
||||||
map-options
|
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
|
<QInput
|
||||||
v-model="scoreboardStore.scoreboard.rightNameOverride"
|
v-model="scoreboardStore.scoreboard.rightNameOverride"
|
||||||
|
|||||||
Reference in New Issue
Block a user