casper's Profile Image

Full Stack Web/Mobile Developer

Jan, 20, 2025

Next Js Tutorial #11 - Ecommerce App - Admin Orders Page & Api Route

We created admin orders page and api route.

Next Js Tutorial #11 - Ecommerce App - Admin Orders Page & Api Route Image

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

Comments (0)