Compare commits
No commits in common. "19c86c99553447b54a07f4fdb0f7a4de67340efc" and "1340a2be873223d0beff7d145f4b73b64bdc5ea7" have entirely different histories.
19c86c9955
...
1340a2be87
@ -1,6 +1,5 @@
|
||||
"use client";
|
||||
import React, { useState, useMemo, useEffect } from "react";
|
||||
import { toPersian } from "../lib/utils";
|
||||
import { Product, PetType } from "../lib/data/products";
|
||||
import { usePetStore } from "../lib/store/usePetStore";
|
||||
import { productService } from "../lib/services/productService";
|
||||
@ -161,53 +160,15 @@ const ArchiveProductCard: React.FC<{ product: Product }> = ({ product }) => {
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="mt-auto flex items-center justify-between pt-4 border-t border-medical-gray-50 gap-2">
|
||||
<span className="font-black text-medical-gray-900 font-vazir text-sm sm:text-base">{product.price}</span>
|
||||
{(() => {
|
||||
const cartItem = useCartStore.getState().items.find(i => i.product.id === product.id);
|
||||
if (cartItem && cartItem.quantity > 0) {
|
||||
return (
|
||||
<div
|
||||
onClick={(e) => { e.preventDefault(); e.stopPropagation(); }}
|
||||
className="flex items-center gap-1 bg-canina-blue/10 border border-canina-blue/20 rounded-xl p-1"
|
||||
>
|
||||
<button
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
useCartStore.getState().updateQuantity(product.id, cartItem.quantity + 1);
|
||||
}}
|
||||
className="w-7 h-7 rounded-lg bg-canina-blue text-white flex items-center justify-center font-bold text-xs"
|
||||
>
|
||||
+
|
||||
</button>
|
||||
<span className="w-5 text-center font-black text-canina-blue text-xs font-vazir">
|
||||
{toPersian(cartItem.quantity)}
|
||||
</span>
|
||||
<button
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
useCartStore.getState().updateQuantity(product.id, cartItem.quantity - 1);
|
||||
}}
|
||||
className="w-7 h-7 rounded-lg bg-white text-medical-gray-700 flex items-center justify-center font-bold text-xs shadow-sm"
|
||||
>
|
||||
-
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<button
|
||||
onClick={handleAddToCart}
|
||||
disabled={isAdding}
|
||||
className="px-3 py-2 rounded-xl bg-canina-blue text-white text-xs font-black flex items-center gap-1.5 hover:bg-canina-dark transition-all disabled:opacity-50 shadow-md shadow-canina-blue/20"
|
||||
>
|
||||
{isAdding ? <Loader2 className="w-3.5 h-3.5 animate-spin" /> : <Plus className="w-3.5 h-3.5" />}
|
||||
<span>خرید</span>
|
||||
</button>
|
||||
);
|
||||
})()}
|
||||
<div className="mt-auto flex items-center justify-between pt-4 border-t border-medical-gray-50">
|
||||
<span className="font-black text-medical-gray-900 font-vazir">{product.price}</span>
|
||||
<button
|
||||
onClick={handleAddToCart}
|
||||
disabled={isAdding}
|
||||
className="w-10 h-10 rounded-xl bg-medical-gray-50 text-canina-blue flex items-center justify-center group-hover:bg-canina-blue group-hover:text-white transition-all disabled:opacity-50"
|
||||
>
|
||||
{isAdding ? <Loader2 className="w-4 h-4 animate-spin" /> : <Plus className="w-4 h-4" />}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</Link>
|
||||
@ -234,7 +195,6 @@ export default function ArchivePage({
|
||||
const [activeSymptoms, setActiveSymptoms] = useState<string[]>(initialSymptoms ? initialSymptoms.split(',') : []);
|
||||
const [searchQuery, setSearchQuery] = useState(initialSearch);
|
||||
const [isUpdating, setIsUpdating] = useState(false);
|
||||
const [isMobileFilterOpen, setIsMobileFilterOpen] = useState(false);
|
||||
const [filteredProducts, setFilteredProducts] = useState<Product[]>([]);
|
||||
const [page, setPage] = useState(1);
|
||||
const [meta, setMeta] = useState({ total: 0, lastPage: 1 });
|
||||
@ -364,36 +324,25 @@ export default function ArchivePage({
|
||||
<div className="min-h-screen bg-medical-gray-50 pb-20 px-4 pt-10 font-vazir" dir="rtl">
|
||||
<div className="max-w-7xl mx-auto">
|
||||
|
||||
{/* Mobile Header & Filter Trigger */}
|
||||
<div className="lg:hidden mb-6 space-y-4">
|
||||
<div className="flex items-center justify-between">
|
||||
<button
|
||||
onClick={() => router.back()}
|
||||
className="flex items-center gap-1 text-sm font-bold text-medical-gray-600"
|
||||
>
|
||||
<ChevronRight className="w-4 h-4 font-vazir" />
|
||||
<span>بازگشت</span>
|
||||
</button>
|
||||
<div className="flex items-center gap-2">
|
||||
<button
|
||||
onClick={() => setIsMobileFilterOpen(!isMobileFilterOpen)}
|
||||
className="flex items-center gap-2 bg-canina-blue text-white px-4 py-2 rounded-xl text-xs font-black shadow-md shadow-canina-blue/20"
|
||||
>
|
||||
<Filter className="w-4 h-4" />
|
||||
<span>فیلترها {activeSymptoms.length > 0 || selectedPet !== "all" || selectedCategory !== "all" ? "•" : ""}</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{/* Mobile Navigation & Breadcrumbs */}
|
||||
<div className="lg:hidden mb-10 space-y-4">
|
||||
<button
|
||||
onClick={() => router.back()}
|
||||
className="flex items-center gap-2 text-medical-gray-500 font-bold hover:text-canina-blue transition-colors"
|
||||
>
|
||||
<ChevronRight className="w-5 h-5 font-vazir" />
|
||||
<span>بازگشت</span>
|
||||
</button>
|
||||
|
||||
<div className="flex items-center gap-1 text-[10px] font-black text-medical-gray-400 uppercase tracking-widest overflow-x-auto whitespace-nowrap pb-1">
|
||||
<div className="flex items-center gap-2 text-[10px] font-black text-medical-gray-400 uppercase tracking-widest overflow-x-auto whitespace-nowrap pb-2">
|
||||
<span className="cursor-pointer hover:text-canina-blue" onClick={() => router.push('/')}>کانینا</span>
|
||||
<ChevronLeft className="w-2.5 h-2.5" />
|
||||
<span className="text-canina-blue">فروشگاه تخصصی ({meta.total || filteredProducts.length} محصول)</span>
|
||||
<span className="text-canina-blue">فروشگاه تخصصی</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Desktop Breadcrumbs */}
|
||||
<div className="hidden lg:flex items-center gap-2 text-[10px] font-black text-medical-gray-400 uppercase tracking-widest mb-10">
|
||||
<div className="flex items-center gap-2 text-[10px] font-black text-medical-gray-400 uppercase tracking-widest mb-10">
|
||||
<span className="cursor-pointer hover:text-canina-blue" onClick={() => router.push('/')}>خانه</span>
|
||||
<ChevronLeft className="w-2.5 h-2.5" />
|
||||
<span className="cursor-pointer hover:text-canina-blue" onClick={() => { setSelectedCategory("all"); }}>کاتالوگ</span>
|
||||
@ -405,22 +354,14 @@ export default function ArchivePage({
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col lg:flex-row gap-8">
|
||||
<div className="flex flex-col lg:flex-row gap-10">
|
||||
|
||||
{/* Sidebar Filters - Collapsible on Mobile */}
|
||||
<aside className={`lg:w-72 flex-shrink-0 space-y-6 ${isMobileFilterOpen ? 'block' : 'hidden lg:block'}`}>
|
||||
{/* Sidebar Filters */}
|
||||
<aside className="lg:w-72 flex-shrink-0 space-y-8">
|
||||
<div className="bg-white rounded-[2rem] p-6 border border-medical-gray-200 shadow-sm">
|
||||
<div className="flex items-center justify-between mb-6">
|
||||
<div className="flex items-center gap-2">
|
||||
<Filter className="w-5 h-5 text-canina-blue" />
|
||||
<h3 className="font-black text-medical-gray-900">فیلترهای تخصصی</h3>
|
||||
</div>
|
||||
<button
|
||||
onClick={() => setIsMobileFilterOpen(false)}
|
||||
className="lg:hidden text-xs text-medical-gray-400 font-bold"
|
||||
>
|
||||
بستن ✕
|
||||
</button>
|
||||
<div className="flex items-center gap-2 mb-6">
|
||||
<Filter className="w-5 h-5 text-canina-blue" />
|
||||
<h3 className="font-black text-medical-gray-900">فیلترهای تخصصی</h3>
|
||||
</div>
|
||||
|
||||
<div className="space-y-6">
|
||||
@ -452,7 +393,7 @@ export default function ArchivePage({
|
||||
{categories.map(cat => (
|
||||
<button
|
||||
key={cat.id}
|
||||
onClick={() => { setSelectedCategory(cat.id); setIsMobileFilterOpen(false); }}
|
||||
onClick={() => setSelectedCategory(cat.id)}
|
||||
className={`flex items-center gap-3 px-4 py-3 rounded-2xl text-xs font-bold transition-all border ${selectedCategory === cat.id ? 'bg-canina-blue border-canina-blue text-white' : 'bg-white border-medical-gray-100 text-medical-gray-600 hover:border-canina-blue/30'}`}
|
||||
>
|
||||
{cat.icon}
|
||||
|
||||
@ -258,21 +258,21 @@ export default function BlogPage({ blogs = [] }: { blogs: BlogPost[] }) {
|
||||
))}
|
||||
|
||||
{/* Newsletter / CTA Box */}
|
||||
<div className="bg-canina-blue rounded-[2.5rem] sm:rounded-[3rem] p-6 sm:p-10 text-white relative overflow-hidden flex flex-col justify-center text-center sm:text-right font-vazir">
|
||||
<div className="absolute top-0 right-0 p-8 opacity-20 pointer-events-none">
|
||||
<div className="bg-canina-blue rounded-[3rem] p-10 text-white relative overflow-hidden flex flex-col justify-center">
|
||||
<div className="absolute top-0 right-0 p-8 opacity-20">
|
||||
<Sparkles className="w-24 h-24" />
|
||||
</div>
|
||||
<h3 className="text-2xl sm:text-3xl font-black mb-4 italic font-lalezar">مشترک خبرنامه علمی شوید</h3>
|
||||
<p className="text-white/80 mb-6 font-medium leading-relaxed text-xs sm:text-sm font-shabnam">
|
||||
<h3 className="text-3xl font-black mb-4 italic">مشترک خبرنامه علمی شوید</h3>
|
||||
<p className="text-white/80 mb-8 font-medium leading-relaxed">
|
||||
ماهانه یک ایمیل حاوی مهمترین نکات سلامت پتها و کدهای تخفیف اختصاصی دریافت کنید.
|
||||
</p>
|
||||
<div className="flex flex-col sm:flex-row gap-2 max-w-md mx-auto sm:mx-0">
|
||||
<div className="flex gap-2">
|
||||
<input
|
||||
type="email"
|
||||
placeholder="آدرس ایمیل شما"
|
||||
className="flex-1 bg-white/10 border border-white/20 rounded-xl px-4 py-3 text-xs outline-none focus:bg-white/20 placeholder:text-white/50 text-white"
|
||||
className="flex-1 bg-white/10 border border-white/20 rounded-xl px-4 py-3 outline-none focus:bg-white/20 placeholder:text-white/40"
|
||||
/>
|
||||
<button className="bg-white text-canina-blue px-6 py-3 rounded-xl font-black text-xs hover:bg-slate-100 transition-all whitespace-nowrap shadow-md">
|
||||
<button className="bg-white text-canina-blue px-6 py-3 rounded-xl font-black">
|
||||
عضویت
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@ -147,112 +147,121 @@ export default function CheckoutPage() {
|
||||
<span className="text-canina-blue">درگاه پرداخت امن و نهاییسازی</span>
|
||||
</div>
|
||||
|
||||
<div className="grid lg:grid-cols-12 gap-8 lg:gap-12">
|
||||
<div className="grid lg:grid-cols-12 gap-12">
|
||||
{/* Main Form */}
|
||||
<div className="lg:col-span-8 space-y-6 sm:space-y-8">
|
||||
<div className="lg:col-span-8 space-y-8">
|
||||
{/* Step 1: Shipping */}
|
||||
<section className="bg-white rounded-[2rem] sm:rounded-[3rem] border border-medical-gray-200 p-5 sm:p-10 overflow-hidden relative">
|
||||
<div className="absolute top-0 right-0 w-2.5 sm:w-3 h-full bg-canina-blue opacity-20" />
|
||||
<div className="flex items-center gap-3 sm:gap-4 mb-6 sm:mb-10">
|
||||
<div className="w-10 h-10 sm:w-12 sm:h-12 bg-medical-gray-900 text-white rounded-2xl flex items-center justify-center font-black text-sm sm:text-base">۱</div>
|
||||
<h2 className="text-xl sm:text-2xl font-black text-medical-gray-900 italic">اطلاعات ارسال</h2>
|
||||
<section className="bg-white rounded-[3rem] border border-medical-gray-200 p-10 overflow-hidden relative">
|
||||
<div className="absolute top-0 right-0 w-3 h-full bg-canina-blue opacity-20" />
|
||||
<div className="flex items-center gap-4 mb-10">
|
||||
<div className="w-12 h-12 bg-medical-gray-900 text-white rounded-2xl flex items-center justify-center font-black">۱</div>
|
||||
<h2 className="text-2xl font-black text-medical-gray-900 italic">اطلاعات ارسال</h2>
|
||||
</div>
|
||||
|
||||
<div className="grid md:grid-cols-2 gap-4 sm:gap-6">
|
||||
<div className="grid md:grid-cols-2 gap-6">
|
||||
<div className="space-y-2">
|
||||
<label className="text-[10px] font-black text-medical-gray-400 uppercase tracking-widest block">نام و نام خانوادگی</label>
|
||||
<input type="text" className="w-full bg-medical-gray-50 border border-medical-gray-200 rounded-2xl py-3 sm:py-4 px-4 sm:px-6 text-xs sm:text-sm focus:outline-none focus:ring-2 focus:ring-canina-blue/20" placeholder="مثلاً: پارسا آقایی" />
|
||||
<input type="text" className="w-full bg-medical-gray-50 border border-medical-gray-200 rounded-2xl py-4 px-6 text-sm focus:outline-none focus:ring-2 focus:ring-canina-blue/20" placeholder="مثلاً: پارسا آقایی" />
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<label className="text-[10px] font-black text-medical-gray-400 uppercase tracking-widest block">شماره تماس</label>
|
||||
<input type="text" className="w-full bg-medical-gray-50 border border-medical-gray-200 rounded-2xl py-3 sm:py-4 px-4 sm:px-6 text-xs sm:text-sm focus:outline-none focus:ring-2 focus:ring-canina-blue/20" placeholder="۰۹۱۲XXXXXXX" />
|
||||
<input type="text" className="w-full bg-medical-gray-50 border border-medical-gray-200 rounded-2xl py-4 px-6 text-sm focus:outline-none focus:ring-2 focus:ring-canina-blue/20" placeholder="۰۹۱۲XXXXXXX" />
|
||||
</div>
|
||||
<div className="md:col-span-2 space-y-2">
|
||||
<label className="text-[10px] font-black text-medical-gray-400 uppercase tracking-widest block">آدرس دقیق پستی</label>
|
||||
<textarea className="w-full bg-medical-gray-50 border border-medical-gray-200 rounded-2xl py-3 sm:py-4 px-4 sm:px-6 text-xs sm:text-sm focus:outline-none focus:ring-2 focus:ring-canina-blue/20 h-28 sm:h-32" placeholder="استان، شهر، خیابان..." />
|
||||
<textarea className="w-full bg-medical-gray-50 border border-medical-gray-200 rounded-2xl py-4 px-6 text-sm focus:outline-none focus:ring-2 focus:ring-canina-blue/20 h-32" placeholder="استان، شهر، خیابان..." />
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Step 2: Payment */}
|
||||
<section className="bg-white rounded-[2rem] sm:rounded-[3rem] border border-medical-gray-200 p-5 sm:p-10 overflow-hidden relative">
|
||||
<div className="absolute top-0 right-0 w-2.5 sm:w-3 h-full bg-medical-gray-900 opacity-20" />
|
||||
<div className="flex items-center gap-3 sm:gap-4 mb-6 sm:mb-10">
|
||||
<div className="w-10 h-10 sm:w-12 sm:h-12 bg-medical-gray-900 text-white rounded-2xl flex items-center justify-center font-black text-sm sm:text-base">۲</div>
|
||||
<h2 className="text-xl sm:text-2xl font-black text-medical-gray-900 italic">شیوه پرداخت</h2>
|
||||
<section className="bg-white rounded-[3rem] border border-medical-gray-200 p-10 overflow-hidden relative">
|
||||
<div className="absolute top-0 right-0 w-3 h-full bg-medical-gray-900 opacity-20" />
|
||||
<div className="flex items-center gap-4 mb-10">
|
||||
<div className="w-12 h-12 bg-medical-gray-900 text-white rounded-2xl flex items-center justify-center font-black">۲</div>
|
||||
<h2 className="text-2xl font-black text-medical-gray-900 italic">شیوه پرداخت</h2>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 sm:grid-cols-3 gap-3 sm:gap-4">
|
||||
<div className="grid md:grid-cols-3 gap-4">
|
||||
{[
|
||||
{ id: 'online', label: 'پرداخت آنلاین', desc: 'کارتهای بانکی', icon: <CreditCard className="w-5 h-5 sm:w-6 sm:h-6" /> },
|
||||
{ id: 'wallet', label: 'اعتبار حساب', desc: 'شارژ شده اختصاصی', icon: <Wallet className="w-5 h-5 sm:w-6 sm:h-6" /> },
|
||||
{ id: 'cod', label: 'پرداخت در محل', desc: 'فقط تهران', icon: <Truck className="w-5 h-5 sm:w-6 sm:h-6" /> }
|
||||
{ id: 'online', label: 'پرداخت آنلاین', desc: 'کارتهای بانکی', icon: <CreditCard className="w-6 h-6" /> },
|
||||
{ id: 'wallet', label: 'اعتبار حساب', desc: 'شارژ شده اختصاصی', icon: <Wallet className="w-6 h-6" /> },
|
||||
{ id: 'cod', label: 'پرداخت در محل', desc: 'فقط تهران', icon: <Truck className="w-6 h-6" /> }
|
||||
].map((pay) => (
|
||||
<div
|
||||
key={pay.id}
|
||||
onClick={async () => {
|
||||
setPaymentMethod(pay.id);
|
||||
try {
|
||||
// In a real scenario, this would call api.post('/payment/init', { method: pay.id, amount: getTotal() })
|
||||
// and redirect to the returned gatewayUrl.
|
||||
} catch (err) {
|
||||
console.error("Payment init failed");
|
||||
}
|
||||
}}
|
||||
className={cn("p-4 sm:p-6 rounded-2xl sm:rounded-3xl border-2 cursor-pointer transition-all group flex sm:flex-col items-center sm:items-start gap-4 sm:gap-0", paymentMethod === pay.id ? "border-canina-blue bg-canina-blue/5" : "border-medical-gray-100 hover:border-canina-blue")}
|
||||
className={cn("p-6 rounded-3xl border-2 cursor-pointer transition-all group", paymentMethod === pay.id ? "border-canina-blue bg-canina-blue/5" : "border-medical-gray-100 hover:border-canina-blue")}
|
||||
>
|
||||
<div className="w-10 h-10 sm:w-12 sm:h-12 bg-medical-gray-50 rounded-xl sm:rounded-2xl flex items-center justify-center text-medical-gray-400 group-hover:text-canina-blue group-hover:bg-canina-blue/10 sm:mb-4 transition-all flex-shrink-0">
|
||||
<div className="w-12 h-12 bg-medical-gray-50 rounded-2xl flex items-center justify-center text-medical-gray-400 group-hover:text-canina-blue group-hover:bg-canina-blue/10 mb-4 transition-all">
|
||||
{pay.icon}
|
||||
</div>
|
||||
<div>
|
||||
<h4 className="font-black text-xs sm:text-sm text-medical-gray-900 mb-0.5 sm:mb-1">{pay.label}</h4>
|
||||
<p className="text-[10px] text-medical-gray-400 font-bold">{pay.desc}</p>
|
||||
</div>
|
||||
<h4 className="font-black text-sm text-medical-gray-900 mb-1">{pay.label}</h4>
|
||||
<p className="text-[10px] text-medical-gray-400 font-bold">{pay.desc}</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Step 3: Charity Section */}
|
||||
<section className="bg-white rounded-[2rem] sm:rounded-[3rem] border border-medical-gray-200 p-5 sm:p-10 overflow-hidden relative">
|
||||
<div className="absolute top-0 right-0 w-2.5 sm:w-3 h-full bg-pink-500 opacity-20" />
|
||||
<div className="flex items-center justify-between mb-6 sm:mb-8">
|
||||
<div className="flex items-center gap-3 sm:gap-4">
|
||||
<div className="w-10 h-10 sm:w-12 sm:h-12 bg-pink-500 text-white rounded-2xl flex items-center justify-center flex-shrink-0">
|
||||
<Heart className="w-5 h-5 sm:w-6 sm:h-6 fill-white" />
|
||||
<section className="bg-white rounded-[3rem] border border-medical-gray-200 p-10 overflow-hidden relative">
|
||||
<div className="absolute top-0 right-0 w-3 h-full bg-pink-500 opacity-20" />
|
||||
<div className="flex items-center justify-between mb-8">
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="w-12 h-12 bg-pink-500 text-white rounded-2xl flex items-center justify-center">
|
||||
<Heart className="w-6 h-6 fill-white" />
|
||||
</div>
|
||||
<div>
|
||||
<h2 className="text-xl sm:text-2xl font-black text-medical-gray-900 italic">ردپای مهربانی</h2>
|
||||
<p className="text-[10px] sm:text-xs font-bold text-pink-500 mt-0.5">سهم شما در حمایت از حیوانات بیپناه</p>
|
||||
<h2 className="text-2xl font-black text-medical-gray-900 italic">ردپای مهربانی</h2>
|
||||
<p className="text-xs font-bold text-pink-500 mt-1">سهم شما در حمایت از حیوانات بیپناه</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="bg-pink-50 rounded-[2rem] sm:rounded-[2.5rem] p-5 sm:p-8 border border-pink-100">
|
||||
<div className="flex flex-col sm:flex-row items-start sm:items-center justify-between gap-4 sm:gap-6">
|
||||
<div className="flex-1">
|
||||
<h4 className="text-base sm:text-lg font-black text-medical-gray-900 italic mb-1 sm:mb-2">رند کردن مبلغ و کمک به پناهگاه</h4>
|
||||
<p className="text-xs sm:text-sm text-medical-gray-600 leading-relaxed font-medium"> مابقی مبلغ تا ۱۰,۰۰۰ تومان بعدی صرف تامین غذا و دارو برای حیوانات بی-سرپرست میشود.</p>
|
||||
<div className="bg-pink-50 rounded-[2.5rem] p-8 border border-pink-100">
|
||||
<div className="flex flex-wrap items-center justify-between gap-6">
|
||||
<div className="flex-1 min-w-[280px]">
|
||||
<h4 className="text-lg font-black text-medical-gray-900 italic mb-2">رند کردن مبلغ و کمک به پناهگاه</h4>
|
||||
<p className="text-sm text-medical-gray-600 leading-relaxed font-medium"> با انتخاب این گزینه، مابقی مبلغ تا ده هزار تومان بعدی یا ۱٪ از خرید شما (هر کدام بیشتر باشد) صرف تامین غذا و دارو برای حیوانات بی-سرپرست تحت حمایت کانینا میشود.</p>
|
||||
<div className="mt-4 flex items-center gap-3 text-pink-600">
|
||||
<ShieldCheck className="w-4 h-4" />
|
||||
<span className="text-[10px] font-black uppercase tracking-widest">گزارش شفاف هزینهکرد در داشبورد شما</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button
|
||||
onClick={handleCharityToggle}
|
||||
className={cn(
|
||||
"w-14 h-14 sm:w-20 sm:h-20 rounded-full flex items-center justify-center transition-all shadow-lg self-end sm:self-center",
|
||||
"w-20 h-20 rounded-full flex items-center justify-center transition-all shadow-xl hover:scale-110 active:scale-95",
|
||||
useRoundUp ? "bg-pink-500 text-white shadow-pink-200" : "bg-white text-medical-gray-300 border-2 border-medical-gray-100"
|
||||
)}
|
||||
>
|
||||
<PlusCircle className={cn("w-7 h-7 sm:w-10 sm:h-10", useRoundUp ? "rotate-45" : "rotate-0")} />
|
||||
<PlusCircle className={cn("w-10 h-10", useRoundUp ? "rotate-45" : "rotate-0")} />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{useRoundUp && (
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 10 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
className="mt-6 pt-6 border-t border-pink-100 flex items-center justify-between"
|
||||
>
|
||||
<span className="text-sm font-black text-pink-600 italic">مبلغ اهدایی شما:</span>
|
||||
<span className="text-lg font-black font-vazir text-pink-500">{toPersian(charityDonation.toLocaleString())} تومان</span>
|
||||
</motion.div>
|
||||
)}
|
||||
|
||||
<p className="mt-6 text-[10px] text-center text-medical-gray-400 font-bold">«با خرید این محصول، شما هم در درمان یک حیوان پناهگاهی سهیم شدید.»</p>
|
||||
</section>
|
||||
{useRoundUp && (
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 10 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
className="mt-6 pt-6 border-t border-pink-100 flex items-center justify-between"
|
||||
>
|
||||
<span className="text-sm font-black text-pink-600 italic">مبلغ اهدایی شما:</span>
|
||||
<span className="text-lg font-black font-vazir text-pink-500">{toPersian(charityDonation.toLocaleString())} تومان</span>
|
||||
</motion.div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<p className="mt-6 text-[10px] text-center text-medical-gray-400 font-bold">«با خرید این محصول، شما هم در درمان یک حیوان پناهگاهی سهیم شدید.»</p>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
{/* Sidebar Summary */}
|
||||
|
||||
@ -130,37 +130,39 @@ export default function Header({
|
||||
</div>
|
||||
|
||||
<header className="sticky top-0 z-50 bg-white/95 backdrop-blur-md border-b border-medical-gray-100 shadow-sm">
|
||||
<div className="max-w-7xl mx-auto h-16 sm:h-20 md:h-24 flex items-center justify-between gap-1 sm:gap-4 px-2 sm:px-6 lg:px-8" dir="rtl">
|
||||
<div className="max-w-7xl mx-auto py-2 min-[470px]:py-0 min-[470px]:h-24 flex flex-col min-[470px]:flex-row min-[470px]:items-center justify-between gap-2 min-[470px]:gap-4 px-3 sm:px-6 lg:px-8" dir="rtl">
|
||||
{/* Logo & Mobile Toggle Area */}
|
||||
<div className="flex items-center gap-1.5 sm:gap-2 min-w-0">
|
||||
{/* Mobile Menu Toggle */}
|
||||
<button
|
||||
onClick={() => setIsMobileMenuOpen(!isMobileMenuOpen)}
|
||||
className="min-[800px]:hidden p-1.5 sm:p-2 rounded-xl text-medical-gray-600 hover:bg-medical-gray-50 transition-all flex-shrink-0"
|
||||
aria-label="منو"
|
||||
>
|
||||
{isMobileMenuOpen ? <X className="w-5 h-5 sm:w-6 sm:h-6" /> : <Menu className="w-5 h-5 sm:w-6 sm:h-6" />}
|
||||
</button>
|
||||
<div className="flex items-center justify-between min-[470px]:justify-start gap-2 w-full min-[470px]:w-auto">
|
||||
<div className="flex items-center gap-2">
|
||||
{/* Mobile Menu Toggle (visible below 800px) */}
|
||||
<button
|
||||
onClick={() => setIsMobileMenuOpen(!isMobileMenuOpen)}
|
||||
className="min-[800px]:hidden p-2 rounded-xl text-medical-gray-600 hover:bg-medical-gray-50 transition-all flex-shrink-0"
|
||||
aria-label="منو"
|
||||
>
|
||||
{isMobileMenuOpen ? <X className="w-6 h-6" /> : <Menu className="w-6 h-6" />}
|
||||
</button>
|
||||
|
||||
{/* Logo Section */}
|
||||
<Link
|
||||
href="/"
|
||||
className="flex items-center gap-1.5 sm:gap-3 cursor-pointer group min-w-0"
|
||||
onClick={() => setIsMobileMenuOpen(false)}
|
||||
>
|
||||
<div className="w-8 h-8 sm:w-12 sm:h-12 bg-canina-blue rounded-xl sm:rounded-2xl flex items-center justify-center text-white font-bold text-base sm:text-2xl group-hover:bg-medical-gray-900 transition-all shadow-md sm:shadow-xl shadow-canina-blue/20 italic flex-shrink-0">C</div>
|
||||
<div className="flex flex-col justify-center min-w-0">
|
||||
<span className="text-canina-blue font-black text-xs sm:text-2xl tracking-tighter italic font-sans flex items-center gap-1 leading-none whitespace-nowrap">
|
||||
Canina
|
||||
<span className="text-[10px] sm:text-sm not-italic font-medium border-r border-medical-gray-200 pr-1 font-vazir">
|
||||
{getText('brand_name_fa', "ایران")}
|
||||
{/* Logo Section */}
|
||||
<Link
|
||||
href="/"
|
||||
className="flex items-center gap-2 sm:gap-3 cursor-pointer group"
|
||||
onClick={() => setIsMobileMenuOpen(false)}
|
||||
>
|
||||
<div className="w-9 h-9 sm:w-12 sm:h-12 bg-canina-blue rounded-2xl flex items-center justify-center text-white font-bold text-lg sm:text-2xl group-hover:bg-medical-gray-900 transition-all shadow-xl shadow-canina-blue/20 italic flex-shrink-0">C</div>
|
||||
<div className="flex flex-col justify-center gap-0.5 sm:gap-1">
|
||||
<span className="text-canina-blue font-black text-base sm:text-2xl tracking-tighter italic font-sans flex items-center gap-1.5 sm:gap-2 leading-none whitespace-nowrap">
|
||||
Canina
|
||||
<span className="text-xs sm:text-sm not-italic font-medium border-r-2 border-medical-gray-200 pr-1.5 sm:pr-2 font-vazir">
|
||||
{getText('brand_name_fa', "ایران")}
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
<span className="text-[7px] sm:text-[9px] text-medical-gray-400 font-bold uppercase tracking-wider font-vazir leading-tight whitespace-nowrap mt-0.5">
|
||||
نماینده رسمی <span className="block sm:inline text-[6px] sm:text-[9px]">CANINA PHARMA GMBH</span>
|
||||
</span>
|
||||
</div>
|
||||
</Link>
|
||||
<span className="text-[8px] sm:text-[9px] text-medical-gray-400 font-bold uppercase tracking-wider font-vazir leading-none whitespace-nowrap">
|
||||
{getText('brand_subtitle', "نماینده رسمی Canina Pharma GmbH آلمان")}
|
||||
</span>
|
||||
</div>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Navigation Items: Centered on XL screens (1224px+) */}
|
||||
|
||||
@ -65,10 +65,8 @@ export default function IngredientWiki() {
|
||||
const el = document.getElementById(`wiki-${termParam}`);
|
||||
if (el) {
|
||||
setTimeout(() => {
|
||||
const yOffset = -120;
|
||||
const y = el.getBoundingClientRect().top + window.pageYOffset + yOffset;
|
||||
window.scrollTo({ top: y, behavior: 'smooth' });
|
||||
}, 200);
|
||||
el.scrollIntoView({ behavior: 'smooth', block: 'center' });
|
||||
}, 100);
|
||||
}
|
||||
}
|
||||
}, [termParam, ingredientsWiki]);
|
||||
|
||||
@ -167,8 +167,22 @@ export default function ProductPage({ productSlug }: { productSlug: string }) {
|
||||
return (
|
||||
<div className="min-h-screen bg-medical-gray-50 pt-2 pb-20 px-4 md:px-0" dir="rtl">
|
||||
<div className="max-w-7xl mx-auto">
|
||||
{/* Breadcrumbs for Mobile and Desktop */}
|
||||
<nav className="flex items-center gap-2 text-xs md:text-sm font-semibold text-medical-gray-600 mb-6 md:mb-10 overflow-x-auto whitespace-nowrap py-3 border-b border-medical-gray-100 font-vazir" dir="rtl">
|
||||
{/* Mobile Header with Back Button */}
|
||||
<div className="flex items-center justify-between mb-6 md:hidden">
|
||||
<button
|
||||
onClick={() => router.back()}
|
||||
className="p-3 bg-white border border-medical-gray-200 rounded-2xl text-medical-gray-700 shadow-sm flex items-center gap-2 font-vazir text-sm font-bold"
|
||||
>
|
||||
<ChevronRight className="w-5 h-5" />
|
||||
بازگشت
|
||||
</button>
|
||||
<div className="text-[10px] font-black text-canina-blue bg-canina-blue/5 px-4 py-2 rounded-xl font-vazir whitespace-nowrap">
|
||||
کانینا ایران
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Breadcrumbs */}
|
||||
<nav className="hidden md:flex items-center gap-2 text-sm font-semibold text-medical-gray-600 mb-10 overflow-x-auto whitespace-nowrap py-3 border-b border-medical-gray-100">
|
||||
<button
|
||||
onClick={() => router.push('/')}
|
||||
className="hover:text-canina-blue transition-colors font-vazir cursor-pointer"
|
||||
@ -183,7 +197,7 @@ export default function ProductPage({ productSlug }: { productSlug: string }) {
|
||||
{product.category}
|
||||
</button>
|
||||
<ChevronLeft className="w-3.5 h-3.5 flex-shrink-0 text-medical-gray-300" />
|
||||
<span className="text-canina-blue font-vazir whitespace-nowrap font-bold">{product.nameFa || product.name}</span>
|
||||
<span className="text-canina-blue font-vazir whitespace-nowrap font-bold">{product.name}</span>
|
||||
</nav>
|
||||
|
||||
{/* Global Single Grid Layout - Aligns Sticky Buy Box at the Top */}
|
||||
@ -755,45 +769,6 @@ export default function ProductPage({ productSlug }: { productSlug: string }) {
|
||||
</div>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
|
||||
{/* Mobile Floating Sticky Bottom Buy Bar */}
|
||||
<div className="lg:hidden fixed bottom-0 left-0 right-0 z-40 bg-white border-t border-medical-gray-200 p-3 shadow-2xl flex items-center justify-between gap-3 font-vazir" dir="rtl">
|
||||
<div>
|
||||
<span className="text-[10px] text-medical-gray-400 font-bold block">قیمت نهایی</span>
|
||||
<span className="text-lg font-black text-medical-gray-900 font-vazir">{toPersian(product.price)}</span>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-2 flex-1 max-w-[240px]">
|
||||
<div className="flex items-center gap-1 bg-medical-gray-50 border border-medical-gray-200 rounded-xl p-1 h-11">
|
||||
<button
|
||||
onClick={() => setItemQuantity(Math.max(1, itemQuantity - 1))}
|
||||
className="w-7 h-7 flex items-center justify-center rounded-lg bg-white text-medical-gray-900 border border-medical-gray-200 font-bold text-xs"
|
||||
>
|
||||
-
|
||||
</button>
|
||||
<span className="w-5 text-center font-black text-medical-gray-900 text-xs font-vazir">
|
||||
{toPersian(itemQuantity)}
|
||||
</span>
|
||||
<button
|
||||
onClick={() => setItemQuantity(itemQuantity + 1)}
|
||||
className="w-7 h-7 flex items-center justify-center rounded-lg bg-white text-medical-gray-900 border border-medical-gray-200 font-bold text-xs"
|
||||
>
|
||||
+
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<button
|
||||
onClick={() => {
|
||||
addItem(product, itemQuantity, { quantity: calculation.dailyDose, unit: calculation.unit });
|
||||
toast.success(`${toPersian(itemQuantity)} عدد به سبد خرید اضافه شد`);
|
||||
}}
|
||||
className="flex-1 bg-canina-blue text-white py-2.5 px-3 rounded-xl font-black text-xs hover:bg-canina-dark transition-all flex items-center justify-center gap-1.5 shadow-md shadow-canina-blue/20 whitespace-nowrap"
|
||||
>
|
||||
<ShoppingBag className="w-4 h-4" />
|
||||
افزودن به سبد
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user