diff --git a/css/styles.css b/css/styles.css index b2e7e6e..a848e53 100644 --- a/css/styles.css +++ b/css/styles.css @@ -1715,3 +1715,217 @@ input:checked + .slider:before { font-size: 0.7rem; color: var(--text-muted); } + +/* ========================================================================== + Equipment Inventory Tiles Grid & Inspector (Matching srtools neonteam) + ========================================================================== */ +.eq-tiles-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(105px, 1fr)); + gap: 0.75rem; + max-height: 720px; + overflow-y: auto; + padding-right: 0.35rem; +} + +.eq-tile-card { + position: relative; + background: var(--bg-card); + border: 2px solid rgba(255, 255, 255, 0.1); + border-radius: 10px; + overflow: hidden; + cursor: pointer; + transition: transform 0.2s cubic-bezier(0.16, 1, 0.3, 1), border-color 0.2s, box-shadow 0.2s; + aspect-ratio: 0.78; + display: flex; + flex-direction: column; + justify-content: flex-end; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4); + user-select: none; +} + +.eq-tile-card:hover { + transform: translateY(-4px) scale(1.03); + border-color: var(--accent-cyan); + box-shadow: 0 8px 24px rgba(56, 189, 248, 0.3); + z-index: 3; +} + +.eq-tile-card.active { + border-color: var(--accent-gold); + box-shadow: 0 0 0 2px var(--accent-gold), 0 8px 25px rgba(234, 179, 8, 0.45); +} + +.eq-tile-card.rarity-5 { + border-color: rgba(234, 179, 8, 0.5); + background: radial-gradient(circle at 50% 20%, rgba(234, 179, 8, 0.25) 0%, rgba(15, 23, 42, 0.95) 85%); +} + +.eq-tile-card.rarity-4 { + border-color: rgba(168, 85, 247, 0.5); + background: radial-gradient(circle at 50% 20%, rgba(168, 85, 247, 0.25) 0%, rgba(15, 23, 42, 0.95) 85%); +} + +.eq-tile-card.rarity-3 { + border-color: rgba(56, 189, 248, 0.5); + background: radial-gradient(circle at 50% 20%, rgba(56, 189, 248, 0.25) 0%, rgba(15, 23, 42, 0.95) 85%); +} + +.eq-tile-img { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + object-fit: cover; + transition: transform 0.3s ease; +} + +.eq-tile-card:hover .eq-tile-img { + transform: scale(1.08); +} + +.eq-tile-top-tag { + position: absolute; + top: 6px; + left: 6px; + background: rgba(11, 15, 25, 0.85); + border: 1px solid rgba(255, 255, 255, 0.2); + color: var(--accent-gold); + font-weight: 800; + font-size: 0.7rem; + padding: 0.1rem 0.35rem; + border-radius: 4px; + z-index: 2; + display: flex; + align-items: center; + gap: 0.2rem; + backdrop-filter: blur(4px); +} + +.eq-tile-wearer-badge { + position: absolute; + top: 6px; + right: 6px; + width: 28px; + height: 28px; + border-radius: 50%; + border: 1.5px solid var(--accent-gold); + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.8); + overflow: hidden; + z-index: 2; + background: #000; +} + +.eq-tile-wearer-img { + width: 100%; + height: 100%; + object-fit: cover; +} + +.eq-tile-bottom-bar { + position: relative; + z-index: 2; + background: linear-gradient(to top, rgba(11, 15, 25, 0.95) 0%, rgba(11, 15, 25, 0.75) 70%, transparent 100%); + padding: 0.4rem 0.5rem 0.35rem; + display: flex; + justify-content: space-between; + align-items: center; +} + +.eq-tile-level { + font-size: 0.725rem; + font-weight: 800; + color: #fff; + font-family: monospace; +} + +.eq-tile-name-snippet { + font-size: 0.675rem; + color: var(--text-muted); + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + max-width: 65px; +} + +/* Side Inspector Card */ +.eq-inspector-wrapper { + background: linear-gradient(135deg, rgba(20, 27, 45, 0.95) 0%, rgba(15, 23, 42, 0.98) 100%); + border: 1px solid var(--border-color); + border-radius: var(--radius-lg); + padding: 1.25rem; + display: flex; + flex-direction: column; + gap: 0.85rem; + box-shadow: 0 12px 36px rgba(0, 0, 0, 0.6); +} + +.eq-inspector-hero { + display: flex; + gap: 1rem; + align-items: center; +} + +.eq-inspector-thumb { + width: 72px; + height: 96px; + border-radius: 8px; + object-fit: cover; + border: 1.5px solid var(--accent-gold); + flex-shrink: 0; + box-shadow: 0 4px 16px rgba(0, 0, 0, 0.6); +} + +.eq-inspector-info { + flex: 1; + min-width: 0; +} + +.eq-inspector-title { + font-weight: 800; + font-size: 1rem; + color: #fff; + line-height: 1.3; +} + +.eq-inspector-stars { + color: var(--accent-gold); + font-size: 0.85rem; + margin-top: 0.2rem; +} + +.eq-inspector-stats { + background: rgba(11, 15, 25, 0.75); + border: 1px solid var(--border-color); + border-radius: var(--radius-md); + padding: 0.75rem; + display: flex; + flex-direction: column; + gap: 0.35rem; + font-size: 0.8rem; +} + +.eq-inspector-stat-row { + display: flex; + justify-content: space-between; + align-items: center; +} + +.eq-inspector-ability { + background: rgba(11, 15, 25, 0.75); + border: 1px solid rgba(56, 189, 248, 0.2); + border-radius: var(--radius-md); + padding: 0.75rem; + font-size: 0.775rem; + line-height: 1.5; + color: #cbd5e1; +} + +.eq-inspector-actions { + display: flex; + flex-direction: column; + gap: 0.5rem; + margin-top: 0.5rem; +} + diff --git a/index.html b/index.html index c52edd2..6aa1b90 100644 --- a/index.html +++ b/index.html @@ -246,35 +246,64 @@
-
- -
-
-
- ðŸ—Ąïļ āļāļĢāļ§āļĒāđāļŠāļ‡āđƒāļ™āļ„āļĨāļąāļ‡ - 0 āļŠāļīāđ‰āļ™ -
- + +
+
+ + +
+ +
-

