[feat] modal prices & volatility set correctly for each condition
This commit is contained in:
@@ -27,15 +27,7 @@ const card = await db.query.cards.findFirst({
|
||||
}
|
||||
});
|
||||
|
||||
const nearMint = await db.query.skus.findFirst({
|
||||
where: {
|
||||
productId: card?.productId || 0,
|
||||
variant: card?.variant || "",
|
||||
}
|
||||
});
|
||||
|
||||
const nearMintPrice = nearMint?.marketPrice ?? null;
|
||||
|
||||
const nearMint = card?.prices.find(price => price.condition === "Near Mint") || null;
|
||||
const calculatedAt = new Date(nearMint?.calculatedAt || 0);
|
||||
|
||||
function timeAgo(date: any) {
|
||||
@@ -59,24 +51,40 @@ function timeAgo(date: any) {
|
||||
return "just now";
|
||||
}
|
||||
|
||||
function getPriceVolatility({ current, low, high }) {
|
||||
if (!current || !low || !high) return "—";
|
||||
const conditionOrder = ["Near Mint", "Lightly Played", "Moderately Played", "Heavily Played", "Damaged"];
|
||||
|
||||
const range = high - low;
|
||||
if (range <= 0) return "Low";
|
||||
const conditionAttributes = (price: any) => {
|
||||
const volatility = (() => {
|
||||
const current = price;
|
||||
const low = price?.lowestPrice;
|
||||
const high = price?.highestPrice;
|
||||
|
||||
const position = (current - low) / range;
|
||||
if (current === null || low === null || high === null) return "—";
|
||||
|
||||
if (position > 0.75) return "High";
|
||||
if (position < 0.46 || position > 0.74) return "Medium";
|
||||
return "Low";
|
||||
}
|
||||
const range = Number(high) - Number(low);
|
||||
if (range <= 0) return "Low";
|
||||
|
||||
const volatility = getPriceVolatility({
|
||||
current: nearMintPrice,
|
||||
low: nearMint?.lowestPrice,
|
||||
high: nearMint?.highestPrice
|
||||
});
|
||||
const position = (Number(current) - Number(low)) / range;
|
||||
if (position > 0.75) return "High";
|
||||
if (position > 0.46) return "Medium";
|
||||
return "Low";
|
||||
})();
|
||||
|
||||
const volatilityClass =
|
||||
volatility === "High" ? "alert-danger" :
|
||||
volatility === "Medium" ? "alert-warning" :
|
||||
volatility === "Low" ? "alert-success" :
|
||||
"";
|
||||
|
||||
const condition: string = price?.condition || "Near Mint";
|
||||
return {
|
||||
"Near Mint": { label: "nav-nm", volatility: volatility, volatilityClass: volatilityClass, class:"show active" },
|
||||
"Lightly Played": { label: "nav-lp", volatility: volatility, volatilityClass: volatilityClass },
|
||||
"Moderately Played": { label: "nav-mp", volatility: volatility, volatilityClass: volatilityClass },
|
||||
"Heavily Played": { label: "nav-hp", volatility: volatility, volatilityClass: volatilityClass },
|
||||
"Damaged": { label: "nav-dmg", volatility: volatility, volatilityClass: volatilityClass},
|
||||
}[condition];
|
||||
};
|
||||
|
||||
---
|
||||
<div class="modal-dialog modal-dialog-centered modal-fullscreen-md-down modal-xl">
|
||||
@@ -84,7 +92,7 @@ const volatility = getPriceVolatility({
|
||||
<div class="modal-content">
|
||||
<div class="modal-header border-0">
|
||||
<div class="container-fluid">
|
||||
<span class="h4 card-title pe-2">{card?.productName}</span><span class="text-secondary ps-2 border-start">{card?.number}</span><span class="text-secondary ps-2">{nearMint?.variant}</span>
|
||||
<span class="h4 card-title pe-2">{card?.productName}</span><span class="text-secondary ps-2 border-start">{card?.number}</span><span class="text-secondary ps-2">{card?.variant}</span>
|
||||
</div>
|
||||
<button type="button" class="btn-close" aria-label="Close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
@@ -121,141 +129,40 @@ const volatility = getPriceVolatility({
|
||||
</li>
|
||||
</ul>
|
||||
<div class="tab-content" id="myTabContent">
|
||||
<div class="tab-pane fade show active" id="nav-nm" role="tabpanel" aria-labelledby="nav-nm" tabindex="0">
|
||||
<div class="row g-2 mt-2">
|
||||
<div class="mt-2 col-12 col-md-3 row row-cols-3 row-cols-md-1">
|
||||
<div class="col alert alert-secondary price-area rounded mb-1 py-2">
|
||||
<p class="h6">Market Price</p>
|
||||
<p class="py-0 mb-1">${nearMintPrice}</p>
|
||||
</div>
|
||||
<div class="col alert alert-secondary price-area rounded mb-1 py-2">
|
||||
<p class="h6">Lowest List</p>
|
||||
<p class="py-0 mb-1">${nearMint?.lowestPrice}</p>
|
||||
</div>
|
||||
<div class="col alert alert-secondary price-area rounded mb-1 py-2">
|
||||
<p class="h6">Highest List</p>
|
||||
<p class="py-0 mb-1">${nearMint?.highestPrice}</p>
|
||||
</div>
|
||||
<div class="col-12 mb-1 py-2 alert alert-secondary rounded" id="volatilityContainer" role="alert">
|
||||
<p class="h6">Volatility</p>
|
||||
<p class="py-0 mb-1" id="volatility">{volatility}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-flex flex-column mt-2 col-12 col-md-9">
|
||||
<div class="alert alert-secondary rounded table-responsive mb-1 py-2">
|
||||
<p class="h6">Latest Sales</p>
|
||||
{card?.prices.slice().sort((a, b) => conditionOrder.indexOf(a.condition) - conditionOrder.indexOf(b.condition)).map((price) => {
|
||||
const attributes = conditionAttributes(price);
|
||||
return (
|
||||
<div class={`tab-pane fade ${attributes?.label} ${attributes?.class}`} id={`${attributes?.label}`} role="tabpanel" tabindex="0">
|
||||
<div class="row g-2 mt-2">
|
||||
<div class="d-flex flex-column mt-2 col-3">
|
||||
<div class="alert alert-secondary rounded p-2 mb-2">
|
||||
<h6>Market Price</h6>
|
||||
<p>${price.marketPrice}</p>
|
||||
</div>
|
||||
<div class="alert alert-secondary rounded p-2 mb-2">
|
||||
<h6>Lowest Price</h6>
|
||||
<p>${price.lowestPrice}</p>
|
||||
</div>
|
||||
<div class="alert alert-secondary rounded p-2 mb-2">
|
||||
<h6>Highest Price</h6>
|
||||
<p>${price.highestPrice}</p>
|
||||
</div>
|
||||
<div class={`alert alert-secondary rounded p-2 mb-2 ${attributes?.volatilityClass}`}>
|
||||
<h6>Volatility</h6>
|
||||
<p>{attributes?.volatility}</p>
|
||||
</div>
|
||||
<div class="alert alert-secondary rounded p-2 mb-2 flex-fill">
|
||||
<h6>Latest Sales</h6>
|
||||
</div>
|
||||
<div class="alert alert-secondary rounded mb-1 py-2 ">
|
||||
<p class="h6">Placeholder for graph</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
|
||||
</div>
|
||||
<div class="alert alert-secondary rounded mb-1 py-2 ">
|
||||
<p class="h6">Placeholder for graph</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tab-pane fade" id="nav-lp" role="tabpanel" aria-labelledby="nav-lp" tabindex="0">
|
||||
<div class="row g-2 mt-2">
|
||||
<div class="d-flex flex-column mt-2 col-3">
|
||||
<div class="alert alert-secondary rounded p-2 mb-2">
|
||||
<h6>Market Price</h6>
|
||||
<p></p>
|
||||
</div>
|
||||
<div class="alert alert-secondary rounded p-2 mb-2">
|
||||
<h6>Lowest Price</h6>
|
||||
<p></p>
|
||||
</div>
|
||||
<div class="alert alert-secondary rounded p-2 mb-2">
|
||||
<h6>Highest Price</h6>
|
||||
<p></p>
|
||||
</div>
|
||||
<div class="alert alert-secondary rounded p-2 mb-2">
|
||||
<h6>Volatility</h6>
|
||||
<p></p>
|
||||
</div>
|
||||
<div class="alert alert-secondary rounded p-2 mb-2 flex-fill">
|
||||
<h6>Latest Sales</h6>
|
||||
<p></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tab-pane fade" id="nav-mp" role="tabpanel" aria-labelledby="nav-mp" tabindex="0">
|
||||
<div class="row g-2 mt-2">
|
||||
<div class="d-flex flex-column mt-2 col-3">
|
||||
<div class="alert alert-secondary rounded p-2 mb-2">
|
||||
<h6>Market Price</h6>
|
||||
<p></p>
|
||||
</div>
|
||||
<div class="alert alert-secondary rounded p-2 mb-2">
|
||||
<h6>Lowest Price</h6>
|
||||
<p></p>
|
||||
</div>
|
||||
<div class="alert alert-secondary rounded p-2 mb-2">
|
||||
<h6>Highest Price</h6>
|
||||
<p></p>
|
||||
</div>
|
||||
<div class="alert alert-secondary rounded p-2 mb-2">
|
||||
<h6>Volatility</h6>
|
||||
<p></p>
|
||||
</div>
|
||||
<div class="alert alert-secondary rounded p-2 mb-2 flex-fill">
|
||||
<h6>Latest Sales</h6>
|
||||
<p></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tab-pane fade" id="nav-hp" role="tabpanel" aria-labelledby="nav-hp" tabindex="0">
|
||||
<div class="row g-2 mt-2">
|
||||
<div class="d-flex flex-column mt-2 col-3">
|
||||
<div class="alert alert-secondary rounded p-2 mb-2">
|
||||
<h6>Market Price</h6>
|
||||
<p></p>
|
||||
</div>
|
||||
<div class="alert alert-secondary rounded p-2 mb-2">
|
||||
<h6>Lowest Price</h6>
|
||||
<p></p>
|
||||
</div>
|
||||
<div class="alert alert-secondary rounded p-2 mb-2">
|
||||
<h6>Highest Price</h6>
|
||||
<p></p>
|
||||
</div>
|
||||
<div class="alert alert-secondary rounded p-2 mb-2">
|
||||
<h6>Volatility</h6>
|
||||
<p></p>
|
||||
</div>
|
||||
<div class="alert alert-secondary rounded p-2 mb-2 flex-fill">
|
||||
<h6>Latest Sales</h6>
|
||||
<p></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tab-pane fade" id="nav-dmg" role="tabpanel" aria-labelledby="nav-dmg" tabindex="0">
|
||||
<div class="row g-2 mt-2">
|
||||
<div class="d-flex flex-column mt-2 col-3">
|
||||
<div class="alert alert-secondary rounded p-2 mb-2">
|
||||
<h6>Market Price</h6>
|
||||
<p></p>
|
||||
</div>
|
||||
<div class="alert alert-secondary rounded p-2 mb-2">
|
||||
<h6>Lowest Price</h6>
|
||||
<p></p>
|
||||
</div>
|
||||
<div class="alert alert-secondary rounded p-2 mb-2">
|
||||
<h6>Highest Price</h6>
|
||||
<p></p>
|
||||
</div>
|
||||
<div class="alert alert-secondary rounded p-2 mb-2">
|
||||
<h6>Volatility</h6>
|
||||
<p></p>
|
||||
</div>
|
||||
<div class="alert alert-secondary rounded p-2 mb-2 flex-fill">
|
||||
<h6>Latest Sales</h6>
|
||||
<p></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tab-pane fade" id="nav-vendor" role="tabpanel" aria-labelledby="nav-vendor" tabindex="0">
|
||||
<div class="row g-2 mt-2">
|
||||
<div class="d-flex flex-column mt-2 col-3">
|
||||
@@ -297,23 +204,3 @@ const volatility = getPriceVolatility({
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const volDiv = document.getElementById("volatility");
|
||||
const parent = volDiv.parentElement;
|
||||
|
||||
// Define the mapping of text → class
|
||||
const classMap = {
|
||||
"Low": "alert-success",
|
||||
"Medium": "alert-warning",
|
||||
"High": "alert-danger"
|
||||
};
|
||||
|
||||
// Get the current text of the div
|
||||
const text = volDiv.textContent.trim();
|
||||
|
||||
// Apply class if the text matches
|
||||
if (classMap[text]) {
|
||||
parent.classList.add(classMap[text]);
|
||||
}
|
||||
</script>
|
||||
Reference in New Issue
Block a user