--- import Layout from '../layouts/Layout.astro'; import ProductCard from '../components/ProductCard.astro'; import SearchBar from '../components/SearchBar.tsx'; import { query as dbQuery } from '../lib/db'; import { getUserFromRequest } from '../lib/user-auth'; const q = Astro.url.searchParams.get('q')?.trim() || ''; const spSize = Astro.cookies.get('sp_size')?.value || undefined; const user = getUserFromRequest(Astro.request); let products: any[] = []; let preferredBrands: string[] = []; // Fetch user's taste profile for personalization if (user) { const { rows: profiles } = await dbQuery( `SELECT preferred_brands, preferred_gender FROM user_taste_profile WHERE user_id = $1`, [user.id] ); if (profiles.length > 0) { const profile = profiles[0]; const brands = (typeof profile.preferred_brands === 'string' ? JSON.parse(profile.preferred_brands) : profile.preferred_brands) || []; preferredBrands = brands.map((b: any) => b.slug || b.name); } } if (q.length >= 2) { const pattern = `%${q}%`; const params: any[] = [pattern]; let sizeFilter = ''; if (spSize) { params.push(spSize); sizeFilter = `AND EXISTS (SELECT 1 FROM jsonb_array_elements(po.sizes) s WHERE s->>'size' = $${params.length})`; } const result = await dbQuery(` SELECT p.id, p.name, p.slug, p.brand, p.colorway, p.gender, p.image_url, p.original_price, MIN(po.price) as lowest_price, MAX(po.original_price) as original_price_offer, COUNT(DISTINCT po.id) as offer_count, COUNT(DISTINCT COALESCE(f.merchant_name, f.name)) as shop_count FROM products p JOIN product_offers po ON po.product_id = p.id AND po.in_stock = true JOIN feeds f ON f.id = po.feed_id WHERE (p.name ILIKE $1 OR p.brand ILIKE $1 OR CONCAT(p.brand, ' ', p.name) ILIKE $1) AND p.is_sneaker = true AND p.image_url IS NOT NULL AND p.image_url != '' ${sizeFilter} GROUP BY p.id HAVING MIN(po.price) > 0 ORDER BY CASE WHEN LOWER(p.brand) = ANY($${params.length > 0 ? params.length + 1 : 2}::text[]) THEN 1 ELSE 0 END DESC, COUNT(po.id) DESC LIMIT 60 `, [...params, preferredBrands.length > 0 ? preferredBrands : null]); products = result.rows.map((r: any) => { const lowestPrice = Number(r.lowest_price); const originalPrice = Number(r.original_price) || Number(r.original_price_offer) || lowestPrice; const shopCount = Number(r.shop_count); const offerCount = Number(r.offer_count); const offers = Array.from({ length: shopCount }, () => ({ shop: '', price: lowestPrice, url: '', inStock: true, sizes: [] })); const brandSlug = (r.brand || 'unknown').toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/(^-|-$)/g, ''); return { id: String(r.id), slug: r.slug, name: r.name, brand: r.brand || 'Unknown', brandSlug, colorway: r.colorway || '', image: r.image_url || '', lowestPrice, originalPrice: originalPrice > lowestPrice ? originalPrice : lowestPrice, offers, offerCount, sizes: [], gender: r.gender || 'unisex', releaseDate: '', trending: false, priceDrop: originalPrice > lowestPrice, priceHistory: [], }; }); // Personalize ranking for logged-in users with taste profile if (preferredBrands.length > 0) { products.sort((a, b) => { // Check if brands are in preferred list const aPreferred = preferredBrands.some(pb => a.brand.toLowerCase().includes(pb) || a.brandSlug.includes(pb)); const bPreferred = preferredBrands.some(pb => b.brand.toLowerCase().includes(pb) || b.brandSlug.includes(pb)); // Preferred brands rank higher if (aPreferred && !bPreferred) return -1; if (!aPreferred && bPreferred) return 1; // Within same preference, sort by offer count (original logic) return (b.offerCount || 0) - (a.offerCount || 0); }); } } const title = q ? `${q} — Vergelijk prijzen bij Nederlandse shops | SneakerPicks` : 'Sneakers zoeken en prijzen vergelijken | SneakerPicks'; const analyticsItems = products.map((s, i) => ({ item_id: s.id, item_name: `${s.brand} ${s.name}`, item_brand: s.brand, price: s.lowestPrice, index: i })); const searchQuery = q; const resultsCount = products.length; ---
{q ? (

{products.length > 0 ? ( {products.length} resultaten voor "{q}" ) : ( Geen resultaten voor "{q}" )}

{products.length > 0 ? (
{products.map((sneaker, i) => ( ))}
) : (

Probeer een andere zoekterm, bijvoorbeeld een merk of model.

)}
) : (

Zoek sneakers

Typ een merk, model of naam om te zoeken.

)}
{searchQuery && ( )}