Skip to content

Commit

Permalink
Merge pull request #10 from udohjeremiah/dev
Browse files Browse the repository at this point in the history
Add /orders route.
  • Loading branch information
udohjeremiah authored Apr 1, 2024
2 parents 6711e8a + c776146 commit ca93f19
Show file tree
Hide file tree
Showing 6 changed files with 266 additions and 11 deletions.
30 changes: 30 additions & 0 deletions prisma/migrations/20240401155831_/migration.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
-- CreateTable
CREATE TABLE "Order" (
"id" TEXT NOT NULL,
"storeId" TEXT NOT NULL,
"isPaid" BOOLEAN NOT NULL DEFAULT false,
"phone" TEXT NOT NULL DEFAULT '',
"address" TEXT NOT NULL DEFAULT '',
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,

CONSTRAINT "Order_pkey" PRIMARY KEY ("id")
);

-- CreateTable
CREATE TABLE "OrderItem" (
"id" TEXT NOT NULL,
"orderId" TEXT NOT NULL,
"productId" TEXT NOT NULL,

CONSTRAINT "OrderItem_pkey" PRIMARY KEY ("id")
);

-- AddForeignKey
ALTER TABLE "Order" ADD CONSTRAINT "Order_storeId_fkey" FOREIGN KEY ("storeId") REFERENCES "Store"("id") ON DELETE RESTRICT ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE "OrderItem" ADD CONSTRAINT "OrderItem_orderId_fkey" FOREIGN KEY ("orderId") REFERENCES "Order"("id") ON DELETE RESTRICT ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE "OrderItem" ADD CONSTRAINT "OrderItem_productId_fkey" FOREIGN KEY ("productId") REFERENCES "Product"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
40 changes: 31 additions & 9 deletions prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ model Store {
Size Size[]
Color Color[]
Product Product[]
Order Order[]
}

