From ec39e4448dc604b26b8f8fa3f9bb9329c01501a0 Mon Sep 17 00:00:00 2001 From: hamid zarghami Date: Tue, 21 Jul 2026 11:25:41 +0330 Subject: [PATCH] base product single page --- app/product/[id]/page.tsx | 7 ++ app/product/components/ProductBreadcrumb.tsx | 25 +++++ app/product/components/ProductDetail.tsx | 37 +++++++ app/product/components/ProductGallery.tsx | 39 ++++++++ .../components/ProductOrderActions.tsx | 41 ++++++++ .../components/ProductPurchaseOptions.tsx | 96 ++++++++++++++++++ app/product/components/ProductRelated.tsx | 27 +++++ app/product/components/ProductTabs.tsx | 73 ++++++++++++++ app/product/constants.ts | 99 +++++++++++++++++++ 9 files changed, 444 insertions(+) create mode 100644 app/product/[id]/page.tsx create mode 100644 app/product/components/ProductBreadcrumb.tsx create mode 100644 app/product/components/ProductDetail.tsx create mode 100644 app/product/components/ProductGallery.tsx create mode 100644 app/product/components/ProductOrderActions.tsx create mode 100644 app/product/components/ProductPurchaseOptions.tsx create mode 100644 app/product/components/ProductRelated.tsx create mode 100644 app/product/components/ProductTabs.tsx create mode 100644 app/product/constants.ts diff --git a/app/product/[id]/page.tsx b/app/product/[id]/page.tsx new file mode 100644 index 0000000..066eb4d --- /dev/null +++ b/app/product/[id]/page.tsx @@ -0,0 +1,7 @@ +import ProductDetail from "../components/ProductDetail"; + +const ProductPage = () => { + return ; +}; + +export default ProductPage; diff --git a/app/product/components/ProductBreadcrumb.tsx b/app/product/components/ProductBreadcrumb.tsx new file mode 100644 index 0000000..a4d6c23 --- /dev/null +++ b/app/product/components/ProductBreadcrumb.tsx @@ -0,0 +1,25 @@ +import { ArrowLeft2 } from "iconsax-reactjs"; +import Link from "next/link"; +import { type FC, Fragment } from "react"; +import { BREADCRUMB_ITEMS } from "../constants"; + +const ProductBreadcrumb: FC = () => { + return ( + + ); +}; + +export default ProductBreadcrumb; diff --git a/app/product/components/ProductDetail.tsx b/app/product/components/ProductDetail.tsx new file mode 100644 index 0000000..cfffe5e --- /dev/null +++ b/app/product/components/ProductDetail.tsx @@ -0,0 +1,37 @@ +"use client"; + +import ContactCtaSection from "@/app/home/components/ContactCtaSection"; +import { useState, type FC } from "react"; +import { PRODUCT_GALLERY_IMAGES, PRODUCT_TITLE, QUANTITY_TIERS, type QuantityTier } from "../constants"; +import ProductBreadcrumb from "./ProductBreadcrumb"; +import ProductGallery from "./ProductGallery"; +import ProductOrderActions from "./ProductOrderActions"; +import ProductPurchaseOptions from "./ProductPurchaseOptions"; +import ProductRelated from "./ProductRelated"; +import ProductTabs from "./ProductTabs"; + +const ProductDetail: FC = () => { + const [selectedTier, setSelectedTier] = useState(QUANTITY_TIERS[0]); + + return ( + <> + + +
+
+ +
+ + +
+
+
+ + + + + + ); +}; + +export default ProductDetail; diff --git a/app/product/components/ProductGallery.tsx b/app/product/components/ProductGallery.tsx new file mode 100644 index 0000000..67acd0d --- /dev/null +++ b/app/product/components/ProductGallery.tsx @@ -0,0 +1,39 @@ +"use client"; + +import { cn } from "@/app/lib/cn"; +import Image, { type StaticImageData } from "next/image"; +import { useState, type FC } from "react"; + +type ProductGalleryProps = { + images: readonly StaticImageData[]; + alt: string; +}; + +const ProductGallery: FC = ({ images, alt }) => { + const [activeIndex, setActiveIndex] = useState(0); + + return ( +
+
+ {alt} +
+ +
+ {images.slice(0, 4).map((image, index) => ( + + ))} +
+
+ ); +}; + +export default ProductGallery; diff --git a/app/product/components/ProductOrderActions.tsx b/app/product/components/ProductOrderActions.tsx new file mode 100644 index 0000000..74d268b --- /dev/null +++ b/app/product/components/ProductOrderActions.tsx @@ -0,0 +1,41 @@ +"use client"; + +import Button from "@/app/components/Button"; +import Select from "@/app/components/Select"; +import { formatPrice, PRODUCT_PROFIT_PERCENT, STICKY_QUANTITY_OPTIONS, type QuantityTier } from "../constants"; + +type ProductOrderActionsProps = { + selectedTier: QuantityTier; +}; + +const ProductOrderActions = ({ selectedTier }: ProductOrderActionsProps) => { + return ( +
+
+

{formatPrice(selectedTier.totalPrice)}﷼

+
+ {formatPrice(selectedTier.unitPrice)} ﷼ به ازای هر عدد + {PRODUCT_PROFIT_PERCENT}٪ سود +
+
+ +
+ +
+
+ تعداد + + + + +