From db12844deae29e5e4796be122a1e7ec2366a9e72 Mon Sep 17 00:00:00 2001 From: Zach Harding Date: Wed, 25 Mar 2026 08:41:21 -0400 Subject: [PATCH] setting up inventory dashboard --- src/assets/css/main.scss | 22 ++-- src/assets/js/priceChart.js | 32 +++--- src/components/CardGrid.astro | 18 ++- src/pages/partials/card-modal.astro | 166 ++++++++++++++++++++++++++-- src/pages/partials/cards.astro | 6 +- 5 files changed, 208 insertions(+), 36 deletions(-) diff --git a/src/assets/css/main.scss b/src/assets/css/main.scss index 4d01fd4..32dbfa1 100644 --- a/src/assets/css/main.scss +++ b/src/assets/css/main.scss @@ -418,22 +418,24 @@ $tiers: ( } .inventory-button { - width: 40px; - height: 40px; - margin-bottom: -2rem; - margin-right: -0.25rem; - border-radius: 0.33rem; + margin-bottom: -2.25rem; + margin-right: -0.5rem; + z-index: 2; background-color: hsl(262, 47%, 55%); color: #fff; } -.inventory-label { - width: 100%; - height: 100%; - font-size: 1rem; - font-weight: 700; +.inventory-button:hover { + background-color: hsl(262, 39%, 40%); + color: #fff; } +#inventoryForm .btn-check:checked + .nav-link { + outline: 2px solid rgba(0, 0, 0, 0.4); + outline-offset: -2px; +} +#inventoryForm .nav-link { cursor: pointer; } + .fs-7 { font-size: 0.9rem !important; } diff --git a/src/assets/js/priceChart.js b/src/assets/js/priceChart.js index dfa3f34..0f6d538 100644 --- a/src/assets/js/priceChart.js +++ b/src/assets/js/priceChart.js @@ -32,6 +32,12 @@ function setEmptyState(isEmpty) { canvasWrapper.classList.toggle('d-none', isEmpty); } +function setChartVisible(visible) { + const modal = document.getElementById('cardModal'); + const chartWrapper = modal?.querySelector('#priceHistoryChart')?.closest('.alert'); + if (chartWrapper) chartWrapper.classList.toggle('d-none', !visible); +} + function buildChartData(history, rangeKey) { const cutoff = RANGE_DAYS[rangeKey] === Infinity ? new Date(0) @@ -39,20 +45,14 @@ function buildChartData(history, rangeKey) { const filtered = history.filter(r => new Date(r.calculatedAt) >= cutoff); - // Always build the full date axis for the selected window, even if sparse. - // Generate one label per day in the range so the x-axis reflects the - // chosen period rather than collapsing to only the days that have data. const dataDateSet = new Set(filtered.map(r => r.calculatedAt)); const allDates = [...dataDateSet].sort((a, b) => new Date(a) - new Date(b)); - // If we have real data, expand the axis to span from cutoff → today so - // empty stretches at the start/end of a range are visible. let axisLabels = allDates; if (allDates.length > 0 && RANGE_DAYS[rangeKey] !== Infinity) { const start = new Date(cutoff); const end = new Date(); const expanded = []; - // Step through every day in the window for (let d = new Date(start); d <= end; d.setDate(d.getDate() + 1)) { expanded.push(d.toISOString().split('T')[0]); } @@ -101,17 +101,9 @@ function buildChartData(history, rangeKey) { function updateChart() { if (!chartInstance) return; const { labels, datasets, hasData, activeConditionHasData } = buildChartData(allHistory, activeRange); - - // Always push the new labels/datasets to the chart so the x-axis - // reflects the selected time window — even when there's no data for - // the active condition. Then toggle the empty state overlay on top. chartInstance.data.labels = labels; chartInstance.data.datasets = datasets; chartInstance.update('none'); - - // Show the empty state overlay if the active condition has no points - // in this window, but leave the (empty) chart visible underneath so - // the axis communicates the selected period. setEmptyState(!hasData || !activeConditionHasData); } @@ -135,7 +127,6 @@ function initPriceChart(canvas) { const { labels, datasets, hasData, activeConditionHasData } = buildChartData(allHistory, activeRange); - // Render the chart regardless — show empty state overlay if needed setEmptyState(!hasData || !activeConditionHasData); chartInstance = new Chart(canvas.getContext('2d'), { @@ -202,9 +193,16 @@ function initFromCanvas(canvas) { activeCondition = "Near Mint"; activeRange = '1m'; const modal = document.getElementById('cardModal'); + modal?.querySelectorAll('.price-range-btn').forEach(b => { b.classList.toggle('active', b.dataset.range === '1m'); }); + + // Hide chart if the vendor tab is already active when the modal opens + // (e.g. opened via the inventory button) + const activeTab = modal?.querySelector('.nav-link.active')?.getAttribute('data-bs-target'); + setChartVisible(activeTab !== '#nav-vendor'); + initPriceChart(canvas); } @@ -225,6 +223,10 @@ function setup() { document.addEventListener('shown.bs.tab', (e) => { if (!modal.contains(e.target)) return; const target = e.target?.getAttribute('data-bs-target'); + + // Hide the chart when the vendor tab is active, show it for all others + setChartVisible(target !== '#nav-vendor'); + const conditionMap = { '#nav-nm': 'Near Mint', '#nav-lp': 'Lightly Played', diff --git a/src/components/CardGrid.astro b/src/components/CardGrid.astro index ac8f0f0..209439c 100644 --- a/src/components/CardGrid.astro +++ b/src/components/CardGrid.astro @@ -118,7 +118,6 @@ import BackToTop from "./BackToTop.astro" canvas.width = img.naturalWidth; canvas.height = img.naturalHeight; - // Load with crossOrigin so toBlob() stays untainted await new Promise((resolve) => { const clean = new Image(); clean.crossOrigin = 'anonymous'; @@ -172,6 +171,19 @@ import BackToTop from "./BackToTop.astro" }, 2000); } + // ── Tab switching helper ────────────────────────────────────────────────── + // Called after every modal swap. Checks sessionStorage for a tab request + // set by the inventory button click, activates it once, then clears it. + function switchToRequestedTab() { + const tab = sessionStorage.getItem('openModalTab'); + if (!tab) return; + sessionStorage.removeItem('openModalTab'); + requestAnimationFrame(() => { + const tabEl = document.querySelector(`#cardModal [data-bs-target="#${tab}"]`); + if (tabEl) bootstrap.Tab.getOrCreateInstance(tabEl).show(); + }); + } + // ── State ───────────────────────────────────────────────────────────────── const cardIndex = []; let currentCardId = null; @@ -263,6 +275,7 @@ import BackToTop from "./BackToTop.astro" if (typeof htmx !== 'undefined') htmx.process(modal); updateNavButtons(modal); initChartAfterSwap(modal); + switchToRequestedTab(); }; if (document.startViewTransition && direction) { @@ -365,6 +378,7 @@ import BackToTop from "./BackToTop.astro" await transition.finished; updateNavButtons(target); initChartAfterSwap(target); + switchToRequestedTab(); } catch (err) { console.error('[card-modal] transition failed:', err); @@ -383,10 +397,12 @@ import BackToTop from "./BackToTop.astro" cardModal.addEventListener('shown.bs.modal', () => { updateNavButtons(cardModal); initChartAfterSwap(cardModal); + switchToRequestedTab(); }); cardModal.addEventListener('hidden.bs.modal', () => { currentCardId = null; updateNavButtons(null); }); + })(); \ No newline at end of file diff --git a/src/pages/partials/card-modal.astro b/src/pages/partials/card-modal.astro index 41cede8..cd716d1 100644 --- a/src/pages/partials/card-modal.astro +++ b/src/pages/partials/card-modal.astro @@ -226,31 +226,31 @@ const altSearchUrl = (card: any) => {