"use client"; import Image from "next/image"; import { Dispatch, SetStateAction, useCallback, useState } from "react"; import Artefact from "@appTypes/Artefact"; import { Currency } from "@appTypes/StoreModel"; import { useStoreState } from "@hooks/store"; // Artefacts Data const artefacts: Artefact[] = [ { id: 1, name: "Golden Scarab", description: "An ancient Egyptian artefact symbolizing rebirth.", location: "Cairo, Egypt", earthquakeID: "h", observatory: "jhd", dateReleased: "12/02/2025", image: "/artefact1.jpg", price: 150, }, { id: 2, name: "Aztec Sunstone", description: "A replica of the Aztec calendar (inscriptions intact).", location: "Peru", earthquakeID: "h", observatory: "jhd", dateReleased: "12/02/2025", image: "/artefact2.jpg", price: 200, }, { id: 3, name: "Medieval Chalice", description: "Used by royalty in medieval ceremonies.", location: "Cambridge, England", earthquakeID: "h", observatory: "jhd", dateReleased: "12/02/2025", image: "/artefact3.jpg", price: 120, }, { id: 4, name: "Roman Coin", description: "An authentic Roman coin from the 2nd century CE.", location: "Rome, Italy", earthquakeID: "h", observatory: "jhd", dateReleased: "12/02/2025", image: "/artefact4.jpg", price: 80, }, { id: 5, name: "Samurai Mask", description: "Replica of Japanese Samurai battle masks.", location: "Tokyo, Japan", earthquakeID: "h", observatory: "jhd", dateReleased: "12/02/2025", image: "/artefact5.jpg", price: 300, }, { id: 6, name: "Ancient Greek Vase", description: "Depicts Greek mythology, found in the Acropolis.", location: "Athens, Greece", earthquakeID: "h", observatory: "jhd", dateReleased: "12/02/2025", image: "/artefact6.jpg", price: 250, }, { id: 7, name: "Incan Pendant", description: "Represents the Sun God Inti.", location: "India", earthquakeID: "h", observatory: "jhd", dateReleased: "12/02/2025", image: "/artefact7.jpg", price: 175, }, { id: 8, name: "Persian Carpet Fragment", description: "Ancient Persian artistry.", location: "Petra, Jordan", earthquakeID: "h", observatory: "jhd", dateReleased: "12/02/2025", image: "/artefact8.jpg", price: 400, }, { id: 9, name: "Stone Buddha", description: "Authentic stone Buddha carving.", location: "India", earthquakeID: "h", observatory: "jhd", dateReleased: "12/02/2025", image: "/artefact9.jpg", price: 220, }, { id: 10, name: "Victorian Brooch", description: "A beautiful Victorian-era brooch with a ruby centre.", location: "Oxford, England", earthquakeID: "h", observatory: "jhd", dateReleased: "12/02/2025", image: "/artefact10.jpg", price: 150, }, { id: 11, name: "Ancient Scroll", description: "A mysterious scroll from ancient times.", location: "Madrid, Spain", earthquakeID: "h", observatory: "jhd", dateReleased: "12/02/2025", image: "/artefact11.jpg", price: 500, }, { id: 12, name: "Ming Dynasty Porcelain", description: "Porcelain from China's Ming Dynasty.", location: "Beijing, China", earthquakeID: "h", observatory: "jhd", dateReleased: "12/02/2025", image: "/artefact12.jpg", price: 300, }, { id: 13, name: "African Tribal Mask", description: "A unique tribal mask from Africa.", location: "Nigeria", earthquakeID: "h", observatory: "jhd", dateReleased: "12/02/2025", image: "/artefact13.jpg", price: 250, }, { id: 14, name: "Crystal Skull", description: "A mystical pre-Columbian artefact.", location: "Colombia", earthquakeID: "h", observatory: "jhd", dateReleased: "12/02/2025", image: "/artefact14.jpg", price: 1000, }, { id: 15, name: "Medieval Armor Fragment", description: "A fragment of medieval armor.", location: "Normandy, France", earthquakeID: "h", observatory: "jhd", dateReleased: "12/02/2025", image: "/artefact15.jpg", price: 400, }, { id: 16, name: "Medieval Helmet Fragment", description: "A fragment of a medieval helmet.", location: "Normandy, France", earthquakeID: "h", observatory: "jhd", dateReleased: "12/02/2025", image: "/artefact16.jpg", price: 500, }, ]; export default function Shop() { const [currentPage, setCurrentPage] = useState(1); const [selectedArtefact, setSelectedArtefact] = useState(null); const [showPaymentModal, setShowPaymentModal] = useState(false); const [artefactToBuy, setArtefactToBuy] = useState(null); const [showThankYouModal, setShowThankYouModal] = useState(false); const [orderNumber, setOrderNumber] = useState(null); const artefactsPerPage = 12; const indexOfLastArtefact = currentPage * artefactsPerPage; const indexOfFirstArtefact = indexOfLastArtefact - artefactsPerPage; const currentArtefacts = artefacts.slice(indexOfFirstArtefact, indexOfLastArtefact); const selectedCurrency = useStoreState((state) => state.currency.selectedCurrency); const conversionRates = useStoreState((state) => state.currency.conversionRates); const currencyTickers = useStoreState((state) => state.currency.tickers); const convertPrice = useCallback( (price: number, currency: Currency) => (price * conversionRates[currency]).toFixed(2), [conversionRates] ); const handleNextPage = () => { if (indexOfLastArtefact < artefacts.length) setCurrentPage((prev) => prev + 1); }; const handlePreviousPage = () => { if (currentPage > 1) setCurrentPage((prev) => prev - 1); }; function ArtefactCard({ artefact }: { artefact: Artefact }) { return (
setSelectedArtefact(artefact)} > {artefact.name}

