Working Shop and footer

This commit is contained in:
IZZY 2025-05-27 13:48:32 +01:00
parent 92d8f9af81
commit 977c35bd57
4 changed files with 88 additions and 211 deletions

View File

@ -10,18 +10,18 @@ generator client {
// User model // User model
model User { model User {
id Int @id @default(autoincrement()) id Int @id @default(autoincrement())
createdAt DateTime @default(now()) createdAt DateTime @default(now())
name String name String
email String @unique email String @unique
passwordHash String passwordHash String
role String @default("GUEST") @db.VarChar(10) // Allowed: ADMIN, SCIENTIST, GUEST role String @default("GUEST") @db.VarChar(10) // Allowed: ADMIN, SCIENTIST, GUEST
scientist Scientist? @relation scientist Scientist? @relation
purchasedOrders Order[] @relation("UserOrders") purchasedOrders Order[] @relation("UserOrders")
requests Request[] @relation("UserRequests") requests Request[] @relation("UserRequests")
earthquakes Earthquake[] @relation("UserEarthquakeCreator") earthquakes Earthquake[] @relation("UserEarthquakeCreator")
observatories Observatory[] @relation("UserObservatoryCreator") observatories Observatory[] @relation("UserObservatoryCreator")
artefacts Artefact[] @relation("UserArtefactCreator") artefacts Artefact[] @relation("UserArtefactCreator")
} }
model Request { model Request {
@ -35,15 +35,15 @@ model Request {
// Scientist model // Scientist model
model Scientist { model Scientist {
id Int @id @default(autoincrement()) id Int @id @default(autoincrement())
createdAt DateTime @default(now()) createdAt DateTime @default(now())
name String name String
level String @db.VarChar(10) // JUNIOR, SENIOR level String @db.VarChar(10) // JUNIOR, SENIOR
user User @relation(fields: [userId], references: [id]) user User @relation(fields: [userId], references: [id])
userId Int @unique userId Int @unique
superior Scientist? @relation("SuperiorRelation", fields: [superiorId], references: [id], onDelete: NoAction, onUpdate: NoAction) superior Scientist? @relation("SuperiorRelation", fields: [superiorId], references: [id], onDelete: NoAction, onUpdate: NoAction)
superiorId Int? superiorId Int?
subordinates Scientist[] @relation("SuperiorRelation") subordinates Scientist[] @relation("SuperiorRelation")
} }
model Earthquake { model Earthquake {
@ -93,7 +93,7 @@ model Artefact {
earthquake Earthquake @relation(fields: [earthquakeId], references: [id]) earthquake Earthquake @relation(fields: [earthquakeId], references: [id])
creatorId Int? creatorId Int?
creator User? @relation("UserArtefactCreator", fields: [creatorId], references: [id], onDelete: NoAction, onUpdate: NoAction) creator User? @relation("UserArtefactCreator", fields: [creatorId], references: [id], onDelete: NoAction, onUpdate: NoAction)
isRequired Boolean @default(true) isRequired Boolean @default(true) @map("isRequired")
dateAddedToShop DateTime? dateAddedToShop DateTime?
shopPrice Float? shopPrice Float?
isSold Boolean @default(false) isSold Boolean @default(false)

BIN
public/BlueBackground.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -0,0 +1,18 @@
import { NextResponse } from "next/server";
import { prisma } from "@utils/prisma";
export async function GET(request: Request) {
try {
const artefact = await prisma.artefact.findMany();
return NextResponse.json({
message: "Got artefacts successfully",
artefact
}, { status: 200 });
} catch (error) {
console.error("Error in artefacts endpoint:", error);
return NextResponse.json({ message: "Internal Server Error" }, { status: 500 });
}
}

View File

@ -1,191 +1,46 @@
"use client"; "use client";
import Image from "next/image"; import Image from "next/image";
import { Dispatch, SetStateAction, useCallback, useState } from "react"; import { Dispatch, SetStateAction, useCallback, useState, useEffect } from "react";
import BottomFooter from "@components/BottomFooter";
import { ExtendedArtefact } from "@appTypes/ApiTypes"; import { ExtendedArtefact } from "@appTypes/ApiTypes";
import { Currency } from "@appTypes/StoreModel"; import { Currency } from "@appTypes/StoreModel";
import { useStoreState } from "@hooks/store"; import { useStoreState } from "@hooks/store";
const artefacts: ExtendedArtefact[] = [
{
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() { export default function Shop() {
const [artefacts, setArtefacts] = useState<ExtendedArtefact[]>([]);
const [loading, setLoading] = useState(true);
// 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, // your database
earthquakeID: a.earthquakeId?.toString() ?? "",
observatory: a.type ?? "", // if you want to display type
dateReleased: a.createdAt ? new Date(a.createdAt).toLocaleDateString() : "",
image: "/artefactImages/" + (a.imageName || "NoImageFound.PNG"),
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);
}
}
fetchArtefacts();
}, []);
const [currentPage, setCurrentPage] = useState(1); const [currentPage, setCurrentPage] = useState(1);
const [selectedArtefact, setSelectedArtefact] = useState<Artefact | null>(null); const [selectedArtefact, setSelectedArtefact] = useState<Artefact | null>(null);
const [showPaymentModal, setShowPaymentModal] = useState(false); const [showPaymentModal, setShowPaymentModal] = useState(false);
@ -434,20 +289,20 @@ export default function Shop() {
} }
return ( return (
<div <div
className="min-h-screen relative flex flex-col" className="min-h-screen bg-blue-50 relative flex flex-col"
style={{ style={{
backgroundImage: "url('/artefacts.jpg')", //backgroundImage: "url('/BlueBackground.png')",
backgroundSize: "cover", backgroundSize: "cover",
backgroundPosition: "center", backgroundPosition: "center",
}} }}
> >
<div className="absolute inset-0 bg-black bg-opacity-50 z-0"></div> <div className="absolute inset-0 bg-black bg-opacity-0 z-0"></div>
<div className="relative z-10 flex flex-col items-center w-full px-2 py-12"> <div className="relative z-10 flex flex-col items-center w-full px-2 py-12">
<h1 className="text-4xl md:text-4xl font-bold text-center text-white mb-2 tracking-tight drop-shadow-lg"> <h1 className="text-4xl md:text-4xl font-bold text-center text-blue-800 mb-2 tracking-tight drop-shadow-lg">
Artefact Shop Artefact Shop
</h1> </h1>
<p className="text-lg md:text-xl text-center text-white mb-10 drop-shadow-md max-w-2xl"> <p className="text-lg md:text-xl text-center text-gray-700 mb-10 drop-shadow-md max-w-2xl">
Discover extraordinary historical artefacts and collectibles from major seismic events from around the world - now Discover extraordinary artefacts and collectibles from major seismic events from around the world - Previously studied by our scientists, now
available for purchase. available for purchase.
</p> </p>
<div className="w-full max-w-7xl grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-10 p-2"> <div className="w-full max-w-7xl grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-10 p-2">
@ -490,6 +345,10 @@ export default function Shop() {
{showThankYouModal && orderNumber && ( {showThankYouModal && orderNumber && (
<ThankYouModal orderNumber={orderNumber} onClose={() => setShowThankYouModal(false)} /> <ThankYouModal orderNumber={orderNumber} onClose={() => setShowThankYouModal(false)} />
)} )}
</div> {!selectedArtefact && !showPaymentModal && !showThankYouModal && (
); <div className="relative z-50">
} <BottomFooter />
</div>
)}
</div>
);