checkout accessibility/category products
This commit is contained in:
@@ -3,6 +3,8 @@
|
||||
import { useCart } from "@/components/context/cartcontext";
|
||||
import Image from "next/image";
|
||||
import Link from "next/link";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { useState } from "react"; // اضافه شدن useState
|
||||
import {
|
||||
Trash2,
|
||||
ShoppingBag,
|
||||
@@ -11,14 +13,33 @@ import {
|
||||
Minus,
|
||||
ShieldCheck,
|
||||
Truck,
|
||||
CreditCard, ChevronRight, Check
|
||||
CreditCard
|
||||
} from "lucide-react";
|
||||
|
||||
// مسیر ایمپورت کامپوننت Notlogin را بر اساس ساختار پوشهبندی خود تنظیم کنید
|
||||
import NotLogin from "@/components/Notlogin";
|
||||
|
||||
export default function CartPage() {
|
||||
const { cart, clearCart, addToCart, decreaseQuantity } = useCart();
|
||||
const router = useRouter();
|
||||
|
||||
// استیت برای مدیریت نمایش مودال/کامپوننت لاگین نشدهها
|
||||
const [showNotLogin, setShowNotLogin] = useState(false);
|
||||
|
||||
// بررسی لاگین کاربر
|
||||
const handleCheckoutNavigation = () => {
|
||||
const token = localStorage.getItem('accessToken');
|
||||
if (token) {
|
||||
// اگر لاگین بود برود به چک اوت
|
||||
router.push('/checkout');
|
||||
} else {
|
||||
// اگر لاگین نبود، کامپوننت Notlogin نمایش داده شود
|
||||
setShowNotLogin(true);
|
||||
}
|
||||
};
|
||||
|
||||
// تبدیل رشته قیمت به عدد
|
||||
const parsePrice = (priceStr?: string | null) => {
|
||||
const parsePrice = (priceStr?: number | null) => {
|
||||
if (!priceStr) return 0;
|
||||
return Number(priceStr.toString().replace(/,/g, ''));
|
||||
};
|
||||
@@ -51,9 +72,16 @@ export default function CartPage() {
|
||||
|
||||
return (
|
||||
<main className="bg-gray-50/30 min-h-screen pb-20">
|
||||
{/* رندر کردن کامپوننت Notlogin به صورت شرطی */}
|
||||
{/* اگر نیاز است که کاربر بتواند آن را ببندد، پراپ onClose را به آن پاس بدهید */}
|
||||
{showNotLogin && (
|
||||
<NotLogin
|
||||
buttonText="بازگشت به سبد خرید"
|
||||
onClose={() => setShowNotLogin(false)} />
|
||||
)}
|
||||
|
||||
<div className="container mx-auto px-4 py-8 max-w-6xl">
|
||||
|
||||
{/* بخش هدر */}
|
||||
<div className="mb-10">
|
||||
<div className="flex items-center justify-between mb-8">
|
||||
<h1 className="text-xl md:text-3xl font-black text-gray-800 flex items-center gap-3">
|
||||
@@ -64,19 +92,13 @@ export default function CartPage() {
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
{/* بخش هدر و تایملاین */}
|
||||
<div className="mb-10">
|
||||
|
||||
{/* Breadcrumb (تایملاین اکتیو شده برای مرحله ۲) */}
|
||||
<div className="relative w-full max-w-2xl mx-auto px-2 sm:px-0 mb-12">
|
||||
{/* خط سراسری بکگراند */}
|
||||
<div className="absolute top-[20px] sm:top-[24px] left-[16.5%] right-[16.5%] h-[2px] bg-gray-200 z-0">
|
||||
{/* پر شدن خط مرحله دوم (۵۰ درصد پیشرفت) */}
|
||||
<div className="h-full bg-[#ffb900] w-[50%] transition-all duration-500 ease-in-out"></div>
|
||||
</div>
|
||||
|
||||
<div className="flex justify-between relative z-10">
|
||||
{/* مرحله 1 (تکمیل شده) */}
|
||||
<Link href="/cart" className="flex flex-col items-center w-1/3 group cursor-pointer">
|
||||
<div className=" w-10 h-10 sm:w-12 sm:h-12 bg-[#ffb900] text-[#1A2332] rounded-full flex items-center justify-center shadow-[0_0_15px_rgba(255,185,0,0.4)] mb-2 sm:mb-3 ring-[6px] ring-[#ffb900]/20 transition-all">
|
||||
<ShoppingBag className="w-5 h-5 sm:w-6 sm:h-6" strokeWidth={2} />
|
||||
@@ -84,16 +106,14 @@ export default function CartPage() {
|
||||
<span className="text-[10px] sm:text-sm font-bold text-[#1A2332] text-center">سبد خرید</span>
|
||||
</Link>
|
||||
|
||||
{/* مرحله 2 (اکتیو و فعلی) */}
|
||||
<Link href={'/checkout'} className="flex flex-col items-center w-1/3">
|
||||
{/* استفاده از ring زرد با opacity برای نشان دادن حالت اکتیو */}
|
||||
<div className="w-10 h-10 sm:w-12 sm:h-12 bg-white border-2 border-gray-200 text-gray-400 rounded-full flex items-center justify-center mb-2 sm:mb-3 ring-[6px] ring-[#f8fafc] sm:ring-[#f8fafc]">
|
||||
{/* کلیک روی آیکون اطلاعات ارسال */}
|
||||
<div onClick={handleCheckoutNavigation} className="flex flex-col items-center w-1/3 cursor-pointer group">
|
||||
<div className="w-10 h-10 sm:w-12 sm:h-12 bg-white border-2 border-gray-200 text-gray-400 rounded-full flex items-center justify-center mb-2 sm:mb-3 ring-[6px] ring-[#f8fafc] sm:ring-[#f8fafc] group-hover:border-[#ffb900] transition-colors">
|
||||
<Truck className="w-4 h-4 sm:w-5 sm:h-5" strokeWidth={2} />
|
||||
</div>
|
||||
<span className="text-[10px] sm:text-sm font-bold text-[#1A2332] text-center">اطلاعات ارسال</span>
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
{/* مرحله 3 (غیرفعال) */}
|
||||
<div className="flex flex-col items-center w-1/3">
|
||||
<div className="w-10 h-10 sm:w-12 sm:h-12 bg-white border-2 border-gray-200 text-gray-400 rounded-full flex items-center justify-center mb-2 sm:mb-3 ring-[6px] ring-[#f8fafc] sm:ring-[#f8fafc]">
|
||||
<CreditCard className="w-4 h-4 sm:w-5 sm:h-5" />
|
||||
@@ -106,8 +126,6 @@ export default function CartPage() {
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col lg:flex-row gap-6 lg:gap-8">
|
||||
|
||||
{/* بخش لیست محصولات */}
|
||||
<div className="flex-1">
|
||||
<div className="bg-white rounded-[1rem] p-4 md:p-8 shadow-sm ">
|
||||
<div className="flex justify-between items-center mb-6 pb-6 border-b border-gray-100">
|
||||
@@ -121,50 +139,25 @@ export default function CartPage() {
|
||||
<div className="flex flex-col gap-6">
|
||||
{cart.map((item) => {
|
||||
const itemTotal = parsePrice(item.price) * item.quantity;
|
||||
|
||||
return (
|
||||
<div key={item.id} className="group flex flex-col sm:flex-row gap-4 sm:gap-6 items-start sm:items-center border-b border-gray-50 pb-6 last:border-0 last:pb-0">
|
||||
|
||||
{/* تصویر محصول */}
|
||||
<div className="bg-gray-50/80 p-3 rounded-2xl border border-gray-100 shrink-0 relative group-hover:bg-white transition-colors duration-300 w-full sm:w-auto flex justify-center">
|
||||
<Image src={item.image} alt={item.title} width={100} height={100} className="object-contain w-24 h-24 drop-shadow-sm" />
|
||||
</div>
|
||||
|
||||
{/* اطلاعات محصول */}
|
||||
<div className="flex-1 w-full">
|
||||
<p className="text-xs font-medium text-blue-500 mb-1.5">{item.brand}</p>
|
||||
<h3 className="text-sm md:text-base font-bold text-gray-800 line-clamp-2 leading-tight mb-3 group-hover:text-blue-600 transition-colors">{item.title}</h3>
|
||||
|
||||
{/* ویژگیها (Badges) */}
|
||||
<div className="flex flex-wrap gap-2 text-[10px] md:text-xs font-medium text-gray-600">
|
||||
<span className="bg-gray-100/80 px-2.5 py-1 rounded-md" dir="ltr">L : {item.l}</span>
|
||||
<span className="bg-gray-100/80 px-2.5 py-1 rounded-md" dir="ltr">D : {item.d}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* قیمت و کنترلر */}
|
||||
<div className="flex sm:flex-col justify-between sm:justify-end items-center sm:items-end w-full sm:w-auto gap-4 shrink-0 mt-2 sm:mt-0">
|
||||
<span className="font-black text-base md:text-lg text-gray-900">
|
||||
{item.price ? `${itemTotal.toLocaleString('fa-IR')} ت` : 'استعلام'}
|
||||
</span>
|
||||
|
||||
{/* کنترلر تعداد طرح کپسولی */}
|
||||
<div className="flex items-center gap-1 bg-gray-50 border border-gray-200 rounded-full p-1 shadow-sm">
|
||||
<button
|
||||
onClick={() => addToCart(item)}
|
||||
className="w-7 h-7 md:w-8 md:h-8 flex items-center justify-center rounded-full bg-white text-gray-600 hover:text-green-600 hover:shadow-sm transition-all"
|
||||
>
|
||||
<button onClick={() => addToCart(item)} className="w-7 h-7 md:w-8 md:h-8 flex items-center justify-center rounded-full bg-white text-gray-600 hover:text-green-600 hover:shadow-sm transition-all">
|
||||
<Plus size={14} strokeWidth={2.5} />
|
||||
</button>
|
||||
|
||||
<span className="text-xs md:text-sm font-bold text-gray-800 w-6 text-center">
|
||||
{item.quantity}
|
||||
</span>
|
||||
|
||||
<button
|
||||
onClick={() => decreaseQuantity(item.id)}
|
||||
className="w-7 h-7 md:w-8 md:h-8 flex items-center justify-center rounded-full bg-white text-gray-600 hover:text-red-500 hover:shadow-sm transition-all"
|
||||
>
|
||||
<span className="text-xs md:text-sm font-bold text-gray-800 w-6 text-center">{item.quantity}</span>
|
||||
<button onClick={() => decreaseQuantity(item.id)} className="w-7 h-7 md:w-8 md:h-8 flex items-center justify-center rounded-full bg-white text-gray-600 hover:text-red-500 hover:shadow-sm transition-all">
|
||||
{item.quantity === 1 ? <Trash2 size={14} /> : <Minus size={14} strokeWidth={2.5} />}
|
||||
</button>
|
||||
</div>
|
||||
@@ -176,26 +169,20 @@ export default function CartPage() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* بخش صورتحساب (Sidebar) */}
|
||||
<div className="w-full lg:w-[340px] shrink-0">
|
||||
<div className="bg-white rounded-[1rem] p-4 md:p-8 shadow-sm sticky top-6">
|
||||
<h2 className="text-lg md:text-xl font-bold text-gray-800 mb-6">خلاصه صورتحساب</h2>
|
||||
|
||||
<div className="space-y-4 mb-6">
|
||||
<div className="flex justify-between items-center text-xs md:text-sm">
|
||||
<span className="text-gray-500">تعداد کالاها</span>
|
||||
<span className="font-bold text-gray-800">{totalItems} عدد</span>
|
||||
</div>
|
||||
|
||||
<div className="flex justify-between items-center text-xs md:text-sm">
|
||||
<span className="text-gray-500">هزینه ارسال</span>
|
||||
<span className="text-blue-600 font-bold bg-blue-50 px-2 py-1 rounded-md text-[10px] md:text-xs">در مرحله بعد</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* خطچین جداکننده */}
|
||||
<div className="w-full border-t-2 border-dashed border-gray-200 my-6"></div>
|
||||
|
||||
<div className="flex justify-between items-center mb-8">
|
||||
<span className="text-xs md:text-sm font-bold text-gray-600">مبلغ قابل پرداخت</span>
|
||||
<span className="font-black text-xl md:text-2xl text-[#ffb900] tracking-tight">
|
||||
@@ -204,22 +191,19 @@ export default function CartPage() {
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<Link href={'/checkout'} className="w-full bg-[#ffb900] hover:bg-[#e5a600] text-black py-3 md:py-4 rounded-xl font-bold text-base md:text-lg transition-all shadow-[0_4px_15px_rgba(255,185,0,0.2)] hover:shadow-[0_6px_20px_rgba(255,185,0,0.3)] flex justify-center items-center gap-2 mb-6">
|
||||
{/* دکمه تایید و ادامه */}
|
||||
<button
|
||||
onClick={handleCheckoutNavigation}
|
||||
className="w-full bg-[#ffb900] hover:bg-[#e5a600] text-black py-3 md:py-4 rounded-xl font-bold text-base md:text-lg transition-all shadow-[0_4px_15px_rgba(255,185,0,0.2)] hover:shadow-[0_6px_20px_rgba(255,185,0,0.3)] flex justify-center items-center gap-2 mb-6"
|
||||
>
|
||||
تایید و ادامه
|
||||
<ChevronLeft size={20} />
|
||||
</Link>
|
||||
</button>
|
||||
|
||||
{/* بجهای اعتماد (Trust Badges) */}
|
||||
<div className="flex items-center justify-center gap-2 md:gap-4 text-[10px] md:text-xs font-medium text-gray-400 bg-gray-50 py-3 rounded-xl border border-gray-100">
|
||||
<div className="flex items-center gap-1">
|
||||
<ShieldCheck size={14} className="text-green-500" />
|
||||
پرداخت امن
|
||||
</div>
|
||||
<div className="flex items-center gap-1"><ShieldCheck size={14} className="text-green-500" /> پرداخت امن</div>
|
||||
<div className="w-1 h-1 bg-gray-300 rounded-full"></div>
|
||||
<div className="flex items-center gap-1">
|
||||
<Truck size={14} className="text-blue-500" />
|
||||
ارسال سریع
|
||||
</div>
|
||||
<div className="flex items-center gap-1"><Truck size={14} className="text-blue-500" /> ارسال سریع</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,40 +1,61 @@
|
||||
import ProductCard from "@/components/productcard"; // 1. ایمپورت کردن کامپوننت کارت محصول
|
||||
import { getProductsByCategory } from "@/public/src/services/products/api";
|
||||
import { Product } from "@/public/src/types/product"; // بهتر است تایپ محصول را هم برای خوانایی ایمپورت کنید
|
||||
|
||||
export default async function CategoryPage({ params }:any) {
|
||||
|
||||
export default async function CategoryPage({ params }: any) {
|
||||
const { categoryName } = await params;
|
||||
|
||||
console.log("🔎 CategoryPage slug:", categoryName);
|
||||
// منطق دریافت دیتا از API بدون تغییر باقی میماند
|
||||
const categoryData = await getProductsByCategory(categoryName);
|
||||
|
||||
const products = await getProductsByCategory(categoryName);
|
||||
// مدیریت حالتی که محصولی یافت نشود
|
||||
if (!categoryData || !categoryData.items || categoryData.items.length === 0) {
|
||||
return (
|
||||
<div className="container mx-auto py-20 text-center">
|
||||
<h1 className="text-2xl font-bold text-gray-800">
|
||||
محصولی در دستهبندی «{decodeURIComponent(categoryName)}» یافت نشد.
|
||||
</h1>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const pageTitle = categoryData.items[0]?.primaryCategory?.name || decodeURIComponent(categoryName);
|
||||
|
||||
return (
|
||||
<div className="p-8">
|
||||
|
||||
<h1 className="text-xl font-bold mb-6">
|
||||
دستهبندی: {categoryName}
|
||||
</h1>
|
||||
|
||||
<div className="grid grid-cols-2 md:grid-cols-4 gap-6">
|
||||
|
||||
{products.items.map((product:any) => (
|
||||
<div key={product.id} className="border p-4 rounded-xl">
|
||||
|
||||
<div className="h-32 bg-gray-100 rounded mb-3" />
|
||||
|
||||
<h3 className="text-sm font-medium">
|
||||
{product.title}
|
||||
</h3>
|
||||
|
||||
<p className="text-xs text-gray-500">
|
||||
{product.brand}
|
||||
</p>
|
||||
|
||||
<main className="bg-gray-50 min-h-screen py-10">
|
||||
<div className="max-w-7xl mx-auto px-4">
|
||||
{/* عنوان و تعداد محصولات */}
|
||||
<div className="mb-8">
|
||||
<h1 className="text-2xl font-bold text-gray-800 flex items-center gap-2">
|
||||
{pageTitle}
|
||||
<span className="text-sm font-normal text-gray-500 bg-gray-200 px-3 py-1 rounded-full">
|
||||
{categoryData.meta.total} کالا
|
||||
</span>
|
||||
</h1>
|
||||
<div className="relative mt-3 h-[2px] bg-gray-200 w-full">
|
||||
<div className="absolute right-0 top-0 h-[2px] w-24 bg-yellow-500"></div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* 2. جایگزینی div ساده با کامپوننت ProductCard در حلقه */}
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-6">
|
||||
{categoryData.items.map((apiProduct: any) => {
|
||||
// 3. تبدیل دادههای API به فرمت مورد انتظار کامپوننت ProductCard
|
||||
const productForCard: Product = {
|
||||
id: apiProduct.id,
|
||||
title: apiProduct.title,
|
||||
brand: apiProduct.brand,
|
||||
slug: apiProduct.slug,
|
||||
price: apiProduct.calculated_price, // تبدیل نام فیلد
|
||||
stock: apiProduct.stock,
|
||||
image: apiProduct.mainImageUrl || "/placeholder.png", // تبدیل نام فیلد و افزودن جایگزین
|
||||
attributes: apiProduct.attributes,
|
||||
};
|
||||
|
||||
return <ProductCard key={productForCard.id} product={productForCard} />;
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2,44 +2,78 @@
|
||||
|
||||
import { useCart } from "@/components/context/cartcontext";
|
||||
import Link from "next/link";
|
||||
import { useState } from "react";
|
||||
import { useState, useEffect } from "react";
|
||||
import {
|
||||
ShoppingBag,
|
||||
ChevronLeft,
|
||||
ChevronRight,
|
||||
Truck,
|
||||
CreditCard,
|
||||
Check,
|
||||
MapPin,
|
||||
User,
|
||||
Phone,
|
||||
Mail
|
||||
Lock // آیکون قفل برای صفحه لاگین نشده
|
||||
} from "lucide-react";
|
||||
|
||||
export default function CheckoutPage() {
|
||||
const { cart } = useCart();
|
||||
|
||||
// استیت برای روش ارسال (صرفا جهت نمایش UI)
|
||||
const [shippingMethod, setShippingMethod] = useState('post');
|
||||
const [isAuthenticated, setIsAuthenticated] = useState(false);
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
|
||||
useEffect(() => {
|
||||
const token = localStorage.getItem('accessToken');
|
||||
if (token) {
|
||||
setIsAuthenticated(true);
|
||||
}
|
||||
setIsLoading(false); // پایان بررسی وضعیت
|
||||
}, []);
|
||||
|
||||
// محاسبه قیمت کل و تعداد
|
||||
const parsePrice = (priceStr?: string | null) => {
|
||||
const parsePrice = (priceStr?: number | null) => {
|
||||
if (!priceStr) return 0;
|
||||
return Number(priceStr.toString().replace(/,/g, ''));
|
||||
};
|
||||
|
||||
const totalPrice = cart.reduce((total, item) => total + (parsePrice(item.price) * item.quantity), 0);
|
||||
const totalItems = cart.reduce((total, item) => total + item.quantity, 0);
|
||||
|
||||
// هزینه ارسال فرضی
|
||||
const shippingCost = shippingMethod === 'post' ? 45000 : 75000;
|
||||
const finalPrice = totalPrice + shippingCost;
|
||||
|
||||
// حالت در حال بررسی توکن
|
||||
if (isLoading) {
|
||||
return (
|
||||
<div className="min-h-screen flex items-center justify-center bg-gray-50/30">
|
||||
<div className="animate-spin rounded-full h-12 w-12 border-b-2 border-[#ffb900]"></div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// اگر کاربر لاگین نبود، این صفحه به جای محتوای چکاوت نمایش داده میشود
|
||||
if (!isAuthenticated) {
|
||||
return (
|
||||
<div className="min-h-screen bg-gray-50/30 flex flex-col items-center justify-center p-6" dir="rtl">
|
||||
<div className="bg-white p-12 rounded-[2rem] shadow-sm border border-gray-100 flex flex-col items-center max-w-md w-full text-center">
|
||||
<div className="bg-gray-100 w-24 h-24 rounded-full flex items-center justify-center mb-6">
|
||||
<Lock size={40} className="text-gray-400" />
|
||||
</div>
|
||||
<h2 className="text-xl font-bold text-gray-800 mb-3">دسترسی محدود</h2>
|
||||
<p className="text-gray-500 mb-8 leading-relaxed text-sm">
|
||||
برای ثبت نهایی سفارش و مشاهده این صفحه، باید ابتدا وارد حساب کاربری خود شوید یا ثبتنام کنید.
|
||||
</p>
|
||||
<Link href="/cart" className="w-full bg-[#ffb900] hover:bg-[#e5a600] text-[#1A2332] font-bold py-3 rounded-xl transition-all flex items-center justify-center gap-2">
|
||||
<ChevronRight size={18} />
|
||||
بازگشت به سبد خرید
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// اگر لاگین بود، محتوای اصلی رندر میشود (کد اصلی شما در اینجا قرار میگیرد)
|
||||
return (
|
||||
<main className="bg-gray-50/30 min-h-screen pb-20" dir="rtl">
|
||||
<div className="container mx-auto px-4 py-8 max-w-6xl">
|
||||
|
||||
{/* بخش هدر و تایملاین */}
|
||||
<div className="mb-10">
|
||||
<div className="flex items-center justify-between mb-8">
|
||||
<h1 className="text-xl md:text-3xl font-black text-[#1A2332]">
|
||||
@@ -51,16 +85,12 @@ export default function CheckoutPage() {
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
{/* Breadcrumb (تایملاین اکتیو شده برای مرحله ۲) */}
|
||||
<div className="relative w-full max-w-2xl mx-auto px-2 sm:px-0 mb-12">
|
||||
{/* خط سراسری بکگراند */}
|
||||
<div className="absolute top-[20px] sm:top-[24px] left-[16.5%] right-[16.5%] h-[2px] bg-gray-200 z-0">
|
||||
{/* پر شدن خط مرحله دوم (۵۰ درصد پیشرفت) */}
|
||||
<div className="h-full bg-[#ffb900] w-[50%] transition-all duration-500 ease-in-out"></div>
|
||||
</div>
|
||||
|
||||
<div className="flex justify-between relative z-10">
|
||||
{/* مرحله 1 (تکمیل شده) */}
|
||||
<Link href="/cart" className="flex flex-col items-center w-1/3 group cursor-pointer">
|
||||
<div className="w-10 h-10 sm:w-12 sm:h-12 bg-[#ffb900] text-[#1A2332] rounded-full flex items-center justify-center shadow-md mb-2 sm:mb-3 ring-[6px] ring-[#f8fafc] sm:ring-[#f8fafc] transition-transform group-hover:scale-110">
|
||||
<ShoppingBag className="w-5 h-5 sm:w-6 sm:h-6" strokeWidth={2} />
|
||||
@@ -68,16 +98,13 @@ export default function CheckoutPage() {
|
||||
<span className="text-[10px] sm:text-sm font-bold text-[#1A2332] text-center">سبد خرید</span>
|
||||
</Link>
|
||||
|
||||
{/* مرحله 2 (اکتیو و فعلی) */}
|
||||
<div className="flex flex-col items-center w-1/3">
|
||||
{/* استفاده از ring زرد با opacity برای نشان دادن حالت اکتیو */}
|
||||
<div className="w-10 h-10 sm:w-12 sm:h-12 bg-[#ffb900] text-[#1A2332] rounded-full flex items-center justify-center shadow-[0_0_15px_rgba(255,185,0,0.4)] mb-2 sm:mb-3 ring-[6px] ring-[#ffb900]/20 transition-all">
|
||||
<Truck className="w-4 h-4 sm:w-5 sm:h-5" strokeWidth={2} />
|
||||
</div>
|
||||
<span className="text-[10px] sm:text-sm font-bold text-[#1A2332] text-center">اطلاعات ارسال</span>
|
||||
</div>
|
||||
|
||||
{/* مرحله 3 (غیرفعال) */}
|
||||
<div className="flex flex-col items-center w-1/3">
|
||||
<div className="w-10 h-10 sm:w-12 sm:h-12 bg-white border-2 border-gray-200 text-gray-400 rounded-full flex items-center justify-center mb-2 sm:mb-3 ring-[6px] ring-[#f8fafc] sm:ring-[#f8fafc]">
|
||||
<CreditCard className="w-4 h-4 sm:w-5 sm:h-5" />
|
||||
@@ -89,11 +116,7 @@ export default function CheckoutPage() {
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col lg:flex-row gap-6 lg:gap-8">
|
||||
|
||||
{/* بخش فرم اطلاعات */}
|
||||
<div className="flex-1 space-y-6">
|
||||
|
||||
{/* فرم مشخصات گیرنده */}
|
||||
<div className="bg-white rounded-[1rem] p-6 md:p-8 shadow-sm ">
|
||||
<div className="flex items-center gap-3 mb-6 pb-4 border-b border-gray-100">
|
||||
<div className="bg-[#1A2332]/5 p-2 rounded-lg text-[#1A2332]">
|
||||
@@ -101,30 +124,18 @@ export default function CheckoutPage() {
|
||||
</div>
|
||||
<h2 className="text-base md:text-lg font-bold text-[#1A2332]">مشخصات گیرنده</h2>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-5">
|
||||
<div className="space-y-2">
|
||||
<label className="text-sm font-medium text-gray-600 block">نام و نام خانوادگی</label>
|
||||
<input
|
||||
type="text"
|
||||
placeholder="مثال: علی رضایی"
|
||||
className="w-full bg-gray-50 border border-gray-200 text-[#1A2332] rounded-xl px-4 py-3 outline-none focus:ring-2 focus:ring-[#ffb900]/40 focus:border-[#ffb900] transition-all placeholder:text-gray-400 placeholder:text-[13px]"
|
||||
/>
|
||||
<input type="text" placeholder="مثال: علی رضایی" className="w-full bg-gray-50 border border-gray-200 text-[#1A2332] rounded-xl px-4 py-3 outline-none focus:ring-2 focus:ring-[#ffb900]/40 focus:border-[#ffb900] transition-all placeholder:text-gray-400 placeholder:text-[13px]" />
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<label className="text-sm font-medium text-gray-600 block">شماره موبایل</label>
|
||||
<div className="relative">
|
||||
<input
|
||||
type="tel"
|
||||
placeholder="09123456789"
|
||||
className="w-full text-right bg-gray-50 border border-gray-200 text-[#1A2332] rounded-xl pl-4 pr-4 py-3 outline-none focus:ring-2 focus:ring-[#ffb900]/40 focus:border-[#ffb900] transition-all placeholder:text-gray-400 placeholder:text-[13px]"
|
||||
/>
|
||||
</div>
|
||||
<input type="tel" placeholder="09123456789" className="w-full text-right bg-gray-50 border border-gray-200 text-[#1A2332] rounded-xl pl-4 pr-4 py-3 outline-none focus:ring-2 focus:ring-[#ffb900]/40 focus:border-[#ffb900] transition-all placeholder:text-gray-400 placeholder:text-[13px]" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* فرم آدرس */}
|
||||
<div className="bg-white rounded-[1rem] p-6 md:p-8 shadow-sm">
|
||||
<div className="flex items-center gap-3 mb-6 pb-4 border-b border-gray-100">
|
||||
<div className="bg-[#1A2332]/5 p-2 rounded-lg text-[#1A2332]">
|
||||
@@ -132,7 +143,6 @@ export default function CheckoutPage() {
|
||||
</div>
|
||||
<h2 className="text-base md:text-lg font-bold text-[#1A2332]">آدرس پستی</h2>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-5 mb-5">
|
||||
<div className="space-y-2">
|
||||
<label className="text-sm font-medium text-gray-600 block">استان</label>
|
||||
@@ -151,63 +161,39 @@ export default function CheckoutPage() {
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="space-y-2 mb-5">
|
||||
<label className="text-sm font-medium text-gray-600 block">آدرس دقیق پستی</label>
|
||||
<textarea
|
||||
rows={3}
|
||||
placeholder="خیابان، کوچه، پلاک، واحد..."
|
||||
className="w-full text-[13px] bg-gray-50 border border-gray-200 text-[#1A2332] rounded-xl px-4 py-3 outline-none focus:ring-2 focus:ring-[#ffb900]/40 focus:border-[#ffb900] transition-all placeholder:text-gray-400 resize-none"
|
||||
/>
|
||||
<textarea rows={3} placeholder="خیابان، کوچه، پلاک، واحد..." className="w-full text-[13px] bg-gray-50 border border-gray-200 text-[#1A2332] rounded-xl px-4 py-3 outline-none focus:ring-2 focus:ring-[#ffb900]/40 focus:border-[#ffb900] transition-all placeholder:text-gray-400 resize-none" />
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-5 mb-5">
|
||||
<div className=" space-y-2">
|
||||
<label className="text-sm font-medium text-gray-600 block">کد پستی (۱۰ رقمی)</label>
|
||||
<input
|
||||
type="text"
|
||||
placeholder="1234567890"
|
||||
className="w-full bg-gray-50 border border-gray-200 text-[#1A2332] rounded-xl px-4 py-3 outline-none focus:ring-2 focus:ring-[#ffb900]/40 focus:border-[#ffb900] transition-all placeholder:text-gray-400 placeholder:text-[13px]"
|
||||
/>
|
||||
<input type="text" placeholder="1234567890" className="w-full bg-gray-50 border border-gray-200 text-[#1A2332] rounded-xl px-4 py-3 outline-none focus:ring-2 focus:ring-[#ffb900]/40 focus:border-[#ffb900] transition-all placeholder:text-gray-400 placeholder:text-[13px]" />
|
||||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
<label className="text-sm font-medium text-gray-600 block">ایمیل</label>
|
||||
<input
|
||||
type="email"
|
||||
placeholder="test@email.com"
|
||||
className="w-full bg-gray-50 border border-gray-200 text-[#1A2332] rounded-xl px-4 py-3 outline-none focus:ring-2 focus:ring-[#ffb900]/40 focus:border-[#ffb900] transition-all placeholder:text-gray-400 placeholder:text-[13px]"
|
||||
/>
|
||||
<input type="email" placeholder="test@email.com" className="w-full bg-gray-50 border border-gray-200 text-[#1A2332] rounded-xl px-4 py-3 outline-none focus:ring-2 focus:ring-[#ffb900]/40 focus:border-[#ffb900] transition-all placeholder:text-gray-400 placeholder:text-[13px]" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
{/* بخش صورتحساب (Sidebar) */}
|
||||
<div className="w-full lg:w-[400px] shrink-0">
|
||||
<div className="bg-white rounded-[1rem] p-6 md:p-8 shadow-sm sticky top-6">
|
||||
<h2 className="text-lg md:text-xl font-bold text-[#1A2332] mb-6">خلاصه سفارش</h2>
|
||||
|
||||
<div className="space-y-4 mb-6">
|
||||
<div className="flex justify-between items-center text-xs md:text-sm">
|
||||
<span className="text-gray-500">مبلغ کالاها ({totalItems})</span>
|
||||
<span className="font-bold text-[#1A2332]">{totalPrice > 0 ? totalPrice.toLocaleString('fa-IR') : '۰'} <span className="text-[10px] font-normal text-gray-500">تومان</span></span>
|
||||
</div>
|
||||
|
||||
<div className="flex justify-between items-center text-xs md:text-sm">
|
||||
<span className="text-gray-500">هزینه ارسال</span>
|
||||
<span className="font-bold text-[#1A2332]">{shippingCost.toLocaleString('fa-IR')} <span className="text-[10px] font-normal text-gray-500">تومان</span></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* خطچین جداکننده */}
|
||||
<div className="w-full border-t-2 border-dashed border-gray-100 my-6"></div>
|
||||
|
||||
{/* انتخاب روش ارسال */}
|
||||
<div className="bg-white rounded-[1rem] pt-4 pb-4">
|
||||
<div className="flex items-center gap-3 mb-6 pb-4 ">
|
||||
<div className="bg-[#1A2332]/5 p-2 rounded-lg text-[#1A2332]">
|
||||
@@ -215,9 +201,7 @@ export default function CheckoutPage() {
|
||||
</div>
|
||||
<h2 className="text-base md:text-lg font-bold text-[#1A2332]">نحوه ارسال</h2>
|
||||
</div>
|
||||
|
||||
<div className="space-y-3">
|
||||
{/* گزینه پست */}
|
||||
<label className={`flex items-center justify-between p-4 rounded-xl border-1 cursor-pointer transition-all ${shippingMethod === 'post' ? 'border-[#ffb900] bg-[#ffb900]/3' : 'border-gray-100 hover:border-gray-200 bg-white'}`}>
|
||||
<div className="flex items-center gap-3">
|
||||
<div className={`w-5 h-5 rounded-full border-1 flex items-center justify-center ${shippingMethod === 'post' ? 'border-[#ffb900]' : 'border-gray-300'}`}>
|
||||
@@ -229,17 +213,8 @@ export default function CheckoutPage() {
|
||||
</div>
|
||||
</div>
|
||||
<div className="font-bold text-[#1A2332]">۴۵,۰۰۰ <span className="text-xs font-normal text-gray-500">تومان</span></div>
|
||||
<input
|
||||
type="radio"
|
||||
name="shipping"
|
||||
value="post"
|
||||
className="hidden"
|
||||
checked={shippingMethod === 'post'}
|
||||
onChange={() => setShippingMethod('post')}
|
||||
/>
|
||||
<input type="radio" name="shipping" value="post" className="hidden" checked={shippingMethod === 'post'} onChange={() => setShippingMethod('post')} />
|
||||
</label>
|
||||
|
||||
{/* گزینه تیپاکس */}
|
||||
<label className={`flex items-center justify-between p-4 rounded-xl border-1 cursor-pointer transition-all ${shippingMethod === 'tipax' ? 'border-[#ffb900] bg-[#ffb900]/3' : 'border-gray-100 hover:border-gray-200 bg-white'}`}>
|
||||
<div className="flex items-center gap-3">
|
||||
<div className={`w-5 h-5 rounded-full border-1 flex items-center justify-center ${shippingMethod === 'tipax' ? 'border-[#ffb900]' : 'border-gray-300'}`}>
|
||||
@@ -251,18 +226,11 @@ export default function CheckoutPage() {
|
||||
</div>
|
||||
</div>
|
||||
<div className="font-bold text-[#1A2332]">۷۵,۰۰۰ <span className="text-xs font-normal text-gray-500">تومان</span></div>
|
||||
<input
|
||||
type="radio"
|
||||
name="shipping"
|
||||
value="tipax"
|
||||
className="hidden"
|
||||
checked={shippingMethod === 'tipax'}
|
||||
onChange={() => setShippingMethod('tipax')}
|
||||
/>
|
||||
<input type="radio" name="shipping" value="tipax" className="hidden" checked={shippingMethod === 'tipax'} onChange={() => setShippingMethod('tipax')} />
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
{/* خطچین جداکننده */}
|
||||
|
||||
<div className="w-full border-t-2 border-dashed border-gray-100 my-6"></div>
|
||||
|
||||
<div className="flex justify-between items-center mb-8">
|
||||
|
||||
@@ -24,6 +24,7 @@ import {
|
||||
TicketStatus,
|
||||
updateAdminTicket,
|
||||
} from "@/public/src/services/tickets/api";
|
||||
import NotLogin from '@/components/Notlogin';
|
||||
|
||||
const sampleOrders = [
|
||||
{ id: "PR-10452", status: "در حال پردازش", statusColor: "amber", total: "500,000", regDate: "15 دی 1404", deliveryDate: "20 دی 1404", delivered: false },
|
||||
@@ -414,19 +415,7 @@ export default function DashboardPage() {
|
||||
if (!authorized) {
|
||||
return (
|
||||
<div className="min-h-screen flex items-center justify-center bg-gray-50 px-4" dir="rtl">
|
||||
<div className="bg-white shadow-xl rounded-2xl p-10 max-w-md w-full text-center border border-gray-100">
|
||||
<div className="flex justify-center mb-6">
|
||||
<div className="bg-red-100 p-4 rounded-full">
|
||||
<ShieldX className="w-10 h-10 text-red-600" />
|
||||
</div>
|
||||
</div>
|
||||
<h1 className="text-2xl font-bold text-gray-800 mb-2">دسترسی غیرمجاز</h1>
|
||||
<p className="text-gray-500 text-sm leading-relaxed mb-6">برای مشاهده داشبورد باید ابتدا وارد حساب کاربری خود شوید.</p>
|
||||
<button onClick={() => router.push("/")} className="flex mx-auto cursor-pointer items-center gap-2 bg-gray-900 text-white px-4 py-2 rounded-lg text-sm hover:bg-black transition">
|
||||
<Home className="w-4 h-4" />
|
||||
بازگشت به صفحه اصلی
|
||||
</button>
|
||||
</div>
|
||||
<NotLogin/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
141
app/page.tsx
141
app/page.tsx
@@ -1,5 +1,5 @@
|
||||
"use client";
|
||||
import { useState } from "react";
|
||||
import { useState, useEffect } from "react";
|
||||
import {
|
||||
Headphones, FileText, Truck, ShieldCheck, CircleDashed,
|
||||
Disc,
|
||||
@@ -11,32 +11,48 @@ import {
|
||||
import ProductCard from "@/components/productcard";
|
||||
import ArticleCard from "@/components/articlecard";
|
||||
import FAQItem from "@/components/faq";
|
||||
import { products } from "@/lib/data";
|
||||
import { articles } from "@/lib/data";
|
||||
import Link from "next/link";
|
||||
import { useCategories } from "@/components/context/categoryprovider";
|
||||
import { getProducts } from "@/public/src/services/products/api";
|
||||
|
||||
|
||||
|
||||
|
||||
export default async function Home() {
|
||||
export default function Home() {
|
||||
const [activeTab, setActiveTab] = useState(0);
|
||||
|
||||
const [products, setProducts] = useState<any[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
|
||||
const brands = ["NTN", "KOYO", "NACHI", "TIMKEN", "FAG", "SKF"];
|
||||
const latestArticles = articles.slice(-4);
|
||||
const { rootCategories } = useCategories();
|
||||
const data = await getProducts(1, 20);
|
||||
|
||||
const products = data.items.map((p: any) => ({
|
||||
id: p.id,
|
||||
title: p.title,
|
||||
brand: p.brand,
|
||||
slug: p.slug,
|
||||
price: p.calculated_price,
|
||||
stock: p.stock,
|
||||
image: p.mainImageUrl || "/placeholder.png",
|
||||
attributes: p.attributes
|
||||
}));
|
||||
useEffect(() => {
|
||||
const fetchInitialProducts = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
const data = await getProducts(1, 20);
|
||||
|
||||
const formattedProducts = data.items.map((p: any) => ({
|
||||
id: p.id,
|
||||
title: p.title,
|
||||
brand: p.brand,
|
||||
slug: p.slug,
|
||||
price: p.calculated_price,
|
||||
stock: p.stock,
|
||||
image: p.mainImageUrl || "/placeholder.png",
|
||||
attributes: p.attributes
|
||||
}));
|
||||
|
||||
setProducts(formattedProducts);
|
||||
} catch (error) {
|
||||
console.error("Error fetching products:", error);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
fetchInitialProducts();
|
||||
}, []);
|
||||
|
||||
const features = [
|
||||
{
|
||||
@@ -61,10 +77,8 @@ export default async function Home() {
|
||||
},
|
||||
];
|
||||
|
||||
|
||||
const tabs = ["پرفروشترینها", "تخفیفدار", "جدیدترینها"];
|
||||
|
||||
|
||||
const faqs = [
|
||||
{
|
||||
question: "آیا تمامی قطعات دارای ضمانت اصالت هستند؟",
|
||||
@@ -83,7 +97,6 @@ export default async function Home() {
|
||||
},
|
||||
];
|
||||
|
||||
|
||||
const categoryIcons = [
|
||||
CircleDashed,
|
||||
Disc,
|
||||
@@ -98,35 +111,24 @@ export default async function Home() {
|
||||
{/* hero section */}
|
||||
<section className="bg-[#0b1d36] text-white py-16">
|
||||
<div className="container mx-auto text-center">
|
||||
{/* Badge */}
|
||||
<div className="inline-block border mb-4 px-3 py-2 bg-[#443A27] text-[#ffb900] text-xs rounded-full">
|
||||
تأمینکننده برتر قطعات
|
||||
</div>
|
||||
|
||||
{/* Heading */}
|
||||
<h1 className=" leading-snug md:text-5xl font-extrabold mb-4">
|
||||
تخصصیترین مرجع
|
||||
<br></br>
|
||||
بلبرینگ و قطعات صنعتی
|
||||
</h1>
|
||||
|
||||
{/* Subtitle */}
|
||||
<p className=" text-[15px] text-[#9a9a9a] mb-10">
|
||||
|
||||
دسترسی به بیش از 10.000 قطعه با ضمانت اصالت کالا
|
||||
</p>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</section>
|
||||
|
||||
{/* hero search */}
|
||||
<div className="w-full px-4">
|
||||
<div className=" max-w-[70.5rem] mx-auto px-4 bg-white -mt-20 text-gray-800 rounded-2xl shadow-lg p-6 flex flex-col md:flex-row gap-4 md:gap-2 items-center justify-between">
|
||||
{/* Filters */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-6 w-full gap-4 justify-between">
|
||||
|
||||
<div className="flex flex-col md:col-span-2">
|
||||
<label htmlFor="partNumber" className="text-xs mb-3 text-black font-bold">
|
||||
شماره فنی (Part Number)
|
||||
@@ -138,7 +140,6 @@ export default async function Home() {
|
||||
className="px-4 py-3 bg-[#f9f9f9] rounded-xl border border-gray-300 text-sm focus:outline-none focus:ring-2 focus:ring-[#e6d3a3]"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col">
|
||||
<label htmlFor="innerDiameter" className="text-xs mb-3 text-black font-bold">
|
||||
قطر داخل
|
||||
@@ -150,7 +151,6 @@ export default async function Home() {
|
||||
className="px-4 bg-[#f9f9f9] py-3 rounded-xl border border-gray-300 text-sm focus:outline-none focus:ring-2 focus:ring-[#e6d3a3]"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col">
|
||||
<label htmlFor="outerDiameter" className="text-xs mb-3 text-black font-bold">
|
||||
قطر خارج
|
||||
@@ -162,7 +162,6 @@ export default async function Home() {
|
||||
className="px-4 bg-[#f9f9f9] py-3 rounded-xl border border-gray-300 text-sm focus:outline-none focus:ring-2 focus:ring-[#e6d3a3]"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col">
|
||||
<label htmlFor="thickness" className="text-xs mb-3 text-black font-bold">
|
||||
ضخامت
|
||||
@@ -174,17 +173,11 @@ export default async function Home() {
|
||||
className="px-4 bg-[#f9f9f9] py-3 rounded-xl border border-gray-300 text-sm focus:outline-none focus:ring-2 focus:ring-[#e6d3a3]"
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
||||
{/* Button */}
|
||||
<button
|
||||
className="mt-6 rounded-xl border-2 md:w-auto md:h-auto w-[100px] h-[48px] border-[#e6d3a3] bg-[#ffb900] text-black font-semibold text-xs transition-all hover:bg-[#da9800]">
|
||||
جستجوی قطعه
|
||||
</button>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -201,7 +194,6 @@ export default async function Home() {
|
||||
<div className="p-3 bg-gray-100 rounded-lg">
|
||||
<Icon size={24} className="text-gray-700" />
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h3 className="font-semibold text-gray-800 text-sm">
|
||||
{item.title}
|
||||
@@ -217,30 +209,19 @@ export default async function Home() {
|
||||
{/* categories card */}
|
||||
<section className="w-full py-12 bg-gray-50">
|
||||
<div className="max-w-6xl mx-auto px-4">
|
||||
|
||||
{/* title */}
|
||||
<div className="w-full mb-10">
|
||||
<div className="flex">
|
||||
<h2 className="text-xl font-bold text-gray-800">
|
||||
دسته بندی های بلبرینگ
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
{/* line */}
|
||||
<div className="relative mt-3 h-[2px] bg-gray-200 w-full">
|
||||
<div className="absolute right-0 top-0 h-[2px] w-24 bg-yellow-500"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
{/* cards */}
|
||||
<div className="grid justify-center grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5 gap-6">
|
||||
|
||||
|
||||
|
||||
{rootCategories.map((cat, index) => {
|
||||
const Icon = categoryIcons[index % categoryIcons.length];
|
||||
|
||||
return (
|
||||
<Link
|
||||
key={cat.id}
|
||||
@@ -249,11 +230,9 @@ export default async function Home() {
|
||||
>
|
||||
<Icon size={34} strokeWidth={1} className="text-gray-400 mb-3 group-hover:text-blue-500 transition-colors" />
|
||||
<span className="text-sm font-medium text-gray-700 group-hover:text-blue-600">{cat.name}</span>
|
||||
|
||||
</Link>
|
||||
);
|
||||
})}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
@@ -262,15 +241,12 @@ export default async function Home() {
|
||||
<section className="py-12">
|
||||
<div className="max-w-6xl mx-auto px-4">
|
||||
<div className="items-center justify-between mb-8">
|
||||
|
||||
{/* title */}
|
||||
<div className="flex flex-wrap md:flex-nowrap justify-between w-full mb-4">
|
||||
<div className="flex">
|
||||
<h3 className="text-xl font-bold text-gray-800">
|
||||
پیشنهاد ویژه صنعتی
|
||||
</h3>
|
||||
</div>
|
||||
{/* tabs */}
|
||||
<div className="flex mt-6 mb-4 md:mt-0 md:mb-0 gap-8 text-sm">
|
||||
{tabs.map((tab, index) => (
|
||||
<button
|
||||
@@ -287,114 +263,93 @@ export default async function Home() {
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* line */}
|
||||
<div className="relative mt-3 h-[2px] bg-gray-200 w-full">
|
||||
<div className="absolute right-0 top-0 h-[2px] w-24 bg-yellow-500"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-6">
|
||||
{products.slice(-4).map((product: any) => (
|
||||
<ProductCard key={product.id} product={product} />
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* 4. نمایش وضعیت لودینگ یا لیست محصولات */}
|
||||
{loading ? (
|
||||
<div className="flex justify-center py-10">
|
||||
<p>در حال بارگذاری محصولات...</p>
|
||||
</div>
|
||||
) : (
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-6">
|
||||
{products.slice(-4).map((product: any) => (
|
||||
<ProductCard key={product.id} product={product} />
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
{/* blog */}
|
||||
<section className="py-16 bg-white">
|
||||
<div className="max-w-6xl mx-auto px-4">
|
||||
|
||||
{/* header */}
|
||||
<div className="mb-8">
|
||||
<div className="flex justify-between w-full mb-4">
|
||||
<h3 className="text-xl font-bold text-gray-800">
|
||||
مجله فنی و مهندسی
|
||||
</h3>
|
||||
|
||||
<a className="text-[#ffb900] text-sm cursor-pointer">
|
||||
مشاهده آرشیو
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div className="relative h-[2px] bg-gray-200 w-full">
|
||||
<div className="absolute right-0 top-0 h-[2px] w-24 bg-yellow-500" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* grid */}
|
||||
<div className="grid md:grid-cols-3 lg:grid-cols-4 gap-6">
|
||||
{latestArticles.map((article, i) => (
|
||||
<ArticleCard key={i} article={article} />
|
||||
))}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
{/* search */}
|
||||
<section className="py-16">
|
||||
<div className="max-w-6xl mx-auto px-4">
|
||||
|
||||
<div className="bg-[#0b1e3b] rounded-2xl p-10 flex flex-col lg:flex-row items-center justify-between gap-8 relative overflow-hidden">
|
||||
|
||||
{/* right content */}
|
||||
<div className="text-right text-white max-w-md">
|
||||
<h2 className="text-2xl font-bold text-amber-400 mb-3">
|
||||
قطعه خاصی مد نظرتان است؟
|
||||
</h2>
|
||||
|
||||
<p className="text-sm text-gray-300 leading-7">
|
||||
تیم فنی ما آماده است تا قطعات صنعتی مورد نیاز شما را در سریعترین زمان
|
||||
ممکن تأمین کند. مشخصات قطعه را وارد کنید.
|
||||
</p>
|
||||
|
||||
<div className="flex items-center gap-2 mt-3 text-sm text-gray-300">
|
||||
<MessageCircleCheckIcon size={16} />
|
||||
پاسخگویی سریع در واتساپ
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* search box */}
|
||||
<div className="bg-[#2a3548] p-4 flex-wrap rounded-xl flex items-center gap-3 w-full max-w-xl">
|
||||
|
||||
<input
|
||||
type="text"
|
||||
placeholder="شماره تماس"
|
||||
className="flex-1 bg-gray-200 rounded-lg md:px-4 px-0 py-3 outline-none text-xs"
|
||||
/>
|
||||
|
||||
<input
|
||||
type="text"
|
||||
placeholder=" کد فنی قطعه"
|
||||
className="flex-1 bg-gray-200 rounded-lg px-0 md:px-4 py-3 outline-none text-xs"
|
||||
/>
|
||||
|
||||
<button className="bg-amber-500 hover:bg-amber-600 text-black px-3 py-3 rounded-lg flex items-center gap-2 text-xs cursor-pointer">
|
||||
ثبت درخواست
|
||||
</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* faq */}
|
||||
<section className="py-6">
|
||||
|
||||
<div className="max-w-3xl mx-auto px-4">
|
||||
|
||||
<h2 className="text-center text-xl font-bold mb-10">
|
||||
سوالات پرتکرار مشتریان
|
||||
</h2>
|
||||
|
||||
{/* faq list */}
|
||||
<div className="space-y-4">
|
||||
{faqs.map((faq, index) => (
|
||||
<FAQItem
|
||||
@@ -404,19 +359,15 @@ export default async function Home() {
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</section>
|
||||
|
||||
{/* brands */}
|
||||
<section className="w-full py-20 px-6">
|
||||
<div className="max-w-6xl mx-auto text-center">
|
||||
|
||||
<h2 className="text-gray-500 text-sm font-semibold mb-10">
|
||||
تامین کننده برندهای معتبر جهان
|
||||
</h2>
|
||||
|
||||
<div className="flex flex-wrap justify-center items-center gap-8">
|
||||
{brands.map((brand) => (
|
||||
<div
|
||||
@@ -429,11 +380,9 @@ export default async function Home() {
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ export default async function ProductsPage() {
|
||||
}));
|
||||
|
||||
return (
|
||||
<div className="container mx-auto p-4">
|
||||
<div className="container mx-auto px-4 max-w-6xl">
|
||||
<h1 className="text-2xl font-bold mb-6">همه محصولات</h1>
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user