{artefact.name}

{artefact.location}

{artefact.earthquakeID}

{currencyTickers[selectedCurrency]} {convertPrice(artefact.price, selectedCurrency)}

); } function Modal({ artefact }: { artefact: Artefact }) { if (!artefact) return null; const handleOverlayClick = (e: React.MouseEvent) => { if (e.target === e.currentTarget) setSelectedArtefact(null); }; return (

{artefact.name}

{artefact.name}

{currencyTickers[selectedCurrency]} {convertPrice(artefact.price, selectedCurrency)}

{artefact.description}

Location: {artefact.location}

{artefact.earthquakeID}

{artefact.observatory}

{artefact.dateReleased}

); } function PaymentModal({ artefact, onClose }: { artefact: Artefact; onClose: () => void }) { const [cardNumber, setCardNumber] = useState(""); const [expiry, setExpiry] = useState(""); const [cvc, setCvc] = useState(""); const [name, setName] = useState(""); const [email, setEmail] = useState(""); const [remember, setRemember] = useState(false); const [error, setError] = useState(""); function validateEmail(email: string) { return ( email.includes("@") && (email.endsWith(".com") || email.endsWith(".co.uk") || email.endsWith(".org") || email.endsWith(".org.uk")) ); } function validateCardNumber(number: string) { return /^\d{12,19}$/.test(number.replace(/\s/g, "")); // 12-19 digits } function validateCVC(number: string) { return /^\d{3,4}$/.test(number); } function validateExpiry(exp: string) { return /^\d{2}\/\d{2}$/.test(exp); } function handlePay() { setError(""); if (!validateEmail(email)) { setError("Please enter a valid email ending"); return; } if (!validateCardNumber(cardNumber)) { setError("Card number must be 12-19 digits."); return; } if (!validateExpiry(expiry)) { setError("Expiry must be in MM/YY format."); return; } if (!validateCVC(cvc)) { setError("CVC must be 3 or 4 digits."); return; } const genOrder = () => "#" + Math.random().toString(36).substring(2, 10).toUpperCase(); setOrderNumber(genOrder()); onClose(); setShowThankYouModal(true); } const handleOverlayClick = (e: React.MouseEvent) => { if (e.target === e.currentTarget) onClose(); }; return (

Buy {artefact.name}

{/* ...Image... */}
{ e.preventDefault(); handlePay(); }} > setEmail(e.target.value)} type="email" required autoFocus /> setName(e.target.value)} required /> setCardNumber(e.target.value.replace(/\D/g, ""))} maxLength={19} required inputMode="numeric" pattern="\d*" />
setExpiry(e.target.value.replace(/[^0-9/]/g, ""))} maxLength={5} required inputMode="numeric" /> setCvc(e.target.value.replace(/\D/g, ""))} maxLength={4} required inputMode="numeric" />
{error &&

{error}

}
); } function ThankYouModal({ orderNumber, onClose }: { orderNumber: string; onClose: () => void }) { const handleOverlayClick = (e: React.MouseEvent) => { if (e.target === e.currentTarget) onClose(); }; return (

Thank you for your purchase!

Your order number is:

{orderNumber}

); } return (

Artefact Shop

Discover extraordinary historical artefacts and collectibles from major seismic events from around the world - now available for purchase.

{currentArtefacts.map((artefact) => ( ))}

{currentPage}

{selectedArtefact && } {artefactToBuy && showPaymentModal && ( { setShowPaymentModal(false); setArtefactToBuy(null); }} /> )} {showThankYouModal && orderNumber && ( setShowThankYouModal(false)} /> )}
); }