[feat] minor tweaks to the inventory modal
This commit is contained in:
@@ -252,9 +252,9 @@ const catalogs = catalogRows
|
||||
purchaseDate: canvas.dataset.purchaseDate || null,
|
||||
condition: canvas.dataset.condition || 'Near Mint',
|
||||
};
|
||||
range = 'all';
|
||||
range = '6m';
|
||||
root.querySelectorAll('.inv-price-range-btn').forEach(b =>
|
||||
b.classList.toggle('active', b.dataset.range === 'all'));
|
||||
b.classList.toggle('active', b.dataset.range === '6m'));
|
||||
|
||||
const emptyEl = root.querySelector('#inventoryPriceEmpty');
|
||||
const wrap = canvas.closest('.chart-canvas-wrap');
|
||||
@@ -390,7 +390,7 @@ const catalogs = catalogRows
|
||||
const delBtn = e.target.closest('[data-inventory-delete]');
|
||||
if (!delBtn) return;
|
||||
|
||||
const form = delBtn.closest('[data-inventory-edit-form]');
|
||||
const form = modal.querySelector('[data-inventory-edit-form]');
|
||||
const inventoryId = form?.querySelector('[name=inventoryId]')?.value;
|
||||
const cardId = form?.querySelector('[name=cardId]')?.value;
|
||||
if (!inventoryId) return;
|
||||
@@ -426,17 +426,16 @@ const catalogs = catalogRows
|
||||
if (!form) return;
|
||||
e.preventDefault();
|
||||
|
||||
const btn = form.querySelector('button[type="submit"]');
|
||||
const btn = modal.querySelector('button[type="submit"][form="inventoryEditForm"]');
|
||||
const original = btn ? btn.textContent : '';
|
||||
if (btn) { btn.disabled = true; btn.textContent = 'Saving…'; }
|
||||
|
||||
try {
|
||||
const res = await fetch('/api/inventory', { method: 'POST', body: new FormData(form) });
|
||||
if (res.ok) {
|
||||
if (btn) { btn.textContent = 'Saved ✓'; btn.classList.remove('btn-success'); btn.classList.add('btn-outline-success'); }
|
||||
setTimeout(() => {
|
||||
if (btn) { btn.textContent = original; btn.disabled = false; btn.classList.add('btn-success'); btn.classList.remove('btn-outline-success'); }
|
||||
}, 1500);
|
||||
const instance = window.bootstrap?.Modal.getInstance(modal);
|
||||
if (instance) instance.hide();
|
||||
else modal.querySelector('[data-bs-dismiss=modal]')?.click();
|
||||
} else if (btn) {
|
||||
btn.textContent = original; btn.disabled = false;
|
||||
}
|
||||
|
||||
@@ -111,15 +111,8 @@ const altSearchUrl = (card: any) => {
|
||||
<!-- Card image column -->
|
||||
<div class="col-sm-12 col-md-3">
|
||||
<div class="position-relative mt-1">
|
||||
<div
|
||||
class="card-image-wrap rounded-4"
|
||||
data-energy={card?.energyType}
|
||||
data-rarity={card?.rarityName}
|
||||
data-variant={card?.variant}
|
||||
data-name={card?.productName}
|
||||
>
|
||||
<img
|
||||
src={`/static/cards/${card?.productId}.jpg`}
|
||||
<div class="card-image-wrap rounded-4" data-energy={card?.energyType} data-rarity={card?.rarityName} data-variant={card?.variant} data-name={card?.productName}>
|
||||
<img src={`/static/cards/${card?.productId}.jpg`}
|
||||
class="card-image w-100 img-fluid rounded-4"
|
||||
alt={card?.productName}
|
||||
crossorigin="anonymous"
|
||||
@@ -148,59 +141,19 @@ const altSearchUrl = (card: any) => {
|
||||
<div class="col-12 col-lg-6">
|
||||
<label class="form-label">Condition</label>
|
||||
<div class="btn-group condition-input w-100 col-12" role="group" aria-label="Condition">
|
||||
<input
|
||||
type="radio"
|
||||
class="btn-check"
|
||||
name="condition"
|
||||
id="cond-nm"
|
||||
value="Near Mint"
|
||||
autocomplete="off"
|
||||
checked
|
||||
/>
|
||||
<input type="radio" class="btn-check" name="condition" id="cond-nm" value="Near Mint" autocomplete="off" checked />
|
||||
<label class="btn btn-cond-nm" for="cond-nm">NM</label>
|
||||
|
||||
<input
|
||||
type="radio"
|
||||
class="btn-check"
|
||||
name="condition"
|
||||
id="cond-lp"
|
||||
value="Lightly Played"
|
||||
autocomplete="off"
|
||||
disabled
|
||||
/>
|
||||
<input type="radio" class="btn-check" name="condition" id="cond-lp" value="Lightly Played" autocomplete="off" disabled />
|
||||
<label class="btn btn-cond-lp" for="cond-lp">LP</label>
|
||||
|
||||
<input
|
||||
type="radio"
|
||||
class="btn-check"
|
||||
name="condition"
|
||||
id="cond-mp"
|
||||
value="Moderately Played"
|
||||
autocomplete="off"
|
||||
disabled
|
||||
/>
|
||||
<input type="radio" class="btn-check" name="condition" id="cond-mp" value="Moderately Played" autocomplete="off" disabled />
|
||||
<label class="btn btn-cond-mp" for="cond-mp">MP</label>
|
||||
|
||||
<input
|
||||
type="radio"
|
||||
class="btn-check"
|
||||
name="condition"
|
||||
id="cond-hp"
|
||||
value="Heavily Played"
|
||||
autocomplete="off"
|
||||
disabled
|
||||
/>
|
||||
<input type="radio" class="btn-check" name="condition" id="cond-hp" value="Heavily Played" autocomplete="off" disabled />
|
||||
<label class="btn btn-cond-hp" for="cond-hp">HP</label>
|
||||
|
||||
<input
|
||||
type="radio"
|
||||
class="btn-check"
|
||||
name="condition"
|
||||
id="cond-dmg"
|
||||
value="Damaged"
|
||||
autocomplete="off"
|
||||
disabled
|
||||
/>
|
||||
<input type="radio" class="btn-check" name="condition" id="cond-dmg" value="Damaged" autocomplete="off" disabled />
|
||||
<label class="btn btn-cond-dmg" for="cond-dmg">DMG</label>
|
||||
</div>
|
||||
<p class="mb-1 my-2">Purchased: <span class="text-secondary">{inv.createdAt ? new Date(inv.createdAt).toLocaleDateString() : '—'}</span></p>
|
||||
@@ -222,11 +175,7 @@ const altSearchUrl = (card: any) => {
|
||||
<div class={`alert rounded p-2 flex-fill ${gainPercent == null ? 'alert-dark' : gainPercent >= 0 ? 'alert-success' : 'alert-danger'}`}>
|
||||
<p class="mb-auto">Gain / Loss (%)</p>
|
||||
<h6 class="mb-0 mt-1">
|
||||
{
|
||||
gainPercent == null
|
||||
? '—'
|
||||
: `${gainPercent >= 0 ? '+' : '−'}${Math.abs(gainPercent).toFixed(2)}%`
|
||||
}
|
||||
{ gainPercent == null ? '—' : `${gainPercent >= 0 ? '+' : '−'}${Math.abs(gainPercent).toFixed(2)}%` }
|
||||
</h6>
|
||||
</div>
|
||||
</div>
|
||||
@@ -234,7 +183,7 @@ const altSearchUrl = (card: any) => {
|
||||
|
||||
<!-- Right column: editable Note + Catalog -->
|
||||
<div class="col-12 col-lg-6">
|
||||
<form data-inventory-edit-form novalidate>
|
||||
<form id="inventoryEditForm" data-inventory-edit-form novalidate>
|
||||
<input type="hidden" name="action" value="update" />
|
||||
<input type="hidden" name="inventoryId" value={inv?.inventoryId} />
|
||||
<input type="hidden" name="cardId" value={card?.cardId} />
|
||||
@@ -242,30 +191,15 @@ const altSearchUrl = (card: any) => {
|
||||
<input type="hidden" name="purchasePrice" value={purchasePrice ?? 0} />
|
||||
|
||||
<label for="catalogName" class="form-label">Catalog</label>
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
id="catalogName"
|
||||
name="catalogName"
|
||||
list="catalogSuggestions"
|
||||
placeholder="Default"
|
||||
autocomplete="off"
|
||||
maxlength="100"
|
||||
value={inv?.catalogName ?? ''}
|
||||
/>
|
||||
<input type="text" class="form-control" id="catalogName" name="catalogName" list="catalogSuggestions" placeholder="Default" maxlength="100" value={inv?.catalogName ?? ''} />
|
||||
<datalist id="catalogSuggestions">
|
||||
{catalogs.map(name => <option value={name}></option>)}
|
||||
</datalist>
|
||||
|
||||
<label for="note" class="form-label mt-2">Note</label>
|
||||
<textarea
|
||||
class="form-control"
|
||||
id="note"
|
||||
name="note"
|
||||
rows="5"
|
||||
maxlength="255"
|
||||
placeholder="e.g. bought at local shop, gift, graded copy…"
|
||||
>{inv?.note ?? ''}</textarea>
|
||||
<textarea class="form-control" id="note" name="note" rows="5" maxlength="255" placeholder="e.g. bought at local shop, gift, graded copy…">
|
||||
{inv?.note ?? ''}
|
||||
</textarea>
|
||||
|
||||
</form>
|
||||
</div>
|
||||
@@ -281,21 +215,14 @@ const altSearchUrl = (card: any) => {
|
||||
No price history for this condition
|
||||
</div>
|
||||
<div class="position-relative chart-canvas-wrap" style="height: 220px;">
|
||||
<canvas
|
||||
id="inventoryPriceChart"
|
||||
class="price-history-chart"
|
||||
data-history={JSON.stringify(priceHistoryForChart)}
|
||||
data-purchase-price={purchasePrice ?? ''}
|
||||
data-purchase-date={purchaseDate ?? ''}
|
||||
data-condition={condition}>
|
||||
</canvas>
|
||||
<canvas id="inventoryPriceChart" class="price-history-chart" data-history={JSON.stringify(priceHistoryForChart)} data-purchase-price={purchasePrice ?? ''} data-purchase-date={purchaseDate ?? ''} data-condition={condition}></canvas>
|
||||
</div>
|
||||
<div class="btn-group btn-group-sm d-flex flex-row gap-1 justify-content-end mt-2" role="group" aria-label="Time range">
|
||||
<button type="button" class="btn btn-dark inv-price-range-btn" data-range="1m">1M</button>
|
||||
<button type="button" class="btn btn-dark inv-price-range-btn" data-range="3m">3M</button>
|
||||
<button type="button" class="btn btn-dark inv-price-range-btn" data-range="6m">6M</button>
|
||||
<button type="button" class="btn btn-dark inv-price-range-btn active" data-range="6m">6M</button>
|
||||
<button type="button" class="btn btn-dark inv-price-range-btn" data-range="1y">1Y</button>
|
||||
<button type="button" class="btn btn-dark inv-price-range-btn active" data-range="all">All</button>
|
||||
<button type="button" class="btn btn-dark inv-price-range-btn" data-range="all">All</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -310,7 +237,7 @@ const altSearchUrl = (card: any) => {
|
||||
<a class="btn btn-dark mb-2 w-100 p-2" href={`${altSearchUrl(card)}`} target="_blank" onclick="dataLayer.push({'event': 'altClick', 'altUrl': this.getAttribute('href')});"><svg width="48" height="20.16" viewBox="0 0 48 20" fill="none"><path d="M14.2761 19.9996H18.5308L11.6934 0.0712891H7.76953L14.2761 19.9996Z" fill="#ffffff"></path><path d="M6.17778 19.9986H6.14536L3.19643 11.2305L0 19.9988L6.17768 19.9989L6.17778 19.9986Z" fill="#ffffff"></path><path d="M24.7842 0H20.6759V19.9661H34.3427V16.5426H24.7842V0Z" fill="#ffffff"></path><path d="M41.6644 3.42355H47.4981V0H31.5033V3.42355H37.5561V19.9661H41.6644V3.42355Z" fill="#ffffff"></path></svg></a>
|
||||
<div class="d-flex gap-2 mt-auto align-items-end justify-content-evenly">
|
||||
<button type="button" class="btn btn-outline-danger flex-fill" data-inventory-delete>Delete</button>
|
||||
<button type="submit" class="btn btn-success flex-fill flex-grow-1">Save</button>
|
||||
<button type="submit" form="inventoryEditForm" class="btn btn-success flex-fill flex-grow-1">Save</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user