feat: add visual avatar picker for equipping new relics and light cones

- replace the ~100-option avatar <select>s in Add Relic / Add Light Cone with a searchable picker modal (keep-in-inventory card + avatar cards with element/path/level)
- warn when the chosen character already wears a relic in that slot or a light cone
- click+Confirm or double-click applies; Esc closes only the picker; search autofocused
- localize all new strings (th/en, other locales fall back to en) and refresh chips/picker on language change
- add AGENTS.md with localization and cache-busting rules
- bump app.js v3.20, styles.css v2.29, i18n.js v2.17 and align all i18n imports
This commit is contained in:
CAtlas0784 committed 2026-11-02 09:21:53 +07:00
1 parent 303332469a
commit 083848ee6e
9 files changed
+347 -41

No files matched your search

+28
View File
@@ -7049,6 +7049,20 @@ for (const [language, description] of Object.entries(ITEM_CATALOG_INTERACTION_DE
// language falls back to en through t(), so no Thai leaks into other locales.
const MODAL_AND_TOOL_TRANSLATIONS = {
th: {
assignPickerTitleRelic: 'สวมใส่รีลิกส์ให้ตัวละคร',
assignPickerTitleLc: 'สวมใส่กรวยแสงให้ตัวละคร',
assignPickerSubtitle: 'เลือกตัวละครที่จะสวมใส่ {item} — หรือเก็บไว้ในคลัง',
assignPickerSearch: '🔍 ค้นหาชื่อหรือ ID ตัวละคร...',
assignKeepInventory: 'เก็บในคลัง (ไม่สวมใส่)',
assignKeepInventoryHint: 'ไอเท็มจะถูกเพิ่มโดยไม่ผูกกับตัวละคร',
assignChoose: 'เลือก',
assignChange: 'เปลี่ยน',
assignChooseHint: 'ยังไม่ได้ผูกกับตัวละคร — คลิกเพื่อเลือก',
assignCurrent: 'เลือกอยู่:',
assignConfirm: 'ตกลง',
assignReplaceLc: 'มีกรวยแสงอยู่แล้ว: {name} (จะถูกแทนที่)',
assignReplaceRelic: 'สล็อตนี้มีอยู่แล้ว: {name} (จะถูกแทนที่)',
assignNoResults: 'ไม่พบตัวละครที่ตรงกับเงื่อนไข',
relicSlotNotEquipped: 'ยังไม่ได้สวมใส่',
relicSlotCreateHint: '+ คลิกเพื่อเลือกหรือสร้าง (แนะนำ: {stat})',
relicSlotUnequip: 'ถอดชิ้นนี้',
@@ -7148,6 +7162,20 @@ const MODAL_AND_TOOL_TRANSLATIONS = {
analystDamageAvPlaceholder: "เฉลี่ยต่อรอบ: -", analystCyclesPlaceholder: "0 รอบ", analystTurnsPlaceholder: "0 เทิร์น", analystAutoTurnsPlaceholder: "เทิร์นอัตโนมัติ: 0", analystDamageAvPlaceholder: "Avg per cycle: -", analystCyclesPlaceholder: "0 Cycles", analystTurnsPlaceholder: "0 Turns", analystAutoTurnsPlaceholder: "Auto Turns: 0", analystDamageAvPlaceholder: "ラウンド平均: -", analystCyclesPlaceholder: "0 ラウンド", analystTurnsPlaceholder: "0 ターン", analystAutoTurnsPlaceholder: "オートターン: 0", analystDamageAvPlaceholder: "라운드당 평균: -", analystCyclesPlaceholder: "0 라운드", analystTurnsPlaceholder: "0 턴", analystAutoTurnsPlaceholder: "자동 턴: 0", analystDamageAvPlaceholder: "Trung bình mỗi vòng: -", analystCyclesPlaceholder: "0 vòng", analystTurnsPlaceholder: "0 lượt", analystAutoTurnsPlaceholder: "Lượt tự động: 0", analystDamageAvPlaceholder: "Rata-rata per siklus: -", analystCyclesPlaceholder: "0 Siklus", analystTurnsPlaceholder: "0 Giliran", analystAutoTurnsPlaceholder: "Giliran otomatis: 0", analystDamageAvPlaceholder: "Promedio por ciclo: -", analystCyclesPlaceholder: "0 ciclos", analystTurnsPlaceholder: "0 turnos", analystAutoTurnsPlaceholder: "Turnos automáticos: 0", analystDamageAvPlaceholder: "Moyenne par cycle : -", analystCyclesPlaceholder: "0 cycle", analystTurnsPlaceholder: "0 tour", analystAutoTurnsPlaceholder: "Tours auto : 0", analystDamageAvPlaceholder: "Durchschnitt pro Zyklus: -", analystCyclesPlaceholder: "0 Zyklen", analystTurnsPlaceholder: "0 Züge", analystAutoTurnsPlaceholder: "Auto-Züge: 0", analystDamageAvPlaceholder: "В среднем за цикл: -", analystCyclesPlaceholder: "0 циклов", analystTurnsPlaceholder: "0 ходов", analystAutoTurnsPlaceholder: "Авто-ходы: 0", analystDamageAvPlaceholder: "Média por ciclo: -", analystCyclesPlaceholder: "0 ciclos", analystTurnsPlaceholder: "0 turnos", analystAutoTurnsPlaceholder: "Turnos automáticos: 0", miniViewFullAnalystTooltip: "เปิดหน้า Damage Analyst ตัวเต็ม", miniViewFullAnalystTooltip: "Open full Damage Analyst", miniViewFullAnalystTooltip: "完全なダメージ分析を開く", miniViewFullAnalystTooltip: "전체 데미지 분석 열기", miniViewFullAnalystTooltip: "Mở Trình phân tích sát thương đầy đủ", miniViewFullAnalystTooltip: "Buka Analis Kerusakan Lengkap", miniViewFullAnalystTooltip: "Abrir analizador de daño completo", miniViewFullAnalystTooltip: "Ouvrir l'analyseur de dégâts complet", miniViewFullAnalystTooltip: "Vollständigen Schadensanalysten öffnen", miniViewFullAnalystTooltip: "Открыть полный анализ урона", miniViewFullAnalystTooltip: "Abrir analisador de dano completo", copyCardGenerated: 'สร้างโดย GaCy-Srtool'
},
en: {
assignPickerTitleRelic: 'Equip Relic to a Character',
assignPickerTitleLc: 'Equip Light Cone to a Character',
assignPickerSubtitle: 'Choose who wears {item} — or keep it in your inventory',
assignPickerSearch: '🔍 Search character name or ID...',
assignKeepInventory: 'Keep in inventory (unequipped)',
assignKeepInventoryHint: 'The item is added without being bound to a character',
assignChoose: 'Choose',
assignChange: 'Change',
assignChooseHint: 'Not bound to a character — click to choose',
assignCurrent: 'Selected:',
assignConfirm: 'Confirm',
assignReplaceLc: 'Already has a Light Cone: {name} (will be replaced)',
assignReplaceRelic: 'This slot is occupied: {name} (will be replaced)',
assignNoResults: 'No characters match your search',
relicSlotNotEquipped: 'Not equipped',
relicSlotCreateHint: '+ Click to choose or create (recommended: {stat})',
relicSlotUnequip: 'Unequip this piece',