āļĢāļēāļĒāļāļēāļĢāļāļĢāļ§āļĒāđāļŠāļ‡āļ—āļąāđ‰āļ‡āļŦāļĄāļ”āļˆāļēāļ freesr-data.json

-
-
āļāļģāļĨāļąāļ‡āđ‚āļŦāļĨāļ”āļ‚āđ‰āļ­āļĄāļđāļĨāļāļĢāļ§āļĒāđāļŠāļ‡...
+ + +
+ + + + +
+ + +
+ + +
+
+
+ + +
+ +
+
+
āļāļģāļĨāļąāļ‡āđ‚āļŦāļĨāļ”āļ‚āđ‰āļ­āļĄāļđāļĨāļāļĢāļ§āļĒāđāļŠāļ‡...
+
+
- -
-
-
- ðŸ›Ąïļ āļĢāļĩāļĨāļīāļāļŠāđŒāđƒāļ™āļ„āļĨāļąāļ‡ - 0 āļŠāļīāđ‰āļ™ -
- -
-

āļĢāļēāļĒāļāļēāļĢāļĢāļĩāļĨāļīāļāļŠāđŒāļ—āļąāđ‰āļ‡āļŦāļĄāļ”āļˆāļēāļ freesr-data.json

-
-
āļāļģāļĨāļąāļ‡āđ‚āļŦāļĨāļ”āļ‚āđ‰āļ­āļĄāļđāļĨāļĢāļĩāļĨāļīāļāļŠāđŒ...
-
+ +
diff --git a/js/app.js b/js/app.js index dbfd649..5295f4e 100644 --- a/js/app.js +++ b/js/app.js @@ -21,7 +21,8 @@ const state = { autoSync: localStorage.getItem('gac_srtool_auto_sync') !== 'false', defaultCreative: localStorage.getItem('gac_srtool_default_creative') === 'true', showcaseRolls: localStorage.getItem('gac_srtool_showcase_rolls') !== 'false', - showcaseAura: localStorage.getItem('gac_srtool_showcase_aura') !== 'false' + showcaseAura: localStorage.getItem('gac_srtool_showcase_aura') !== 'false', + eqActiveSubtab: 'lc' }; // UI Elements Map @@ -68,10 +69,17 @@ const el = { btnReloadAvatars: document.getElementById('btn-reload-avatars'), // Equipment - lightconesList: document.getElementById('lightcones-list'), - relicsList: document.getElementById('relics-list'), + lightconesGrid: document.getElementById('lightcones-grid'), + relicsGrid: document.getElementById('relics-grid'), badgeTotalLc: document.getElementById('badge-total-lc'), badgeTotalRelics: document.getElementById('badge-total-relics'), + eqSearch: document.getElementById('eq-search'), + eqFilterRarity: document.getElementById('eq-filter-rarity'), + eqFilterEquipped: document.getElementById('eq-filter-equipped'), + eqFilterExtra: document.getElementById('eq-filter-extra'), + btnEqSubtabLc: document.getElementById('btn-eq-subtab-lc'), + btnEqSubtabRelic: document.getElementById('btn-eq-subtab-relic'), + eqInspectorCard: document.getElementById('eq-inspector-card'), btnOpenAddLc: document.getElementById('btn-open-add-lc'), modalAddLc: document.getElementById('modal-add-lc'), btnCloseAddLcModal: document.getElementById('btn-close-add-lc-modal'), @@ -1114,9 +1122,6 @@ const RECOMMENDED_RELIC_BUILDS = { Remembrance: { cavern: 114, planar: 310, name: "Messenger (4) + Broken Keel (2)" } }; -// Active Lightcone Superimposition Rank in Modal (1 - 5) -let selectedLcRank = 5; - // Modal Sub-tabs Handler function setupModalSubtabs() { const tabBtns = document.querySelectorAll('.modal-subtab-btn'); @@ -2410,6 +2415,17 @@ async function saveFreesrChangesToServer() { } } +// Equipment Sub-tab & Filter Helpers (Matching srtools neonteam) +const ROMAN_RANKS = { 1: 'I', 2: 'II', 3: 'III', 4: 'IV', 5: 'V' }; +const RELIC_SLOT_NAMES = { + 1: "āļŠāđˆāļ§āļ™āļŦāļąāļ§", + 2: "āļŠāđˆāļ§āļ™āļĄāļ·āļ­", + 3: "āļĨāļģāļ•āļąāļ§", + 4: "āļĢāļ­āļ‡āđ€āļ—āđ‰āļē", + 5: "āļĨāļđāļāđāļāđ‰āļ§", + 6: "āļŠāļĢāđ‰āļ­āļĒ" +}; + // Load Equipment (Lightcones & Relics) async function loadEquipment() { try { @@ -2428,107 +2444,375 @@ async function loadEquipment() { } } - el.badgeTotalLc.textContent = t('itemCount', { n: lcs.length }); - el.badgeTotalRelics.textContent = t('itemCount', { n: relics.length }); + if (el.badgeTotalLc) el.badgeTotalLc.textContent = lcs.length; + if (el.badgeTotalRelics) el.badgeTotalRelics.textContent = relics.length; - // Render Lightcones - el.lightconesList.innerHTML = ''; - if (lcs.length === 0) { - el.lightconesList.innerHTML = `
${t('noLcData')}
`; - } else { - lcs.slice(0, 100).forEach(lc => { - const item = document.createElement('div'); - item.className = 'card'; - item.style.padding = '0.75rem'; - item.style.display = 'flex'; - item.style.justifyContent = 'space-between'; - item.style.alignItems = 'center'; - - const lcInfo = getLightconeInfo(lc.item_id); - const equipped = lc.equip_avatar ? getAvatarInfo(lc.equip_avatar).name : t('notEquipped'); - item.innerHTML = ` -
-
- ${lcInfo.name} - ★ ${lcInfo.rarity} - (ID: ${lc.item_id}) -
-
- Lv. ${lc.level} â€Ē S${lc.rank} â€Ē ${t('equippedBy')}: ${equipped} -
-
-
- -
- `; - el.lightconesList.appendChild(item); - }); - - // Bind delete LC buttons - el.lightconesList.querySelectorAll('.btn-delete-lc').forEach(btn => { - btn.addEventListener('click', async (e) => { - const uid = parseInt(e.currentTarget.getAttribute('data-uid'), 10); - if (state.fullFreesrData?.lightcones) { - state.fullFreesrData.lightcones = state.fullFreesrData.lightcones.filter(l => l.internal_uid !== uid); - await saveFreesrChangesToServer(); - loadEquipment(); - showToast(t('toastItemDeleted'), 'info'); - } - }); - }); - } - - // Render Relics - el.relicsList.innerHTML = ''; - if (relics.length === 0) { - el.relicsList.innerHTML = `
${t('noRelicData')}
`; - } else { - relics.slice(0, 100).forEach(r => { - const item = document.createElement('div'); - item.className = 'card'; - item.style.padding = '0.75rem'; - item.style.display = 'flex'; - item.style.justifyContent = 'space-between'; - item.style.alignItems = 'center'; - - const setId = r.relic_set_id || r.relic_id || r.item_id; - const relicInfo = getRelicSetInfo(setId); - const equipped = r.equip_avatar ? getAvatarInfo(r.equip_avatar).name : t('notEquipped'); - item.innerHTML = ` -
-
- ${relicInfo.name} - (ID: ${r.relic_id || setId}) -
-
- Lv. ${r.level} â€Ē ${t('equippedBy')}: ${equipped} -
-
-
- -
- `; - el.relicsList.appendChild(item); - }); - - // Bind delete Relic buttons - el.relicsList.querySelectorAll('.btn-delete-relic').forEach(btn => { - btn.addEventListener('click', async (e) => { - const uid = parseInt(e.currentTarget.getAttribute('data-uid'), 10); - if (state.fullFreesrData?.relics) { - state.fullFreesrData.relics = state.fullFreesrData.relics.filter(r => r.internal_uid !== uid); - await saveFreesrChangesToServer(); - loadEquipment(); - showToast(t('toastItemDeleted'), 'info'); - } - }); - }); - } + renderEquipment(); } catch (err) { console.warn('Equipment loading error:', err); } } +// Render active equipment subtab +function renderEquipment() { + if (state.eqActiveSubtab === 'relic') { + renderRelicsGrid(); + } else { + renderLightconesGrid(); + } +} + +// Render Light Cones Grid +function renderLightconesGrid() { + if (!el.lightconesGrid) return; + const lcs = state.fullFreesrData?.lightcones || []; + const search = el.eqSearch?.value.trim().toLowerCase() || ''; + const rarity = el.eqFilterRarity?.value || 'all'; + const equipped = el.eqFilterEquipped?.value || 'all'; + const pathFilter = el.eqFilterExtra?.value || 'all'; + + const filtered = lcs.filter(lc => { + const meta = getLightconeInfo(lc.item_id); + const matchesSearch = !search || meta.name.toLowerCase().includes(search) || String(lc.item_id).includes(search); + const matchesRarity = rarity === 'all' || String(meta.rarity) === rarity; + const matchesEquipped = equipped === 'all' || + (equipped === 'equipped' && lc.equip_avatar) || + (equipped === 'unequipped' && !lc.equip_avatar); + const matchesPath = pathFilter === 'all' || normalizePath(meta.path) === normalizePath(pathFilter); + return matchesSearch && matchesRarity && matchesEquipped && matchesPath; + }); + + el.lightconesGrid.innerHTML = ''; + if (filtered.length === 0) { + el.lightconesGrid.innerHTML = `
${t('noLcData')}
`; + return; + } + + filtered.forEach(lc => { + const meta = getLightconeInfo(lc.item_id); + const roman = ROMAN_RANKS[lc.rank] || `S${lc.rank || 1}`; + const card = document.createElement('div'); + card.className = `eq-tile-card rarity-${meta.rarity || 4}`; + card.setAttribute('data-uid', lc.internal_uid); + card.title = `${meta.name} (★${meta.rarity} ${meta.path || ''})`; + + const wearerBadgeHtml = lc.equip_avatar ? ` +
+ Wearer +
+ ` : ''; + + const primaryImg = `https://raw.githubusercontent.com/Mar-7th/StarRailRes/master/image/light_cone_preview/${lc.item_id}.png`; + const fallbackImg = `https://cdn.jsdelivr.net/gh/Mar-7th/StarRailRes@master/image/light_cone_preview/${lc.item_id}.png`; + + card.innerHTML = ` + ${meta.name} +
${roman}
+ ${wearerBadgeHtml} +
+ Lv.${lc.level || 80} + ${meta.name} +
+ `; + + card.addEventListener('click', () => { + document.querySelectorAll('#lightcones-grid .eq-tile-card').forEach(c => c.classList.remove('active')); + card.classList.add('active'); + showLcInspector(lc); + }); + + el.lightconesGrid.appendChild(card); + }); +} + +// Render Relics Grid +function renderRelicsGrid() { + if (!el.relicsGrid) return; + const relics = state.fullFreesrData?.relics || []; + const search = el.eqSearch?.value.trim().toLowerCase() || ''; + const rarity = el.eqFilterRarity?.value || 'all'; + const equipped = el.eqFilterEquipped?.value || 'all'; + const slotFilter = el.eqFilterExtra?.value || 'all'; + + const filtered = relics.filter(r => { + const slotNum = (r.relic_id % 10) || 1; + const setId = Math.floor((r.relic_id % 10000) / 10); + const rInfo = getRelicSetInfo(setId); + const matchesSearch = !search || rInfo.name.toLowerCase().includes(search) || String(r.relic_id).includes(search); + const matchesRarity = rarity === 'all' || (rarity === '5'); + const matchesEquipped = equipped === 'all' || + (equipped === 'equipped' && r.equip_avatar) || + (equipped === 'unequipped' && !r.equip_avatar); + const matchesSlot = slotFilter === 'all' || String(slotNum) === slotFilter; + return matchesSearch && matchesRarity && matchesEquipped && matchesSlot; + }); + + el.relicsGrid.innerHTML = ''; + if (filtered.length === 0) { + el.relicsGrid.innerHTML = `
${t('noRelicData')}
`; + return; + } + + filtered.forEach(r => { + const slotNum = (r.relic_id % 10) || 1; + const setId = Math.floor((r.relic_id % 10000) / 10); + const rInfo = getRelicSetInfo(setId); + const slotName = RELIC_SLOT_NAMES[slotNum] || `Slot ${slotNum}`; + + const card = document.createElement('div'); + card.className = 'eq-tile-card rarity-5'; + card.setAttribute('data-uid', r.internal_uid); + card.title = `${rInfo.name} (${slotName})`; + + const wearerBadgeHtml = r.equip_avatar ? ` +
+ Wearer +
+ ` : ''; + + const primaryImg = `https://raw.githubusercontent.com/Mar-7th/StarRailRes/master/icon/relic/${setId}.png`; + const fallbackImg = `https://cdn.jsdelivr.net/gh/Mar-7th/StarRailRes@master/icon/relic/${setId}.png`; + + card.innerHTML = ` + ${rInfo.name} +
${slotName}
+ ${wearerBadgeHtml} +
+ +${r.level || 15} + ${rInfo.name} +
+ `; + + card.addEventListener('click', () => { + document.querySelectorAll('#relics-grid .eq-tile-card').forEach(c => c.classList.remove('active')); + card.classList.add('active'); + showRelicInspector(r); + }); + + el.relicsGrid.appendChild(card); + }); +} + +// Show Light Cone Details Inspector +function showLcInspector(lc) { + if (!el.eqInspectorCard) return; + const lcInfo = getLightconeInfo(lc.item_id); + const lcMeta = LIGHTCONE_METADATA[lc.item_id] || {}; + const roman = ROMAN_RANKS[lc.rank] || `S${lc.rank || 1}`; + + let avatarOpts = ``; + const sortedAvatars = [...state.avatarsList].sort((a, b) => b.avatar_id - a.avatar_id); + sortedAvatars.forEach(av => { + const info = getAvatarInfo(av.avatar_id); + const sel = (lc.equip_avatar === av.avatar_id) ? 'selected' : ''; + avatarOpts += ``; + }); + + const hp = lcMeta.rarity === 5 ? 1164 : (lcMeta.rarity === 4 ? 953 : 846); + const atk = lcMeta.rarity === 5 ? 582 : (lcMeta.rarity === 4 ? 423 : 317); + const def = lcMeta.rarity === 5 ? 529 : (lcMeta.rarity === 4 ? 396 : 264); + + el.eqInspectorCard.style.display = 'flex'; + el.eqInspectorCard.innerHTML = ` +
+
+ ${lcInfo.name} +
+
${lcInfo.name}
+
${'★'.repeat(lcInfo.rarity || 5)}
+
+ ${getPathIconHtml(lcInfo.path, 16)} ${lcInfo.path || 'All'} â€Ē Lv. ${lc.level || 80}/80 +
+
+ Superimposition ${roman} +
+
+
+ +
+ + +
+
+ âĪïļ HP + +${hp} +
+
+ ⚔ïļ ATK + +${atk} +
+
+ ðŸ›Ąïļ DEF + +${def} +
+
+ + +
+
${lcMeta.skill_name || 'āļŠāļāļīāļĨāļžāļīāđ€āļĻāļĐāļ›āļĢāļ°āļˆāļģāļāļĢāļ§āļĒāđāļŠāļ‡'}
+
${lcMeta.desc || 'āđ€āļžāļīāđˆāļĄāļžāļĨāļąāļ‡āļ•āđˆāļ­āļŠāļđāđ‰āđāļĨāļ°āđ€āļŠāļĢāļīāļĄāļāļĨāđ„āļāđ€āļ‰āļžāļēāļ°āļŠāļēāļĒāļ‚āļ­āļ‡āļ•āļąāļ§āļĨāļ°āļ„āļĢāđ€āļĄāļ·āđˆāļ­āļ•āļīāļ”āļ•āļąāđ‰āļ‡'}
+
+ + +
+ + + +
+ + +
+
+ `; + + document.getElementById('btn-close-eq-inspector')?.addEventListener('click', () => { + el.eqInspectorCard.style.display = 'none'; + document.querySelectorAll('.eq-tile-card.active').forEach(c => c.classList.remove('active')); + }); + + document.getElementById('btn-inspector-save-wearer')?.addEventListener('click', async () => { + const newAvatarId = parseInt(document.getElementById('sel-inspector-wearer').value, 10); + if (newAvatarId !== 0 && state.fullFreesrData?.lightcones) { + state.fullFreesrData.lightcones.forEach(otherLc => { + if (otherLc.equip_avatar === newAvatarId && otherLc.internal_uid !== lc.internal_uid) { + otherLc.equip_avatar = 0; + } + }); + } + lc.equip_avatar = newAvatarId; + if (state.isConnected) { + await saveFreesrChangesToServer(); + } + showToast(`āļ­āļąāļ›āđ€āļ”āļ•āļœāļđāđ‰āļŠāļ§āļĄāđƒāļŠāđˆ ${lcInfo.name} āđ€āļĢāļĩāļĒāļšāļĢāđ‰āļ­āļĒ`, 'success'); + renderEquipment(); + showLcInspector(lc); + }); + + document.getElementById('btn-inspector-delete')?.addEventListener('click', async () => { + if (!confirm(`āļĒāļ·āļ™āļĒāļąāļ™āļāļēāļĢāļĨāļš ${lcInfo.name} āļ­āļ­āļāļˆāļēāļāļ„āļĨāļąāļ‡ FreeSR āļŦāļĢāļ·āļ­āđ„āļĄāđˆ?`)) return; + if (state.fullFreesrData?.lightcones) { + state.fullFreesrData.lightcones = state.fullFreesrData.lightcones.filter(l => l.internal_uid !== lc.internal_uid); + if (state.isConnected) { + await saveFreesrChangesToServer(); + } + el.eqInspectorCard.style.display = 'none'; + showToast(t('toastItemDeleted'), 'info'); + renderEquipment(); + } + }); +} + +// Show Relic Details Inspector +function showRelicInspector(relic) { + if (!el.eqInspectorCard) return; + const slotNum = (relic.relic_id % 10) || 1; + const setId = Math.floor((relic.relic_id % 10000) / 10); + const rInfo = getRelicSetInfo(setId); + const slotName = RELIC_SLOT_NAMES[slotNum] || `āļŠāļīāđ‰āļ™āļ—āļĩāđˆ ${slotNum}`; + + let avatarOpts = ``; + const sortedAvatars = [...state.avatarsList].sort((a, b) => b.avatar_id - a.avatar_id); + sortedAvatars.forEach(av => { + const info = getAvatarInfo(av.avatar_id); + const sel = (relic.equip_avatar === av.avatar_id) ? 'selected' : ''; + avatarOpts += ``; + }); + + el.eqInspectorCard.style.display = 'flex'; + el.eqInspectorCard.innerHTML = ` +
+
+ ${rInfo.name} +
+
${rInfo.name}
+
★★★★★
+
+ ${slotName} â€Ē +${relic.level || 15} +
+
+ ID: ${relic.relic_id || setId} +
+
+
+ +
+ + +
+
+ Main Stat + +15 Max +
+
+ CRIT Rate / DMG + +3.2% / +6.4% +
+
+ SPD / ATK + +4 / +4.3% +
+
+ + +
+
Set Bonus (${rInfo.name})
+
2-Piece: āđ€āļžāļīāđˆāļĄāļ›āļĢāļ°āļŠāļīāļ—āļ˜āļīāļ āļēāļžāļ•āļēāļĄāđ€āļ‹āđ‡āļ•āļ—āļĩāđˆāļāļģāļŦāļ™āļ”
4-Piece: āļ›āļĨāļ”āļĨāđ‡āļ­āļāđ€āļ­āļŸāđ€āļŸāļāļ•āđŒāļ•āđˆāļ­āļŠāļđāđ‰āļ‚āļąāđ‰āļ™āļŠāļđāļ‡
+
+ + +
+ + + +
+ + +
+
+ `; + + document.getElementById('btn-close-eq-inspector')?.addEventListener('click', () => { + el.eqInspectorCard.style.display = 'none'; + document.querySelectorAll('.eq-tile-card.active').forEach(c => c.classList.remove('active')); + }); + + document.getElementById('btn-inspector-save-wearer')?.addEventListener('click', async () => { + const newAvatarId = parseInt(document.getElementById('sel-inspector-wearer').value, 10); + if (newAvatarId !== 0 && state.fullFreesrData?.relics) { + state.fullFreesrData.relics.forEach(otherR => { + const otherSlot = (otherR.relic_id % 10) || 1; + if (otherR.equip_avatar === newAvatarId && otherSlot === slotNum && otherR.internal_uid !== relic.internal_uid) { + otherR.equip_avatar = 0; + } + }); + } + relic.equip_avatar = newAvatarId; + if (state.isConnected) { + await saveFreesrChangesToServer(); + } + showToast(`āļ­āļąāļ›āđ€āļ”āļ•āļœāļđāđ‰āļŠāļ§āļĄāđƒāļŠāđˆ ${rInfo.name} (${slotName}) āđ€āļĢāļĩāļĒāļšāļĢāđ‰āļ­āļĒ`, 'success'); + renderEquipment(); + showRelicInspector(relic); + }); + + document.getElementById('btn-inspector-delete')?.addEventListener('click', async () => { + if (!confirm(`āļĒāļ·āļ™āļĒāļąāļ™āļāļēāļĢāļĨāļš ${rInfo.name} āļ­āļ­āļāļˆāļēāļāļ„āļĨāļąāļ‡ FreeSR āļŦāļĢāļ·āļ­āđ„āļĄāđˆ?`)) return; + if (state.fullFreesrData?.relics) { + state.fullFreesrData.relics = state.fullFreesrData.relics.filter(r => r.internal_uid !== relic.internal_uid); + if (state.isConnected) { + await saveFreesrChangesToServer(); + } + el.eqInspectorCard.style.display = 'none'; + showToast(t('toastItemDeleted'), 'info'); + renderEquipment(); + } + }); +} + // Open Add Light Cone Modal function openAddLcModal() { if (!el.modalAddLc) return; @@ -3195,6 +3479,76 @@ function setupEvents() { el.formAddRelic.addEventListener('submit', handleAddRelicSubmit); } + // Equipment Subtab Switching & Filters (Tiles View) + const updateEqFiltersExtra = () => { + if (!el.eqFilterExtra) return; + el.eqFilterExtra.innerHTML = ''; + if (state.eqActiveSubtab === 'relic') { + el.eqFilterExtra.innerHTML = ` + + + + + + + + `; + } else { + el.eqFilterExtra.innerHTML = ` + + + + + + + + + + `; + } + }; + + if (el.btnEqSubtabLc) { + el.btnEqSubtabLc.addEventListener('click', () => { + state.eqActiveSubtab = 'lc'; + el.btnEqSubtabLc.classList.add('active', 'btn-primary'); + el.btnEqSubtabLc.classList.remove('btn-secondary'); + el.btnEqSubtabRelic.classList.remove('active', 'btn-primary'); + el.btnEqSubtabRelic.classList.add('btn-secondary'); + if (el.lightconesGrid) el.lightconesGrid.style.display = 'grid'; + if (el.relicsGrid) el.relicsGrid.style.display = 'none'; + if (el.btnOpenAddLc) el.btnOpenAddLc.style.display = ''; + if (el.btnOpenAddRelic) el.btnOpenAddRelic.style.display = 'none'; + if (el.eqInspectorCard) el.eqInspectorCard.style.display = 'none'; + updateEqFiltersExtra(); + renderEquipment(); + }); + } + + if (el.btnEqSubtabRelic) { + el.btnEqSubtabRelic.addEventListener('click', () => { + state.eqActiveSubtab = 'relic'; + el.btnEqSubtabRelic.classList.add('active', 'btn-primary'); + el.btnEqSubtabRelic.classList.remove('btn-secondary'); + el.btnEqSubtabLc.classList.remove('active', 'btn-primary'); + el.btnEqSubtabLc.classList.add('btn-secondary'); + if (el.relicsGrid) el.relicsGrid.style.display = 'grid'; + if (el.lightconesGrid) el.lightconesGrid.style.display = 'none'; + if (el.btnOpenAddRelic) el.btnOpenAddRelic.style.display = ''; + if (el.btnOpenAddLc) el.btnOpenAddLc.style.display = 'none'; + if (el.eqInspectorCard) el.eqInspectorCard.style.display = 'none'; + updateEqFiltersExtra(); + renderEquipment(); + }); + } + + if (el.eqSearch) el.eqSearch.addEventListener('input', renderEquipment); + if (el.eqFilterRarity) el.eqFilterRarity.addEventListener('change', renderEquipment); + if (el.eqFilterEquipped) el.eqFilterEquipped.addEventListener('change', renderEquipment); + if (el.eqFilterExtra) el.eqFilterExtra.addEventListener('change', renderEquipment); + + updateEqFiltersExtra(); + // Avatar Search & Filters el.avatarSearch.addEventListener('input', renderAvatarsGrid); el.avatarFilterRarity.addEventListener('change', renderAvatarsGrid); @@ -3500,8 +3854,10 @@ function init() { setupModalSubtabs(); setupEvents(); applyTranslations(); - refreshStatus(); + renderLineup(state.statusData?.lineups || DEFAULT_LINEUP); renderAvatarsGrid(); + loadEquipment(); + refreshStatus(); startPingLoop(); }