diff --git a/public/artifact.png b/public/artefact.png similarity index 100% rename from public/artifact.png rename to public/artefact.png diff --git a/public/artifacts.jpg b/public/artefacts.jpg similarity index 100% rename from public/artifacts.jpg rename to public/artefacts.jpg diff --git a/src/app/api/login/route.ts b/src/app/api/login/route.ts index 0f66f55..2eab077 100644 --- a/src/app/api/login/route.ts +++ b/src/app/api/login/route.ts @@ -1,11 +1,11 @@ -import bcryptjs from 'bcryptjs'; -import { SignJWT } from 'jose'; -import { NextResponse } from 'next/server'; +import bcryptjs from "bcryptjs"; +import { SignJWT } from "jose"; +import { NextResponse } from "next/server"; -import { PrismaClient } from '@prisma/client'; -import { env } from '@utils/env'; +import { PrismaClient } from "@prisma/client"; +import { env } from "@utils/env"; -import { findUserByEmail, readUserCsv, User } from '../functions/csvReadWrite'; +import { findUserByEmail, readUserCsv, User } from "../functions/csvReadWrite"; const usingPrisma = false; let prisma: PrismaClient; @@ -45,12 +45,12 @@ export async function POST(req: Request) { include: { earthquakes: true, observatories: true, - artifacts: true, + artefacts: true, superior: true, subordinates: true, }, }, - purchasedArtifacts: true, + purchasedArtefacts: true, }, }); diff --git a/src/app/api/warehouse/route.ts b/src/app/api/warehouse/route.ts index ffcc6d0..4a2fcd0 100644 --- a/src/app/api/warehouse/route.ts +++ b/src/app/api/warehouse/route.ts @@ -1,15 +1,15 @@ -import { NextResponse } from 'next/server'; +import { NextResponse } from "next/server"; -import { PrismaClient } from '@prisma/client'; -import { env } from '@utils/env'; -import { verifyJwt } from '@utils/verifyJwt'; +import { PrismaClient } from "@prisma/client"; +import { env } from "@utils/env"; +import { verifyJwt } from "@utils/verifyJwt"; const usingPrisma = false; let prisma: PrismaClient; if (usingPrisma) prisma = new PrismaClient(); -// Artifact type -interface Artifact { +// Artefact type +interface Artefact { id: number; name: string; description: string; @@ -29,7 +29,7 @@ export async function POST(req: Request) { if (!token) return NextResponse.json({ message: "Unauthorised" }, { status: 401 }); await verifyJwt({ token, secret: env.JWT_SECRET_KEY }); - const warehouseArtifacts: Artifact[] = [ + const warehouseArtefacts: Artefact[] = [ { id: 1, name: "Solidified Lava Chunk", @@ -87,17 +87,17 @@ export async function POST(req: Request) { }, ]; - let artifacts; - if (usingPrisma) artifacts = await prisma.artifacts.findMany(); + let artefacts; + if (usingPrisma) artefacts = await prisma.artefacts.findMany(); - if (artifacts) { - return NextResponse.json({ message: "Got artifacts successfully", artifacts }, { status: 200 }); + if (artefacts) { + return NextResponse.json({ message: "Got artefacts successfully", artefacts }, { status: 200 }); } else { - return NextResponse.json({ message: "Got earthquakes successfully", earthquakes: warehouseArtifacts }, { status: 200 }); + return NextResponse.json({ message: "Got earthquakes successfully", earthquakes: warehouseArtefacts }, { status: 200 }); // return NextResponse.json({ message: "Failed to get earthquakes" }, { status: 401 }); } } catch (error) { - console.error("Error in artifacts endpoint:", error); + console.error("Error in artefacts endpoint:", error); return NextResponse.json({ message: "Internal Server Error" }, { status: 500 }); } finally { if (usingPrisma) await prisma.$disconnect(); diff --git a/src/app/contact-us/page.tsx b/src/app/contact-us/page.tsx index fc371e8..1ab18d9 100644 --- a/src/app/contact-us/page.tsx +++ b/src/app/contact-us/page.tsx @@ -1,6 +1,6 @@ "use client"; -import Image from 'next/image'; -import React, { useState } from 'react'; +import Image from "next/image"; +import React, { useState } from "react"; const ContactUs = () => { const [formData, setFormData] = useState({ @@ -37,8 +37,8 @@ const ContactUs = () => { {/* Header */}

