Compare commits

..

2 Commits

6 changed files with 222 additions and 147 deletions

View File

@ -1,5 +1,6 @@
"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";
@ -160,15 +161,53 @@ 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">
<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 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>
</div>
</Link>
@ -195,6 +234,7 @@ 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 });
@ -324,25 +364,36 @@ 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 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>
{/* 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>
<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">
<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">
<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">فروشگاه تخصصی</span>
<span className="text-canina-blue">فروشگاه تخصصی ({meta.total || filteredProducts.length} محصول)</span>
</div>
</div>
{/* Desktop Breadcrumbs */}
<div className="flex items-center gap-2 text-[10px] font-black text-medical-gray-400 uppercase tracking-widest mb-10">
<div className="hidden lg: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>
@ -354,14 +405,22 @@ export default function ArchivePage({
)}
</div>
<div className="flex flex-col lg:flex-row gap-10">
<div className="flex flex-col lg:flex-row gap-8">
{/* Sidebar Filters */}
<aside className="lg:w-72 flex-shrink-0 space-y-8">
{/* Sidebar Filters - Collapsible on Mobile */}
<aside className={`lg:w-72 flex-shrink-0 space-y-6 ${isMobileFilterOpen ? 'block' : 'hidden lg:block'}`}>
<div className="bg-white rounded-[2rem] p-6 border border-medical-gray-200 shadow-sm">
<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 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>
<div className="space-y-6">
@ -393,7 +452,7 @@ export default function ArchivePage({
{categories.map(cat => (
<button
key={cat.id}
onClick={() => setSelectedCategory(cat.id)}
onClick={() => { setSelectedCategory(cat.id); setIsMobileFilterOpen(false); }}
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}

View File

@ -258,21 +258,21 @@ export default function BlogPage({ blogs = [] }: { blogs: BlogPost[] }) {
))}
{/* Newsletter / CTA Box */}
<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">
<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">
<Sparkles className="w-24 h-24" />
</div>
<h3 className="text-3xl font-black mb-4 italic">مشترک خبرنامه علمی شوید</h3>
<p className="text-white/80 mb-8 font-medium leading-relaxed">
<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">
ماهانه یک ایمیل حاوی مهم‌ترین نکات سلامت پت‌ها و کدهای تخفیف اختصاصی دریافت کنید.
</p>
<div className="flex gap-2">
<div className="flex flex-col sm:flex-row gap-2 max-w-md mx-auto sm:mx-0">
<input
type="email"
placeholder="آدرس ایمیل شما"
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"
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"
/>
<button className="bg-white text-canina-blue px-6 py-3 rounded-xl font-black">
<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>
</div>

View File

@ -147,121 +147,112 @@ export default function CheckoutPage() {
<span className="text-canina-blue">درگاه پرداخت امن و نهایی‌سازی</span>
</div>
<div className="grid lg:grid-cols-12 gap-12">
<div className="grid lg:grid-cols-12 gap-8 lg:gap-12">
{/* Main Form */}
<div className="lg:col-span-8 space-y-8">
<div className="lg:col-span-8 space-y-6 sm:space-y-8">
{/* Step 1: Shipping */}
<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>
<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>
</div>
<div className="grid md:grid-cols-2 gap-6">
<div className="grid md:grid-cols-2 gap-4 sm: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-4 px-6 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-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="مثلاً: پارسا آقایی" />
</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-4 px-6 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-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" />
</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-4 px-6 text-sm focus:outline-none focus:ring-2 focus:ring-canina-blue/20 h-32" placeholder="استان، شهر، خیابان..." />
<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="استان، شهر، خیابان..." />
</div>
</div>
</section>
{/* Step 2: Payment */}
<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>
<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>
</div>
<div className="grid md:grid-cols-3 gap-4">
<div className="grid grid-cols-1 sm:grid-cols-3 gap-3 sm:gap-4">
{[
{ 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" /> }
{ 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" /> }
].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-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")}
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")}
>
<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">
<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">
{pay.icon}
</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>
<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>
</div>
))}
</div>
</section>
{/* Step 3: Charity Section */}
<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" />
<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" />
</div>
<div>
<h2 className="text-2xl font-black text-medical-gray-900 italic">ردپای مهربانی</h2>
<p className="text-xs font-bold text-pink-500 mt-1">سهم شما در حمایت از حیوانات بی‌پناه</p>
<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>
</div>
</div>
</div>
<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 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>
<button
onClick={handleCharityToggle}
className={cn(
"w-20 h-20 rounded-full flex items-center justify-center transition-all shadow-xl hover:scale-110 active:scale-95",
"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",
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-10 h-10", useRoundUp ? "rotate-45" : "rotate-0")} />
<PlusCircle className={cn("w-7 h-7 sm:w-10 sm:h-10", useRoundUp ? "rotate-45" : "rotate-0")} />
</button>
</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>
)}
</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>
)}
<p className="mt-6 text-[10px] text-center text-medical-gray-400 font-bold">«با خرید این محصول، شما هم در درمان یک حیوان پناهگاهی سهیم شدید.»</p>
</section>
</div>
{/* Sidebar Summary */}

View File

@ -130,39 +130,37 @@ 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 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">
<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">
{/* Logo & Mobile Toggle Area */}
<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>
<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>
{/* 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>
{/* 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', "ایران")}
</span>
<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>
</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>
</div>
{/* Navigation Items: Centered on XL screens (1224px+) */}

View File

@ -65,8 +65,10 @@ export default function IngredientWiki() {
const el = document.getElementById(`wiki-${termParam}`);
if (el) {
setTimeout(() => {
el.scrollIntoView({ behavior: 'smooth', block: 'center' });
}, 100);
const yOffset = -120;
const y = el.getBoundingClientRect().top + window.pageYOffset + yOffset;
window.scrollTo({ top: y, behavior: 'smooth' });
}, 200);
}
}
}, [termParam, ingredientsWiki]);

View File

@ -167,22 +167,8 @@ 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">
{/* 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">
{/* 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">
<button
onClick={() => router.push('/')}
className="hover:text-canina-blue transition-colors font-vazir cursor-pointer"
@ -197,7 +183,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.name}</span>
<span className="text-canina-blue font-vazir whitespace-nowrap font-bold">{product.nameFa || product.name}</span>
</nav>
{/* Global Single Grid Layout - Aligns Sticky Buy Box at the Top */}
@ -769,6 +755,45 @@ 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>
);
}