--- import { client } from '../../db/typesense'; import { db } from '../../db'; import RarityIcon from '../../components/RarityIcon.astro'; export const prerender = false; // 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 filters = Array.from(formData.entries()) .filter(([key, value]) => key !== 'q' && key !== 'start') .reduce((acc, [key, value]) => { if (!acc[key]) { acc[key] = []; } acc[key].push(value.toString()); return acc; }, {} as Record); const filterChecked = (field: string, value: string) => { return (filters[field]?.includes(value) ?? false) ? 'checked' : ''; }; const filterBy = Object.entries(filters).map(([field, values]) => { return `${field}:=[${values.join(',')}]`; }).join(' && '); // use typesense to search for cards matching the query and return the productIds of the results const searchResults = await client.collections('cards').documents().search({ q: query, filter_by: `sealed:false${filterBy ? ` && ${filterBy}` : ''}`, query_by: 'productLineName,productName,setName,number,rarityName,Artist', per_page: 20, facet_by: 'productLineName,setName,rarityName,cardType,energyType', page: Math.floor(start / 20) + 1, }); const productIds = searchResults.hits?.map((hit: any) => hit.document.productId) ?? []; const totalHits = searchResults.found; const facets = searchResults.facet_counts; // get pokemon data with prices and set info using searchResults and then query the database for each card to get the prices and set info const pokemon = await db.query.cards.findMany({ where: { productId: { in: productIds, }, }, with: { prices: true, set: true, } }); // format price to 2 decimal places (or 0 if price >=100) and adds a $ sign, if the price is null it returns "–" const formatPrice = (price:any) => { if (price === null) { return "—"; } price = Number(price); if (price > 99.99) return `$${Math.round(price)}`; return `$${price.toFixed(2)}`; }; const conditionOrder = ["Near Mint", "Lightly Played", "Moderately Played", "Heavily Played", "Damaged"]; const conditionShort = (condition:string) => { return { "Near Mint": "NM", "Lightly Played": "LP", "Moderately Played": "MP", "Heavily Played": "HP", "Damaged": "DMG" }[condition] || condition.split(' ').map((w) => w[0]).join(''); } const facetNames = (name:string) => { return { "productLineName": "Product Line", "setName": "Set", "rarityName": "Rarity", "cardType": "Card Type", "energyType": "Energy Type" }[name] || name; } --- {(start === 0) &&
{facets.map((facet) => (
{facetNames(facet.field_name)}
{facet.counts.map((count) => (
))}
))}
} {pokemon.map((card) => (
+/-
{card.productName}
{card.prices .slice() .sort((a, b) => conditionOrder.indexOf(a.condition) - conditionOrder.indexOf(b.condition)) .filter((price, index, arr) => arr.findIndex(p => p.condition === price.condition) === index ) .map((price) => (
{ conditionShort(price.condition) }
{formatPrice(price.marketPrice)}
))}
{card.productName}
{card.set?.setCode}
{card.number}
{card.variant}{card.productId}
))} {start + 20 < totalHits &&
Loading...
}