diff --git a/src/dashboard/example/components/ScoreboardPanel.vue b/src/dashboard/example/components/ScoreboardPanel.vue index ebf0e56..596ee88 100644 --- a/src/dashboard/example/components/ScoreboardPanel.vue +++ b/src/dashboard/example/components/ScoreboardPanel.vue @@ -26,8 +26,9 @@ const rightCountryOptions = ref(countryOptions); const leftCharacterInput = ref(''); const rightCharacterInput = ref(''); +const gameInput = ref(''); -const fightingGameOptions = [ +const allFightingGameOptions = [ 'Street Fighter 6', 'TEKKEN 8', 'Guilty Gear -Strive-', @@ -40,7 +41,12 @@ const fightingGameOptions = [ value: game, })); +const fightingGameOptions = ref(allFightingGameOptions); + const characterOptions = computed(() => getCharactersByGame(scoreboardStore.scoreboard.game)); +type CharacterOption = ReturnType[number]; +const leftCharacterOptions = ref([]); +const rightCharacterOptions = ref([]); const leftCharacterImage = computed(() => { const match = characterOptions.value.find((option) => option.value === scoreboardStore.scoreboard.leftCharacter); @@ -52,6 +58,9 @@ const rightCharacterImage = computed(() => { return match?.image ?? ''; }); +const leftPanelImage = computed(() => leftCharacterImage.value); +const rightPanelImage = computed(() => rightCharacterImage.value); + const normalizeName = (value: string) => value.trim().toLowerCase(); @@ -90,6 +99,41 @@ const onRightCountryFilter = (value: string, update: (callback: () => void) => v filterCountries(value, update, rightCountryOptions); }; + +const filterCharacters = ( + value: string, + update: (callback: () => void) => void, + target: Ref, +) => { + update(() => { + const needle = value.toLowerCase().trim(); + if (!needle) { + target.value = characterOptions.value; + return; + } + target.value = characterOptions.value.filter((character) => character.label.toLowerCase().includes(needle)); + }); +}; + +const onLeftCharacterFilter = (value: string, update: (callback: () => void) => void) => { + filterCharacters(value, update, leftCharacterOptions); +}; + +const onRightCharacterFilter = (value: string, update: (callback: () => void) => void) => { + filterCharacters(value, update, rightCharacterOptions); +}; + +const onGameFilter = (value: string, update: (callback: () => void) => void) => { + update(() => { + const needle = value.toLowerCase().trim(); + if (!needle) { + fightingGameOptions.value = allFightingGameOptions; + return; + } + fightingGameOptions.value = allFightingGameOptions.filter((game) => game.label.toLowerCase().includes(needle)); + }); +}; + const playerOptions = computed(() => { const base = [{ label: '(Sin asignar)', value: '' }]; const entries = Object.entries(playersStore.players) as [string, Schemas.Players[string]][]; @@ -386,6 +430,14 @@ const onRightSelect = (playerId: string) => { applyRightPlayerData(playerId); }; +const adjustLeftScore = (delta: number) => { + scoreboardStore.leftScore = Math.max(0, scoreboardStore.leftScore + delta); +}; + +const adjustRightScore = (delta: number) => { + scoreboardStore.rightScore = Math.max(0, scoreboardStore.rightScore + delta); +}; + const createPlayerId = (name: string) => { const base = name .trim() @@ -583,10 +635,22 @@ watchEffect(() => { } }); + +watch( + () => scoreboardStore.scoreboard.game, + (value) => { + const match = allFightingGameOptions.find((option) => option.value === value); + gameInput.value = match?.label ?? ''; + }, + { immediate: true }, +); + watch( () => scoreboardStore.scoreboard.game, () => { const options = getCharactersByGame(scoreboardStore.scoreboard.game); + leftCharacterOptions.value = options; + rightCharacterOptions.value = options; const allowed = new Set(options.map((option) => option.value)); if (!allowed.has(scoreboardStore.scoreboard.leftCharacter)) { @@ -630,32 +694,63 @@ watch( -
-
- - -
- Left side + +
+
+
+
+ +
+ Left image +
- - - + +
+
- -
- Left character preview -
- -
- Right character preview -
@@ -945,40 +1030,209 @@ watch( gap: 16px; } -.scoreboard-grid { + +.scoreboard-preview { display: grid; - grid-template-columns: 1fr; - gap: 24px; - align-items: start; + grid-template-columns: minmax(0, 1fr) minmax(320px, auto) minmax(0, 1fr); + gap: 18px; + padding: 16px; + align-items: center; } -.scoreboard-grid__side, -.scoreboard-grid__center { - min-width: 0; +.scoreboard-preview__side { + display: flex; + align-items: center; } -.character-preview { +.scoreboard-preview__image-column { + width: min(100%, 320px); + display: flex; + flex-direction: column; + gap: 8px; +} + +.scoreboard-preview__side-inner { width: 100%; - border-radius: 8px; - overflow: hidden; - border: 1px solid rgba(255, 255, 255, 0.12); - background: rgba(0, 0, 0, 0.25); + display: grid; + grid-template-columns: minmax(220px, 320px) minmax(180px, 1fr); + align-items: center; + gap: 14px; } -.character-preview img { +.scoreboard-preview__side--right { + text-align: right; +} + +.scoreboard-preview__side--right .scoreboard-preview__side-inner { + grid-template-columns: minmax(180px, 1fr) minmax(220px, 320px); +} + + +.scoreboard-preview__side .scoreboard-preview__image-column { + justify-self: start; +} + +.scoreboard-preview__side--right .scoreboard-preview__image-column { + justify-self: end; +} + +.scoreboard-preview__image-wrap { + width: min(100%, 320px); + aspect-ratio: 4 / 4; + border-radius: 10px; + overflow: hidden; + border: 1px solid rgba(255, 255, 255, 0.14); + background: #2f3a4f; +} + +.scoreboard-preview__image { display: block; width: 100%; - height: 88px; - object-fit: cover; + height: 100%; + object-fit: contain; + object-position: center; + transform: scale(2); + transform-origin: center; } +.scoreboard-preview__empty { + height: 100%; + display: flex; + align-items: center; + justify-content: center; + color: rgba(255, 255, 255, 0.65); + font-weight: 600; +} + +.scoreboard-preview__controls { + width: min(100%, 260px); + justify-self: center; + display: flex; + flex-direction: column; + gap: 6px; +} + +.scoreboard-preview__field { + margin: 0; +} + +.scoreboard-preview__character-field { + margin-top: 2px; +} + +.scoreboard-preview__field :deep(.q-field__control) { + min-height: 28px; + padding: 0; + background: transparent !important; + border-radius: 0; +} + +.scoreboard-preview__field :deep(.q-field__control:before), +.scoreboard-preview__field :deep(.q-field__control:after) { + border: 0; + border-bottom: 1px solid rgba(255, 255, 255, 0.34); +} + +.scoreboard-preview__field :deep(.q-field__native), +.scoreboard-preview__field :deep(.q-field__input), +.scoreboard-preview__field :deep(.q-field__label) { + color: rgba(255, 255, 255, 0.92); +} + +.scoreboard-preview__center { + display: flex; + flex-direction: column; + align-items: center; + align-self: stretch; + justify-content: flex-start; + padding-top: 2px; + gap: 10px; +} + +.scoreboard-preview__game-field { + width: min(100%, 240px); + margin-bottom: 56px; +} + +.scoreboard-preview__score-controls { + display: flex; + align-items: center; + justify-content: center; + gap: 18px; +} + +.scoreboard-preview__actions { + display: flex; + align-items: center; + gap: 10px; +} + +.scoreboard-preview__action-btn { + color: #fff; + opacity: 0.85; +} + +.scoreboard-preview__action-btn:hover { + opacity: 1; + text-shadow: 0 0 10px rgba(255, 255, 255, 0.45); +} + +.scoreboard-preview__score-side { + display: inline-flex; + flex-direction: column; + align-items: center; + gap: 4px; +} + +.scoreboard-preview__score-value { + min-width: 64px; + text-align: center; + font-size: clamp(4rem, 7vw, 5.6rem); + font-weight: 800; + line-height: 1; +} + +.scoreboard-preview__dash { + opacity: 0.7; + font-size: clamp(3rem, 5vw, 4rem); + font-weight: 700; +} + + @media (min-width: 1024px) { - .scoreboard-grid { - grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr); - } - - .scoreboard-grid__center { - width: 220px; + .scoreboard-preview { + grid-template-columns: minmax(0, 1fr) minmax(320px, auto) minmax(0, 1fr); } } + +@media (max-width: 900px) { + .scoreboard-preview { + grid-template-columns: 1fr; + gap: 12px; + } + + .scoreboard-preview__center { + order: -1; + justify-self: center; + } + + .scoreboard-preview__image-wrap { + width: min(100%, 280px); + } + + .scoreboard-preview__side-inner { + grid-template-columns: 1fr; + align-items: flex-start; + justify-items: flex-start; + } + + .scoreboard-preview__side--right { + text-align: left; + } + + .scoreboard-preview__side--right .scoreboard-preview__side-inner { + grid-template-columns: 1fr; + } +} +