-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #9 from udohjeremiah/dev
Add /products and /products/[productId] routes.
- Loading branch information
Showing
29 changed files
with
2,327 additions
and
193 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
-- CreateTable | ||
CREATE TABLE "Product" ( | ||
"id" TEXT NOT NULL, | ||
"storeId" TEXT NOT NULL, | ||
"categoryId" TEXT NOT NULL, | ||
"sizeId" TEXT NOT NULL, | ||
"colorId" TEXT NOT NULL, | ||
"name" TEXT NOT NULL, | ||
"price" DECIMAL(65,30) NOT NULL, | ||
"isFeatured" BOOLEAN NOT NULL DEFAULT false, | ||
"isArchived" BOOLEAN NOT NULL DEFAULT false, | ||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, | ||
"updatedAt" TIMESTAMP(3) NOT NULL, | ||
|
||
CONSTRAINT "Product_pkey" PRIMARY KEY ("id") | ||
); | ||
|
||
-- CreateTable | ||
CREATE TABLE "Image" ( | ||
"id" TEXT NOT NULL, | ||
"productId" TEXT NOT NULL, | ||
"publicId" TEXT NOT NULL, | ||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, | ||
"updatedAt" TIMESTAMP(3) NOT NULL, | ||
|
||
CONSTRAINT "Image_pkey" PRIMARY KEY ("id") | ||
); | ||
|
||
-- AddForeignKey | ||
ALTER TABLE "Product" ADD CONSTRAINT "Product_storeId_fkey" FOREIGN KEY ("storeId") REFERENCES "Store"("id") ON DELETE RESTRICT ON UPDATE CASCADE; | ||
|
||
-- AddForeignKey | ||
ALTER TABLE "Product" ADD CONSTRAINT "Product_categoryId_fkey" FOREIGN KEY ("categoryId") REFERENCES "Category"("id") ON DELETE RESTRICT ON UPDATE CASCADE; | ||
|
||
-- AddForeignKey | ||
ALTER TABLE "Product" ADD CONSTRAINT "Product_sizeId_fkey" FOREIGN KEY ("sizeId") REFERENCES "Size"("id") ON DELETE RESTRICT ON UPDATE CASCADE; | ||
|
||
-- AddForeignKey | ||
ALTER TABLE "Product" ADD CONSTRAINT "Product_colorId_fkey" FOREIGN KEY ("colorId") REFERENCES "Color"("id") ON DELETE RESTRICT ON UPDATE CASCADE; | ||
|
||
-- AddForeignKey | ||
ALTER TABLE "Image" ADD CONSTRAINT "Image_productId_fkey" FOREIGN KEY ("productId") REFERENCES "Product"("id") ON DELETE CASCADE ON UPDATE CASCADE; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
/* | ||
Warnings: | ||
- You are about to drop the column `publicId` on the `Image` table. All the data in the column will be lost. | ||
- Added the required column `imagePublicId` to the `Image` table without a default value. This is not possible if the table is not empty. | ||
*/ | ||
-- AlterTable | ||
ALTER TABLE "Image" DROP COLUMN "publicId", | ||
ADD COLUMN "imagePublicId" TEXT NOT NULL; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
158 changes: 158 additions & 0 deletions
158
src/app/(dashboard)/[storeId]/products/[productId]/page.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,158 @@ | ||
import type { Metadata } from "next"; | ||
|
||
import { redirect } from "next/navigation"; | ||
|
||
import { auth } from "@clerk/nextjs"; | ||
import { format } from "date-fns"; | ||
|
||
import APIList from "@/components/APIList"; | ||
import Heading from "@/components/Heading"; | ||
import DeleteProductDialog from "@/components/dialogs/DeleteProductDialog"; | ||
import ProductForm from "@/components/forms/ProductForm"; | ||
import { Separator } from "@/components/ui/separator"; | ||
|
||
import { cn } from "@/lib/utils"; | ||
import prisma from "@/lib/prisma"; | ||
|
||
interface ProductPageProps { | ||
params: { storeId: string; productId: string }; | ||
} | ||
|
||
export async function generateMetadata({ | ||
params, | ||
}: { | ||
params: { storeId: string; productId: string }; | ||
}): Promise<Metadata> { | ||
const { userId } = auth(); | ||
|
||
if (!userId) { | ||
return {}; | ||
} | ||
|
||
const store = await prisma.store.findUnique({ | ||
where: { id: params.storeId, userId }, | ||
}); | ||
|
||
const product = await prisma.product.findUnique({ | ||
where: { id: params.productId, storeId: params.storeId }, | ||
}); | ||
|
||
return { | ||
title: `${store?.name} Store ${product?.name} Product | E-Commerce CMS`, | ||
description: `Manage the ${product?.name} product for your ${store?.name} store.`, | ||
}; | ||
} | ||
|
||
export default async function ProductPage({ params }: ProductPageProps) { | ||
const { userId } = auth(); | ||
|
||
if (!userId) { | ||
redirect("/login"); | ||
} | ||
|
||
const store = await prisma.store.findFirst({ | ||
where: { id: params.storeId, userId }, | ||
}); | ||
|
||
if (!store) { | ||
redirect("/"); | ||
} | ||
|
||
const categories = await prisma.category.findMany({ | ||
where: { storeId: params.storeId }, | ||
}); | ||
|
||
const sizes = await prisma.size.findMany({ | ||
where: { storeId: params.storeId }, | ||
}); | ||
|
||
const colors = await prisma.color.findMany({ | ||
where: { storeId: params.storeId }, | ||
}); | ||
|
||
const product = await prisma.product.findUnique({ | ||
where: { id: params.productId, storeId: store.id }, | ||
include: { | ||
Category: true, | ||
Size: true, | ||
Color: true, | ||
Image: true, | ||
}, | ||
}); | ||
|
||
if (!product) { | ||
redirect(`/${store.id}/products`); | ||
} | ||
|
||
return ( | ||
<main | ||
className={cn( | ||
"container flex flex-1 flex-col gap-4 py-4", | ||
"md:gap-8 md:py-8", | ||
)} | ||
> | ||
<div | ||
className={cn( | ||
"flex flex-col gap-4", | ||
"md:flex-row md:items-center md:justify-between", | ||
)} | ||
> | ||
<Heading | ||
title={`${store?.name} Store Product`} | ||
description={`Manage this product for your ${store?.name} store.`} | ||
/> | ||
<DeleteProductDialog | ||
product={{ | ||
id: product.id, | ||
name: product.name, | ||
isFeatured: product.isFeatured, | ||
isArchived: product.isArchived, | ||
price: new Intl.NumberFormat("en-US", { | ||
style: "currency", | ||
currency: "USD", | ||
}).format(product.price.toNumber()), | ||
category: product.Category.name, | ||
size: product.Size.name, | ||
color: product.Color.value, | ||
createdAt: format(product.createdAt, "MMMM do, yyyy"), | ||
}} | ||
triggerBtnClassName="w-max" | ||
/> | ||
</div> | ||
<Separator /> | ||
<ProductForm | ||
product={product} | ||
images={product.Image} | ||
categories={categories} | ||
sizes={sizes} | ||
colors={colors} | ||
/> | ||
<Separator /> | ||
<Heading title="API" description="API calls for product" /> | ||
<APIList | ||
apis={[ | ||
{ | ||
title: "NEXT_PUBLIC_API_URL", | ||
variant: "public", | ||
route: "", | ||
}, | ||
{ | ||
title: "GET", | ||
variant: "public", | ||
route: `products/{productId}`, | ||
}, | ||
{ | ||
title: "PATCH", | ||
variant: "admin", | ||
route: `products/{productId}`, | ||
}, | ||
{ | ||
title: "DELETE", | ||
variant: "admin", | ||
route: `products/{productId}`, | ||
}, | ||
]} | ||
/> | ||
</main> | ||
); | ||
} |
Oops, something went wrong.