Files
parsshop/app/cart/page.tsx
2026-03-27 22:48:14 +03:30

233 lines
15 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
'use client';
import { useCart } from "@/components/context/cartcontext";
import Image from "next/image";
import Link from "next/link";
import {
Trash2,
ShoppingBag,
ChevronLeft,
Plus,
Minus,
ShieldCheck,
Truck,
CreditCard
} from "lucide-react";
export default function CartPage() {
const { cart, clearCart, addToCart, decreaseQuantity } = useCart();
// تبدیل رشته قیمت به عدد
const parsePrice = (priceStr?: string | 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);
// دیزاین حالت سبد خرید خالی
if (cart.length === 0) {
return (
<div className="min-h-screen bg-gray-50/50 flex flex-col items-center justify-center p-6">
<div className="bg-white p-12 rounded-[3rem] shadow-sm border border-gray-100 flex flex-col items-center max-w-md w-full text-center">
<div className="bg-blue-50/50 w-32 h-32 rounded-full flex items-center justify-center mb-8 relative">
<ShoppingBag size={56} className="text-blue-500 relative z-10" />
<div className="absolute inset-0 bg-blue-100 rounded-full animate-ping opacity-20"></div>
</div>
<h2 className="text-2xl font-black text-gray-800 mb-3">سبد خرید شما خالی است!</h2>
<p className="text-gray-500 mb-10 leading-relaxed text-sm">
هنوز هیچ محصولی به سبد خرید خود اضافه نکردهاید. برای مشاهده محصولات به صفحه اصلی برگردید.
</p>
<Link href="/" className="w-full bg-[#ffb900] hover:bg-[#e5a600] text-black font-bold text-lg px-8 py-4 rounded-2xl transition-all shadow-[0_4px_20px_rgba(255,185,0,0.3)] hover:shadow-[0_6px_25px_rgba(255,185,0,0.4)] flex items-center justify-center gap-2">
بازگشت به فروشگاه
<ChevronLeft size={20} />
</Link>
</div>
</div>
);
}
return (
<main className="bg-gray-50/30 min-h-screen pb-20">
<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">
سبد خرید
<span className="bg-[#ffb900]/20 text-[#d99d00] text-xs md:text-sm font-bold py-1 px-3 rounded-xl flex items-center">
{totalItems} کالا
</span>
</h1>
</div>
{/* Breadcrumb (مراحل پرداخت) - کاملا رسپانسیو شده */}
<div className="relative w-full max-w-2xl mx-auto px-2 sm:px-0">
{/* خط سراسری بک‌گراند */}
{/*
تنظیمات top: در موبایل آیکون 40px است (وسط آن میشود 20px)
در دسکتاپ آیکون 48px است (وسط آن میشود 24px)
*/}
<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-0 transition-all"></div>
</div>
<div className="flex justify-between relative z-10">
{/* مرحله 1 */}
<div className="flex flex-col items-center w-1/3">
<div className="w-10 h-10 sm:w-12 sm:h-12 bg-[#ffb900] text-black rounded-full flex items-center justify-center shadow-md mb-2 sm:mb-3 ring-[6px] ring-[#f8fafc] sm:ring-[#f8fafc]">
<ShoppingBag className="w-4 h-4 sm:w-5 sm:h-5" />
</div>
<span className="text-[10px] sm:text-sm font-bold text-gray-800 text-center">سبد خرید</span>
</div>
{/* مرحله 2 */}
<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]">
<Truck className="w-4 h-4 sm:w-5 sm:h-5" />
</div>
<span className="text-[10px] sm:text-sm font-medium text-gray-400 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" />
</div>
<span className="text-[10px] sm:text-sm font-medium text-gray-400 text-center">پرداخت</span>
</div>
</div>
</div>
</div>
<div className="flex flex-col lg:flex-row gap-6 lg:gap-8">
{/* بخش لیست محصولات */}
<div className="flex-1">
<div className="bg-white rounded-[2rem] p-4 md:p-8 shadow-sm border border-gray-100">
<div className="flex justify-between items-center mb-6 pb-6 border-b border-gray-100">
<h2 className="text-base md:text-lg font-bold text-gray-800">محصولات انتخاب شده</h2>
<button onClick={clearCart} className="text-xs md:text-sm text-red-500 hover:text-red-700 transition flex items-center gap-1.5 bg-red-50 hover:bg-red-100 px-3 py-1.5 rounded-lg">
<Trash2 size={16} />
حذف همه
</button>
</div>
<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"
>
<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"
>
{item.quantity === 1 ? <Trash2 size={14} /> : <Minus size={14} strokeWidth={2.5} />}
</button>
</div>
</div>
</div>
);
})}
</div>
</div>
</div>
{/* بخش صورتحساب (Sidebar) */}
<div className="w-full lg:w-[340px] shrink-0">
<div className="bg-white rounded-[2rem] p-6 md:p-8 shadow-xl shadow-gray-200/20 border border-gray-100 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">
{totalPrice > 0 ? `${totalPrice.toLocaleString('fa-IR')}` : 'استعلام'}
{totalPrice > 0 && <span className="text-xs md:text-sm font-medium text-gray-500 mr-1">تومان</span>}
</span>
</div>
<button 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} />
</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="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>
</div>
</div>
</div>
</div>
</main>
);
}