new border pattern for each condition on modal, added icon display for 1st edition on both card/card modal

This commit is contained in:
zach
2026-03-09 12:00:29 -04:00
parent f5fcd7b3e7
commit 68bed6ff8e
5 changed files with 60 additions and 17 deletions

View File

@@ -220,7 +220,7 @@ $tiers: (
color: rgba(255, 255, 255, 0.87); color: rgba(255, 255, 255, 0.87);
} }
} }
} }
} }
/* -------------------------------------------------- /* --------------------------------------------------
@@ -250,6 +250,12 @@ $tiers: (
margin-top: -0.25rem; margin-top: -0.25rem;
} }
.medium-icon svg {
width: 100%;
max-height: 32px;
margin-left: -0.25rem;
}
/* Black silhouette overlay */ /* Black silhouette overlay */
.masked-image { .masked-image {
z-index: 1000; z-index: 1000;
@@ -272,7 +278,7 @@ $tiers: (
/* SVG sizes */ /* SVG sizes */
.energy-icon svg, .energy-icon svg,
.rarity-icon-large svg, .rarity-icon-large svg,
.set-icon svg { .set-icon svg, .edition-icon svg {
width: 2.5rem; width: 2.5rem;
z-index: 999; z-index: 999;
} }
@@ -355,6 +361,20 @@ $tiers: (
); );
} }
$tiers: (
nm: rgba(156, 204, 102, 1),
lp: rgba(211, 225, 86, 1),
mp: rgba(255, 238, 87, 1),
hp: rgba(255, 201, 41, 1),
dmg: rgba(255, 167, 36, 1)
);
@each $name, $color in $tiers {
.nav-#{$name} div.alert-secondary {
border-left: 3px solid $color;
}
}
.inventory-button { .inventory-button {
margin-bottom: -2rem; margin-bottom: -2rem;
margin-right: -0.25rem; margin-right: -0.25rem;

View File

@@ -0,0 +1,13 @@
---
import first from "/src/svg/edition/firstEdition.svg?raw";
const { edition } = Astro.props;
const editionMap = {
"1st Edition Holofoil": first,
};
const svg = editionMap[edition as keyof typeof editionMap] ?? "";
---
<div class="edition-icon shadow-filter" set:html={svg}></div>

View File

@@ -5,6 +5,7 @@ import EnergyIcon from '../../components/EnergyIcon.astro';
import RarityIcon from '../../components/RarityIcon.astro'; import RarityIcon from '../../components/RarityIcon.astro';
import { db } from '../../db/index'; import { db } from '../../db/index';
import { privateDecrypt } from "node:crypto"; import { privateDecrypt } from "node:crypto";
import FirstEditionIcon from "../../components/FirstEditionIcon.astro";
export const partial = true; export const partial = true;
export const prerender = false; export const prerender = false;
@@ -77,7 +78,7 @@ const conditionAttributes = (price: any) => {
const high = price?.highestPrice; const high = price?.highestPrice;
const median = price?.medianPrice; const median = price?.medianPrice;
if (current === null || low === null || high === null) return ""; if (current === null || low === null || high === null) return "Indeterminate";
const range = Number(high) - Number(low); const range = Number(high) - Number(low);
if (range <= 0) return "Low"; if (range <= 0) return "Low";
@@ -88,19 +89,26 @@ const conditionAttributes = (price: any) => {
return "Low"; return "Low";
})(); })();
const volatilityClass = // Updated logic:
volatility === "High" ? "alert-danger" : // ❗ If High / Medium / Low → never "alert-secondary"
volatility === "Medium" ? "alert-warning" : // ❗ If Indeterminate → "alert-secondary"
volatility === "Low" ? "alert-success" : const volatilityClass = (() => {
""; switch (volatility) {
case "High": return "alert-danger";
case "Medium": return "alert-warning";
case "Low": return "alert-success";
default: return "alert-secondary"; // Only for Indeterminate
}
})();
const condition: string = price?.condition || "Near Mint"; const condition: string = price?.condition || "Near Mint";
return { return {
"Near Mint": { label: "nav-nm", volatility: volatility, volatilityClass: volatilityClass, class:"show active" }, "Near Mint": { label: "nav-nm", volatility, volatilityClass, class: "show active" },
"Lightly Played": { label: "nav-lp", volatility: volatility, volatilityClass: volatilityClass }, "Lightly Played": { label: "nav-lp", volatility, volatilityClass },
"Moderately Played": { label: "nav-mp", volatility: volatility, volatilityClass: volatilityClass }, "Moderately Played": { label: "nav-mp", volatility, volatilityClass },
"Heavily Played": { label: "nav-hp", volatility: volatility, volatilityClass: volatilityClass }, "Heavily Played": { label: "nav-hp", volatility, volatilityClass },
"Damaged": { label: "nav-dmg", volatility: volatility, volatilityClass: volatilityClass}, "Damaged": { label: "nav-dmg", volatility, volatilityClass }
}[condition]; }[condition];
}; };
@@ -136,7 +144,7 @@ const ebaySearchUrl = (card: any) => {
<div class="card mb-2 border-0"> <div class="card mb-2 border-0">
<div class="row g-4"> <div class="row g-4">
<div class="col-sm-12 col-md-3"> <div class="col-sm-12 col-md-3">
<div class="position-relative mt-1"><img src={`/cards/${card?.productId}.jpg`} class="card-image w-100 img-fluid rounded-4" alt={card?.productName} onerror="this.onerror=null;this.src='/cards/default.jpg'" onclick="copyImage(this); dataLayer.push({'event': 'copiedImage'});"><span class="position-absolute bottom-0 start-0 d-inline"><SetIcon set={card?.set?.setCode} /></span><span class="position-absolute top-0 end-0 d-inline"><EnergyIcon energy={card?.energyType} /></span><span class="rarity-icon-large position-absolute bottom-0 end-0 d-inline"><RarityIcon rarity={card?.rarityName} /></span></div> <div class="position-relative mt-1"><img src={`/cards/${card?.productId}.jpg`} class="card-image w-100 img-fluid rounded-4" alt={card?.productName} onerror="this.onerror=null;this.src='/cards/default.jpg'" onclick="copyImage(this); dataLayer.push({'event': 'copiedImage'});"><span class="position-absolute top-50 start-0 d-inline"><FirstEditionIcon edition={card?.variant} /></span><span class="position-absolute bottom-0 start-0 d-inline"><SetIcon set={card?.set?.setCode} /></span><span class="position-absolute top-0 end-0 d-inline"><EnergyIcon energy={card?.energyType} /></span><span class="rarity-icon-large position-absolute bottom-0 end-0 d-inline"><RarityIcon rarity={card?.rarityName} /></span></div>
<div class="d-flex flex-row justify-content-between mt-2"> <div class="d-flex flex-row justify-content-between mt-2">
<div class="p text-secondary">{card?.set?.setCode}</div> <div class="p text-secondary">{card?.set?.setCode}</div>
<div class="p text-secondary">Illustrator: {card?.Artist}</div> <div class="p text-secondary">Illustrator: {card?.Artist}</div>
@@ -184,7 +192,7 @@ const ebaySearchUrl = (card: any) => {
</div> </div>
<div class={`alert alert-secondary rounded p-2 flex-fill mb-1 ${attributes?.volatilityClass}`}> <div class={`alert alert-secondary rounded p-2 flex-fill mb-1 ${attributes?.volatilityClass}`}>
<h6>Volatility</h6> <h6>Volatility</h6>
<p class="pb-0">{attributes?.volatility}</p> <p class="pb-0 small">{attributes?.volatility}</p>
</div> </div>
</div> </div>
<div class="d-flex flex-column gap-1 col-12 col-md-10 mb-0 me-2"> <div class="d-flex flex-column gap-1 col-12 col-md-10 mb-0 me-2">

View File

@@ -1,6 +1,7 @@
--- ---
import { client } from '../../db/typesense'; import { client } from '../../db/typesense';
import RarityIcon from '../../components/RarityIcon.astro'; import RarityIcon from '../../components/RarityIcon.astro';
import FirstEditionIcon from "../../components/FirstEditionIcon.astro";
export const prerender = false; export const prerender = false;
import * as util from 'util'; import * as util from 'util';
@@ -220,8 +221,8 @@ const facets = searchResults.results.slice(1).map((result: any) => {
<div class="inventory-button position-relative float-end shadow-filter text-center d-none"> <div class="inventory-button position-relative float-end shadow-filter text-center d-none">
<div class="inventory-label pt-2">+/-</div> <div class="inventory-label pt-2">+/-</div>
</div> </div>
<div class="card-trigger" data-card-id={card.cardId} hx-get={`/partials/card-modal?cardId=${card.cardId}`} hx-target="#cardModal" hx-trigger="click" data-bs-toggle="modal" data-bs-target="#cardModal" onclick="const cardTitle = this.querySelector('#cardImage').getAttribute('alt'); dataLayer.push({'event': 'virtualPageview', 'pageUrl': this.getAttribute('hx-get'), 'pageTitle': cardTitle, 'previousUrl': '/pokemon'});"> <div class="card-trigger position-relative" data-card-id={card.cardId} hx-get={`/partials/card-modal?cardId=${card.cardId}`} hx-target="#cardModal" hx-trigger="click" data-bs-toggle="modal" data-bs-target="#cardModal" onclick="const cardTitle = this.querySelector('#cardImage').getAttribute('alt'); dataLayer.push({'event': 'virtualPageview', 'pageUrl': this.getAttribute('hx-get'), 'pageTitle': cardTitle, 'previousUrl': '/pokemon'});">
<img src={`/cards/${card.productId}.jpg`} alt={card.productName} id="cardImage" loading="lazy" decoding="async" class="img-fluid rounded-4 mb-2 card-image image-grow w-100" onerror="this.onerror=null;this.src='/cards/default.jpg'"/> <div class="image-grow"><img src={`/cards/${card.productId}.jpg`} alt={card.productName} id="cardImage" loading="lazy" decoding="async" class="img-fluid rounded-4 mb-2 card-image w-100" onerror="this.onerror=null;this.src='/cards/default.jpg'"/><span class="position-absolute top-50 start-0 d-inline medium-icon"><FirstEditionIcon edition={card?.variant} /></span></div>
</div> </div>
<div class="row row-cols-5 gx-1 price-row mb-2"> <div class="row row-cols-5 gx-1 price-row mb-2">
{conditionOrder.map((condition) => ( {conditionOrder.map((condition) => (

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><svg id="a" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 48 48"><image width="48" height="48" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAQAAAD9CzEMAAAFRklEQVR42u2XXYhVVRTH5+PemcnsC0NjaPqizOghc5Iw08gs7CUTihT6UAqqB0v8wiyxkcIIwwoKRQrH0Qn0ITWNyszIZmxGyzDDMs3R7CG1B2lm7pyv/Wu17mLfe5ghL9d5dC3OOf+z9t7rv/Zea5+7b8UFGQQhrZWIGh401xmy4rQKucxSrWpE5+M6q84VD6hZ31qG+xof73A2u33R7qA92BUeDkngU5fhJmut0pmUueaNbjNbSUiLGiJiaGa0ZaYMgukcDXCo9BGdinZGbWF7vMOdcIQxXtowCtWSXNfI9bKFGhC6BBopNM9BxH3JEWkVanhRjHVUU/O/JN65xqKRB61UsVaZbtPFloKSazEi2vkByIFb4LmrLG8Du7cyVE164YQTwK2A8y7vtbfP9W0WuAB+iHaEnW4nj1sJ9ycwdrlLp66AHKEMxEbsJS+jBN8DRL7lsKCcS6w9hk7nKQZ232Kdzc1+NT4mqBeYLHgCKupjRN6p3LrCjgiJS96O9KuqohrYEGm9fOjmui3maKw2nFY8QdD9ir5Q63LFnbYhLqYLuoVioWZygPhbQgjgOsSg8ckA1il+Sl1NElSv6Am1/iFogyJTnVDyu8IUQVauGYm6rxd4uR9wEhimAYWCGhCbT/fNwNl8PyHcrs/VDvpQ6He3xZ/8BIQZbXszH63oSEGrFK0UtJ63eBc4rJZXBU316JSiZU7rVoM2Cn0Rv64NCJZZRCuARxX9LWg0H/A9i5nGM7JYdzGHLazyM3kS+M3GnY4hPirAZ1YfWhKXarU5W1Pm06vPz4BfeURQWsfwHXCtbrblZpsNLsT9GZ4FXssbleWXCha5Ba7VEQjJLut+ja34fHsfwlCyeWSWZXQUUc5Ak+jA5Gkkebo8bDOrS+gGTvpB+3hJ903WW6YxRdc0o7YFfGSUa/Divk7ok8deJLvSSr2DkBwRKgFwhuHSsJ1v5V5rm+R2mfUx4D3BdWqplWut93uEZp7lFm35JoEwR0WgOZgUQTJDQCs97PEDXofC90sGHuS42l/BCIwYfmakIqsYzaCWa4Mm2S10kBsn5hbRCqYg1IzS7WSuTBuUYClmtTnMZZd/q9V6eQiRKIGpeYLVCJ1EQzfz5L6BfyyyaixK24sT0wS+tYurZPnm2ftzHJXZaxbeVoK4HbojAYzjSrk3aYVN1VRXpiY+Pk3gvzGdQBtD7LAxQu25COL9ShAI/DixAd7lEnZr3OcgULRGv0hp3QaE5Gcg8ICbzWTqizpsZI3cLyqJoJX3fRYmSmifOIm/B8gTcCCBhHyphgfjja7JNXKCzSXPYCUBD7PWnYnpE+jAZJYSuHoOxeSUw4uDPaXkQAthk43Qh3LEHazmTsSB9LBcjWWmeyPZGR3XH0ygR8zpKrpbXTQZQUH/AnrFcXzMNbvnaSxm14eWQrEOozmCcLI6LszgDiVYZARGK/70lNRK+ohckx9aqLaMmOo81VAhoD3v2OsUJXiH9AGqHZIQrrdDci2ZgQ5hqeO5BvhVDMF0AcKq0R8q+uqM0ZiG6MeaMIIfBXrH5xDL3BWadNfgP8+X+RguodKsV4PDJRZ/iedTP/cX/psD3OBzUNCM/zbpUWWpfZZKJvDnDKWImwT21zmQ6PKst94lEqRPSut0ofriZEVR9d3Ick7pj0oMLYXepYvNwcmdBx0BIgk5AZFoKChGHkI+08+2rD9RlbbYS5NcHw4vwiQMTWX9v+l/nLfneLc42eT2uo5kq1vCfYWdVpb7dLo9SVqzqdSWT+IXq06uStFqQVm/qQZHGEAvyCDJv7+zPKs2IGdiAAAAAElFTkSuQmCC"/></svg>

After

Width:  |  Height:  |  Size: 2.0 KiB