diff --git a/src/app/shop/page.tsx b/src/app/shop/page.tsx index a838498..aef989d 100644 --- a/src/app/shop/page.tsx +++ b/src/app/shop/page.tsx @@ -1,41 +1,43 @@ "use client"; import Image from "next/image"; -import { useCallback, useEffect, useState } from "react"; +import { Dispatch, SetStateAction, useCallback, useEffect, useState } from "react"; import { ExtendedArtefact } from "@appTypes/ApiTypes"; import { Currency } from "@appTypes/StoreModel"; import BottomFooter from "@components/BottomFooter"; import { useStoreState } from "@hooks/store"; +interface SuperExtendedArtefact extends ExtendedArtefact { + location: string; + dateReleased: string; + image: string; + price: number; +} + export default function Shop() { - const [artefacts, setArtefacts] = useState([]); + const [artefacts, setArtefacts] = useState([]); const [hiddenArtefactIds, setHiddenArtefactIds] = useState([]); const [loading, setLoading] = useState(true); - - const [cart, setCart] = useState([]); - const [showCartModal, setShowCartModal] = useState(false); - const user = useStoreState((state) => state.user); + // 3. Fetch from your API route and map data to fit your existing fields useEffect(() => { async function fetchArtefacts() { setLoading(true); try { const res = await fetch("/api/artefacts"); - const data = await res.json(); - const transformed = data.artefact.map((a: any) => ({ - id: a.id, - name: a.name, - description: a.description, - location: a.warehouseArea, - earthquakeID: a.earthquakeId?.toString() ?? "", - observatory: a.type ?? "", + const data: { artefact: ExtendedArtefact[] } = await res.json(); + + const transformed = data.artefact.map((a) => ({ + ...a, + location: a.warehouseArea, // your database dateReleased: a.createdAt ? new Date(a.createdAt).toLocaleDateString() : "", image: "/artefactImages/" + (a.imageName || "NoImageFound.PNG"), - price: a.shopPrice ?? 100, + price: a.shopPrice ?? 100, // fallback price if not in DB })); setArtefacts(transformed); } catch (e) { + // Optionally handle error console.error("Failed to fetch artefacts", e); } finally { setLoading(false); @@ -45,10 +47,9 @@ export default function Shop() { }, []); const [currentPage, setCurrentPage] = useState(1); - const [selectedArtefact, setSelectedArtefact] = useState(null); + const [selectedArtefact, setSelectedArtefact] = useState(null); const [showPaymentModal, setShowPaymentModal] = useState(false); - const [artefactToBuy, setArtefactToBuy] = useState(null); - const [cartCheckout, setCartCheckout] = useState(false); // true = checkout cart (not single artefact) + const [artefactToBuy, setArtefactToBuy] = useState(null); const [showThankYouModal, setShowThankYouModal] = useState(false); const [orderNumber, setOrderNumber] = useState(null); @@ -73,7 +74,7 @@ export default function Shop() { if (currentPage > 1) setCurrentPage((prev) => prev - 1); }; - function ArtefactCard({ artefact }: { artefact: ExtendedArtefact }) { + function ArtefactCard({ artefact }: { artefact: SuperExtendedArtefact }) { return (

{artefact.name}

{artefact.location}

-

{artefact.earthquakeID}

+

{artefact.earthquakeCode}

{currencyTickers[selectedCurrency]} {convertPrice(artefact.price, selectedCurrency)} @@ -92,14 +93,11 @@ export default function Shop() {

); } - - function Modal({ artefact }: { artefact: ExtendedArtefact }) { + function Modal({ artefact }: { artefact: SuperExtendedArtefact }) { if (!artefact) return null; const handleOverlayClick = (e: React.MouseEvent) => { if (e.target === e.currentTarget) setSelectedArtefact(null); }; - const inCart = cart.some((a) => a.id === artefact.id); - return (

{artefact.description}

Location: {artefact.location}

-

{artefact.earthquakeID}

-

{artefact.observatory}

+

{artefact.earthquakeCode}

+

{artefact.type}

{artefact.dateReleased}

-
+
-
@@ -156,99 +138,15 @@ export default function Shop() { ); } - function CartModal() { - const total = cart.reduce((sum, art) => sum + art.price, 0); - - const handleOverlayClick = (e: React.MouseEvent) => { - if (e.target === e.currentTarget) setShowCartModal(false); - }; - - return ( -
-
-
-

Your Cart

- -
- {cart.length === 0 ? ( -

Your cart is empty.

- ) : ( - <> -
    - {cart.map((art) => ( -
  • -
    - {art.name} -
    -
    -

    {art.name}

    -

    {art.location}

    -
    -

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

    - -
  • - ))} -
-
- Total: - - {currencyTickers[selectedCurrency]} - {convertPrice(total, selectedCurrency)} - -
-
- -
- - )} -
-
- ); - } - - function PaymentModal({ - artefact, - onClose, - cartItems, - }: { - artefact?: ExtendedArtefact; - onClose: () => void; - cartItems?: ExtendedArtefact[]; - }) { + function PaymentModal({ artefact, onClose }: { artefact: SuperExtendedArtefact; onClose: () => void }) { const [cardNumber, setCardNumber] = useState(""); const [expiry, setExpiry] = useState(""); const [cvc, setCvc] = useState(""); const [name, setName] = useState(""); - const [email, setEmail] = useState(user?.email || ""); + const [email, setEmail] = useState(""); const [remember, setRemember] = useState(false); const [error, setError] = useState(""); - const artefactsToBuy = artefact ? [artefact] : cartItems || []; - const total = artefactsToBuy.reduce((sum, art) => sum + art.price, 0); - function validateEmail(email: string) { return ( email.includes("@") && @@ -264,13 +162,18 @@ export default function Shop() { function validateExpiry(exp: string) { return /^\d{2}\/\d{2}$/.test(exp); } + function handlePay() { setError(""); - const paymentEmail = user?.email || email; - if (!validateEmail(paymentEmail)) { - setError("Please enter a valid email"); + if (email || user?.email) { + if (!validateEmail(email)) { + setError("Please enter a valid email ending"); + return; + } + } else { return; } + if (!validateCardNumber(cardNumber)) { setError("Card number must be 12-19 digits."); return; @@ -283,51 +186,44 @@ export default function Shop() { setError("CVC must be 3 or 4 digits."); return; } - // remove all artefacts that were bought (works for both cart and single) - setHiddenArtefactIds((ids) => [...ids, ...artefactsToBuy.map((a) => a.id)]); - // todo create receiving api route - // todo handle sending to api route + + setHiddenArtefactIds((ids) => [...ids, artefact.id]); + + // todo!! create receiving api route + // todo!! handle sending to api route const genOrder = () => "#" + Math.random().toString(36).substring(2, 10).toUpperCase(); setOrderNumber(genOrder()); onClose(); setShowThankYouModal(true); - setCart((c) => c.filter((a) => !artefactsToBuy.map((x) => x.id).includes(a.id))); } const handleOverlayClick = (e: React.MouseEvent) => { if (e.target === e.currentTarget) onClose(); }; return (
-

- Checkout {artefact ? artefact.name : artefactsToBuy.length + " item(s)"} - {!artefact && ({artefactsToBuy.map((x) => x.name).join(", ")})} -

+

Buy {artefact.name}

+ {/* ...Image... */}
{ e.preventDefault(); handlePay(); }} > - {/* Email autofill */} - setEmail(e.target.value)} - type="email" - required - autoFocus - disabled={!!user?.email} - /> - {user?.email && ( -

- Signed in as {user.email} -

- )} + {!user ? ( + setEmail(e.target.value)} + type="email" + required + autoFocus + /> + ) : null} {error &&

{error}

} -
- Total: - - {currencyTickers[selectedCurrency]} - {convertPrice(total, selectedCurrency)} - -

Artefact Shop @@ -453,7 +320,7 @@ export default function Shop() {

{currentArtefacts - .filter((x) => !hiddenArtefactIds.includes(x.id)) + .filter((x) => !hiddenArtefactIds.includes(x.id) && x.isRequired === false) .map((artefact) => ( ))} @@ -481,22 +348,19 @@ export default function Shop() {
{selectedArtefact && } - {showCartModal && } - {showPaymentModal && (cartCheckout || artefactToBuy) && ( + {artefactToBuy && showPaymentModal && ( { setShowPaymentModal(false); setArtefactToBuy(null); - setCartCheckout(false); }} /> )} {showThankYouModal && orderNumber && ( setShowThankYouModal(false)} /> )} - {!selectedArtefact && !showPaymentModal && !showThankYouModal && !showCartModal && ( + {!selectedArtefact && !showPaymentModal && !showThankYouModal && (