mejoras de UI
This commit is contained in:
@@ -2,7 +2,9 @@
|
|||||||
<div class="panel glass">
|
<div class="panel glass">
|
||||||
<h2 class="panel-title">Eventos y comparación</h2>
|
<h2 class="panel-title">Eventos y comparación</h2>
|
||||||
<div v-if="loading" class="placeholder">Cargando datos…</div>
|
<div v-if="loading" class="placeholder">Cargando datos…</div>
|
||||||
<div v-else class="bars big">
|
|
||||||
|
<!-- Regular bars view -->
|
||||||
|
<div v-else-if="viewMode !== 'ratio'" class="bars big">
|
||||||
<div
|
<div
|
||||||
v-for="eventType in eventTypes"
|
v-for="eventType in eventTypes"
|
||||||
:key="eventType"
|
:key="eventType"
|
||||||
@@ -43,6 +45,47 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="hint small">Basado en mensajes disponibles por sala. Click jugador para comparar.</div>
|
<div class="hint small">Basado en mensajes disponibles por sala. Click jugador para comparar.</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Ratio bars view -->
|
||||||
|
<div v-else class="ratio-bars">
|
||||||
|
<div
|
||||||
|
v-for="(group, index) in ratioData"
|
||||||
|
:key="group.name"
|
||||||
|
class="ratio-group"
|
||||||
|
:class="{ highlight: highlighted === group.name }"
|
||||||
|
@mouseenter="highlighted = group.name"
|
||||||
|
@mouseleave="highlighted = ''"
|
||||||
|
>
|
||||||
|
<div class="ratio-bar">
|
||||||
|
<div
|
||||||
|
v-for="(action, actionIndex) in group.actions"
|
||||||
|
:key="action"
|
||||||
|
class="ratio-segment"
|
||||||
|
:style="{
|
||||||
|
width: group.percentages[actionIndex] + '%',
|
||||||
|
background: eventStyles[action]?.gradient || 'linear-gradient(90deg, #94a3b8, #64748b)'
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="ratio-event-chip"
|
||||||
|
v-if="group.percentages[actionIndex] > 5"
|
||||||
|
:style="{
|
||||||
|
background: getEventChipBg(action),
|
||||||
|
borderColor: getEventBorderColor(action)
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<span class="ratio-icon">{{ eventStyles[action]?.icon || '📊' }}</span>
|
||||||
|
<span class="ratio-label">{{ group.labels[actionIndex] }}</span>
|
||||||
|
<span class="ratio-count">{{ group.values[actionIndex] }} ({{ Math.round(group.percentages[actionIndex]) }}%)</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="hint small">
|
||||||
|
{{ selectedPlayerUuid ? 'Ratios del jugador seleccionado' : 'Ratios globales' }}.
|
||||||
|
Los segmentos muestran la proporción relativa dentro de cada categoría.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -56,7 +99,7 @@ interface Props {
|
|||||||
playerEventCounts: Record<string, number>;
|
playerEventCounts: Record<string, number>;
|
||||||
selectedPlayerUuid?: string;
|
selectedPlayerUuid?: string;
|
||||||
playerBarGradient: string;
|
playerBarGradient: string;
|
||||||
showPercent: boolean;
|
viewMode: 'count' | 'percent' | 'ratio';
|
||||||
loading?: boolean;
|
loading?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,6 +110,54 @@ const props = withDefaults(defineProps<Props>(), {
|
|||||||
|
|
||||||
const highlighted = ref('');
|
const highlighted = ref('');
|
||||||
|
|
||||||
|
// Define ratio groups for superposed view
|
||||||
|
const ratioGroups = [
|
||||||
|
{
|
||||||
|
name: 'Ofertas',
|
||||||
|
actions: ['p1_propose', 'p1_no_offer'],
|
||||||
|
labels: ['Ofrecer', 'No Ofrecer']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Respuestas',
|
||||||
|
actions: ['p2_accept', 'p2_reject', 'p2_snatch'],
|
||||||
|
labels: ['Aceptar', 'Rechazar', 'Robar']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Fuerzas',
|
||||||
|
actions: ['p2_force', 'p2_no_force'],
|
||||||
|
labels: ['Forzar', 'No Forzar']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Vergüenzas',
|
||||||
|
actions: ['p1_shame', 'p1_no_shame'],
|
||||||
|
labels: ['Asignar', 'No Asignar']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Denuncias',
|
||||||
|
actions: ['p1_report', 'p1_no_report'],
|
||||||
|
labels: ['Denunciar', 'No Denunciar']
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
// Compute ratio data for each group
|
||||||
|
const ratioData = computed(() => {
|
||||||
|
return ratioGroups.map(group => {
|
||||||
|
const counts = props.selectedPlayerUuid
|
||||||
|
? props.playerEventCounts
|
||||||
|
: props.globalEventCounts;
|
||||||
|
|
||||||
|
const values = group.actions.map(action => counts[action] || 0);
|
||||||
|
const total = values.reduce((sum, val) => sum + val, 0);
|
||||||
|
|
||||||
|
return {
|
||||||
|
...group,
|
||||||
|
values,
|
||||||
|
total,
|
||||||
|
percentages: total > 0 ? values.map(val => (val / total) * 100) : values.map(() => 0)
|
||||||
|
};
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
// Global calculations
|
// Global calculations
|
||||||
const globalMax = computed(() => {
|
const globalMax = computed(() => {
|
||||||
const vals = props.eventTypes.map(k => props.globalEventCounts[k] || 0);
|
const vals = props.eventTypes.map(k => props.globalEventCounts[k] || 0);
|
||||||
@@ -80,12 +171,12 @@ const globalTotal = computed(() =>
|
|||||||
|
|
||||||
function globalBarWidth(eventType: string) {
|
function globalBarWidth(eventType: string) {
|
||||||
const v = props.globalEventCounts[eventType] || 0;
|
const v = props.globalEventCounts[eventType] || 0;
|
||||||
return Math.round((v / (props.showPercent ? globalTotal.value : globalMax.value)) * 100);
|
return Math.round((v / (props.viewMode === 'percent' ? globalTotal.value : globalMax.value)) * 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
function globalValueLabel(eventType: string) {
|
function globalValueLabel(eventType: string) {
|
||||||
const v = props.globalEventCounts[eventType] || 0;
|
const v = props.globalEventCounts[eventType] || 0;
|
||||||
return props.showPercent ? `${Math.round((v / globalTotal.value) * 100)}%` : String(v);
|
return props.viewMode === 'percent' ? `${Math.round((v / globalTotal.value) * 100)}%` : String(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Player calculations
|
// Player calculations
|
||||||
@@ -101,12 +192,12 @@ const playerTotal = computed(() =>
|
|||||||
|
|
||||||
function playerBarWidth(eventType: string) {
|
function playerBarWidth(eventType: string) {
|
||||||
const v = props.playerEventCounts[eventType] || 0;
|
const v = props.playerEventCounts[eventType] || 0;
|
||||||
return Math.round((v / (props.showPercent ? playerTotal.value : playerMax.value)) * 100);
|
return Math.round((v / (props.viewMode === 'percent' ? playerTotal.value : playerMax.value)) * 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
function playerValueLabel(eventType: string) {
|
function playerValueLabel(eventType: string) {
|
||||||
const v = props.playerEventCounts[eventType] || 0;
|
const v = props.playerEventCounts[eventType] || 0;
|
||||||
return props.showPercent ? `${Math.round((v / playerTotal.value) * 100)}%` : String(v);
|
return props.viewMode === 'percent' ? `${Math.round((v / playerTotal.value) * 100)}%` : String(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Styling helpers
|
// Styling helpers
|
||||||
@@ -310,6 +401,101 @@ function friendlyEventName(eventType: string): string {
|
|||||||
color: #64748b;
|
color: #64748b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Ratio bars styles */
|
||||||
|
.ratio-bars {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 16px;
|
||||||
|
flex: 1 1 auto;
|
||||||
|
min-height: 0;
|
||||||
|
padding: 8px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ratio-group {
|
||||||
|
flex: 1 1 0;
|
||||||
|
min-height: 60px;
|
||||||
|
transition: transform .18s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ratio-group.highlight {
|
||||||
|
transform: translateX(4px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.ratio-bar {
|
||||||
|
position: relative;
|
||||||
|
height: 100%;
|
||||||
|
background: linear-gradient(135deg, rgba(238,242,255,0.4) 0%, rgba(199,210,254,0.2) 100%);
|
||||||
|
border-radius: 12px;
|
||||||
|
overflow: hidden;
|
||||||
|
border: 1px solid rgba(199,210,254,0.3);
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ratio-segment {
|
||||||
|
height: 100%;
|
||||||
|
transition: all 0.6s cubic-bezier(.2,.7,.1,1);
|
||||||
|
backdrop-filter: blur(4px);
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ratio-segment:first-child {
|
||||||
|
border-top-left-radius: 12px;
|
||||||
|
border-bottom-left-radius: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ratio-segment:last-child {
|
||||||
|
border-top-right-radius: 12px;
|
||||||
|
border-bottom-right-radius: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ratio-event-chip {
|
||||||
|
position: absolute;
|
||||||
|
left: 50%;
|
||||||
|
top: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
padding: 5px 10px;
|
||||||
|
border-radius: 999px;
|
||||||
|
border: 1px solid;
|
||||||
|
box-shadow: 0 4px 12px rgba(0,0,0,0.08), inset 0 1px 0 rgba(255,255,255,0.4);
|
||||||
|
backdrop-filter: blur(8px) saturate(120%);
|
||||||
|
-webkit-backdrop-filter: blur(8px) saturate(120%);
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
white-space: nowrap;
|
||||||
|
max-width: 95%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ratio-segment:hover .ratio-event-chip {
|
||||||
|
transform: translate(-50%, -50%) scale(1.05);
|
||||||
|
box-shadow: 0 6px 16px rgba(0,0,0,0.12), inset 0 1px 0 rgba(255,255,255,0.6);
|
||||||
|
}
|
||||||
|
|
||||||
|
.ratio-icon {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ratio-label {
|
||||||
|
color: #0f172a;
|
||||||
|
font-weight: 800;
|
||||||
|
font-size: 13px;
|
||||||
|
letter-spacing: .1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ratio-count {
|
||||||
|
color: #1f2937;
|
||||||
|
font-weight: 800;
|
||||||
|
background: rgba(255,255,255,0.7);
|
||||||
|
border: 1px solid rgba(229,231,235,0.5);
|
||||||
|
border-radius: 999px;
|
||||||
|
padding: 2px 6px;
|
||||||
|
font-size: 11px;
|
||||||
|
margin-left: 2px;
|
||||||
|
box-shadow: 0 1px 3px rgba(0,0,0,0.06);
|
||||||
|
}
|
||||||
|
|
||||||
/* Responsive chip sizing */
|
/* Responsive chip sizing */
|
||||||
@media (min-width: 1200px) {
|
@media (min-width: 1200px) {
|
||||||
.bar-chip {
|
.bar-chip {
|
||||||
@@ -395,5 +581,83 @@ function friendlyEventName(eventType: string): string {
|
|||||||
font-size: 8px;
|
font-size: 8px;
|
||||||
margin-left: 1px;
|
margin-left: 1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Ratio responsive styles */
|
||||||
|
.ratio-event-chip {
|
||||||
|
padding: 3px 6px;
|
||||||
|
gap: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ratio-icon {
|
||||||
|
font-size: 11px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ratio-label {
|
||||||
|
font-size: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ratio-count {
|
||||||
|
font-size: 8px;
|
||||||
|
padding: 1px 3px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 767px) {
|
||||||
|
.ratio-event-chip {
|
||||||
|
padding: 3px 7px;
|
||||||
|
gap: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ratio-icon {
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ratio-label {
|
||||||
|
font-size: 11px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ratio-count {
|
||||||
|
font-size: 9px;
|
||||||
|
padding: 1px 4px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 768px) and (max-width: 1199px) {
|
||||||
|
.ratio-event-chip {
|
||||||
|
padding: 4px 8px;
|
||||||
|
gap: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ratio-icon {
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ratio-label {
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ratio-count {
|
||||||
|
font-size: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 1200px) {
|
||||||
|
.ratio-event-chip {
|
||||||
|
padding: 6px 12px;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ratio-icon {
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ratio-label {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ratio-count {
|
||||||
|
font-size: 12px;
|
||||||
|
padding: 3px 8px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
@@ -4,8 +4,8 @@
|
|||||||
<h1>📈 Leaderboard</h1>
|
<h1>📈 Leaderboard</h1>
|
||||||
<div class="actions">
|
<div class="actions">
|
||||||
<button class="btn" @click="refreshAll" :disabled="loading">{{ loading ? 'Actualizando…' : 'Actualizar' }}</button>
|
<button class="btn" @click="refreshAll" :disabled="loading">{{ loading ? 'Actualizando…' : 'Actualizar' }}</button>
|
||||||
<button class="btn toggle" :class="{ active: showPercent }" @click="showPercent = !showPercent" :disabled="loading">
|
<button class="btn toggle" @click="cycleViewMode" :disabled="loading">
|
||||||
{{ showPercent ? 'Ver conteos' : 'Ver %' }}
|
{{ viewModeLabel }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -29,7 +29,14 @@
|
|||||||
<span class="key player" v-if="selectedUuid"></span> Jugador
|
<span class="key player" v-if="selectedUuid"></span> Jugador
|
||||||
</div>
|
</div>
|
||||||
<div class="player-chips">
|
<div class="player-chips">
|
||||||
<input class="search" v-model="search" placeholder="Buscar jugador…" />
|
<div class="search-controls">
|
||||||
|
<input class="search" v-model="search" placeholder="Buscar jugador…" />
|
||||||
|
<div class="pagination compact" v-if="pageCount > 1">
|
||||||
|
<button class="pg-btn compact" @click="prevPage" :disabled="page <= 1">‹</button>
|
||||||
|
<span class="pg-ind">{{ page }}/{{ pageCount }}</span>
|
||||||
|
<button class="pg-btn compact" @click="nextPage" :disabled="page >= pageCount">›</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="chips">
|
<div class="chips">
|
||||||
<button
|
<button
|
||||||
v-for="p in playersPage"
|
v-for="p in playersPage"
|
||||||
@@ -45,11 +52,6 @@
|
|||||||
</button>
|
</button>
|
||||||
<button v-if="selectedUuid" class="chip clear" @click="clearPlayer">Quitar selección</button>
|
<button v-if="selectedUuid" class="chip clear" @click="clearPlayer">Quitar selección</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="pagination">
|
|
||||||
<button class="pg-btn" @click="prevPage" :disabled="page <= 1">«</button>
|
|
||||||
<span class="pg-ind">{{ page }} / {{ pageCount }}</span>
|
|
||||||
<button class="pg-btn" @click="nextPage" :disabled="page >= pageCount">»</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -60,7 +62,7 @@
|
|||||||
:player-event-counts="playerEventCounts"
|
:player-event-counts="playerEventCounts"
|
||||||
:selected-player-uuid="selectedUuid"
|
:selected-player-uuid="selectedUuid"
|
||||||
:player-bar-gradient="playerBarGradient"
|
:player-bar-gradient="playerBarGradient"
|
||||||
:show-percent="showPercent"
|
:view-mode="viewMode"
|
||||||
:loading="loading"
|
:loading="loading"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -78,6 +80,27 @@ interface RoomState { players?: any[]; systemMessages?: { kind: string }[] }
|
|||||||
|
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
const eventFilters = useEventFilters();
|
const eventFilters = useEventFilters();
|
||||||
|
|
||||||
|
// View mode cycling
|
||||||
|
type ViewMode = 'count' | 'percent' | 'ratio';
|
||||||
|
const viewMode = ref<ViewMode>('count');
|
||||||
|
|
||||||
|
const viewModeLabel = computed(() => {
|
||||||
|
switch (viewMode.value) {
|
||||||
|
case 'count': return 'Ver conteos';
|
||||||
|
case 'percent': return 'Ver %';
|
||||||
|
case 'ratio': return 'Ver superpuesto';
|
||||||
|
default: return 'Ver conteos';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function cycleViewMode() {
|
||||||
|
const modes: ViewMode[] = ['count', 'percent', 'ratio'];
|
||||||
|
const currentIndex = modes.indexOf(viewMode.value);
|
||||||
|
const nextIndex = (currentIndex + 1) % modes.length;
|
||||||
|
viewMode.value = modes[nextIndex];
|
||||||
|
}
|
||||||
|
|
||||||
const EVENTS = [
|
const EVENTS = [
|
||||||
'p1_propose', 'p1_no_offer',
|
'p1_propose', 'p1_no_offer',
|
||||||
'p2_snatch', 'p2_accept', 'p2_force', 'p2_no_force', 'p2_reject',
|
'p2_snatch', 'p2_accept', 'p2_force', 'p2_no_force', 'p2_reject',
|
||||||
@@ -98,7 +121,6 @@ const EVENT_STYLES: Record<string, { icon: string; color: string; gradient: stri
|
|||||||
'p1_report': { icon: '⚖️', color: '#8b5cf6', gradient: 'linear-gradient(135deg, #8b5cf6 0%, #7c3aed 100%)' },
|
'p1_report': { icon: '⚖️', color: '#8b5cf6', gradient: 'linear-gradient(135deg, #8b5cf6 0%, #7c3aed 100%)' },
|
||||||
'p1_no_report': { icon: '🤝', color: '#6b7280', gradient: 'linear-gradient(135deg, #94a3b8 0%, #64748b 100%)' }
|
'p1_no_report': { icon: '🤝', color: '#6b7280', gradient: 'linear-gradient(135deg, #94a3b8 0%, #64748b 100%)' }
|
||||||
};
|
};
|
||||||
const showPercent = ref(false);
|
|
||||||
|
|
||||||
// Watch for changes in filters and data source
|
// Watch for changes in filters and data source
|
||||||
watch([eventFilters.dataSource, eventFilters.roundFilter, eventFilters.gameFilter], () => {
|
watch([eventFilters.dataSource, eventFilters.roundFilter, eventFilters.gameFilter], () => {
|
||||||
@@ -119,11 +141,25 @@ watch(search, () => {
|
|||||||
page.value = 1;
|
page.value = 1;
|
||||||
});
|
});
|
||||||
const page = ref(1);
|
const page = ref(1);
|
||||||
const pageSize = 20;
|
const containerWidth = ref(1200); // Default width, will be updated dynamically
|
||||||
const pageCount = computed(() => Math.max(1, Math.ceil((playersFiltered.value.length || 0) / pageSize)));
|
const dynamicPageSize = computed(() => {
|
||||||
|
// Estimate space needed per chip and controls
|
||||||
|
const chipWidth = 140; // Average chip width including gap
|
||||||
|
const clearBtnWidth = selectedUuid.value ? 150 : 0; // "Quitar selección" button
|
||||||
|
const searchWidth = 240; // Search input
|
||||||
|
const paginationWidth = pageCount.value > 1 ? 100 : 0; // Compact pagination
|
||||||
|
const margin = 40; // Container margins
|
||||||
|
|
||||||
|
const availableWidth = containerWidth.value - searchWidth - paginationWidth - clearBtnWidth - margin;
|
||||||
|
const maxChips = Math.max(3, Math.floor(availableWidth / chipWidth)); // Minimum 3 chips
|
||||||
|
|
||||||
|
return Math.min(maxChips, 15); // Maximum 15 chips per page
|
||||||
|
});
|
||||||
|
|
||||||
|
const pageCount = computed(() => Math.max(1, Math.ceil((playersFiltered.value.length || 0) / dynamicPageSize.value)));
|
||||||
const playersPage = computed(() => {
|
const playersPage = computed(() => {
|
||||||
const start = (page.value - 1) * pageSize;
|
const start = (page.value - 1) * dynamicPageSize.value;
|
||||||
return playersFiltered.value.slice(start, start + pageSize);
|
return playersFiltered.value.slice(start, start + dynamicPageSize.value);
|
||||||
});
|
});
|
||||||
|
|
||||||
const selectedUuid = ref('');
|
const selectedUuid = ref('');
|
||||||
@@ -368,12 +404,25 @@ async function loadPlayerHistory() {
|
|||||||
playerLoading.value = false;
|
playerLoading.value = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update container width on resize
|
||||||
|
function updateContainerWidth() {
|
||||||
|
containerWidth.value = window.innerWidth;
|
||||||
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
setupStreams();
|
setupStreams();
|
||||||
// Initialize with aggregated data as default
|
// Initialize with aggregated data as default
|
||||||
eventFilters.globalEventCounts.value = { ...eventFilters.globalEventCountsAggregated.value };
|
eventFilters.globalEventCounts.value = { ...eventFilters.globalEventCountsAggregated.value };
|
||||||
|
|
||||||
|
// Set initial container width and add resize listener
|
||||||
|
updateContainerWidth();
|
||||||
|
window.addEventListener('resize', updateContainerWidth);
|
||||||
|
});
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
closeStreams();
|
||||||
|
window.removeEventListener('resize', updateContainerWidth);
|
||||||
});
|
});
|
||||||
onUnmounted(closeStreams);
|
|
||||||
|
|
||||||
// Reset to first page when search changes or players list length shrinks below current page
|
// Reset to first page when search changes or players list length shrinks below current page
|
||||||
watch(() => search.value, () => { page.value = 1; });
|
watch(() => search.value, () => { page.value = 1; });
|
||||||
@@ -406,10 +455,41 @@ const allPlayersActions = ref<{ uuid: string; name: string; total: number }[]>([
|
|||||||
.key.player { background: linear-gradient(90deg, #a78bfa, #6366f1); box-shadow: 0 0 8px rgba(99,102,241,0.35); }
|
.key.player { background: linear-gradient(90deg, #a78bfa, #6366f1); box-shadow: 0 0 8px rgba(99,102,241,0.35); }
|
||||||
.sep { opacity: 0.6; }
|
.sep { opacity: 0.6; }
|
||||||
|
|
||||||
.player-chips { display:flex; align-items:flex-start; gap: 10px; flex-wrap: wrap; }
|
.player-chips {
|
||||||
.search { padding:8px 10px; border:1px solid #cbd5e1; background:#fff; color:#0f172a; border-radius: 10px; min-width: 240px; outline:none; }
|
display: flex;
|
||||||
.search::placeholder { color:#64748b; }
|
flex-direction: column;
|
||||||
.chips { display:flex; gap:10px; flex-wrap: wrap; }
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-controls {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12px;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search {
|
||||||
|
padding: 8px 10px;
|
||||||
|
border: 1px solid #cbd5e1;
|
||||||
|
background: #fff;
|
||||||
|
color: #0f172a;
|
||||||
|
border-radius: 10px;
|
||||||
|
min-width: 240px;
|
||||||
|
outline: none;
|
||||||
|
flex: 1;
|
||||||
|
max-width: 300px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search::placeholder {
|
||||||
|
color: #64748b;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chips {
|
||||||
|
display: flex;
|
||||||
|
gap: 10px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
.chip { display:flex; align-items:center; gap:8px; background: color-mix(in srgb, var(--primary) 6%, white); border:1px solid color-mix(in srgb, var(--primary) 24%, #e5e7eb); padding:8px 12px; border-radius: 999px; color:#111827; cursor:pointer; transition: transform .18s ease, background .18s ease, box-shadow .18s ease; }
|
.chip { display:flex; align-items:center; gap:8px; background: color-mix(in srgb, var(--primary) 6%, white); border:1px solid color-mix(in srgb, var(--primary) 24%, #e5e7eb); padding:8px 12px; border-radius: 999px; color:#111827; cursor:pointer; transition: transform .18s ease, background .18s ease, box-shadow .18s ease; }
|
||||||
.chip:hover { transform: translateY(-1px); background: color-mix(in srgb, var(--primary) 10%, white); box-shadow: 0 6px 18px rgba(102,126,234,0.18); }
|
.chip:hover { transform: translateY(-1px); background: color-mix(in srgb, var(--primary) 10%, white); box-shadow: 0 6px 18px rgba(102,126,234,0.18); }
|
||||||
.chip.active { background: color-mix(in srgb, var(--primary) 18%, white); border-color: color-mix(in srgb, var(--primary) 45%, #c7d2fe); box-shadow: 0 6px 22px rgba(99,102,241,0.22); }
|
.chip.active { background: color-mix(in srgb, var(--primary) 18%, white); border-color: color-mix(in srgb, var(--primary) 45%, #c7d2fe); box-shadow: 0 6px 22px rgba(99,102,241,0.22); }
|
||||||
@@ -422,16 +502,21 @@ const allPlayersActions = ref<{ uuid: string; name: string; total: number }[]>([
|
|||||||
.pagination {
|
.pagination {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 12px;
|
gap: 8px;
|
||||||
padding: 8px 12px;
|
padding: 6px 10px;
|
||||||
background: rgba(255,255,255,0.82);
|
background: rgba(255,255,255,0.82);
|
||||||
border: 1px solid rgba(229,231,235,0.9);
|
border: 1px solid rgba(229,231,235,0.9);
|
||||||
border-radius: 999px;
|
border-radius: 999px;
|
||||||
box-shadow: 0 6px 18px rgba(0,0,0,0.08), inset 0 1px 0 rgba(255,255,255,0.6);
|
box-shadow: 0 4px 12px rgba(0,0,0,0.08), inset 0 1px 0 rgba(255,255,255,0.6);
|
||||||
backdrop-filter: blur(10px) saturate(120%);
|
backdrop-filter: blur(10px) saturate(120%);
|
||||||
-webkit-backdrop-filter: blur(10px) saturate(120%);
|
-webkit-backdrop-filter: blur(10px) saturate(120%);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.pagination.compact {
|
||||||
|
gap: 6px;
|
||||||
|
padding: 4px 8px;
|
||||||
|
}
|
||||||
|
|
||||||
.pg-btn {
|
.pg-btn {
|
||||||
width: 32px;
|
width: 32px;
|
||||||
height: 32px;
|
height: 32px;
|
||||||
@@ -449,11 +534,23 @@ const allPlayersActions = ref<{ uuid: string; name: string; total: number }[]>([
|
|||||||
box-shadow: 0 4px 12px rgba(102,126,234,0.25);
|
box-shadow: 0 4px 12px rgba(102,126,234,0.25);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.pg-btn.compact {
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 800;
|
||||||
|
box-shadow: 0 2px 8px rgba(102,126,234,0.2);
|
||||||
|
}
|
||||||
|
|
||||||
.pg-btn:hover:not(:disabled) {
|
.pg-btn:hover:not(:disabled) {
|
||||||
transform: translateY(-2px);
|
transform: translateY(-1px);
|
||||||
box-shadow: 0 6px 16px rgba(102,126,234,0.35);
|
box-shadow: 0 6px 16px rgba(102,126,234,0.35);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.pg-btn.compact:hover:not(:disabled) {
|
||||||
|
box-shadow: 0 4px 12px rgba(102,126,234,0.3);
|
||||||
|
}
|
||||||
|
|
||||||
.pg-btn:disabled {
|
.pg-btn:disabled {
|
||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
@@ -463,23 +560,54 @@ const allPlayersActions = ref<{ uuid: string; name: string; total: number }[]>([
|
|||||||
}
|
}
|
||||||
|
|
||||||
.pg-ind {
|
.pg-ind {
|
||||||
font-weight: 700;
|
font-weight: 600;
|
||||||
color: #334155;
|
color: #334155;
|
||||||
font-size: 14px;
|
font-size: 12px;
|
||||||
min-width: 60px;
|
min-width: 35px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@media (max-width: 480px) {
|
@media (max-width: 768px) {
|
||||||
.player-chips {
|
.search-controls {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
align-items: stretch;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.pagination {
|
.search {
|
||||||
width: 100%;
|
min-width: auto;
|
||||||
|
max-width: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pagination.compact {
|
||||||
|
align-self: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 480px) {
|
||||||
|
.player-chips {
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chips {
|
||||||
|
gap: 8px;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.chip {
|
||||||
|
padding: 6px 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pg-btn.compact {
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pg-ind {
|
||||||
|
font-size: 11px;
|
||||||
|
min-width: 30px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user