From f3ad2c8ed8f53242f18d95a1b656ff23d8c5ae67 Mon Sep 17 00:00:00 2001
From: Tim Howitz
Date: Mon, 2 Jun 2025 08:16:23 +0100
Subject: [PATCH] Added shop receiving route
---
src/app/api/earthquakes/log/route.ts | 88 ++++++++++++++--------------
src/app/api/shop/purchase/route.ts | 50 ++++++++++++++++
src/app/shop/page.tsx | 12 +++-
3 files changed, 103 insertions(+), 47 deletions(-)
create mode 100644 src/app/api/shop/purchase/route.ts
diff --git a/src/app/api/earthquakes/log/route.ts b/src/app/api/earthquakes/log/route.ts
index f6404ca..e718313 100644
--- a/src/app/api/earthquakes/log/route.ts
+++ b/src/app/api/earthquakes/log/route.ts
@@ -3,50 +3,50 @@ import { prisma } from "@utils/prisma";
// Generates code using only the country, and highest id in DB for numbering
async function generateEarthquakeCode(type: string, country: string) {
- const typeLetter = type.trim().charAt(0).toUpperCase();
- // Remove non-alphanumeric for the country part
- const countrySlug = (country || "Unknown").replace(/[^\w]/gi, "");
- // Use highest DB id to find the latest added earthquake's code number
- const last = await prisma.earthquake.findFirst({
- orderBy: { id: "desc" },
- select: { code: true }
- });
- let num = 10000;
- if (last?.code) {
- const parts = last.code.split("-");
- const lastNum = parseInt(parts[parts.length - 1], 10);
- if (!isNaN(lastNum)) num = lastNum + 1;
- }
- return `E${typeLetter}-${countrySlug}-${num.toString().padStart(5, "0")}`;
+ const typeLetter = type.trim().charAt(0).toUpperCase();
+ // Remove non-alphanumeric for the country part
+ const countrySlug = (country || "Unknown").replace(/[^\w]/gi, "");
+ // Use highest DB id to find the latest added earthquake's code number
+ const last = await prisma.earthquake.findFirst({
+ orderBy: { id: "desc" },
+ select: { code: true },
+ });
+ let num = 10000;
+ if (last?.code) {
+ const parts = last.code.split("-");
+ const lastNum = parseInt(parts[parts.length - 1], 10);
+ if (!isNaN(lastNum)) num = lastNum + 1;
+ }
+ return `E${typeLetter}-${countrySlug}-${num.toString().padStart(5, "0")}`;
}
export async function POST(request: NextRequest) {
- try {
- const body = await request.json();
- const { date, magnitude, type, location, latitude, longitude, depth, country } = body;
- const creatorId = 1;
- if (!date || !magnitude || !type || !location || !latitude || !longitude || !depth || !country) {
- return NextResponse.json({ error: "Missing fields" }, { status: 400 });
- }
- if (+magnitude > 10) {
- return NextResponse.json({ error: "Magnitude cannot exceed 10" }, { status: 400 });
- }
- const code = await generateEarthquakeCode(type, country);
- const eq = await prisma.earthquake.create({
- data: {
- date: new Date(date),
- code,
- magnitude: +magnitude,
- type,
- location, // "city, country"
- latitude: +latitude,
- longitude: +longitude,
- depth,
- creatorId,
- }
- });
- return NextResponse.json({ id: eq.id, code }, { status: 201 });
- } catch (e: any) {
- return NextResponse.json({ error: e.message }, { status: 500 });
- }
-}
\ No newline at end of file
+ try {
+ const body = await request.json();
+ const { date, magnitude, type, location, latitude, longitude, depth, country } = body;
+ const creatorId = 1;
+ if (!date || !magnitude || !type || !location || !latitude || !longitude || !depth || !country) {
+ return NextResponse.json({ error: "Missing fields" }, { status: 400 });
+ }
+ if (+magnitude > 10) {
+ return NextResponse.json({ error: "Magnitude cannot exceed 10" }, { status: 400 });
+ }
+ const code = await generateEarthquakeCode(type, country);
+ const eq = await prisma.earthquake.create({
+ data: {
+ date: new Date(date),
+ code,
+ magnitude: +magnitude,
+ type,
+ location, // "city, country"
+ latitude: +latitude,
+ longitude: +longitude,
+ depth,
+ creatorId,
+ },
+ });
+ return NextResponse.json({ id: eq.id, code }, { status: 201 });
+ } catch (e: any) {
+ return NextResponse.json({ error: e.message }, { status: 500 });
+ }
+}
diff --git a/src/app/api/shop/purchase/route.ts b/src/app/api/shop/purchase/route.ts
new file mode 100644
index 0000000..ceb5804
--- /dev/null
+++ b/src/app/api/shop/purchase/route.ts
@@ -0,0 +1,50 @@
+import { prisma } from "@utils/prisma";
+import { NextResponse } from "next/server";
+import { NextRequest } from "next/server";
+import { ExtendedArtefact } from "@appTypes/ApiTypes";
+
+interface SuperExtendedArtefact extends ExtendedArtefact {
+ location: string;
+ dateReleased: string;
+ image: string;
+ price: number;
+}
+
+export async function POST(request: NextRequest) {
+ try {
+ const {
+ artefacts,
+ email,
+ orderNumber,
+ userId,
+ }: { artefacts: SuperExtendedArtefact[]; email: string; orderNumber: string; userId: number | undefined } =
+ await request.json();
+
+ if (!email || !artefacts || !orderNumber) {
+ return NextResponse.json({ error: "Missing fields" }, { status: 401 });
+ }
+
+ const order = await prisma.order.create({
+ data: {
+ orderNumber,
+ email,
+ userId: userId,
+ artefacts: {
+ connect: artefacts.map((artefact) => ({ id: artefact.id })),
+ },
+ },
+ });
+
+ await prisma.artefact.updateMany({
+ where: { id: { in: artefacts.map((a) => a.id) } },
+ data: {
+ isSold: true,
+ },
+ });
+
+ return NextResponse.json({ order }, { status: 201 });
+ } catch (error) {
+ console.error("Error creating order:", error);
+ return NextResponse.json({ error: "Failed to create order" }, { status: 500 });
+ }
+}
diff --git a/src/app/shop/page.tsx b/src/app/shop/page.tsx
index 81494de..faa8adf 100644
--- a/src/app/shop/page.tsx
+++ b/src/app/shop/page.tsx
@@ -292,13 +292,19 @@ export default function Shop() {
// 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
- const genOrder = () => "#" + Math.random().toString(36).substring(2, 10).toUpperCase();
+ const genOrder = () =>
+ "#" + Math.random().toString(24).substring(2, 10).toUpperCase() + new Date().toLocaleDateString("en-GB");
const orderNum = genOrder();
// todo add display of error
(async () => {
try {
- const response = await axios.post("/api/shop/purchase", artefactsToBuy);
+ const response = await axios.post("/api/shop/purchase", {
+ artefacts: artefactsToBuy,
+ email: paymentEmail,
+ orderNumber: orderNum,
+ userId: user?.id,
+ });
setOrderNumber(orderNum);
onClose();
setShowThankYouModal(true);
@@ -469,7 +475,7 @@ export default function Shop() {
{currentArtefacts
- .filter((x) => !hiddenArtefactIds.includes(x.id) && x.isRequired === false)
+ .filter((x) => !hiddenArtefactIds.includes(x.id) && x.isRequired === false && x.isSold === false)
.map((artefact) => (
))}