Files
pokemon/src/pages/partials/inventory-cards.astro

113 lines
5.6 KiB
Plaintext

---
import { client } from '../../db/typesense';
import RarityIcon from '../../components/RarityIcon.astro';
import FirstEditionIcon from "../../components/FirstEditionIcon.astro";
export const prerender = false;
import * as util from 'util';
// get the query from post request using form data
const formData = await Astro.request.formData();
const query = formData.get('q')?.toString() || '';
const start = Number(formData.get('start')?.toString() || '0');
const { userId } = Astro.locals.auth();
// primary search values (for cards)
let searchArray = [{
collection: 'inventories',
filter_by: `userId:=${userId} && $skus($cards(id:*))`,
per_page: 20,
facet_by: '',
max_facet_values: 0,
page: Math.floor(start / 20) + 1,
include_fields: '$skus(*),$cards(*)',
}];
// on first load (start === 0) we want to get the facets for the filters
// if (start === 0) {
// for (const facet of Object.keys(facetFields)) {
// searchArray.push({
// collection: 'cards',
// filter_by: facetFilter(facet),
// per_page: 0,
// facet_by: facet,
// max_facet_values: 500,
// page: 1,
// sort_by: '',
// include_fields: '',
// });
// }
// }
const searchRequests = { searches: searchArray };
const commonSearchParams = {
q: query,
query_by: 'content,setName,productLineName,rarityName,energyType,cardType'
// query_by: 'userId',
};
// use typesense to search for cards matching the query and return the productIds of the results
const searchResults = await client.multiSearch.perform(searchRequests, commonSearchParams);
const inventoryResults = searchResults.results[0] as any;
console.log('inventoryResults', util.inspect(inventoryResults, { depth: null }));
const pokemon = inventoryResults.hits?.map((hit: any) => hit.document) ?? [];
const totalHits = inventoryResults?.found;
console.log(`totalHits: ${totalHits}`);
---
{pokemon.map((inventory:any) => {
const sku = inventory.skus;
const card = inventory.cards;
const market = sku.marketPrice/100 || 0;
const purchase = inventory.purchasePrice/100 || 0;
const diff = market - purchase;
const pct = purchase > 0 ? (diff / purchase) * 100 : 0;
const isGain = diff >= 0;
return (
<div class="col">
<article class="inv-grid-card">
<div class="card-trigger position-relative inv-grid-media" data-card-id={card.productId} data-bs-toggle="modal" data-bs-target="#cardModal">
<div class="rounded-4 card-image" data-energy={card.energyType} data-rarity={card.rarityName} data-variant={card.variant} data-name={card.productName}>
<img src={`static/cards/${card.productId}.jpg`} alt={card.productName} loading="lazy" decoding="async" class="img-fluid rounded-4 w-100" onerror="this.onerror=null;this.src='static/cards/default.jpg';this.closest('.image-grow')?.setAttribute('data-default','true')" />
<span class="position-absolute top-50 start-0 d-inline medium-icon" style="z-index:4">
<FirstEditionIcon edition={card.variant} />
</span>
</div>
</div>
<div class="d-flex flex-row justify-content-between my-1 align-items-center">
<input type="number" class="form-control text-center" style="max-width: 33%;" value="1" min="1" max="999" aria-label="Quantity input" aria-describedby="button-minus button-plus">
<div class="" aria-label="Edit controls">
<button type="button" class="btn btn-outline-warning me-2"><svg class="edit-svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><path d="M100.4 417.2C104.5 402.6 112.2 389.3 123 378.5L304.2 197.3L338.1 163.4C354.7 180 389.4 214.7 442.1 267.4L476 301.3L442.1 335.2L260.9 516.4C250.2 527.1 236.8 534.9 222.2 539L94.4 574.6C86.1 576.9 77.1 574.6 71 568.4C64.9 562.2 62.6 553.3 64.9 545L100.4 417.2zM156 413.5C151.6 418.2 148.4 423.9 146.7 430.1L122.6 517L209.5 492.9C215.9 491.1 221.7 487.8 226.5 483.2L155.9 413.5zM510 267.4C493.4 250.8 458.7 216.1 406 163.4L372 129.5C398.5 103 413.4 88.1 416.9 84.6C430.4 71 448.8 63.4 468 63.4C487.2 63.4 505.6 71 519.1 84.6L554.8 120.3C568.4 133.9 576 152.3 576 171.4C576 190.5 568.4 209 554.8 222.5C551.3 226 536.4 240.9 509.9 267.4z"/></svg></button>
<button type="button" class="btn btn-outline-danger"><svg class="delete-svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><path d="M232.7 69.9L224 96L128 96C110.3 96 96 110.3 96 128C96 145.7 110.3 160 128 160L512 160C529.7 160 544 145.7 544 128C544 110.3 529.7 96 512 96L416 96L407.3 69.9C402.9 56.8 390.7 48 376.9 48L263.1 48C249.3 48 237.1 56.8 232.7 69.9zM512 208L128 208L149.1 531.1C150.7 556.4 171.7 576 197 576L443 576C468.3 576 489.3 556.4 490.9 531.1L512 208z"/></svg></button>
</div>
</div>
<div class="d-flex flex-row mt-1">
<div class="p fs-7 text-body-tertiary">{card.setName}</div>
</div>
<div class="d-flex flex-row mt-1">
<div class="fs-6 fw-semibold my-0">{card.productName}</div>
</div>
<div class="d-flex flex-row mt-1 justify-content-between align-items-baseline">
<div class={`inv-grid-trend small ${isGain ? "up" : "down"}`}>
<span class="inv-grid-arrow">{isGain ? "▲" : "▼"}</span>
<span class="h6 my-0">${market.toFixed(2)}</span>
</div>
<div class={`inv-grid-delta small ${isGain ? "up" : "down"}`}>
{isGain ? "+" : "-"}${Math.abs(diff).toFixed(2)}</br>{isGain ? "+" : "-"}{Math.abs(pct).toFixed(2)}%
</div>
</div>
</article>
</div>
);
})