
Next Js Tutorial #11 - Ecommerce App - Admin Orders Page & Api Route
We created admin orders page and api route.

You can also watch the YouTube video:
Next Js Tutorial #11 | Ecommerce App - Admin Orders Page & Api Route
I forget to change the name of create product page function name let's edit the function name before we start.
Edit page.js
in app/auth/admin/create-product
folder:
import CreateProduct from "@/components/Admin/CreateProduct";
export default function CreateProductPage() {
return <CreateProduct />;
}
Edit page.js
in app/auth/admin
folder:
"use client";
import AreaChartComponent from "@/components/Admin/AreaChartComponent";
import BarChartComponent from "@/components/Admin/BarChartComponent";
import PieChartComponent from "@/components/Admin/PieChartComponent";
import Link from "next/link";
const AdminPage = () => {
return (
<div className="container mx-auto py-8 px-4 lg:py-16">
<h1 className="mb-4 text-3xl font-bold text-gray-900 dark:text-white">
Dashboard
</h1>
<ul className="my-4">
<Link href="/auth/admin/orders">
<li className="btn">Orders</li>
</Link>
</ul>
<div className="grid grid-cols-3 gap-4">
<AreaChartComponent />
<BarChartComponent />
<PieChartComponent />
</div>
</div>
);
};
export default AdminPage;
Create route.js
in app/api/admin/orders
folder:
import { NextResponse } from "next/server";
import { PrismaClient } from "@prisma/client";
import { cookies } from "next/headers";
import jwt from "jsonwebtoken";
const prisma = new PrismaClient();
export async function GET() {
try {
const tokenCookie = await cookies();
const getToken = tokenCookie.get("token");
if (getToken) {
const token = jwt.verify(getToken.value, "appSecret");
const userId = token.id;
if (!userId) {
return NextResponse.json(
{ error: "Unauthorized request!" },
{ status: 200 }
);
}
const user = await prisma.user.findUnique({ where: { id: userId } });
if (!user) {
return NextResponse.json(
{ error: "Unauthorized request!" },
{ status: 200 }
);
}
if (user.role !== "ADMIN") {
return NextResponse.json(
{ error: "Unauthorized request!" },
{ status: 200 }
);
}
const orders = await prisma.order.findMany({
orderBy: { createdAt: "desc" },
include: {
cartProducts: { include: { product: true } },
createdBy: true,
},
});
return NextResponse.json({ orders });
} else {
return NextResponse.json(
{ error: "Unauthorized request!" },
{ status: 200 }
);
}
} catch (error) {
console.log(error);
return NextResponse.json(
{ error: "Failed to get orders" },
{ status: 500 }
);
} finally {
await prisma.$disconnect();
}
}
Create page.js
in app/auth/admin/orders
folder:
"use client";
import { Loader2 } from "lucide-react";
import Image from "next/image";
import Link from "next/link";
import { useState, useEffect } from "react";
const OrdersPage = () => {
const [orders, setOrders] = useState([]);
const [loading, setLoading] = useState(false);
const getOrders = async () => {
try {
setLoading(true);
const response = await fetch("/api/admin/orders");
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
setOrders(data.orders);
return data;
} catch (error) {
console.error("There was a problem with the fetch operation:", error);
} finally {
setLoading(false);
}
};
useEffect(() => {
getOrders();
}, []);
console.log(orders);
return (
<div className="container mx-auto py-8 px-4 lg:py-16">
<h1 className="mb-4 text-3xl font-bold text-gray-900 dark:text-white">
Orders
</h1>
{loading ? (
<div className="flex items-center justify-center">
<Loader2 className="w-8 h-8 animate-spin" />
</div>
) : null}
{orders
? orders.map((order) => (
<div key={order.id}>
<div className="rounded-lg border">
{/* Card Header */}
<div className="flex flex-col space-y-1.5 p-6">
{/* Card Title */}
<h1 className="text-2xl font-semibold leading-none tracking-tight">
Order #{order.numId}
</h1>
{/* Card Description */}
<div className="text-sm text-gray-900 dark:text-gray-50">
<p>{order.createdAt}</p>
<p>
Total:{" "}
<span className="font-semibold">${order.total} USD</span>
</p>
<p>
User:{" "}
<span className="font-semibold">
{order.createdBy.email}
</span>
</p>
<p>
Status:{" "}
<span className="font-semibold">{order.status}</span>
</p>
</div>
</div>
{/* Card Content */}
<div className="p-6 pt-0">
<ul
className={
"divide-y divide-gray-200 border-b border-t border-gray-200"
}
>
{order.cartProducts
? order.cartProducts.map((cartProduct) => {
return (
<li
key={cartProduct.id}
className="flex py-6 sm:py-10"
>
<div className="flex-shrink-0">
<div className="relative h-24 w-24">
<Image
fill
src={cartProduct.product.image}
alt="product image"
className="h-full w-full rounded-md object-cover object-center sm:h-48 sm:w-48"
/>
</div>
</div>
<div className="ml-4 flex flex-1 flex-col justify-between sm:ml-6">
<div className="relative pr-9 sm:grid sm:grid-cols-2 sm:gap-x-6 sm:pr-0">
<div>
<div className="flex justify-between">
<h3 className="text-sm">
<Link
href={`/${cartProduct.product.id}`}
className="font-medium text-gray-700 dark:text-gray-50 dark:hover:text-gray-200 hover:text-gray-800"
>
{cartProduct.product.title}{" "}
{cartProduct.quantity > 1
? `(${cartProduct.quantity})`
: null}
</Link>
</h3>
</div>
<p className="mt-1 text-sm font-medium text-gray-900 dark:text-gray-50">
${cartProduct.product.price} USD
</p>
</div>
</div>
</div>
</li>
);
})
: null}
</ul>
</div>
</div>
</div>
))
: null}
</div>
);
};
export default OrdersPage;
That's it for this tutorial, we created admin orders page and api route.
Next tutorial we'll create edit profile page and api route.
0
0