model Billboard {
Expand Down Expand Up @@ -73,22 +74,23 @@ model Color {
}

model Product {
id String @id @default(uuid())
id String @id @default(uuid())
storeId String
categoryId String
sizeId String
colorId String
name String
price Decimal
isFeatured Boolean @default(false)
isArchived Boolean @default(false)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
Store Store @relation(fields: [storeId], references: [id])
Category Category @relation(fields: [categoryId], references: [id])
Size Size @relation(fields: [sizeId], references: [id])
Color Color @relation(fields: [colorId], references: [id])
isFeatured Boolean @default(false)
isArchived Boolean @default(false)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
Store Store @relation(fields: [storeId], references: [id])
Category Category @relation(fields: [categoryId], references: [id])
Size Size @relation(fields: [sizeId], references: [id])
Color Color @relation(fields: [colorId], references: [id])
Image Image[]
OrderItem OrderItem[]
}

model Image {
Expand All @@ -99,3 +101,23 @@ model Image {
updatedAt DateTime @updatedAt
Product Product @relation(fields: [productId], references: [id], onDelete: Cascade)
}

model Order {
id String @id @default(uuid())
storeId String
isPaid Boolean @default(false)
phone String @default("")
address String @default("")
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
Store Store @relation(fields: [storeId], references: [id])
OrderItem OrderItem[]
}

model OrderItem {
id String @id @default(uuid())
orderId String
productId String
Order Order @relation(fields: [orderId], references: [id])
Product Product @relation(fields: [productId], references: [id])
}
105 changes: 105 additions & 0 deletions src/app/(dashboard)/[storeId]/orders/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import type { Metadata } from "next";

import { redirect } from "next/navigation";

import { auth } from "@clerk/nextjs";
import { format } from "date-fns";

import DataTable from "@/components/DataTable";
import Heading from "@/components/Heading";
import { OrderColumn, columns } from "@/components/columns/OrderColumns";
import { Separator } from "@/components/ui/separator";

import { cn } from "@/lib/utils";
import prisma from "@/lib/prisma";

interface OrdersPageProps {
params: { storeId: string };
}

export async function generateMetadata({
params,
}: {
params: { storeId: string };
}): Promise<Metadata> {
const { userId } = auth();

if (!userId) {
return {};
}

const store = await prisma.store.findUnique({
where: { id: params.storeId, userId },
});

return {
title: `${store?.name} Store Orders | E-Commerce CMS`,
description: `Manage the orders for your ${store?.name} store.`,
};
}

export default async function OrdersPage({ params }: OrdersPageProps) {
const { userId } = auth();

if (!userId) {
redirect("/login");
}

const store = await prisma.store.findFirst({
where: { id: params.storeId, userId },
});

if (!store) {
redirect("/");
}

const orders = await prisma.order.findMany({
where: { storeId: store.id },
include: {
OrderItem: {
include: { Product: true },
},
},
orderBy: { createdAt: "desc" },
});

const formattedOrders: OrderColumn[] = orders.map((order) => ({
id: order.id,
isPaid: order.isPaid,
phone: order.phone,
address: order.address,
products: order.OrderItem.map((orderItem) => orderItem.Product.name).join(
", ",
),
totalPrice: new Intl.NumberFormat("en-US", {
style: "currency",
currency: "USD",
}).format(
order.OrderItem.reduce(
(total, orderItem) => total + Number(orderItem.Product.price),
0,
),
),
createdAt: format(order.createdAt, "MMMM do, yyyy"),
}));

return (
<main
className={cn(
"container flex flex-1 flex-col gap-4 py-4",
"md:gap-8 md:py-8",
)}
>
<Heading
title={`Orders (${orders.length})`}
description={`Manage the orders for your ${store.name} store.`}
/>
<Separator />
<DataTable
columns={columns}
filterColumn="products"
data={formattedOrders}
/>
</main>
);
}
93 changes: 93 additions & 0 deletions src/components/columns/OrderColumns.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
"use client";

import { ColumnDef } from "@tanstack/react-table";
import { ArrowUpDown } from "lucide-react";

import { Button } from "@/components/ui/button";

export type OrderColumn = {
id: string;
isPaid: boolean;
phone: string;
address: string;
products: string;
totalPrice: string;
createdAt: string;
};

export const columns: ColumnDef<OrderColumn>[] = [
{
accessorKey: "products",
header: ({ column }) => {
return (
<Button
variant="ghost"
onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
>
Products
<ArrowUpDown className="ml-2 h-4 w-4" />
</Button>
);
},
},
{
accessorKey: "phone",
header: ({ column }) => {
return (
<Button
variant="ghost"
onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
>
Phone
<ArrowUpDown className="ml-2 h-4 w-4" />
</Button>
);
},
},
{
accessorKey: "address",
header: ({ column }) => {
return (
<Button
variant="ghost"
onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
>
Address
<ArrowUpDown className="ml-2 h-4 w-4" />
</Button>
);
},
},
{
accessorKey: "totalPrice",
header: ({ column }) => {
return (
<Button
variant="ghost"
onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
>
Total Price
<ArrowUpDown className="ml-2 h-4 w-4" />
</Button>
);
},
},
{
accessorKey: "isPaid",
header: "Paid",
},
{
accessorKey: "createdAt",
header: ({ column }) => {
return (
<Button
variant="ghost"
onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
>
Date
<ArrowUpDown className="ml-2 h-4 w-4" />
</Button>
);
},
},
];
4 changes: 2 additions & 2 deletions src/components/layout/MobileNav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export default function MobileNav() {
href="/"
onClick={() => setOpen(false)}
className={cn(
"flex items-center gap-2 text-lg font-bold",
"flex w-max items-center gap-2 text-lg font-bold",
"md:text-base",
)}
>
Expand All @@ -58,7 +58,7 @@ export default function MobileNav() {
href={`/${params.storeId}/${href}`}
onClick={() => setOpen(false)}
className={cn(
"text-muted-foreground transition-colors",
"w-max text-muted-foreground transition-colors",
"hover:text-foreground",
active(pathName, `/${params.storeId}${href && `/${href}`}`) &&
"text-foreground",
Expand Down
5 changes: 5 additions & 0 deletions src/data/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ export const routes = [
label: "Products",
active: (pathName: string, route: string) => pathName.startsWith(route),
},
{
href: "orders",
label: "Orders",
active: (pathName: string, route: string) => pathName.startsWith(route),
},
{
href: "settings",
label: "Settings",
Expand Down

0 comments on commit ca93f19

Please sign in to comment.