feat: complete inventory search frontend — weapons, filters, status column
- Add Weapons and Clothing equipment type radio options - Add Weapon/Combat Stats filter card: damage, attack bonus, crit resist, tinks - Add Item Properties filter card: material, level req, workmanship, value, burden - Add Item State filter card: spell text search, bonded, attuned, rare checkboxes - Add Status column (Equipped/Inventory) to results table - Remove dead Slot View button and section (no JS handlers existed) - Update clearAllFields() for all new inputs - All changes frontend-only — suitbuilder and backend API untouched Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
8432c5f7c3
commit
5b26a19666
2 changed files with 126 additions and 18 deletions
|
|
@ -538,6 +538,14 @@
|
|||
<input type="radio" name="equipmentType" id="pantsOnly" value="pants" style="margin-right: 3px;">
|
||||
Pants Only
|
||||
</label>
|
||||
<label style="display: flex; align-items: center; font-weight: normal;">
|
||||
<input type="radio" name="equipmentType" id="weaponOnly" value="weapon" style="margin-right: 3px;">
|
||||
Weapons
|
||||
</label>
|
||||
<label style="display: flex; align-items: center; font-weight: normal;">
|
||||
<input type="radio" name="equipmentType" id="clothingOnly" value="clothing" style="margin-right: 3px;">
|
||||
Clothing
|
||||
</label>
|
||||
<label style="display: flex; align-items: center; font-weight: normal;">
|
||||
<input type="radio" name="equipmentType" id="allItems" value="all" style="margin-right: 3px;">
|
||||
All Items
|
||||
|
|
@ -624,6 +632,89 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Weapon / Combat Stats -->
|
||||
<div class="filter-card">
|
||||
<div class="filter-card-header">Weapon / Combat Stats</div>
|
||||
<div class="filter-row">
|
||||
<div class="filter-group">
|
||||
<label>Damage:</label>
|
||||
<input type="number" id="searchMinDamage" placeholder="Min">
|
||||
<span class="range-separator">-</span>
|
||||
<input type="number" id="searchMaxDamage" placeholder="Max">
|
||||
</div>
|
||||
<div class="filter-group">
|
||||
<label>Attack Bonus:</label>
|
||||
<input type="number" id="searchMinAttackBonus" placeholder="Min" step="0.01">
|
||||
</div>
|
||||
<div class="filter-group">
|
||||
<label>Crit Resist:</label>
|
||||
<input type="number" id="searchMinCritResistRating" placeholder="Min">
|
||||
</div>
|
||||
<div class="filter-group">
|
||||
<label>Tinks:</label>
|
||||
<input type="number" id="searchMinTinks" placeholder="Min">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Item Properties -->
|
||||
<div class="filter-card">
|
||||
<div class="filter-card-header">Item Properties</div>
|
||||
<div class="filter-row">
|
||||
<div class="filter-group">
|
||||
<label>Material:</label>
|
||||
<input type="text" id="searchMaterial" placeholder="e.g. Gold" style="width: 80px;">
|
||||
</div>
|
||||
<div class="filter-group">
|
||||
<label>Level Req:</label>
|
||||
<input type="number" id="searchMinLevel" placeholder="Min">
|
||||
<span class="range-separator">-</span>
|
||||
<input type="number" id="searchMaxLevel" placeholder="Max">
|
||||
</div>
|
||||
<div class="filter-group">
|
||||
<label>Workmanship:</label>
|
||||
<input type="number" id="searchMinWorkmanship" placeholder="Min" step="0.5">
|
||||
<span class="range-separator">-</span>
|
||||
<input type="number" id="searchMaxWorkmanship" placeholder="Max" step="0.5">
|
||||
</div>
|
||||
</div>
|
||||
<div class="filter-row">
|
||||
<div class="filter-group">
|
||||
<label>Value:</label>
|
||||
<input type="number" id="searchMinValue" placeholder="Min">
|
||||
<span class="range-separator">-</span>
|
||||
<input type="number" id="searchMaxValue" placeholder="Max">
|
||||
</div>
|
||||
<div class="filter-group">
|
||||
<label>Max Burden:</label>
|
||||
<input type="number" id="searchMaxBurden" placeholder="Max">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Item State & Spell Search -->
|
||||
<div class="filter-card">
|
||||
<div class="filter-card-header">Item State & Spell Search</div>
|
||||
<div class="filter-row">
|
||||
<div class="filter-group">
|
||||
<label>Spell Search:</label>
|
||||
<input type="text" id="searchSpellContains" placeholder="Spell name contains..." style="width: 150px;">
|
||||
</div>
|
||||
<div class="filter-group">
|
||||
<label style="min-width: auto;">Bonded:</label>
|
||||
<input type="checkbox" id="searchBonded" style="width: auto; height: auto;">
|
||||
</div>
|
||||
<div class="filter-group">
|
||||
<label style="min-width: auto;">Attuned:</label>
|
||||
<input type="checkbox" id="searchAttuned" style="width: auto; height: auto;">
|
||||
</div>
|
||||
<div class="filter-group">
|
||||
<label style="min-width: auto;">Rare:</label>
|
||||
<input type="checkbox" id="searchIsRare" style="width: auto; height: auto;">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Checkbox Sections in Grid Layout -->
|
||||
<div class="checkbox-sections-container">
|
||||
<!-- Equipment Sets -->
|
||||
|
|
@ -985,7 +1076,6 @@
|
|||
<button type="button" class="btn btn-secondary" id="clearBtn">Clear All</button>
|
||||
<button type="submit" class="btn btn-primary">Search Items</button>
|
||||
<button type="button" class="btn btn-secondary" id="setAnalysisBtn">Analyze Sets</button>
|
||||
<button type="button" class="btn btn-secondary" id="slotViewBtn">Slot View</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
|
|
@ -1034,21 +1124,6 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Slot View Section -->
|
||||
<div class="slot-view-section" id="slotViewSection" style="display: none;">
|
||||
<div class="slot-view-header">
|
||||
<h3>Equipment Slot View</h3>
|
||||
<div class="filter-row">
|
||||
<button type="button" class="btn btn-primary" id="loadSlotView">Load Items</button>
|
||||
<button type="button" class="btn btn-secondary" id="backToSearchFromSlots">Back to Search</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="slots-grid" id="slotsGrid">
|
||||
<!-- Slots will be populated by JavaScript -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="results-container" id="searchResults">
|
||||
<div class="no-results">Enter search criteria above and click "Search Items" to find inventory items.</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -171,6 +171,12 @@ function clearAllFields() {
|
|||
// Reset slot filter
|
||||
document.getElementById('slotFilter').value = '';
|
||||
|
||||
// Clear item state checkboxes (not covered by form.reset for standalone checkboxes)
|
||||
['searchBonded', 'searchAttuned', 'searchIsRare'].forEach(id => {
|
||||
const el = document.getElementById(id);
|
||||
if (el) el.checked = false;
|
||||
});
|
||||
|
||||
// Reset page
|
||||
currentPage = 1;
|
||||
|
||||
|
|
@ -250,6 +256,10 @@ function buildSearchParameters() {
|
|||
params.append('shirt_only', 'true');
|
||||
} else if (equipmentType === 'pants') {
|
||||
params.append('pants_only', 'true');
|
||||
} else if (equipmentType === 'weapon') {
|
||||
params.append('weapon_only', 'true');
|
||||
} else if (equipmentType === 'clothing') {
|
||||
params.append('clothing_only', 'true');
|
||||
}
|
||||
// If 'all' is selected, don't add any type filter
|
||||
|
||||
|
|
@ -294,7 +304,14 @@ function buildSearchParameters() {
|
|||
addParam(params, 'min_vitality_rating', 'searchMinVitalityRating');
|
||||
addParam(params, 'min_damage_resist_rating', 'searchMinDamageResistRating');
|
||||
addParam(params, 'min_crit_damage_resist_rating', 'searchMinCritDamageResistRating');
|
||||
|
||||
|
||||
// Weapon / combat stats
|
||||
addParam(params, 'min_damage', 'searchMinDamage');
|
||||
addParam(params, 'max_damage', 'searchMaxDamage');
|
||||
addParam(params, 'min_attack_bonus', 'searchMinAttackBonus');
|
||||
addParam(params, 'min_crit_resist_rating', 'searchMinCritResistRating');
|
||||
addParam(params, 'min_tinks', 'searchMinTinks');
|
||||
|
||||
// Requirements parameters
|
||||
addParam(params, 'min_level', 'searchMinLevel');
|
||||
addParam(params, 'max_level', 'searchMaxLevel');
|
||||
|
|
@ -305,7 +322,21 @@ function buildSearchParameters() {
|
|||
addParam(params, 'min_value', 'searchMinValue');
|
||||
addParam(params, 'max_value', 'searchMaxValue');
|
||||
addParam(params, 'max_burden', 'searchMaxBurden');
|
||||
|
||||
|
||||
// Spell text search
|
||||
addParam(params, 'spell_contains', 'searchSpellContains');
|
||||
|
||||
// Item state filters (only send when checked)
|
||||
if (document.getElementById('searchBonded')?.checked) {
|
||||
params.append('bonded', 'true');
|
||||
}
|
||||
if (document.getElementById('searchAttuned')?.checked) {
|
||||
params.append('attuned', 'true');
|
||||
}
|
||||
if (document.getElementById('searchIsRare')?.checked) {
|
||||
params.append('is_rare', 'true');
|
||||
}
|
||||
|
||||
// Equipment set filters
|
||||
const selectedEquipmentSets = getSelectedEquipmentSets();
|
||||
if (selectedEquipmentSets.length === 1) {
|
||||
|
|
@ -418,6 +449,7 @@ function displayResults(data) {
|
|||
<thead>
|
||||
<tr>
|
||||
<th class="sortable" data-sort="character_name">Character${getSortIcon('character_name')}</th>
|
||||
<th class="sortable" data-sort="is_equipped">Status${getSortIcon('is_equipped')}</th>
|
||||
<th class="sortable" data-sort="name">Item Name${getSortIcon('name')}</th>
|
||||
<th class="sortable" data-sort="item_type_name">Type${getSortIcon('item_type_name')}</th>
|
||||
<th class="text-right narrow-col sortable" data-sort="slot_name">Slot${getSortIcon('slot_name')}</th>
|
||||
|
|
@ -508,6 +540,7 @@ function displayResults(data) {
|
|||
html += `
|
||||
<tr>
|
||||
<td>${item.character_name}</td>
|
||||
<td class="${statusClass}">${status}</td>
|
||||
<td class="item-name">${displayName}</td>
|
||||
<td>${itemType}</td>
|
||||
<td class="text-right narrow-col">${slot}</td>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue