294 lines
16 KiB
HTML
294 lines
16 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<title>Inventory Search — mockup</title>
|
||
<style>
|
||
* { box-sizing: border-box; margin: 0; padding: 0; }
|
||
html, body { height: 100%; }
|
||
body { background:#111; color:#eee; font-family:"Segoe UI",sans-serif; font-size:13px; display:flex; flex-direction:column; }
|
||
|
||
/* ── Top bar ── */
|
||
.topbar { display:flex; align-items:center; gap:10px; padding:10px 14px; background:#1a1a1a; border-bottom:2px solid #333; }
|
||
.topbar .title { color:#88f; font-weight:600; font-size:15px; white-space:nowrap; }
|
||
.searchbox { flex:1; max-width:520px; background:#222; border:1px solid #444; border-radius:4px; padding:7px 12px; color:#eee; font-size:13px; outline:none; }
|
||
.searchbox:focus { border-color:#88f; }
|
||
.searchbox::placeholder { color:#666; }
|
||
.btn { background:#333; border:1px solid #555; color:#ccc; border-radius:4px; padding:6px 14px; font-size:12px; cursor:pointer; }
|
||
.btn:hover { background:#444; color:#fff; }
|
||
.count { margin-left:auto; color:#888; font-size:12px; white-space:nowrap; }
|
||
.count b { color:#eee; }
|
||
|
||
/* ── Chips ── */
|
||
.chipsrow { display:flex; align-items:center; flex-wrap:wrap; gap:6px; padding:8px 14px; background:#151515; border-bottom:1px solid #2a2a2a; min-height:37px; }
|
||
.chipsrow .lbl { color:#666; font-size:10px; letter-spacing:1px; }
|
||
.chip { display:inline-flex; align-items:center; gap:6px; background:#23233a; border:1px solid #55f; border-radius:12px; padding:2px 10px; font-size:11px; color:#bbd; cursor:default; }
|
||
.chip .x { color:#c66; cursor:pointer; font-weight:bold; }
|
||
.chip .x:hover { color:#f88; }
|
||
.chip.gold { border-color:#a80; color:#fc6; background:#2a2418; }
|
||
|
||
/* ── Main ── */
|
||
.main { display:flex; flex:1; overflow:hidden; }
|
||
|
||
/* ── Sidebar ── */
|
||
.sidebar { width:210px; min-width:210px; background:#1a1a1a; border-right:2px solid #333; overflow-y:auto; padding:8px 10px; }
|
||
.grp { border-bottom:1px solid #262626; padding:6px 0; }
|
||
.grp-head { display:flex; align-items:center; gap:6px; cursor:pointer; color:#999; text-transform:uppercase; font-size:10px; letter-spacing:1px; padding:3px 0; user-select:none; }
|
||
.grp-head:hover { color:#ccc; }
|
||
.grp-head .arrow { font-size:9px; transition:transform .15s; }
|
||
.grp.open .arrow { transform:rotate(90deg); }
|
||
.grp-head .badge { margin-left:auto; background:#3a3a6e; color:#cce; border-radius:8px; padding:0 7px; font-size:9px; }
|
||
.grp-body { display:none; padding:5px 0 3px; }
|
||
.grp.open .grp-body { display:block; }
|
||
.minisearch { width:100%; background:#222; border:1px solid #3a3a3a; border-radius:3px; padding:4px 8px; color:#ccc; font-size:11px; outline:none; margin-bottom:5px; }
|
||
.minisearch::placeholder { color:#555; }
|
||
.fitem { display:flex; align-items:center; gap:6px; padding:2px 0; font-size:12px; color:#bbb; cursor:pointer; }
|
||
.fitem:hover { color:#fff; }
|
||
.fitem input { accent-color:#88f; }
|
||
.fitem .online { width:6px; height:6px; border-radius:50%; background:#4c4; }
|
||
.fitem.gold { color:#fc6; }
|
||
.subhead { color:#666; font-size:9px; text-transform:uppercase; letter-spacing:1px; margin:6px 0 2px; }
|
||
.linky { color:#88f; font-size:10px; cursor:pointer; }
|
||
.linky:hover { text-decoration:underline; }
|
||
.range { display:flex; gap:4px; align-items:center; margin:2px 0; }
|
||
.range label { flex:1; color:#999; font-size:11px; }
|
||
.range input { width:52px; background:#222; border:1px solid #3a3a3a; border-radius:3px; color:#ccc; padding:2px 5px; font-size:11px; }
|
||
|
||
/* ── Results ── */
|
||
.results { flex:1; overflow-y:auto; display:flex; flex-direction:column; }
|
||
table { width:100%; border-collapse:collapse; }
|
||
thead { position:sticky; top:0; background:#191919; z-index:1; }
|
||
th { text-align:left; color:#88f; font-size:11px; font-weight:600; padding:8px 10px; border-bottom:2px solid #333; cursor:pointer; white-space:nowrap; user-select:none; }
|
||
th:hover { color:#aaf; }
|
||
th.sorted::after { content:" ▼"; font-size:9px; }
|
||
td { padding:6px 10px; border-bottom:1px solid #1e1e1e; font-size:12px; color:#bbb; vertical-align:top; }
|
||
tbody tr { cursor:pointer; }
|
||
tbody tr:hover td { background:#191922; }
|
||
tbody tr.sel td { background:#20203a; }
|
||
td .leg { color:#fc6; }
|
||
td .spells { color:#889; font-size:11px; }
|
||
td.num { text-align:right; font-variant-numeric:tabular-nums; }
|
||
.equipped { color:#4c4; font-size:10px; }
|
||
.pager { display:flex; align-items:center; gap:8px; padding:8px 14px; color:#888; font-size:12px; border-top:1px solid #262626; background:#151515; margin-top:auto; }
|
||
.pager .pg { padding:2px 8px; border:1px solid #333; border-radius:3px; cursor:pointer; }
|
||
.pager .pg.cur { background:#3a3a6e; border-color:#88f; color:#fff; }
|
||
|
||
/* ── Detail panel ── */
|
||
.detail { width:250px; min-width:250px; background:#161620; border-left:2px solid #333; overflow-y:auto; padding:12px; }
|
||
.detail h3 { color:#88f; font-size:14px; margin-bottom:2px; }
|
||
.detail .sub { color:#777; font-size:11px; margin-bottom:10px; }
|
||
.kv { display:flex; justify-content:space-between; padding:2px 0; font-size:12px; color:#999; }
|
||
.kv b { color:#ddd; font-weight:normal; text-align:right; }
|
||
.detail hr { border:none; border-top:1px solid #2a2a35; margin:9px 0; }
|
||
.detail .sphead { color:#666; font-size:10px; text-transform:uppercase; letter-spacing:1px; margin-bottom:4px; }
|
||
.sp { padding:2px 0; font-size:12px; color:#bbb; }
|
||
.sp.leg { color:#fc6; }
|
||
.detail .hint { color:#555; font-size:10px; margin-top:12px; }
|
||
.closex { float:right; color:#666; cursor:pointer; font-size:14px; }
|
||
.closex:hover { color:#f88; }
|
||
</style>
|
||
</head>
|
||
<body>
|
||
|
||
<div class="topbar">
|
||
<span class="title">⚔ Inventory Search</span>
|
||
<input class="searchbox" placeholder="Search name or material… (e.g. 'sapphire ring')">
|
||
<button class="btn" onclick="document.querySelectorAll('.chip').forEach(c=>c.remove())">Reset</button>
|
||
<button class="btn">⚙ Columns</button>
|
||
<span class="count"><b>56</b> items · 24 ms</span>
|
||
</div>
|
||
|
||
<div class="chipsrow">
|
||
<span class="lbl">ACTIVE</span>
|
||
<span class="chip">Jewelry <span class="x" onclick="this.parentNode.remove()">×</span></span>
|
||
<span class="chip">Slot: Ring <span class="x" onclick="this.parentNode.remove()">×</span></span>
|
||
<span class="chip gold">Legendary Invulnerability <span class="x" onclick="this.parentNode.remove()">×</span></span>
|
||
<span class="chip gold">Legendary Summoning <span class="x" onclick="this.parentNode.remove()">×</span></span>
|
||
</div>
|
||
|
||
<div class="main">
|
||
|
||
<div class="sidebar">
|
||
<div class="grp open">
|
||
<div class="grp-head" onclick="this.parentNode.classList.toggle('open')"><span class="arrow">▶</span> Characters <span class="badge">All</span></div>
|
||
<div class="grp-body">
|
||
<input class="minisearch" placeholder="filter characters…">
|
||
<div style="margin-bottom:4px"><span class="linky">All</span> · <span class="linky">None</span> · <span class="linky">Online</span></div>
|
||
<div class="fitem"><input type="checkbox" checked> Bank of Sawato</div>
|
||
<div class="fitem"><input type="checkbox" checked> Bowgod <span class="online"></span></div>
|
||
<div class="fitem"><input type="checkbox" checked> Larsson <span class="online"></span></div>
|
||
<div class="fitem"><input type="checkbox" checked> Mrbow</div>
|
||
<div class="fitem"><input type="checkbox" checked> Kosmo Kramer <span class="online"></span></div>
|
||
<div class="fitem" style="color:#555">… 33 more</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="grp open">
|
||
<div class="grp-head" onclick="this.parentNode.classList.toggle('open')"><span class="arrow">▶</span> Item type <span class="badge">1</span></div>
|
||
<div class="grp-body">
|
||
<div class="fitem"><input type="radio" name="t"> All items</div>
|
||
<div class="fitem"><input type="radio" name="t"> Armor</div>
|
||
<div class="fitem"><input type="radio" name="t" checked> Jewelry</div>
|
||
<div class="fitem"><input type="radio" name="t"> Weapons</div>
|
||
<div class="fitem"><input type="radio" name="t"> Clothing</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="grp open">
|
||
<div class="grp-head" onclick="this.parentNode.classList.toggle('open')"><span class="arrow">▶</span> Slots <span class="badge">1</span></div>
|
||
<div class="grp-body">
|
||
<div class="fitem"><input type="checkbox" checked> Ring</div>
|
||
<div class="fitem"><input type="checkbox"> Bracelet</div>
|
||
<div class="fitem"><input type="checkbox"> Neck</div>
|
||
<div class="fitem"><input type="checkbox"> Trinket</div>
|
||
<div class="fitem"><input type="checkbox"> Cloak</div>
|
||
<span class="linky">show armor slots ▾</span>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="grp open">
|
||
<div class="grp-head" onclick="this.parentNode.classList.toggle('open')"><span class="arrow">▶</span> Cantrips <span class="badge">2</span></div>
|
||
<div class="grp-body">
|
||
<input class="minisearch" id="cantripSearch" placeholder="find cantrip… e.g. invuln" oninput="filterCantrips(this.value)">
|
||
<div class="subhead">Selected</div>
|
||
<div class="fitem gold"><input type="checkbox" checked> Invulnerability</div>
|
||
<div class="fitem gold"><input type="checkbox" checked> Summoning</div>
|
||
<div class="subhead">Attributes</div>
|
||
<div class="fitem cf"><input type="checkbox"> Strength</div>
|
||
<div class="fitem cf"><input type="checkbox"> Endurance</div>
|
||
<div class="fitem cf"><input type="checkbox"> Quickness</div>
|
||
<div class="fitem cf"><input type="checkbox"> Focus</div>
|
||
<div class="subhead">Skills</div>
|
||
<div class="fitem cf"><input type="checkbox"> Heavy Weapon</div>
|
||
<div class="fitem cf"><input type="checkbox"> War Magic</div>
|
||
<div class="fitem cf"><input type="checkbox"> Defender</div>
|
||
<div class="subhead">Defense</div>
|
||
<div class="fitem cf"><input type="checkbox"> Impenetrability</div>
|
||
<div class="fitem cf"><input type="checkbox"> Magic Resistance</div>
|
||
<div class="fitem" style="color:#555">… all 45 in real page</div>
|
||
<div class="subhead">Any-tier spell search</div>
|
||
<input class="minisearch" placeholder="spell name contains… e.g. Epic Invuln">
|
||
</div>
|
||
</div>
|
||
|
||
<div class="grp">
|
||
<div class="grp-head" onclick="this.parentNode.classList.toggle('open')"><span class="arrow">▶</span> Ratings</div>
|
||
<div class="grp-body">
|
||
<div class="range"><label>Dmg rating ≥</label><input placeholder="min"></div>
|
||
<div class="range"><label>Crit dmg ≥</label><input placeholder="min"></div>
|
||
<div class="range"><label>Heal boost ≥</label><input placeholder="min"></div>
|
||
<div class="range"><label>Vitality ≥</label><input placeholder="min"></div>
|
||
<span class="linky">all 20 ratings ▾</span>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="grp">
|
||
<div class="grp-head" onclick="this.parentNode.classList.toggle('open')"><span class="arrow">▶</span> Equipment sets</div>
|
||
<div class="grp-body"><input class="minisearch" placeholder="find set…"></div>
|
||
</div>
|
||
|
||
<div class="grp">
|
||
<div class="grp-head" onclick="this.parentNode.classList.toggle('open')"><span class="arrow">▶</span> Item state</div>
|
||
<div class="grp-body">
|
||
<div class="fitem"><input type="checkbox"> Equipped only</div>
|
||
<div class="fitem"><input type="checkbox"> Bonded</div>
|
||
<div class="fitem"><input type="checkbox"> Rare</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="grp">
|
||
<div class="grp-head" onclick="this.parentNode.classList.toggle('open')"><span class="arrow">▶</span> Reqs & value</div>
|
||
<div class="grp-body">
|
||
<div class="range"><label>Wield lvl ≤</label><input placeholder="max"></div>
|
||
<div class="range"><label>Value ≥</label><input placeholder="min"></div>
|
||
<div class="range"><label>Workmanship ≥</label><input placeholder="min"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="results">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Item</th><th>Character</th><th>Slot</th><th class="num sorted">Value</th><th>Wield</th><th>Spells / Cantrips</th></tr>
|
||
</thead>
|
||
<tbody id="rows"></tbody>
|
||
</table>
|
||
<div class="pager">
|
||
<span class="pg">◀</span><span class="pg cur">1</span><span class="pg">2</span><span class="pg">3</span><span class="pg">▶</span>
|
||
<span style="margin-left:auto">200 / page</span>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="detail" id="detail"></div>
|
||
|
||
</div>
|
||
|
||
<script>
|
||
const items = [
|
||
{ name:"Gold Ring", char:"Bowgod", slot:"Ring", value:24510, wield:"180", equipped:false, burden:50, work:"—", mana:"142/200",
|
||
spells:[["Legendary Invulnerability",1],["Legendary Summoning Prowess",1],["Major Heavy Weapon Aptitude",0],["Blessing of the Arrow Turner",0]] },
|
||
{ name:"Sapphire Ring", char:"Larsson", slot:"Ring", value:18200, wield:"150", equipped:true, burden:50, work:"—", mana:"98/180",
|
||
spells:[["Legendary Invulnerability",1],["Epic Focus",0],["Minor Impenetrability",0]] },
|
||
{ name:"Bronze Ring", char:"Mrbow", slot:"Ring", value:9340, wield:"125", equipped:false, burden:50, work:"—", mana:"77/120",
|
||
spells:[["Legendary Invulnerability",1],["Epic Willpower",0]] },
|
||
{ name:"Diamond Ring", char:"Kosmo Kramer", slot:"Ring", value:31000, wield:"200", equipped:false, burden:50, work:"—", mana:"200/200",
|
||
spells:[["Legendary Invulnerability",1],["Legendary Willpower",1],["Epic Mana Conversion Prowess",0]] },
|
||
{ name:"Ivory Ring", char:"Bank of Sawato", slot:"Ring", value:12750, wield:"150", equipped:false, burden:50, work:"—", mana:"64/150",
|
||
spells:[["Legendary Invulnerability",1],["Major Void Magic Aptitude",0]] },
|
||
{ name:"Black Opal Ring", char:"Bowgod", slot:"Ring", value:27890, wield:"180", equipped:true, burden:50, work:"—", mana:"180/220",
|
||
spells:[["Legendary Invulnerability",1],["Legendary Critical Damage",1]] },
|
||
];
|
||
|
||
function render() {
|
||
const tb = document.getElementById('rows');
|
||
tb.innerHTML = items.map((it,i) => `
|
||
<tr onclick="sel(${i})" id="r${i}">
|
||
<td>${it.name}${it.equipped ? ' <span class="equipped">⚔</span>' : ''}</td>
|
||
<td>${it.char}</td><td>${it.slot}</td>
|
||
<td class="num">${it.value.toLocaleString()}</td><td>${it.wield}</td>
|
||
<td class="spells">${it.spells.map(([s,l]) => l ? `<span class="leg">${s}</span>` : s).join(', ')}</td>
|
||
</tr>`).join('');
|
||
}
|
||
|
||
function sel(i) {
|
||
document.querySelectorAll('tbody tr').forEach(r=>r.classList.remove('sel'));
|
||
document.getElementById('r'+i).classList.add('sel');
|
||
const it = items[i];
|
||
document.getElementById('detail').innerHTML = `
|
||
<span class="closex" onclick="document.getElementById('detail').innerHTML=hint">×</span>
|
||
<h3>${it.name}</h3>
|
||
<div class="sub">${it.slot} · ${it.equipped ? '⚔ Equipped' : '📦 Inventory'}</div>
|
||
<div class="kv"><span>Character</span><b>${it.char}</b></div>
|
||
<div class="kv"><span>Value</span><b>${it.value.toLocaleString()}</b></div>
|
||
<div class="kv"><span>Burden</span><b>${it.burden}</b></div>
|
||
<div class="kv"><span>Wield req</span><b>Level ${it.wield}</b></div>
|
||
<div class="kv"><span>Workmanship</span><b>${it.work}</b></div>
|
||
<div class="kv"><span>Mana</span><b>${it.mana}</b></div>
|
||
<hr>
|
||
<div class="sphead">Spells (${it.spells.length})</div>
|
||
${it.spells.map(([s,l]) => `<div class="sp${l ? ' leg' : ''}">${s}</div>`).join('')}
|
||
<div class="hint">↑/↓ next item · Esc close</div>`;
|
||
}
|
||
|
||
function filterCantrips(q) {
|
||
q = q.toLowerCase();
|
||
document.querySelectorAll('.cf').forEach(el => {
|
||
el.style.display = el.textContent.toLowerCase().includes(q) ? '' : 'none';
|
||
});
|
||
}
|
||
|
||
const hint = '<div class="hint">Click a row to inspect an item.</div>';
|
||
document.getElementById('detail').innerHTML = hint;
|
||
render();
|
||
sel(0);
|
||
document.addEventListener('keydown', e => {
|
||
const cur = document.querySelector('tbody tr.sel');
|
||
if (!cur) return;
|
||
const i = +cur.id.slice(1);
|
||
if (e.key === 'ArrowDown' && i < items.length-1) { sel(i+1); e.preventDefault(); }
|
||
if (e.key === 'ArrowUp' && i > 0) { sel(i-1); e.preventDefault(); }
|
||
if (e.key === 'Escape') { document.querySelectorAll('tbody tr').forEach(r=>r.classList.remove('sel')); document.getElementById('detail').innerHTML = hint; }
|
||
});
|
||
</script>
|
||
</body>
|
||
</html>
|