Contact Us

- Have questions or concerns about earthquakes, observatories or artifacts? Contact us via phone, email, social media or using the form below with the relevant - contact details. + Have questions or concerns about earthquakes, observatories or artefacts? Contact us via phone, email, social media or + using the form below with the relevant contact details.

{/* Content Section */} diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 4c384d7..2d539a3 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -32,7 +32,7 @@ const store = createStore({ name: "Emily Neighbour", role: "ADMIN", scientist: undefined, - purchasedArtifacts: [], + purchasedArtefacts: [], }, }); diff --git a/src/app/page.tsx b/src/app/page.tsx index 817f41f..ece9666 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -39,10 +39,10 @@ export default function Home() { href="/shop" className="flex flex-col items-center p-6 hover:bg-white hover:bg-opacity-10 rounded-xl transition-colors duration-300" > - Technology Icon -

Artifacts

+ Technology Icon +

Artefacts

- View or purchase recently discovered artifacts from seismic events + View or purchase recently discovered artefacts from seismic events

diff --git a/src/app/shop/page.tsx b/src/app/shop/page.tsx index 5994280..c8b7088 100644 --- a/src/app/shop/page.tsx +++ b/src/app/shop/page.tsx @@ -1,19 +1,22 @@ "use client"; -import Image from 'next/image'; -import { Dispatch, SetStateAction, useCallback, useState } from 'react'; +import Image from "next/image"; +import { Dispatch, SetStateAction, useCallback, useState } from "react"; -import Artifact from '@appTypes/Artifact'; -import { Currency } from '@appTypes/StoreModel'; -import { useStoreState } from '@hooks/store'; +import Artefact from "@appTypes/Artefact"; +import { Currency } from "@appTypes/StoreModel"; +import { useStoreState } from "@hooks/store"; -// Artifacts Data -const artifacts: Artifact[] = [ +// Artefacts Data +const artefacts: Artefact[] = [ { id: 1, name: "Golden Scarab", - description: "An ancient Egyptian artifact symbolizing rebirth.", + description: "An ancient Egyptian artefact symbolizing rebirth.", location: "Cairo, Egypt", - image: "/artifact1.jpg", + earthquakeID: "h", + observatory: "jhd", + dateReleased: "12/02/2025", + image: "/artefact1.jpg", price: 150, }, { @@ -21,7 +24,10 @@ const artifacts: Artifact[] = [ name: "Aztec Sunstone", description: "A replica of the Aztec calendar (inscriptions intact).", location: "Peru", - image: "/artifact2.jpg", + earthquakeID: "h", + observatory: "jhd", + dateReleased: "12/02/2025", + image: "/artefact2.jpg", price: 200, }, { @@ -29,7 +35,10 @@ const artifacts: Artifact[] = [ name: "Medieval Chalice", description: "Used by royalty in medieval ceremonies.", location: "Cambridge, England", - image: "/artifact3.jpg", + earthquakeID: "h", + observatory: "jhd", + dateReleased: "12/02/2025", + image: "/artefact3.jpg", price: 120, }, { @@ -37,7 +46,10 @@ const artifacts: Artifact[] = [ name: "Roman Coin", description: "An authentic Roman coin from the 2nd century CE.", location: "Rome, Italy", - image: "/artifact4.jpg", + earthquakeID: "h", + observatory: "jhd", + dateReleased: "12/02/2025", + image: "/artefact4.jpg", price: 80, }, { @@ -45,7 +57,10 @@ const artifacts: Artifact[] = [ name: "Samurai Mask", description: "Replica of Japanese Samurai battle masks.", location: "Tokyo, Japan", - image: "/artifact5.jpg", + earthquakeID: "h", + observatory: "jhd", + dateReleased: "12/02/2025", + image: "/artefact5.jpg", price: 300, }, { @@ -53,7 +68,10 @@ const artifacts: Artifact[] = [ name: "Ancient Greek Vase", description: "Depicts Greek mythology, found in the Acropolis.", location: "Athens, Greece", - image: "/artifact6.jpg", + earthquakeID: "h", + observatory: "jhd", + dateReleased: "12/02/2025", + image: "/artefact6.jpg", price: 250, }, { @@ -61,7 +79,10 @@ const artifacts: Artifact[] = [ name: "Incan Pendant", description: "Represents the Sun God Inti.", location: "India", - image: "/artifact7.jpg", + earthquakeID: "h", + observatory: "jhd", + dateReleased: "12/02/2025", + image: "/artefact7.jpg", price: 175, }, { @@ -69,7 +90,10 @@ const artifacts: Artifact[] = [ name: "Persian Carpet Fragment", description: "Ancient Persian artistry.", location: "Petra, Jordan", - image: "/artifact8.jpg", + earthquakeID: "h", + observatory: "jhd", + dateReleased: "12/02/2025", + image: "/artefact8.jpg", price: 400, }, { @@ -77,7 +101,10 @@ const artifacts: Artifact[] = [ name: "Stone Buddha", description: "Authentic stone Buddha carving.", location: "India", - image: "/artifact9.jpg", + earthquakeID: "h", + observatory: "jhd", + dateReleased: "12/02/2025", + image: "/artefact9.jpg", price: 220, }, { @@ -85,7 +112,10 @@ const artifacts: Artifact[] = [ name: "Victorian Brooch", description: "A beautiful Victorian-era brooch with a ruby centre.", location: "Oxford, England", - image: "/artifact10.jpg", + earthquakeID: "h", + observatory: "jhd", + dateReleased: "12/02/2025", + image: "/artefact10.jpg", price: 150, }, { @@ -93,7 +123,10 @@ const artifacts: Artifact[] = [ name: "Ancient Scroll", description: "A mysterious scroll from ancient times.", location: "Madrid, Spain", - image: "/artifact11.jpg", + earthquakeID: "h", + observatory: "jhd", + dateReleased: "12/02/2025", + image: "/artefact11.jpg", price: 500, }, { @@ -101,7 +134,10 @@ const artifacts: Artifact[] = [ name: "Ming Dynasty Porcelain", description: "Porcelain from China's Ming Dynasty.", location: "Beijing, China", - image: "/artifact12.jpg", + earthquakeID: "h", + observatory: "jhd", + dateReleased: "12/02/2025", + image: "/artefact12.jpg", price: 300, }, { @@ -109,15 +145,21 @@ const artifacts: Artifact[] = [ name: "African Tribal Mask", description: "A unique tribal mask from Africa.", location: "Nigeria", - image: "/artifact13.jpg", + earthquakeID: "h", + observatory: "jhd", + dateReleased: "12/02/2025", + image: "/artefact13.jpg", price: 250, }, { id: 14, name: "Crystal Skull", - description: "A mystical pre-Columbian artifact.", + description: "A mystical pre-Columbian artefact.", location: "Colombia", - image: "/artifact14.jpg", + earthquakeID: "h", + observatory: "jhd", + dateReleased: "12/02/2025", + image: "/artefact14.jpg", price: 1000, }, { @@ -125,159 +167,169 @@ const artifacts: Artifact[] = [ name: "Medieval Armor Fragment", description: "A fragment of medieval armor.", location: "Normandy, France", - image: "/artifact15.jpg", + 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", - image: "/artifact16.jpg", + earthquakeID: "h", + observatory: "jhd", + dateReleased: "12/02/2025", + image: "/artefact16.jpg", price: 500, }, ]; export default function Shop() { - const [currentPage, setCurrentPage] = useState(1); - const [selectedArtifact, setSelectedArtifact] = useState(null); - const artifactsPerPage = 12; - const indexOfLastArtifact = currentPage * artifactsPerPage; - const indexOfFirstArtifact = indexOfLastArtifact - artifactsPerPage; - const currentArtifacts = artifacts.slice(indexOfFirstArtifact, indexOfLastArtifact); + const [currentPage, setCurrentPage] = useState(1); + const [selectedArtefact, setSelectedArtefact] = 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 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), - [] - ); + const convertPrice = useCallback((price: number, currency: Currency) => (price * conversionRates[currency]).toFixed(2), []); - const handleNextPage = () => { - if (indexOfLastArtifact < artifacts.length) { - setCurrentPage((prev) => prev + 1); - } - }; - const handlePreviousPage = () => { - if (currentPage > 1) { - setCurrentPage((prev) => prev - 1); - } - }; + const handleNextPage = () => { + if (indexOfLastArtefact < artefacts.length) { + setCurrentPage((prev) => prev + 1); + } + }; + const handlePreviousPage = () => { + if (currentPage > 1) { + setCurrentPage((prev) => prev - 1); + } + }; - function Modal({ artifact }: { artifact: Artifact }) { - if (!artifact) return null; - const handleOverlayClick = (e: { target: any; currentTarget: any }) => { - if (e.target === e.currentTarget) { - setSelectedArtifact(null); - } - }; - return ( -
-
-

{artifact.name}

- {artifact.name} -

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

-

{artifact.description}

-

Location: {artifact.location}

-
- -
-
-
- ); - } + function Modal({ artefact }: { artefact: Artefact }) { + if (!artefact) return null; + const handleOverlayClick = (e: { target: any; currentTarget: any }) => { + 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 ArtifactCard({ artifact }: { artifact: Artifact }) { - return ( -
setSelectedArtifact(artifact)} - > - {artifact.name} -
-

{artifact.name}

-

{artifact.location}

-

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

-
-
- ); - } + function ArtefactCard({ artefact }: { artefact: Artefact }) { + return ( +
setSelectedArtefact(artefact)} + > + {artefact.name} +
+

{artefact.name}

+

{artefact.location}

+

{artefact.earthquakeID}

+

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

+
+
+ ); + } - return ( -
- {/* Overlay */} -
-
- {/* Title & Subheading */} -

- Artifact Shop -

-

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

+ return ( +
+ {/* Overlay */} +
+
+ {/* Title & Subheading */} +

+ Artefact Shop +

+

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

- {/* Artifact Grid */} -
{/* gap-10 for more spacing */} - {currentArtifacts.map((artifact) => ( - - ))} -
+ {/* Artefact Grid */} +
+ {" "} + {/* gap-10 for more spacing */} + {currentArtefacts.map((artefact) => ( + + ))} +
- {/* Pagination Footer */} -
- -

{currentPage}

- -
-
+ {/* Pagination Footer */} +
+ +

{currentPage}

+ +
+
- {/* Modal */} - {selectedArtifact && } -
- ); -} \ No newline at end of file + {/* Modal */} + {selectedArtefact && } +
+ ); +} diff --git a/src/app/warehouse/page.tsx b/src/app/warehouse/page.tsx index dcd9ede..cbc6dc7 100644 --- a/src/app/warehouse/page.tsx +++ b/src/app/warehouse/page.tsx @@ -1,12 +1,12 @@ "use client"; -import { Dispatch, SetStateAction, useMemo, useState } from 'react'; -import { FaTimes } from 'react-icons/fa'; -import { FaCalendarPlus, FaCartShopping, FaWarehouse } from 'react-icons/fa6'; -import { IoFilter, IoFilterCircleOutline, IoFilterOutline, IoToday } from 'react-icons/io5'; +import { Dispatch, SetStateAction, useMemo, useState } from "react"; +import { FaTimes } from "react-icons/fa"; +import { FaCalendarPlus, FaCartShopping, FaWarehouse } from "react-icons/fa6"; +import { IoFilter, IoFilterCircleOutline, IoFilterOutline, IoToday } from "react-icons/io5"; -// import type { Artifact } from "@prisma/client"; +// import type { Artefact } from "@prisma/client"; -interface Artifact { +interface Artefact { id: number; name: string; description: string; @@ -18,8 +18,8 @@ interface Artifact { dateAdded: string; } -// Warehouse Artifacts Data -const warehouseArtifacts: Artifact[] = [ +// Warehouse Artefacts Data +const warehouseArtefacts: Artefact[] = [ { id: 1, name: "Solidified Lava Chunk", @@ -140,14 +140,14 @@ function FilterInput({ } // Table Component -function ArtifactTable({ - artifacts, +function ArtefactTable({ + artefacts, filters, setFilters, - setEditArtifact, + setEditArtefact, clearSort, }: { - artifacts: Artifact[]; + artefacts: Artefact[]; filters: Record; setFilters: Dispatch< SetStateAction<{ @@ -162,15 +162,15 @@ function ArtifactTable({ dateAdded: string; }> >; - setEditArtifact: (artifact: Artifact) => void; + setEditArtefact: (artefact: Artefact) => void; clearSort: () => void; }) { const [sortConfig, setSortConfig] = useState<{ - key: keyof Artifact; + key: keyof Artefact; direction: "asc" | "desc"; } | null>(null); - const handleSort = (key: keyof Artifact) => { + const handleSort = (key: keyof Artefact) => { setSortConfig((prev) => { if (!prev || prev.key !== key) { return { key, direction: "asc" }; @@ -186,9 +186,9 @@ function ArtifactTable({ clearSort(); }; - const sortedArtifacts = useMemo(() => { - if (!sortConfig) return artifacts; - const sorted = [...artifacts].sort((a, b) => { + const sortedArtefacts = useMemo(() => { + if (!sortConfig) return artefacts; + const sorted = [...artefacts].sort((a, b) => { const aValue = a[sortConfig.key]; const bValue = b[sortConfig.key]; if (aValue < bValue) return sortConfig.direction === "asc" ? -1 : 1; @@ -196,9 +196,9 @@ function ArtifactTable({ return 0; }); return sorted; - }, [artifacts, sortConfig]); + }, [artefacts, sortConfig]); - const columns: { label: string; key: keyof Artifact; width: string }[] = [ + const columns: { label: string; key: keyof Artefact; width: string }[] = [ { label: "ID", key: "id", width: "5%" }, { label: "Name", key: "name", width: "12%" }, { label: "Earthquake ID", key: "earthquakeId", width: "10%" }, @@ -217,7 +217,7 @@ function ArtifactTable({ {columns.map(({ label, key, width }) => (
-
handleSort(key as keyof Artifact)}> +
handleSort(key as keyof Artefact)}>
{label}
@@ -250,11 +250,11 @@ function ArtifactTable({ - {sortedArtifacts.map((artifact) => ( + {sortedArtefacts.map((artefact) => ( setEditArtifact(artifact)} + onClick={() => setEditArtefact(artefact)} > {columns.map(({ key, width }) => ( {key === "isRequired" - ? artifact.isRequired + ? artefact.isRequired ? "Yes" : "No" : key === "isSold" - ? artifact.isSold + ? artefact.isSold ? "Yes" : "No" : key === "isCollected" - ? artifact.isCollected + ? artefact.isCollected ? "Yes" : "No" - : artifact[key]} + : artefact[key]} ))} @@ -284,7 +284,7 @@ function ArtifactTable({ ); } -// Modal Component for Logging Artifact +// Modal Component for Logging Artefact function LogModal({ onClose }: { onClose: () => void }) { const [name, setName] = useState(""); const [description, setDescription] = useState(""); @@ -312,7 +312,7 @@ function LogModal({ onClose }: { onClose: () => void }) { alert(`Logged ${name} to storage: ${storageLocation}`); onClose(); } catch { - setError("Failed to log artifact. Please try again."); + setError("Failed to log artefact. Please try again."); } finally { setIsSubmitting(false); } @@ -324,7 +324,7 @@ function LogModal({ onClose }: { onClose: () => void }) { onClick={handleOverlayClick} >
-

Log New Artifact

+

Log New Artefact

{error &&

{error}

}
void }) { value={name} onChange={(e) => setName(e.target.value)} className="w-full p-2 border border-neutral-300 rounded-md placeholder-neutral-400 focus:ring-2 focus:ring-blue-500" - aria-label="Artifact Name" + aria-label="Artefact Name" disabled={isSubmitting} />