/* shared.jsx — icons, data, primitives */ // =========================================================== // Icons (small set, hand-tuned) // =========================================================== const Icon = { Crown: ({size = 24}) => ( ), Diamond: ({size = 16}) => ( ), Heart: ({size = 16, filled = false}) => ( ), Search: ({size = 18}) => ( ), Bag: ({size = 18}) => ( ), User: ({size = 18}) => ( ), WhatsApp: ({size = 28}) => ( ), Arrow: ({size = 14, dir = "right"}) => { const rotate = {right: 0, left: 180, up: -90, down: 90}[dir]; return ( ); }, Plus: ({size = 14}) => ( ), Minus: ({size = 14}) => ( ), Close: ({size = 18}) => ( ), Check: ({size = 14}) => ( ), Map: ({size = 16}) => ( ), Phone: ({size = 14}) => ( ), Globe: ({size = 14}) => ( ), }; // =========================================================== // PalacesMark — wordmark, drawn as SVG-friendly composite // =========================================================== const PalacesMark = ({size = 22}) => ( { e.preventDefault(); window.__nav && window.__nav('home'); window.scrollTo(0,0); }} style={{display: 'flex', alignItems: 'center', gap: 10}}> Palaces JEWELLERY ); // =========================================================== // Product data // =========================================================== const PRODUCTS = [ { id: 'aureveris', name: 'Aureveris', cat: 'Bridal', img: 'assets/p-aureveris.webp', price: 48399, metal: 'rose', tag: 'Signature', desc: 'Multi-sapphire lotus crown, set in 18k rose gold with pavé brilliants on a tapered shank.' }, { id: 'velantrix', name: 'Velantrix', cat: 'Bridal', img: 'assets/p-velantrix.webp', price: 49299, metal: 'white', tag: 'Couture', desc: 'Emerald cabochon framed by a starburst of marquise and round-brilliant diamonds.' }, { id: 'seraphelis', name: 'Seraphelis', cat: 'Bridal', img: 'assets/p-seraphelis.webp', price: 33199, metal: 'white', desc: 'Bridal cluster with a halo of pavé and side-pavé stones.' }, { id: 'eagle-ring', name: 'Eagle of Noor — Ring', cat: 'Signature', img: 'assets/p-eagle-ring.webp', price: 23899, metal: 'yellow', tag: 'House Motif' }, { id: 'eagle-pendant', name: 'Eagle of Noor — Pendant', cat: 'Signature', img: 'assets/p-eagle-pendant.webp', price: 14189, metal: 'yellow' }, { id: 'imperial-eagle', name: 'Imperial Eagle of Noor', cat: 'Signature', img: 'assets/p-imperial-eagle.webp', price: 30499, metal: 'yellow', tag: 'Couture' }, { id: 'celeste', name: 'Celeste Crown Eternity', cat: 'Bridal', img: 'assets/p-celeste-crown.webp', price: 33409, metal: 'white', priceFrom: 16769 }, { id: 'twilight', name: 'Twilight Petal', cat: 'Gemstone', img: 'assets/p-twilight-petal.webp', price: 19600, metal: 'white' }, { id: 'midnight', name: 'Midnight Tide', cat: 'Gemstone', img: 'assets/p-midnight-tide.webp', price: 19599, metal: 'white' }, { id: 'prismara', name: 'Prismara Butterfly', cat: 'Gemstone', img: 'assets/p-prismara.webp', price: 12729, metal: 'white' }, { id: 'magnolia', name: 'Magnolia Earring', cat: 'Couture', img: 'assets/p-magnolia.webp', price: 44899, metal: 'yellow' }, { id: 'honeycrest', name: 'Honeycrest Earring', cat: 'Earring', img: 'assets/p-honeycrest.webp', price: 20699, metal: 'yellow' }, { id: 'celestial-leaf', name: 'Celestial Leaf', cat: 'Earring', img: 'assets/p-celestial-leaf.webp', price: 20100, metal: 'white' }, { id: 'skyhold', name: 'Skyhold Solitaire', cat: 'Bridal', img: 'assets/p-skyhold.webp', price: 9299, metal: 'rose', tag: 'Accessible' }, { id: 'radiant-horizon', name: 'Radiant Horizon Pendant', cat: 'Pendant', img: 'assets/p-radiant-horizon.webp', price: 11399, metal: 'yellow' }, { id: 'rosabella', name: 'Rosabella', cat: 'Gemstone', img: 'assets/p-rosabella.webp', price: 20099, metal: 'rose' }, { id: 'sunlure', name: 'Sunlure', cat: 'Gemstone', img: 'assets/p-sunlure.webp', price: 20399, metal: 'yellow' }, { id: 'ember-hoops', name: 'Ember Arc Hoops', cat: 'Earring', img: 'assets/p-ember-hoops.webp', price: 11299, metal: 'white' }, { id: 'trilight', name: 'Trilight Hoops', cat: 'Earring', img: 'assets/p-trilight.webp', price: 21499, metal: 'white' }, ]; const byId = (id) => PRODUCTS.find(p => p.id === id); const fmtAED = (n) => `AED ${n.toLocaleString('en-US')}`; // =========================================================== // ProductCard // =========================================================== const ProductCard = ({product, onOpen}) => { const [liked, setLiked] = React.useState(() => { try { return JSON.parse(localStorage.getItem('palaces-likes') || '{}')[product.id] || false; } catch { return false; } }); const toggleLike = (e) => { e.stopPropagation(); const next = !liked; setLiked(next); try { const obj = JSON.parse(localStorage.getItem('palaces-likes') || '{}'); if (next) obj[product.id] = true; else delete obj[product.id]; localStorage.setItem('palaces-likes', JSON.stringify(obj)); } catch {} }; return (
onOpen && onOpen(product.id)}>
{product.name} {product.tag && ( {product.tag} )}

{product.name}

{product.priceFrom ? `from ${fmtAED(product.priceFrom)}` : fmtAED(product.price)}

{product.cat} · 18k {metalName(product.metal)}

); }; const metalName = (m) => ({ white: 'White Gold', yellow: 'Yellow Gold', rose: 'Rose Gold', platinum: 'Platinum', })[m] || 'Gold'; // =========================================================== // Section header // =========================================================== const SectionHead = ({eyebrow, title, sub, align = 'left', action}) => (
{eyebrow &&
{eyebrow}
}

{title}

{sub &&

{sub}

}
{action}
); // Export to window so component files can pick these up Object.assign(window, { Icon, PalacesMark, PRODUCTS, byId, fmtAED, metalName, ProductCard, SectionHead, });