From f4a0e18686cf741750685955652a1ff9a1db7804 Mon Sep 17 00:00:00 2001 From: haunter Date: Fri, 1 May 2026 21:11:47 +0300 Subject: [PATCH] redesign of recruit troops --- static/js/api.js | 2 +- static/js/components/commandForm.js | 144 +++++++++++++++++++--------- static/js/state.js | 2 +- templates/dashboard.html | 47 ++++----- 4 files changed, 116 insertions(+), 79 deletions(-) diff --git a/static/js/api.js b/static/js/api.js index 795a8dd..d7eb683 100644 --- a/static/js/api.js +++ b/static/js/api.js @@ -132,7 +132,7 @@ window.sendCommand = async function() { payload = { building_id }; } else if (type === 'recruit') { - const unit_id = document.getElementById('unit-select').value; + const unit_id = window.selectedUnitId; if (!unit_id) return alert('Παρακαλώ επιλέξτε Μονάδα προς εκπαίδευση.'); const amount = parseInt(document.getElementById('recruit-amount').value) || 1; diff --git a/static/js/components/commandForm.js b/static/js/components/commandForm.js index a7dd21b..a844711 100644 --- a/static/js/components/commandForm.js +++ b/static/js/components/commandForm.js @@ -240,70 +240,122 @@ window.selectResearch = function(key, name) { +window.selectedUnitId = null; +window.UNIT_ICONS = { + sword: '⚔️', slinger: '🪨', archer: '🏹', hoplite: '🛡️', + rider: '🐎', chariot: '🛷', catapult: '☄️', godsent: '👼', + big_transporter: '⛴️', small_transporter: '🚤', bireme: '🛶', + attack_ship: '🔥', trireme: '🔱', colonize_ship: '⚓', + medusa: '🐍', zyklop: '👁️', harpy: '🦅', pegasus: '🐴', + minotaur: '🐂', manticore: '🦁', cerberus: '🐕', + hydra: '🐉', sea_monster: '🦑', militia: '🧑‍🌾' +}; window.renderUnitDropdown = function() { + // No-op - selection now happens via modal +}; + +window.openUnitModal = function() { const town = window.getSelectedTown(); if (!town) return; - const uSelect = document.getElementById('unit-select'); - const uData = town.unit_data || {}; + const grid = document.getElementById('unit-grid'); + const uData = town.unit_data || {}; - const currentVal = uSelect.value; - uSelect.innerHTML = ''; + // Group units into categories for better display + const categories = { + 'Ξηρά': ['sword', 'slinger', 'archer', 'hoplite', 'rider', 'chariot', 'catapult', 'godsent'], + 'Ναυτικές': ['big_transporter', 'small_transporter', 'bireme', 'attack_ship', 'trireme', 'colonize_ship'], + 'Μυθικές': ['medusa', 'zyklop', 'harpy', 'pegasus', 'minotaur', 'manticore', 'cerberus', 'hydra', 'sea_monster'] + }; - for (const [key, nameGr] of Object.entries(window.UNIT_NAMES_GR)) { - if (key === 'militia') continue; + let html = ''; + + for (const [catName, units] of Object.entries(categories)) { + let catHtml = ''; - const data = uData[key]; - let text = `${nameGr}`; - - if (data) { - const w = window.fmt(data.wood || 0); - const st = window.fmt(data.stone || 0); - const i = window.fmt(data.iron || 0); - const pop = data.pop || 0; + for (const key of units) { + if (key === 'militia') continue; - // Unit build_time is usually raw seconds in GameData - let t = data.build_time || 0; - let tStr = `${t}s`; - if (t > 60) { - let m = Math.floor(t / 60); - let s = t % 60; - tStr = `${m}m ${s}s`; - } + const nameGr = window.UNIT_NAMES_GR[key] || key; + const data = uData[key]; + const icon = window.UNIT_ICONS[key] || '💂'; + const isSelected = key === window.selectedUnitId; - const costStr = `Ξ:${w} Π:${st} Α:${i} 🧔:${pop} · ⏱ ${tStr}`; - - const missingKeys = data.missing_dependencies ? Object.keys(data.missing_dependencies) : []; - const isLocked = missingKeys.length > 0; - - const option = document.createElement('option'); - option.value = key; - - if (isLocked) { - option.textContent = `${text} — 🔒 Κλειδωμένο`; - option.style.color = '#ff4444'; - } else if (data.enough_resources === false) { - option.textContent = `${text} — ❌ ${costStr} (Λείπουν Πόροι 1x)`; - option.style.color = '#aa5555'; + let statusClass, statusLabel, cardClass = ''; + let costStr = ''; + let clickable = false; + + if (data) { + const missingKeys = data.missing_dependencies ? Object.keys(data.missing_dependencies) : []; + const isLocked = missingKeys.length > 0; + + const w = window.fmt(data.wood || 0); + const st = window.fmt(data.stone || 0); + const i = window.fmt(data.iron || 0); + const pop = data.pop || 0; + + let t = data.build_time || 0; + let tStr = `${t}s`; + if (t > 60) { + let m = Math.floor(t / 60); + let s = t % 60; + tStr = `${m}m ${s}s`; + } + + // Show favor if it's a mythical unit or godsent + const favorStr = (data.favor && data.favor > 0) ? ` ⚡:${data.favor}` : ''; + costStr = `Ξ:${w} Π:${st} Α:${i}${favorStr} 🧔:${pop} · ⏱ ${tStr}`; + + if (isLocked) { + statusClass = 'locked'; statusLabel = '🔒 Κλειδωμένο'; cardClass = 'bld-locked'; + } else if (data.enough_resources === false) { + statusClass = 'no-resources'; statusLabel = '❌ Λείπουν Πόροι'; + } else { + statusClass = 'can-build'; statusLabel = '✅ Διαθέσιμο'; + clickable = true; + } } else { - option.textContent = `${text} — ✅ ${costStr}`; + // If no data is available for this unit, treat it as locked/unknown + statusClass = 'locked'; statusLabel = '🔒 Άγνωστο'; cardClass = 'bld-locked'; } - uSelect.appendChild(option); - } else { - const option = document.createElement('option'); - option.value = key; - option.textContent = text; - uSelect.appendChild(option); + const onclick = clickable ? `onclick="window.selectUnit('${key}', '${nameGr}')"` : ''; + + catHtml += `
+ ${icon} + ${nameGr} + ${statusLabel} + ${costStr} +
`; + } + + if (catHtml) { + html += `

${catName}

+
${catHtml}
+
`; } } - if (currentVal && Array.from(uSelect.options).some(o => o.value === currentVal)) { - uSelect.value = currentVal; - } + grid.innerHTML = html; + document.getElementById('unit-modal-overlay').classList.add('open'); }; +window.closeUnitModal = function(e) { + if (e && e.target !== document.getElementById('unit-modal-overlay') && e.target !== document.getElementById('unit-modal-close')) return; + document.getElementById('unit-modal-overlay').classList.remove('open'); +}; + +window.selectUnit = function(key, nameGr) { + window.selectedUnitId = key; + document.getElementById('selected-unit-label').textContent = `${window.UNIT_ICONS[key] || '💂'} ${nameGr}`; + window.openUnitModal(); + setTimeout(() => document.getElementById('unit-modal-overlay').classList.remove('open'), 180); +}; + +// ================================================================ + + window.renderBuildQueuePreview = function() { const town = window.getSelectedTown(); const el = document.getElementById('build-queue-preview'); diff --git a/static/js/state.js b/static/js/state.js index d899f10..0010120 100644 --- a/static/js/state.js +++ b/static/js/state.js @@ -25,7 +25,7 @@ window.BUILDING_NAMES_GR = { window.UNIT_NAMES_GR = { sword: "Ξιφομάχος", slinger: "Σφενδονήτης", archer: "Τοξότης", hoplite: "Οπλίτης", - rider: "Ιππέας", chariot: "Άρμα", catapult: "Καταπέλτης", + rider: "Ιππέας", chariot: "Άρμα", catapult: "Καταπέλτης", godsent: "Θεόσταλτος", big_transporter: "Μεταφορικό", small_transporter: "Γρήγ. Μεταφορικό", bireme: "Διήρης", attack_ship: "Πλοίο Φάρος", trireme: "Τριήρης", colonize_ship: "Αποικιακό", medusa: "Μέδουσα", zyklop: "Κύκλωπας", harpy: "Άρπυια", pegasus: "Πήγασος", diff --git a/templates/dashboard.html b/templates/dashboard.html index 8f29705..593732d 100644 --- a/templates/dashboard.html +++ b/templates/dashboard.html @@ -114,37 +114,11 @@ @@ -243,6 +217,17 @@ + + +