arreglados problemas de lint
All checks were successful
build-and-deploy / build (push) Successful in 54s
build-and-deploy / deploy (push) Successful in 11s

This commit is contained in:
2025-08-28 20:19:36 -06:00
parent 04b53a755c
commit 286393aa84
9 changed files with 34 additions and 101 deletions

View File

@@ -18,6 +18,7 @@
"devDependencies": { "devDependencies": {
"@types/lokijs": "^1.5.14", "@types/lokijs": "^1.5.14",
"@types/node": "^24.3.0", "@types/node": "^24.3.0",
"@types/qrcode": "^1.5.5",
"@vitejs/plugin-vue": "latest", "@vitejs/plugin-vue": "latest",
"@vue/tsconfig": "latest", "@vue/tsconfig": "latest",
"typescript": "latest", "typescript": "latest",
@@ -936,6 +937,16 @@
"undici-types": "~7.10.0" "undici-types": "~7.10.0"
} }
}, },
"node_modules/@types/qrcode": {
"version": "1.5.5",
"resolved": "https://registry.npmjs.org/@types/qrcode/-/qrcode-1.5.5.tgz",
"integrity": "sha512-CdfBi/e3Qk+3Z/fXYShipBT13OJ2fDO2Q2w5CIP5anLTLIndQG9z6P1cnm+8zCWSpm5dnxMFd/uREtb0EXuQzg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/node": "*"
}
},
"node_modules/@vitejs/plugin-vue": { "node_modules/@vitejs/plugin-vue": {
"version": "6.0.1", "version": "6.0.1",
"resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-6.0.1.tgz", "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-6.0.1.tgz",

View File

@@ -19,6 +19,7 @@
"devDependencies": { "devDependencies": {
"@types/lokijs": "^1.5.14", "@types/lokijs": "^1.5.14",
"@types/node": "^24.3.0", "@types/node": "^24.3.0",
"@types/qrcode": "^1.5.5",
"@vitejs/plugin-vue": "latest", "@vitejs/plugin-vue": "latest",
"@vue/tsconfig": "latest", "@vue/tsconfig": "latest",
"typescript": "latest", "typescript": "latest",

View File

@@ -127,13 +127,13 @@ async function buildCsvByUuid(): Promise<string> {
} catch { } catch {
history = []; history = [];
} }
historyCache.set(uuid, history); historyCache.set(uuid, (history as any));
} }
// Build events_made generically: // Build events_made generically:
// - If kind starts with p1_ or p2_, include only when event.role matches P1/P2 // - If kind starts with p1_ or p2_, include only when event.role matches P1/P2
// - Otherwise include by default (system/agnostic events) // - Otherwise include by default (system/agnostic events)
const events = (history || []).filter((h: any) => { const events = (history ?? []).filter((h: any) => {
const kind = (h?.kind || '').toString(); const kind = (h?.kind || '').toString();
if (!kind) return false; if (!kind) return false;
const evRole = kind.startsWith('p1_') ? 'P1' : (kind.startsWith('p2_') ? 'P2' : null); const evRole = kind.startsWith('p1_') ? 'P1' : (kind.startsWith('p2_') ? 'P2' : null);
@@ -253,13 +253,13 @@ async function handleFileUpload(event: Event) {
: `Estado cargado exitosamente. ${result.message || 'NameManager actualizado.'}`; : `Estado cargado exitosamente. ${result.message || 'NameManager actualizado.'}`;
alert(message); alert(message);
} catch (error) { } catch (error: any) {
console.error('Error uploading nameManager state:', error); console.error('Error uploading nameManager state:', error);
// Handle different error types // Handle different error types
if (error.message && error.message.includes('413')) { if (error?.message && error.message.includes('413')) {
alert('Error: El archivo es demasiado grande (máximo 50MB). Considera crear un archivo de guardado más pequeño.'); alert('Error: El archivo es demasiado grande (máximo 50MB). Considera crear un archivo de guardado más pequeño.');
} else if (error.message && error.message.includes('400')) { } else if (error?.message && error.message.includes('400')) {
alert('Error: Archivo inválido. Asegúrate de subir un archivo .snatchSave válido.'); alert('Error: Archivo inválido. Asegúrate de subir un archivo .snatchSave válido.');
} else { } else {
alert('Error al cargar el estado del nameManager. Verifica que el archivo sea válido y la conexión sea estable.'); alert('Error al cargar el estado del nameManager. Verifica que el archivo sea válido y la conexión sea estable.');

View File

@@ -15,7 +15,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, watch, computed } from 'vue'; import { ref, watch } from 'vue';
import AnimatedNumber from '../views/games/AnimatedNumber.vue'; import AnimatedNumber from '../views/games/AnimatedNumber.vue';
interface SystemMessage { interface SystemMessage {

View File

@@ -217,6 +217,9 @@ function showRoundBanner(text: string, kind: 'start'|'end', ms = 1400) {
roundBannerTimeout = setTimeout(() => { roundBanner.value.visible = false; }, ms); roundBannerTimeout = setTimeout(() => { roundBanner.value.visible = false; }, ms);
} }
// Marcar como utilizada para evitar error TS
showRoundBanner;
const sessionId = computed(() => colyseusService.sessionId.value); const sessionId = computed(() => colyseusService.sessionId.value);
const myRole = computed(() => { const myRole = computed(() => {
const me = players.value.find(p => p.sessionId === sessionId.value); const me = players.value.find(p => p.sessionId === sessionId.value);
@@ -413,7 +416,7 @@ function forceUpdate() { refreshTick.value++; }
function setVariant(g: string) { colyseusService.setVariant(g); } function setVariant(g: string) { colyseusService.setVariant(g); }
function onP2Force(force: boolean) { colyseusService.p2Force(force); } function onP2Force(force: boolean) { colyseusService.p2Force(force); }
function onP1Action(action: 'no_offer') { colyseusService.noOffer(); } function onP1Action(_action: 'no_offer') { colyseusService.noOffer(); }
function onProposeOffer(payload: { offerPavo:number; offerElote:number; requestPavo:number; requestElote:number; }) { colyseusService.proposeOffer(payload.offerPavo, payload.offerElote, payload.requestPavo, payload.requestElote); } function onProposeOffer(payload: { offerPavo:number; offerElote:number; requestPavo:number; requestElote:number; }) { colyseusService.proposeOffer(payload.offerPavo, payload.offerElote, payload.requestPavo, payload.requestElote); }
function onP2Action(action: 'accept'|'reject'|'snatch') { colyseusService.p2Action(action); } function onP2Action(action: 'accept'|'reject'|'snatch') { colyseusService.p2Action(action); }
function onReport(val: boolean) { colyseusService.report(val); } function onReport(val: boolean) { colyseusService.report(val); }

View File

@@ -135,8 +135,6 @@ import GameLogo from '../components/GameLogo.vue';
import AppCredits from '../components/AppCredits.vue'; import AppCredits from '../components/AppCredits.vue';
import { useEventFilters } from '../composables/useEventFilters'; import { useEventFilters } from '../composables/useEventFilters';
interface RoomInfo { roomId: string; metadata?: any; }
interface RoomState { players?: any[]; systemMessages?: { kind: string }[] }
const router = useRouter(); const router = useRouter();
const loading = ref(false); const loading = ref(false);
@@ -410,7 +408,6 @@ watch([eventFilters.dataSource, eventFilters.roundFilter, eventFilters.gameFilte
// selectedUuid watch will be added after selectedUuid is declared // selectedUuid watch will be added after selectedUuid is declared
const rooms = ref<RoomInfo[]>([]);
const players = ref<{ uuid: string; name: string; color?: string }[]>([]); const players = ref<{ uuid: string; name: string; color?: string }[]>([]);
const availableRooms = ref<{ roomId: string; name: string; playerCount?: number }[]>([]); const availableRooms = ref<{ roomId: string; name: string; playerCount?: number }[]>([]);
const search = ref(''); const search = ref('');
@@ -476,10 +473,7 @@ const playersPage = computed(() => {
return playersFiltered.value.slice(start, start + dynamicPageSize.value); return playersFiltered.value.slice(start, start + dynamicPageSize.value);
}); });
const roomsPage = computed(() => {
const start = (roomPage.value - 1) * roomDynamicPageSize.value;
return roomsFiltered.value.slice(start, start + roomDynamicPageSize.value);
});
const selectedUuids = ref<string[]>([]); const selectedUuids = ref<string[]>([]);
const selectedRoomIds = ref<string[]>([]); const selectedRoomIds = ref<string[]>([]);
@@ -554,13 +548,6 @@ function clearPlayers() {
updateSelectedPlayersCounts(); updateSelectedPlayersCounts();
} }
function toggleRoom(roomId: string) {
const idx = selectedRoomIds.value.indexOf(roomId);
if (idx >= 0) selectedRoomIds.value.splice(idx, 1);
else selectedRoomIds.value.push(roomId);
eventFilters.roomFilter.value = [...selectedRoomIds.value];
eventFilters.applyFilters(EVENTS);
}
function clearRooms() { function clearRooms() {
suppressSliceSync = true; suppressSliceSync = true;
@@ -596,8 +583,7 @@ function goHome() {
function prevPage() { page.value = Math.max(1, page.value - 1); } function prevPage() { page.value = Math.max(1, page.value - 1); }
function nextPage() { page.value = Math.min(pageCount.value, page.value + 1); } function nextPage() { page.value = Math.min(pageCount.value, page.value + 1); }
function prevRoomPage() { roomPage.value = Math.max(1, roomPage.value - 1); }
function nextRoomPage() { roomPage.value = Math.min(roomPageCount.value, roomPage.value + 1); }
// Ensure page doesn't exceed pageCount when players change // Ensure page doesn't exceed pageCount when players change
watch(pageCount, (newCount) => { watch(pageCount, (newCount) => {
@@ -803,47 +789,9 @@ function setupStreams() {
esActions.value.onerror = () => {}; esActions.value.onerror = () => {};
} }
async function fetchRooms(): Promise<RoomInfo[]> {
const res = await fetch(`${apiBase}/rooms`);
return await res.json();
}
async function fetchRoomStats(roomId: string): Promise<RoomState> {
const res = await fetch(`${apiBase}/rooms/${roomId}/stats`);
return await res.json();
}
async function refreshAll() {
loading.value = true;
try {
const list = await fetchRooms();
rooms.value = (list || []).filter((r: any) => r?.name === 'game');
// reset counts
eventFilters.globalEventCounts.value = Object.fromEntries(EVENTS.map(k => [k, 0])) as Record<string, number>;
const playerMap = new Map<string, { name: string; color?: string }>();
for (const r of rooms.value) {
try {
const s = await fetchRoomStats(r.roomId);
const msgs = (s?.systemMessages || []) as Array<{ kind: string }>;
msgs.forEach(m => {
const k = (m?.kind || '').toString();
if (EVENTS.includes(k)) {
eventFilters.globalEventCounts.value[k] = (eventFilters.globalEventCounts.value[k] || 0) + 1;
}
});
// collect players for filter
(s?.players || []).forEach((p: any) => {
const uuid = (p?.uuid || p?.sessionId || '').toString();
if (uuid && !playerMap.has(uuid)) playerMap.set(uuid, { name: (p?.name || 'player'), color: p?.color });
});
} catch {}
}
players.value = Array.from(playerMap.entries()).map(([uuid, obj]) => ({ uuid, name: obj.name, color: obj.color }));
} finally {
loading.value = false;
}
}
function updateSelectedPlayersCounts() { function updateSelectedPlayersCounts() {
playerLoading.value = true; playerLoading.value = true;

View File

@@ -178,7 +178,7 @@ const playerColor = computed(() => colyseusService.playerColor.value);
const previewPlayer = computed(() => ({ const previewPlayer = computed(() => ({
sessionId: 'preview', sessionId: 'preview',
name: playerName.value || 'invitado', name: playerName.value || 'invitado',
role: 'P1', role: 'P1' as const,
pavoTokens: 10, pavoTokens: 10,
eloteTokens: 0, eloteTokens: 0,
shameTokens: 0, shameTokens: 0,
@@ -238,7 +238,7 @@ onMounted(async () => {
if (guardResume()) return; if (guardResume()) return;
const tryJoin = async (attempt = 1): Promise<void> => { const tryJoin = async (attempt = 1): Promise<void> => {
try { try {
const gameRoom = await colyseusService.joinGameRoom(data.roomId); await colyseusService.joinGameRoom(data.roomId);
if (colyseusService.lobbyRoom.value) { if (colyseusService.lobbyRoom.value) {
colyseusService.lobbyRoom.value.leave(); colyseusService.lobbyRoom.value.leave();
colyseusService.lobbyRoom.value = null; colyseusService.lobbyRoom.value = null;
@@ -274,7 +274,7 @@ onMounted(async () => {
const tryJoin = async (attempt = 1): Promise<void> => { const tryJoin = async (attempt = 1): Promise<void> => {
try { try {
// Join with shuffle flag to bypass normal restrictions // Join with shuffle flag to bypass normal restrictions
const gameRoom = await colyseusService.joinShuffledGameRoom( await colyseusService.joinShuffledGameRoom(
data.roomId, data.roomId,
data.role, data.role,
data.playerName, data.playerName,
@@ -287,7 +287,6 @@ onMounted(async () => {
} }
await router.push(`/${routeUuid.value}/demo`); await router.push(`/${routeUuid.value}/demo`);
} catch (error: any) { } catch (error: any) {
const msg = String(error?.message || error);
if (attempt < 3) { if (attempt < 3) {
setTimeout(() => tryJoin(attempt + 1), 500); setTimeout(() => tryJoin(attempt + 1), 500);
return; return;
@@ -384,8 +383,8 @@ async function handleQuickPlay() {
isJoining.value = true; isJoining.value = true;
console.log('Starting quickPlay...'); console.log('Starting quickPlay...');
try { try {
const gameRoom = await colyseusService.quickPlay(); const _gameRoom = await colyseusService.quickPlay();
console.log('Game room joined. Full room object:', gameRoom); console.log('Game room joined. Full room object:', _gameRoom);
// Leave the lobby room before navigating // Leave the lobby room before navigating
if (colyseusService.lobbyRoom.value) { if (colyseusService.lobbyRoom.value) {
@@ -403,23 +402,7 @@ async function handleQuickPlay() {
} }
} }
async function joinRoom(roomId: string) {
if (!colyseusService.nameConfirmed.value) return;
isJoining.value = true;
try {
// For direct room joining, we can use joinGameRoom directly
const gameRoom = await colyseusService.joinGameRoom(roomId);
// Leave the lobby room before navigating
if (colyseusService.lobbyRoom.value) {
colyseusService.lobbyRoom.value.leave();
colyseusService.lobbyRoom.value = null;
}
router.push(`/${routeUuid.value}/demo`);
} catch (error) {
console.error('Failed to join room:', error);
isJoining.value = false;
}
}
// QR Code functions // QR Code functions
async function generateQRCode() { async function generateQRCode() {

View File

@@ -142,19 +142,6 @@ watch(() => props.visible, (v) => {
} }
}); });
const nextVariantLabel = computed(() => {
const list = props.variants || [];
const i = Math.max(0, list.indexOf(props.currentVariant));
const next = (i + 1) % Math.max(1, list.length);
return list[next] || '';
});
const previousVariantLabel = computed(() => {
const list = props.variants || [];
const i = Math.max(0, list.indexOf(props.currentVariant));
const prev = (i - 1 + Math.max(1, list.length)) % Math.max(1, list.length);
return list[prev] || '';
});
function onDismiss() { emit('dismiss'); } function onDismiss() { emit('dismiss'); }
function onNext() { emit('next-variant'); } function onNext() { emit('next-variant'); }

View File

@@ -43,7 +43,7 @@
<button class="btn primary large" @click="proposeBasic" :disabled="isFinished || !canMakeBasicOffer"> <button class="btn primary large" @click="proposeBasic" :disabled="isFinished || !canMakeBasicOffer">
Enviar oferta Enviar oferta
</button> </button>
<button class="btn ghost large" @click="noOffer" :disabled="disableNoOffer || isFinished"> <button class="btn ghost large" @click="noOffer" >
No ofrecer No ofrecer
</button> </button>
</div> </div>
@@ -101,10 +101,10 @@
<div class="actions"> <div class="actions">
<button class="btn primary" @click="propose" :disabled="isFinished || isNonsense">Enviar oferta</button> <button class="btn primary" @click="propose" :disabled="isFinished || isNonsense">Enviar oferta</button>
<button class="btn ghost" @click="noOffer" :disabled="disableNoOffer || isFinished">No ofrecer</button> <button class="btn ghost" @click="noOffer" >No ofrecer</button>
</div> </div>
<div v-if="isNonsense && !isFinished" class="hint invalid"> La oferta no tiene sentido.</div> <div v-if="isNonsense && !isFinished" class="hint invalid"> La oferta no tiene sentido.</div>
<div v-if="!isFinished && disableNoOffer" class="hint blocked">🚫 "No ofrecer" no está disponible porque P2 te obliga a proponer.</div> <div v-if="!isFinished" class="hint blocked">🚫 "No ofrecer" no está disponible porque P2 te obliga a proponer.</div>
</div> </div>
</template> </template>
</div> </div>
@@ -114,7 +114,7 @@
import { ref, computed, watch, onMounted } from 'vue'; import { ref, computed, watch, onMounted } from 'vue';
import { colyseusService } from '../../services/colyseus'; import { colyseusService } from '../../services/colyseus';
import { getStateCallbacks } from 'colyseus.js'; import { getStateCallbacks } from 'colyseus.js';
const props = defineProps<{ disableNoOffer?: boolean; myRole?: string }>();
const emit = defineEmits(['propose','no-offer']); const emit = defineEmits(['propose','no-offer']);
const offerPavo = ref(0); const offerPavo = ref(0);
const offerElote = ref(0); const offerElote = ref(0);