mirror of
https://github.com/Pandipipas/scoreko-dev.git
synced 2026-06-06 03:32:06 +00:00
Agregar BracketPanel para selección de ronda y reubicar detalles en el dashboard (#22)
* Add bracket panel for round details * Agregar BracketPanel para selección de ronda y reubicar detalles en el dashboard ### Motivation - Separar y enriquecer el control de "Detalles de la ronda" en su propio panel para permitir selección de Stage, Bracket side o texto Custom. - Mover la UI de ronda fuera de `ScoreboardPanel` para mantenerlo enfocado en jugadores y puntuaciones y colocar el nuevo `BracketPanel` a la derecha en el dashboard. - No se empleó ninguna skill de `/opt/codex/skills`; los cambios se hicieron directamente sobre los componentes existentes. ### Description - Se añadió `src/dashboard/example/components/BracketPanel.vue` con opciones de `Stage` (pools, top 128, ..., Grand Final Reset), `Bracket side` (None/Winners/Loosers) y modo `Custom` activable mediante `QBtnToggle`, y lógica para parsear/actualizar `scoreboard.round` en el store. - Se eliminó el bloque de "Detalles de la ronda" de `src/dashboard/example/components/ScoreboardPanel.vue` para evitar duplicidad y mantener responsabilidad única. - Se actualizó `src/dashboard/example/views/Dashboard.vue` para mostrar `ScoreboardPanel` y `BracketPanel` lado a lado dentro de tarjetas y ajustar estilos de layout. ### Testing - Se levantó el servidor de desarrollo con `npx vite --host 0.0.0.0 --port 5173` y `vite` reportó inputs escritos y el servidor listo; `vue-tsc` devolvió `Found 0 errors`, por lo que el proyecto se inspeccionó sin errores de tipo. - Se tomó una captura automática del dashboard mediante Playwright y el script guardó `artifacts/dashboard-bracket-panel.png` exitosamente. - Los comandos de commit se ejecutaron y los cambios fueron registrados en el repositorio sin errores. * Agregar BracketPanel para selección de ronda y reubicar detalles en el dashboard ### Motivation - Separar y enriquecer el control de "Detalles de la ronda" en su propio panel para permitir selección de Stage, Bracket side o texto Custom. - Mover la UI de ronda fuera de `ScoreboardPanel` para mantenerlo enfocado en jugadores y puntuaciones y colocar el nuevo `BracketPanel` a la derecha en el dashboard. - No se empleó ninguna skill de `/opt/codex/skills`; los cambios se hicieron directamente sobre los componentes existentes. ### Description - Se añadió `src/dashboard/example/components/BracketPanel.vue` con opciones de `Stage` (pools, top 128, ..., Grand Final Reset), `Bracket side` (None/Winners/Loosers) y modo `Custom` activable mediante `QBtnToggle`, y lógica para parsear/actualizar `scoreboard.round` en el store. - Se eliminó el bloque de "Detalles de la ronda" de `src/dashboard/example/components/ScoreboardPanel.vue` para evitar duplicidad y mantener responsabilidad única. - Se actualizó `src/dashboard/example/views/Dashboard.vue` para mostrar `ScoreboardPanel` y `BracketPanel` lado a lado dentro de tarjetas y ajustar estilos de layout. ### Testing - Se levantó el servidor de desarrollo con `npx vite --host 0.0.0.0 --port 5173` y `vite` reportó inputs escritos y el servidor listo; `vue-tsc` devolvió `Found 0 errors`, por lo que el proyecto se inspeccionó sin errores de tipo. - Se tomó una captura automática del dashboard mediante Playwright y el script guardó `artifacts/dashboard-bracket-panel.png` exitosamente. - Los comandos de commit se ejecutaron y los cambios fueron registrados en el repositorio sin errores. * Agregar BracketPanel para selección de ronda y reubicar detalles en el dashboard ### Motivation - Separar y enriquecer el control de "Detalles de la ronda" en su propio panel para permitir selección de Stage, Bracket side o texto Custom. - Mover la UI de ronda fuera de `ScoreboardPanel` para mantenerlo enfocado en jugadores y puntuaciones y colocar el nuevo `BracketPanel` a la derecha en el dashboard. - No se empleó ninguna skill de `/opt/codex/skills`; los cambios se hicieron directamente sobre los componentes existentes. ### Description - Se añadió `src/dashboard/example/components/BracketPanel.vue` con opciones de `Stage` (pools, top 128, ..., Grand Final Reset), `Bracket side` (None/Winners/Loosers) y modo `Custom` activable mediante `QBtnToggle`, y lógica para parsear/actualizar `scoreboard.round` en el store. - Se eliminó el bloque de "Detalles de la ronda" de `src/dashboard/example/components/ScoreboardPanel.vue` para evitar duplicidad y mantener responsabilidad única. - Se actualizó `src/dashboard/example/views/Dashboard.vue` para mostrar `ScoreboardPanel` y `BracketPanel` lado a lado dentro de tarjetas y ajustar estilos de layout. ### Testing - Se levantó el servidor de desarrollo con `npx vite --host 0.0.0.0 --port 5173` y `vite` reportó inputs escritos y el servidor listo; `vue-tsc` devolvió `Found 0 errors`, por lo que el proyecto se inspeccionó sin errores de tipo. - Se tomó una captura automática del dashboard mediante Playwright y el script guardó `artifacts/dashboard-bracket-panel.png` exitosamente. - Los comandos de commit se ejecutaron y los cambios fueron registrados en el repositorio sin errores. * Agregar BracketPanel para selección de ronda y reubicar detalles en el dashboard ### Motivation - Separar y enriquecer el control de "Detalles de la ronda" en su propio panel para permitir selección de Stage, Bracket side o texto Custom. - Mover la UI de ronda fuera de `ScoreboardPanel` para mantenerlo enfocado en jugadores y puntuaciones y colocar el nuevo `BracketPanel` a la derecha en el dashboard. - No se empleó ninguna skill de `/opt/codex/skills`; los cambios se hicieron directamente sobre los componentes existentes. ### Description - Se añadió `src/dashboard/example/components/BracketPanel.vue` con opciones de `Stage` (pools, top 128, ..., Grand Final Reset), `Bracket side` (None/Winners/Loosers) y modo `Custom` activable mediante `QBtnToggle`, y lógica para parsear/actualizar `scoreboard.round` en el store. - Se eliminó el bloque de "Detalles de la ronda" de `src/dashboard/example/components/ScoreboardPanel.vue` para evitar duplicidad y mantener responsabilidad única. - Se actualizó `src/dashboard/example/views/Dashboard.vue` para mostrar `ScoreboardPanel` y `BracketPanel` lado a lado dentro de tarjetas y ajustar estilos de layout. ### Testing - Se levantó el servidor de desarrollo con `npx vite --host 0.0.0.0 --port 5173` y `vite` reportó inputs escritos y el servidor listo; `vue-tsc` devolvió `Found 0 errors`, por lo que el proyecto se inspeccionó sin errores de tipo. - Se tomó una captura automática del dashboard mediante Playwright y el script guardó `artifacts/dashboard-bracket-panel.png` exitosamente. - Los comandos de commit se ejecutaron y los cambios fueron registrados en el repositorio sin errores. * Agregar BracketPanel para selección de ronda y reubicar detalles en el dashboard ### Motivation - Separar y enriquecer el control de "Detalles de la ronda" en su propio panel para permitir selección de Stage, Bracket side o texto Custom. - Mover la UI de ronda fuera de `ScoreboardPanel` para mantenerlo enfocado en jugadores y puntuaciones y colocar el nuevo `BracketPanel` a la derecha en el dashboard. - No se empleó ninguna skill de `/opt/codex/skills`; los cambios se hicieron directamente sobre los componentes existentes. ### Description - Se añadió `src/dashboard/example/components/BracketPanel.vue` con opciones de `Stage` (pools, top 128, ..., Grand Final Reset), `Bracket side` (None/Winners/Loosers) y modo `Custom` activable mediante `QBtnToggle`, y lógica para parsear/actualizar `scoreboard.round` en el store. - Se eliminó el bloque de "Detalles de la ronda" de `src/dashboard/example/components/ScoreboardPanel.vue` para evitar duplicidad y mantener responsabilidad única. - Se actualizó `src/dashboard/example/views/Dashboard.vue` para mostrar `ScoreboardPanel` y `BracketPanel` lado a lado dentro de tarjetas y ajustar estilos de layout. ### Testing - Se levantó el servidor de desarrollo con `npx vite --host 0.0.0.0 --port 5173` y `vite` reportó inputs escritos y el servidor listo; `vue-tsc` devolvió `Found 0 errors`, por lo que el proyecto se inspeccionó sin errores de tipo. - Se tomó una captura automática del dashboard mediante Playwright y el script guardó `artifacts/dashboard-bracket-panel.png` exitosamente. - Los comandos de commit se ejecutaron y los cambios fueron registrados en el repositorio sin errores.
This commit is contained in:
@@ -0,0 +1,176 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { onMounted, ref, watch } from 'vue';
|
||||||
|
import { useScoreboardStore } from '../stores/scoreboard';
|
||||||
|
|
||||||
|
const scoreboardStore = useScoreboardStore();
|
||||||
|
|
||||||
|
const stageOptions = [
|
||||||
|
'pools',
|
||||||
|
'top 128',
|
||||||
|
'top 96',
|
||||||
|
'top 64',
|
||||||
|
'top 48',
|
||||||
|
'top 32',
|
||||||
|
'top 16',
|
||||||
|
'top 8',
|
||||||
|
'top 4',
|
||||||
|
'Quarter Final',
|
||||||
|
'Semi Final',
|
||||||
|
'Final',
|
||||||
|
'Grand Final',
|
||||||
|
'Grand Final Reset',
|
||||||
|
];
|
||||||
|
|
||||||
|
const bracketSideOptions = [
|
||||||
|
{ label: 'None', value: '' },
|
||||||
|
{ label: 'Winners', value: 'Winners' },
|
||||||
|
{ label: 'Loosers', value: 'Loosers' },
|
||||||
|
];
|
||||||
|
|
||||||
|
const stage = ref(stageOptions[0]);
|
||||||
|
const bracketSide = ref('');
|
||||||
|
const customActive = ref(false);
|
||||||
|
const customText = ref('');
|
||||||
|
const hasChanges = ref(false);
|
||||||
|
|
||||||
|
const parseInitialRound = () => {
|
||||||
|
const round = scoreboardStore.scoreboard.round.trim();
|
||||||
|
if (!round) {
|
||||||
|
customText.value = '';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const option of bracketSideOptions) {
|
||||||
|
if (!option.value) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const prefix = `${option.value} `;
|
||||||
|
if (round.startsWith(prefix)) {
|
||||||
|
const remainder = round.slice(prefix.length);
|
||||||
|
if (stageOptions.includes(remainder)) {
|
||||||
|
stage.value = remainder;
|
||||||
|
bracketSide.value = option.value;
|
||||||
|
customText.value = round;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stageOptions.includes(round)) {
|
||||||
|
stage.value = round;
|
||||||
|
bracketSide.value = '';
|
||||||
|
customText.value = round;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
customActive.value = true;
|
||||||
|
customText.value = round;
|
||||||
|
};
|
||||||
|
|
||||||
|
const updateRound = () => {
|
||||||
|
if (!hasChanges.value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (customActive.value) {
|
||||||
|
scoreboardStore.scoreboard.round = customText.value.trim();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const prefix = bracketSide.value ? `${bracketSide.value} ` : '';
|
||||||
|
scoreboardStore.scoreboard.round = `${prefix}${stage.value}`.trim();
|
||||||
|
};
|
||||||
|
|
||||||
|
watch([stage, bracketSide, customText, customActive], updateRound);
|
||||||
|
|
||||||
|
watch(customActive, (value) => {
|
||||||
|
if (value && !customText.value) {
|
||||||
|
customText.value = scoreboardStore.scoreboard.round;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
watch(customText, (value) => {
|
||||||
|
if (!value.trim()) {
|
||||||
|
customActive.value = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
parseInitialRound();
|
||||||
|
hasChanges.value = true;
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="bracket-panel">
|
||||||
|
<QCard flat bordered>
|
||||||
|
<QCardSection class="bracket-panel-header">
|
||||||
|
<div class="text-h4">Bracket</div>
|
||||||
|
</QCardSection>
|
||||||
|
<QSeparator />
|
||||||
|
|
||||||
|
<QCardSection class="column q-gutter-md">
|
||||||
|
<QSelect
|
||||||
|
v-model="stage"
|
||||||
|
label="Stage"
|
||||||
|
:options="stageOptions"
|
||||||
|
dense
|
||||||
|
outlined
|
||||||
|
/>
|
||||||
|
<QSelect
|
||||||
|
v-model="bracketSide"
|
||||||
|
label="Bracket side"
|
||||||
|
:options="bracketSideOptions"
|
||||||
|
dense
|
||||||
|
outlined
|
||||||
|
emit-value
|
||||||
|
map-options
|
||||||
|
/>
|
||||||
|
<div class="bracket-panel-custom">
|
||||||
|
<QInput
|
||||||
|
v-model="customText"
|
||||||
|
label="Custom progress"
|
||||||
|
dense
|
||||||
|
outlined
|
||||||
|
class="bracket-panel-custom-input"
|
||||||
|
/>
|
||||||
|
<QToggle
|
||||||
|
v-model="customActive"
|
||||||
|
:disable="!customText.trim()"
|
||||||
|
color="secondary"
|
||||||
|
class="bracket-panel-custom-toggle"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</QCardSection>
|
||||||
|
</QCard>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.bracket-panel {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bracket-panel-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bracket-panel-custom {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: minmax(0, 1fr) auto;
|
||||||
|
align-items: center;
|
||||||
|
column-gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bracket-panel-custom-input {
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bracket-panel-custom-toggle {
|
||||||
|
align-self: center;
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -114,20 +114,6 @@ const playerOptions = computed(() => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<QCard flat bordered class="q-mt-lg">
|
|
||||||
<QCardSection>
|
|
||||||
<div class="text-subtitle1 text-weight-bold">Detalles de la ronda</div>
|
|
||||||
</QCardSection>
|
|
||||||
<QSeparator />
|
|
||||||
<QCardSection>
|
|
||||||
<QInput
|
|
||||||
v-model="scoreboardStore.scoreboard.round"
|
|
||||||
label="Ronda (ej. Winners Finals)"
|
|
||||||
dense
|
|
||||||
outlined
|
|
||||||
/>
|
|
||||||
</QCardSection>
|
|
||||||
</QCard>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useHead } from '@unhead/vue';
|
import { useHead } from '@unhead/vue';
|
||||||
|
import BracketPanel from '../components/BracketPanel.vue';
|
||||||
import ScoreboardPanel from '../components/ScoreboardPanel.vue';
|
import ScoreboardPanel from '../components/ScoreboardPanel.vue';
|
||||||
|
|
||||||
useHead({ title: 'Dashboard' });
|
useHead({ title: 'Dashboard' });
|
||||||
@@ -7,22 +8,35 @@ useHead({ title: 'Dashboard' });
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<QPage class="q-pa-lg">
|
<QPage class="q-pa-lg">
|
||||||
<QCard bordered class="dashboard-scoreboard-window q-mt-lg">
|
<div class="row q-col-gutter-lg items-start dashboard-panels q-mt-lg">
|
||||||
<QCardSection class="dashboard-scoreboard-content">
|
<div class="col-12 col-lg-7">
|
||||||
<ScoreboardPanel />
|
<QCard bordered class="dashboard-panel-card">
|
||||||
</QCardSection>
|
<QCardSection class="dashboard-panel-content">
|
||||||
</QCard>
|
<ScoreboardPanel />
|
||||||
|
</QCardSection>
|
||||||
|
</QCard>
|
||||||
|
</div>
|
||||||
|
<div class="col-12 col-lg-5">
|
||||||
|
<QCard bordered class="dashboard-panel-card">
|
||||||
|
<QCardSection class="dashboard-panel-content">
|
||||||
|
<BracketPanel />
|
||||||
|
</QCardSection>
|
||||||
|
</QCard>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</QPage>
|
</QPage>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.dashboard-scoreboard-window {
|
.dashboard-panels {
|
||||||
width: 50vw;
|
width: 100%;
|
||||||
min-width: 320px;
|
|
||||||
max-width: 100%;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.dashboard-scoreboard-content {
|
.dashboard-panel-card {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dashboard-panel-content {
|
||||||
padding-bottom: 16px;
|
padding-bottom: 16px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user