diff --git a/client/src/views/UuidSelector.vue b/client/src/views/UuidSelector.vue index becb7bd..a7e3107 100644 --- a/client/src/views/UuidSelector.vue +++ b/client/src/views/UuidSelector.vue @@ -17,19 +17,37 @@ 🔍 -
-
-
{{ getUuidIndex(uuidInfo.uuid) }}
-
{{ uuidInfo.name }}
-
{{ formatUuid(uuidInfo.uuid) }}
+ +
+
+

Cargando UUIDs...

+
+ + +
+
+
+
{{ getUuidIndex(uuidInfo.uuid) }}
+
{{ uuidInfo.name }}
+
{{ formatUuid(uuidInfo.uuid) }}
+
+
+ +
+ +
@@ -74,20 +92,6 @@
- -
-
-

Cargando UUIDs...

-
- -
- - -
@@ -131,10 +135,26 @@ const printModal = ref({ onMounted(async () => { try { + console.log('Loading UUIDs with names...'); const response = await fetch(`${import.meta.env.VITE_API_URL || 'http://localhost:3000/api'}/admin/uuids-with-names`); - const data = await response.json(); - allUuids.value = data.uuids || []; - filteredUuids.value = allUuids.value; // Show all UUIDs + + if (!response.ok) { + console.warn('Failed to fetch uuids-with-names, trying fallback...'); + // Fallback to regular UUIDs endpoint + const fallbackResponse = await fetch(`${import.meta.env.VITE_API_URL || 'http://localhost:3000/api'}/admin/uuids`); + const fallbackData = await fallbackResponse.json(); + allUuids.value = (fallbackData.uuids || []).map((uuid: string) => ({ + uuid, + name: null, + hasName: false + })); + } else { + const data = await response.json(); + allUuids.value = data.uuids || []; + } + + filteredUuids.value = allUuids.value; + console.log(`Loaded ${allUuids.value.length} UUIDs`); } catch (error) { console.error('Failed to load UUIDs:', error); allUuids.value = []; @@ -192,10 +212,8 @@ function showContextMenu(event: MouseEvent, uuidInfo: UuidInfo) { } // Hide context menu when clicking elsewhere -onMounted(() => { - document.addEventListener('click', () => { - contextMenu.value.visible = false; - }); +document.addEventListener('click', () => { + contextMenu.value.visible = false; }); // QR Print functions diff --git a/client/src/views/games/OfferControls.vue b/client/src/views/games/OfferControls.vue index 210bba9..3712ee5 100644 --- a/client/src/views/games/OfferControls.vue +++ b/client/src/views/games/OfferControls.vue @@ -1,7 +1,53 @@ @@ -66,6 +112,7 @@ const offerPavo = ref(0); const offerElote = ref(0); const requestPavo = ref(0); const requestElote = ref(0); +const advancedMode = ref(false); // Start in basic mode const room = computed(() => colyseusService.gameRoom.value as any); const p1 = computed(() => room.value?.state ? room.value.state.players.get(room.value.state.p1Id) : null); @@ -76,6 +123,7 @@ const maxOfferElote = computed(() => (p1.value?.eloteTokens ?? Infinity)); const maxRequestPavo = computed(() => (p2.value?.pavoTokens ?? Infinity)); const maxRequestElote = computed(() => (p2.value?.eloteTokens ?? Infinity)); const isNonsense = computed(() => (offerPavo.value|0) === (requestPavo.value|0) && (offerElote.value|0) === (requestElote.value|0)); +const canMakeBasicOffer = computed(() => (p1.value?.pavoTokens ?? 0) >= 3); function clampAll() { offerPavo.value = Math.max(0, Math.min(offerPavo.value | 0, maxOfferPavo.value)); @@ -127,6 +175,18 @@ function propose() { requestElote.value = 0; } +function proposeBasic() { + if (isFinished.value || !canMakeBasicOffer.value) return; + // Send fixed basic offer: 3 pavos for 3 elotes + const payload = { + offerPavo: 3, + offerElote: 0, + requestPavo: 0, + requestElote: 3 + }; + emit('propose', payload); +} + function noOffer() { if (isFinished.value) return; // Clear inputs @@ -169,4 +229,152 @@ function noOffer() { .btn.ghost:disabled { opacity:0.5; cursor:not-allowed; } .btn.primary:disabled { opacity: 0.5; cursor: not-allowed; box-shadow: none; } .ctrl input:disabled { background: #f8fafc; color:#94a3b8; } + +/* Mode Toggle */ +.mode-toggle { + display: flex; + background: #f1f5f9; + border-radius: 12px; + padding: 4px; + margin-bottom: 16px; + gap: 2px; +} + +.mode-btn { + flex: 1; + padding: 8px 12px; + border: none; + border-radius: 8px; + font-size: 14px; + font-weight: 600; + cursor: pointer; + transition: all 0.2s; + background: transparent; + color: #64748b; +} + +.mode-btn.active { + background: #667eea; + color: white; + box-shadow: 0 2px 8px rgba(102, 126, 234, 0.25); +} + +.mode-btn:hover:not(.active) { + background: #e2e8f0; + color: #475569; +} + +/* Basic Mode */ +.basic-mode { + padding: 12px; + background: linear-gradient(135deg, #f8fafc 0%, #e2e8f0 100%); + border-radius: 12px; + border: 1px solid #e5e9f0; +} + +.basic-offer { + text-align: center; +} + +.offer-text { + font-size: 16px; + font-weight: 600; + color: #334155; + margin-bottom: 16px; + line-height: 1.4; +} + +.token.pill { + display: inline-flex; + align-items: center; + gap: 4px; + padding: 4px 8px; + border-radius: 999px; + background: #f7f7f7; + border: 1px solid #eee; + white-space: nowrap; +} + +.token.pill .icon { + font-size: 14px; +} + +.token.pill .val { + font-weight: 600; + color: #333; + display: inline-block; + min-width: 1ch; +} + +.basic-actions { + display: flex; + flex-direction: column; + gap: 8px; + align-items: stretch; +} + +.btn.large { + padding: 10px 16px; + font-size: 14px; + border-radius: 10px; + width: 100%; + min-height: 44px; +} + +.btn.primary.large { + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + box-shadow: 0 2px 8px rgba(102, 126, 234, 0.3); + transform: translateY(0); + transition: all 0.2s; +} + +.btn.primary.large:hover:not(:disabled) { + transform: translateY(-1px); + box-shadow: 0 4px 12px rgba(102, 126, 234, 0.4); +} + +.btn.ghost.large { + background: white; + color: #64748b; + border: 1px solid #e2e8f0; +} + +.btn.ghost.large:hover:not(:disabled) { + background: #f8fafc; + border-color: #cbd5e1; +} + +@media (min-width: 320px) { + .offer-text { + font-size: 14px; + margin-bottom: 12px; + } + + .basic-mode { + padding: 16px; + } +} + +@media (min-width: 480px) { + .basic-actions { + flex-direction: row; + gap: 12px; + } + + .btn.large { + width: auto; + min-width: 140px; + padding: 12px 20px; + font-size: 15px; + } + + .offer-text { + font-size: 16px; + margin-bottom: 16px; + } + + .basic-mode { + padding: 20px; + } +}