203 lines
6.7 KiB
TypeScript
203 lines
6.7 KiB
TypeScript
"use client";
|
|
|
|
import { Heart, ShoppingCart, Trash2, TrendingDown } from "lucide-react";
|
|
import { useState } from "react";
|
|
|
|
import { AspectRatio } from "@/components/ui/aspect-ratio";
|
|
import { Badge } from "@/components/ui/badge";
|
|
import { Button } from "@/components/ui/button";
|
|
import { Card, CardContent } from "@/components/ui/card";
|
|
import { cn } from "@/lib/utils";
|
|
|
|
interface WishlistItem {
|
|
id: string;
|
|
name: string;
|
|
image: string;
|
|
price: number;
|
|
originalPrice?: number;
|
|
inStock: boolean;
|
|
priceDrop?: boolean;
|
|
}
|
|
|
|
const DEFAULT_ITEMS: WishlistItem[] = [
|
|
{
|
|
id: "1",
|
|
name: "هدفون بیسیم نویزکنسل",
|
|
image:
|
|
"/block-media/shadcnblocks/block/ecommerce/electronics/Modern-White-Headphones-1.png",
|
|
price: 50000,
|
|
originalPrice: 60000,
|
|
inStock: true,
|
|
priceDrop: true,
|
|
},
|
|
{
|
|
id: "2",
|
|
name: "کیف چرمی کراسبادی",
|
|
image:
|
|
"/block-media/shadcnblocks/block/ecommerce/clothes/maroon-leather-handbag.png",
|
|
price: 180000,
|
|
inStock: true,
|
|
},
|
|
{
|
|
id: "3",
|
|
name: "پالتو پشمی کلاسیک",
|
|
image:
|
|
"/block-media/shadcnblocks/block/ecommerce/clothes/Young-Man-in-White-Hoodie-1.png",
|
|
price: 1200000,
|
|
inStock: false,
|
|
},
|
|
{
|
|
id: "4",
|
|
name: "گوشواره حلقهای طلا",
|
|
image:
|
|
"/block-media/shadcnblocks/block/ecommerce/accessories/Elegant-Gold-Earrings-1.png",
|
|
price: 8000000,
|
|
originalPrice: 9000000,
|
|
inStock: true,
|
|
priceDrop: true,
|
|
},
|
|
{
|
|
id: "5",
|
|
name: "هودی پنبهای اوورسایز",
|
|
image:
|
|
"/block-media/shadcnblocks/block/ecommerce/clothes/black-hoodie-against-light-background.png",
|
|
price: 6500000,
|
|
inStock: true,
|
|
},
|
|
{
|
|
id: "6",
|
|
name: "ساعت مینیمال",
|
|
image:
|
|
"/block-media/shadcnblocks/block/ecommerce/accessories/Elegant-Watch-on-Womans-Wrist-1.png",
|
|
price: 12500000,
|
|
inStock: true,
|
|
},
|
|
];
|
|
|
|
interface Wishlist1Props {
|
|
items?: WishlistItem[];
|
|
className?: string;
|
|
}
|
|
|
|
const Wishlist1 = ({ items = DEFAULT_ITEMS, className }: Wishlist1Props) => {
|
|
const [wishlistItems, setWishlistItems] = useState(items);
|
|
|
|
const removeItem = (id: string) => {
|
|
setWishlistItems((prev) => prev.filter((item) => item.id !== id));
|
|
};
|
|
|
|
const formatPrice = (price: number) => {
|
|
return new Intl.NumberFormat("fa-IR", {
|
|
style: "currency",
|
|
currency: "IRR",
|
|
}).format(price);
|
|
};
|
|
|
|
return (
|
|
<section dir="rtl" lang="fa" className={cn("w-full py-16 md:py-24", className)}>
|
|
<div className="w-full px-4 sm:px-6 lg:px-8">
|
|
<div className="flex w-full flex-col gap-8">
|
|
{/* Header */}
|
|
<div className="flex items-center justify-between">
|
|
<div>
|
|
<h1 className="text-xl font-semibold tracking-tight md:text-3xl">
|
|
لیست علاقهمندیهای من
|
|
</h1>
|
|
<p className="mt-1 text-muted-foreground">
|
|
{wishlistItems.length.toLocaleString("fa-IR")} مورد ذخیره شده
|
|
</p>
|
|
</div>
|
|
{wishlistItems.length > 0 && (
|
|
<Button variant="outline">
|
|
<ShoppingCart className="me-2 size-4" />
|
|
افزودن همه به سبد
|
|
</Button>
|
|
)}
|
|
</div>
|
|
|
|
{/* Grid */}
|
|
{wishlistItems.length > 0 ? (
|
|
<div className="grid gap-6 sm:grid-cols-2 lg:grid-cols-3">
|
|
{wishlistItems.map((item) => (
|
|
<Card key={item.id} className="group gap-0 overflow-hidden p-0">
|
|
<div className="relative">
|
|
<AspectRatio ratio={1} className="bg-muted">
|
|
<img
|
|
src={item.image}
|
|
alt={item.name}
|
|
className={cn(
|
|
"size-full object-cover",
|
|
!item.inStock && "opacity-50",
|
|
)}
|
|
/>
|
|
</AspectRatio>
|
|
|
|
{/* Badges */}
|
|
<div className="absolute top-3 start-3 flex flex-col gap-2">
|
|
{item.priceDrop && (
|
|
<Badge className="bg-emerald-600 hover:bg-emerald-600">
|
|
<TrendingDown className="me-1 size-3" />
|
|
کاهش قیمت
|
|
</Badge>
|
|
)}
|
|
{!item.inStock && (
|
|
<Badge variant="secondary">ناموجود</Badge>
|
|
)}
|
|
</div>
|
|
|
|
{/* Remove Button */}
|
|
<Button
|
|
variant="secondary"
|
|
size="icon"
|
|
className="absolute top-3 end-3 opacity-0 transition-opacity group-hover:opacity-100"
|
|
onClick={() => removeItem(item.id)}
|
|
>
|
|
<Trash2 className="size-4" />
|
|
</Button>
|
|
</div>
|
|
|
|
<CardContent className="p-4">
|
|
<h3 className="leading-tight font-medium">{item.name}</h3>
|
|
<div className="mt-2 flex items-center gap-2">
|
|
<span className="text-lg font-semibold">
|
|
{formatPrice(item.price)}
|
|
</span>
|
|
{item.originalPrice && (
|
|
<span className="text-sm text-muted-foreground line-through">
|
|
{formatPrice(item.originalPrice)}
|
|
</span>
|
|
)}
|
|
</div>
|
|
<Button
|
|
className="mt-4 w-full"
|
|
disabled={!item.inStock}
|
|
variant={item.inStock ? "default" : "secondary"}
|
|
>
|
|
{item.inStock ? "افزودن به سبد" : "هنگام موجود بودن اطلاع بده"}
|
|
</Button>
|
|
</CardContent>
|
|
</Card>
|
|
))}
|
|
</div>
|
|
) : (
|
|
<Card className="p-0">
|
|
<CardContent className="flex flex-col items-center justify-center py-16 text-center">
|
|
<div className="mb-4 flex size-16 items-center justify-center rounded-full bg-muted">
|
|
<Heart className="size-8 text-muted-foreground" />
|
|
</div>
|
|
<h2 className="text-xl font-semibold">لیست علاقهمندی شما خالی است</h2>
|
|
<p className="mt-2 max-w-sm text-muted-foreground">
|
|
با کلیک روی آیکن قلب در هر محصول، موارد مورد علاقه را ذخیره کنید
|
|
</p>
|
|
<Button className="mt-6">ادامه خرید</Button>
|
|
</CardContent>
|
|
</Card>
|
|
)}
|
|
</div>
|
|
</div>
|
|
</section>
|
|
);
|
|
};
|
|
|
|
export { Wishlist1 };
|