mejoras UI,

This commit is contained in:
2025-08-28 01:35:38 -06:00
parent 91f0e93a28
commit fd3338cf2d
3 changed files with 75 additions and 4 deletions

View File

@@ -70,6 +70,7 @@
<div
v-for="group in ratioData"
:key="group.name"
v-show="group.total > 0"
class="ratio-group"
:class="{ highlight: highlighted === group.name }"
@mouseenter="highlighted = group.name"

View File

@@ -1,7 +1,12 @@
<template>
<div class="leaderboard light">
<div class="header glass light">
<h1>📈 Leaderboard</h1>
<div class="header-left">
<button class="btn-back" @click="goHome" title="Volver al inicio">
Inicio
</button>
<h1>📈 Leaderboard</h1>
</div>
<div class="actions">
<button class="btn-collapse" @click="filtersCollapsed = !filtersCollapsed" :title="filtersCollapsed ? 'Mostrar filtros' : 'Ocultar filtros'">
<span class="collapse-icon" :class="{ rotated: filtersCollapsed }"></span>
@@ -123,6 +128,7 @@
<script setup lang="ts">
import { ref, computed, onMounted, onUnmounted, watch } from 'vue';
import { useRouter } from 'vue-router';
import EventChart from '../components/EventChart.vue';
import EventFilters from '../components/EventFilters.vue';
import DataSourceSelector from '../components/DataSourceSelector.vue';
@@ -131,6 +137,7 @@ import { useEventFilters } from '../composables/useEventFilters';
interface RoomInfo { roomId: string; metadata?: any; }
interface RoomState { players?: any[]; systemMessages?: { kind: string }[] }
const router = useRouter();
const loading = ref(false);
const eventFilters = useEventFilters();
const filtersCollapsed = ref(false);
@@ -193,6 +200,26 @@ const selectedPlayerMetrics = ref<Record<string, number>>({
// Store room score history from players
const allPlayersWithScores = ref<any[]>([]);
// Function to check if a score passes the current filters
function scorePassesFilters(score: any, roomId: string) {
// Room filter
if (eventFilters.roomFilter.value !== 'all' && roomId !== eventFilters.roomFilter.value) {
return false;
}
// Round filter
if (eventFilters.roundFilter.value !== 'all' && score.round !== eventFilters.roundFilter.value) {
return false;
}
// Game variant filter
if (eventFilters.gameFilter.value !== 'all' && score.variant !== eventFilters.gameFilter.value) {
return false;
}
return true;
}
// Function to compute additional metrics from players' score history
function computeMetricsFromScores() {
if (!allPlayersWithScores.value.length) return;
@@ -213,6 +240,11 @@ function computeMetricsFromScores() {
if (player.roomScoreHistory) {
player.roomScoreHistory.forEach((roomScore: any) => {
roomScore.scores.forEach((score: any) => {
// Apply filters to scores
if (!scorePassesFilters(score, roomScore.roomId)) {
return;
}
if (score.role === 'P1') {
totalP1Scores += score.score;
p1Count++;
@@ -259,6 +291,11 @@ function computeSelectedPlayerMetrics(uuid: string) {
playerData.roomScoreHistory.forEach((roomScore: any) => {
roomScore.scores.forEach((score: any) => {
// Apply filters to scores
if (!scorePassesFilters(score, roomScore.roomId)) {
return;
}
if (score.role === 'P1') {
totalP1Scores += score.score;
p1Count++;
@@ -328,11 +365,16 @@ const averageScoreTotal = computed(() => {
let totalScores = 0;
let totalScoreCount = 0;
// Sum all individual scores from all players regardless of role
// Sum all individual scores from all players regardless of role, applying filters
allPlayersWithScores.value.forEach((player: any) => {
if (player.roomScoreHistory) {
player.roomScoreHistory.forEach((roomScore: any) => {
roomScore.scores.forEach((score: any) => {
// Apply filters to scores
if (!scorePassesFilters(score, roomScore.roomId)) {
return;
}
totalScores += score.score;
totalScoreCount++;
});
@@ -360,6 +402,8 @@ const activeFilters = computed(() => ({
// Watch for changes in filters and data source
watch([eventFilters.dataSource, eventFilters.roundFilter, eventFilters.gameFilter, eventFilters.roomFilter], () => {
eventFilters.applyFilters(EVENTS);
// Recalculate metrics when filters change
computeMetricsFromScores();
});
// selectedUuid watch will be added after selectedUuid is declared
@@ -480,6 +524,10 @@ function clearRoom() {
eventFilters.applyFilters(EVENTS);
}
function goHome() {
router.push('/');
}
function prevPage() { page.value = Math.max(1, page.value - 1); }
function nextPage() { page.value = Math.min(pageCount.value, page.value + 1); }
function prevRoomPage() { roomPage.value = Math.max(1, roomPage.value - 1); }
@@ -875,6 +923,9 @@ function downloadCSV() {
.header { display:flex; align-items:center; justify-content:space-between; padding: 12px 14px; margin-bottom: 14px; }
.header h1 { margin: 0; }
.header-left { display:flex; align-items:center; gap: 16px; }
.btn-back { background:#667eea; color:#fff; border:none; border-radius:8px; padding:8px 14px; font-weight:600; cursor:pointer; transition: all 0.3s ease; font-size: 14px; }
.btn-back:hover { background:#5b6bda; transform: translateY(-1px); box-shadow: 0 2px 8px rgba(102, 126, 234, 0.3); }
.actions { display:flex; gap: 8px; }
.actions .btn { background:#667eea; color:#fff; border:none; border-radius:10px; padding:8px 12px; font-weight:800; cursor:pointer; }
.actions .btn.toggle { background:#eef2ff; color:#3949ab; border:1px solid #c7d2fe; }

View File

@@ -48,6 +48,9 @@
<button @click="goToDashboard" class="btn-dashboard">
🎛 Dashboard Admin
</button>
<button @click="goToLeaderboard" class="btn-leaderboard">
📈 Leaderboard
</button>
</div>
<!-- QR Mode Toggle -->
@@ -230,6 +233,10 @@ function goToDashboard() {
router.push('/dashboard');
}
function goToLeaderboard() {
router.push('/leaderboard');
}
// Context menu functions
function showContextMenu(event: MouseEvent, uuidInfo: UuidInfo) {
contextMenu.value = {
@@ -796,7 +803,8 @@ async function copyToClipboard() {
}
.btn-random,
.btn-dashboard {
.btn-dashboard,
.btn-leaderboard {
padding: 12px 30px;
border: none;
border-radius: 10px;
@@ -826,6 +834,16 @@ async function copyToClipboard() {
box-shadow: 0 5px 15px rgba(79, 172, 254, 0.4);
}
.btn-leaderboard {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
}
.btn-leaderboard:hover {
transform: translateY(-2px);
box-shadow: 0 5px 15px rgba(102, 126, 234, 0.4);
}
/* Context Menu */
.context-menu {
position: fixed;
@@ -1038,7 +1056,8 @@ async function copyToClipboard() {
}
.btn-random,
.btn-dashboard {
.btn-dashboard,
.btn-leaderboard {
width: 100%;
}