50% رضایت کالا
@@ -26,19 +54,19 @@ const ShopInformation = () => {
-
گارانتی اصالت و سلامت فیزیکی کالا
+
{warranty.name}
-
گارانتی اصالت و سلامت فیزیکی کالا
+
مدت گارانتی: {warranty.duration}
-
ارسال از سندس حداکثر پس از 3 روز کاری
+
ارسال از {shop.shopName} حداکثر پس از {postingTime} روز کاری
@@ -47,17 +75,21 @@ const ShopInformation = () => {
گارانتی اصالت و سلامت فیزیکی کالا
-
-
قیمت برای شما
-
70,400,000
-
+ {hasDiscount && (
+
+
قیمت برای شما
+
{formatPrice(price.retailPrice)}
+
+ )}
-
- 5%
-
+ {hasDiscount && (
+
+ {discountPercent}%
+
+ )}
- 70,400,000 تومان
+ {formatPrice(price.selling_price)} تومان
diff --git a/src/app/product/components/SingleProduct.tsx b/src/app/product/components/SingleProduct.tsx
new file mode 100644
index 0000000..41b4053
--- /dev/null
+++ b/src/app/product/components/SingleProduct.tsx
@@ -0,0 +1,89 @@
+'use client'
+import {
+ Breadcrumb,
+ BreadcrumbItem,
+ BreadcrumbLink,
+ BreadcrumbList,
+ BreadcrumbPage,
+ BreadcrumbSeparator,
+} from '@/components/ui/breadcrumb'
+import ProductImage from '@/app/product/components/ProductImage'
+import BaseInformation from '@/app/product/components/BaseInformation'
+import ShopInformation from '@/app/product/components/ShopInformation'
+import Specifications from '@/app/product/components/Specifications'
+import ProsCons from '@/app/product/components/ProsCons'
+import Description from '@/app/product/components/Description'
+import Reviews from '@/app/product/components/Reviews'
+import Questions from '@/app/product/components/Questions'
+import { useGetDetailProduct } from '@/app/product/hooks/useProductData'
+import PageLoading from '@/components/PageLoading'
+import { notFound } from 'next/navigation'
+
+interface SingleProductProps {
+ id: string
+}
+
+const SingleProduct = ({ id }: SingleProductProps) => {
+ const { data: productData, isLoading, error } = useGetDetailProduct(id)
+
+ if (isLoading) {
+ return
+ }
+
+ if (error || !productData) {
+ notFound()
+ }
+
+ const { product, categoryPath, reviews, questions } = productData.results
+
+ return (
+
+
+
+
+
+ فروشگاه آناهیتا
+
+ {categoryPath.map((category, index) => (
+
+ /
+
+ {index === categoryPath.length - 1 ? (
+ {category.title_fa}
+ ) : (
+
+ {category.title_fa}
+
+ )}
+
+
+ ))}
+
+
+
+
فروشنده شوید
+
+
+
+
+ )
+}
+
+export default SingleProduct
diff --git a/src/app/product/components/Specifications.tsx b/src/app/product/components/Specifications.tsx
index aac00fc..32d0d2d 100644
--- a/src/app/product/components/Specifications.tsx
+++ b/src/app/product/components/Specifications.tsx
@@ -1,29 +1,13 @@
+'use client'
import { FC, Fragment } from 'react'
import { Separator } from '@/components/ui/separator'
+import { Product } from '@/types/product.types'
-type SpecItem = {
- label: string
- value: string | string[]
+interface SpecificationsProps {
+ product: Product
}
-const SPEC_ITEMS: SpecItem[] = [
- { label: 'ابعاد', value: 'میلیمتر 163.3×79×8.6' },
- { label: 'وزن', value: '233 گرم' },
- { label: 'توضیحات سیم کارت', value: 'سایز نانو (12.3 × 8.8 میلیمتر)' },
- {
- label: 'ویژگیهای خاص',
- value: [
- 'مجهز به حسگر اثرانگشت',
- 'مقاوم در برابر آب',
- 'مناسب بازی',
- 'مناسب عکاسی',
- 'مناسب عکاسی سلفی',
- ],
- },
- { label: 'تعداد سیم کارت', value: 'دو عدد' },
-]
-
-const Specifications: FC = () => {
+const Specifications: FC
= ({ product }) => {
return (
@@ -32,26 +16,22 @@ const Specifications: FC = () => {
- {SPEC_ITEMS.map((item, index) => (
-
+ {product.specifications.map((spec, index) => (
+
- {item.label}
+ {spec.title}
- {Array.isArray(item.value) ? (
-
- {item.value.map((v) => (
-
{v}
- ))}
-
- ) : (
-
{item.value}
- )}
+
+ {spec.values.map((value, valueIndex) => (
+
{value}
+ ))}
+
- {index !== SPEC_ITEMS.length - 1 && }
+ {index !== product.specifications.length - 1 && }
))}
diff --git a/src/app/product/hooks/useProductData.ts b/src/app/product/hooks/useProductData.ts
new file mode 100644
index 0000000..1993c75
--- /dev/null
+++ b/src/app/product/hooks/useProductData.ts
@@ -0,0 +1,14 @@
+import { useQuery } from "@tanstack/react-query";
+import * as api from "../service/Service";
+
+export const useGetDetailProduct = (id: string) => {
+ return useQuery({
+ queryKey: ["product", id],
+ queryFn: () => api.getProduct(id),
+ });
+};
+
+export const getProductQueryOptions = (id: string) => ({
+ queryKey: ["product", id],
+ queryFn: () => api.getProduct(id),
+});
diff --git a/src/app/product/service/Service.ts b/src/app/product/service/Service.ts
new file mode 100644
index 0000000..3b1074e
--- /dev/null
+++ b/src/app/product/service/Service.ts
@@ -0,0 +1,9 @@
+import axios from "@/config/axios";
+import { ProductDetailResponse } from "@/types/product.types";
+
+export const getProduct = async (
+ id: string
+): Promise
=> {
+ const { data } = await axios.get(`/product/${id}`);
+ return data;
+};
diff --git a/src/app/profile/page.tsx b/src/app/profile/page.tsx
index 810ab01..8992f7c 100644
--- a/src/app/profile/page.tsx
+++ b/src/app/profile/page.tsx
@@ -40,7 +40,6 @@ const ProfilePage = () => {
- {/* Left Content - Form */}
@@ -150,25 +149,32 @@ const ProfilePage = () => {
- {/* Quick Actions Cards */}
-
-
-
-
+
+
+
-
- سفارشات
+
+
+
+
+
+ علاقه مندی ها
+
-
-
-
-
-
- علاقه مندی ها
-
+
+
+
+
+
diff --git a/src/components/ProductCard.tsx b/src/components/ProductCard.tsx
index c35dd65..5e923eb 100644
--- a/src/components/ProductCard.tsx
+++ b/src/components/ProductCard.tsx
@@ -1,3 +1,4 @@
+'use client'
import { IProduct } from '@/types/landing.types'
import { NumberFormat } from '@/config/func'
import { Heart } from 'iconsax-react'
@@ -5,6 +6,7 @@ import Image from 'next/image'
import { FC, useState } from 'react'
import { useAddWishlist, useRemoveWishlist } from '@/app/products/hooks/useProductsData'
import { useSharedStore } from '@/share/store/sharedStore'
+import Link from 'next/link'
type Props = {
item?: IProduct
@@ -34,7 +36,7 @@ const ProductCard: FC
= ({ item }) => {
}
if (item) return (
-
+
+
)
return (
diff --git a/src/types/product.types.ts b/src/types/product.types.ts
new file mode 100644
index 0000000..f3e73de
--- /dev/null
+++ b/src/types/product.types.ts
@@ -0,0 +1,163 @@
+export interface ProductPrice {
+ order_limit: number;
+ retailPrice: number;
+ selling_price: number;
+ is_specialSale: boolean;
+ discount_percent: number;
+ specialSale_order_limit: number | null;
+ specialSale_quantity: number | null;
+ specialSale_endDate: string | null;
+}
+
+export interface ProductSize {
+ _id: number;
+ value: string;
+}
+
+export interface ProductWarranty {
+ _id: number;
+ duration: string;
+ logoUrl: string;
+ name: string;
+}
+
+export interface ProductShop {
+ _id: string;
+ shopName: string;
+ shopCode: number;
+ owner: string;
+ shopDescription: string;
+ telephoneNumber: string;
+ isChatActive: boolean;
+ shopPostalCode: string;
+ logo: string;
+}
+
+export interface ShipmentMethod {
+ _id: number;
+ name: string;
+ description: string;
+ deliveryTime: number;
+ deliveryType: string;
+}
+
+export interface ProductVariant {
+ _id: string;
+ market_status: string;
+ price: ProductPrice;
+ stock: number;
+ postingTime: number;
+ isFreeShip: boolean;
+ isWholeSale: boolean;
+ shop: ProductShop;
+ shipmentMethod: ShipmentMethod[];
+ warranty: ProductWarranty;
+ size: ProductSize;
+}
+
+export interface ProductBrand {
+ _id: string;
+ status: string;
+ title_en: string;
+ title_fa: string;
+ images: string[];
+ logoUrl: string;
+}
+
+export interface ProductCategory {
+ _id: string;
+ title_fa: string;
+ title_en: string;
+ icon: string;
+ imageUrl: string;
+ theme: string;
+ description: string;
+ leaf: boolean;
+ parent: string;
+}
+
+export interface ProductSpecification {
+ title: string;
+ values: string[];
+}
+
+export interface ProductImages {
+ cover: string;
+ list: string[];
+}
+
+export interface CategoryPathItem {
+ id: string;
+ title_fa: string;
+ title_en: string;
+}
+
+export interface Review {
+ _id: string;
+ user: {
+ name: string;
+ avatar?: string;
+ };
+ rating: number;
+ comment: string;
+ date: string;
+ isVerified: boolean;
+ helpful: number;
+}
+
+export interface Question {
+ _id: string;
+ user: {
+ name: string;
+ avatar?: string;
+ };
+ question: string;
+ answers: Answer[];
+ date: string;
+ helpful: number;
+}
+
+export interface Answer {
+ _id: string;
+ user: {
+ name: string;
+ avatar?: string;
+ };
+ answer: string;
+ date: string;
+ helpful: number;
+}
+
+export interface Product {
+ _id: number;
+ url: string;
+ title_fa: string;
+ title_en: string;
+ seoTitle: string | null;
+ seoDescription: string | null;
+ source: string;
+ description: string;
+ metaDescription: string;
+ tags: string[];
+ advantages: string[];
+ disAdvantages: string[];
+ imagesUrl: ProductImages;
+ isFake: string;
+ voice: string | null;
+ specifications: ProductSpecification[];
+ brand: ProductBrand;
+ category: ProductCategory;
+ default_variant: ProductVariant;
+ variants: ProductVariant[];
+}
+
+export interface ProductDetailResponse {
+ status: number;
+ success: boolean;
+ results: {
+ product: Product;
+ categoryPath: CategoryPathItem[];
+ reviews?: Review[];
+ questions?: Question[];
+ };
+}