Compare commits

..

2 Commits

6 changed files with 222 additions and 147 deletions

View File

@ -1,5 +1,6 @@
"use client"; "use client";
import React, { useState, useMemo, useEffect } from "react"; import React, { useState, useMemo, useEffect } from "react";
import { toPersian } from "../lib/utils";
import { Product, PetType } from "../lib/data/products"; import { Product, PetType } from "../lib/data/products";
import { usePetStore } from "../lib/store/usePetStore"; import { usePetStore } from "../lib/store/usePetStore";
import { productService } from "../lib/services/productService"; import { productService } from "../lib/services/productService";
@ -160,15 +161,53 @@ const ArchiveProductCard: React.FC<{ product: Product }> = ({ product }) => {
))} ))}
</div> </div>
<div className="mt-auto flex items-center justify-between pt-4 border-t border-medical-gray-50"> <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">{product.price}</span> <span className="font-black text-medical-gray-900 font-vazir text-sm sm:text-base">{product.price}</span>
<button {(() => {
onClick={handleAddToCart} const cartItem = useCartStore.getState().items.find(i => i.product.id === product.id);
disabled={isAdding} if (cartItem && cartItem.quantity > 0) {
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" return (
> <div
{isAdding ? <Loader2 className="w-4 h-4 animate-spin" /> : <Plus className="w-4 h-4" />} onClick={(e) => { e.preventDefault(); e.stopPropagation(); }}
</button> 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>
</div> </div>
</Link> </Link>
@ -195,6 +234,7 @@ export default function ArchivePage({
const [activeSymptoms, setActiveSymptoms] = useState<string[]>(initialSymptoms ? initialSymptoms.split(',') : []); const [activeSymptoms, setActiveSymptoms] = useState<string[]>(initialSymptoms ? initialSymptoms.split(',') : []);
const [searchQuery, setSearchQuery] = useState(initialSearch); const [searchQuery, setSearchQuery] = useState(initialSearch);
const [isUpdating, setIsUpdating] = useState(false); const [isUpdating, setIsUpdating] = useState(false);
const [isMobileFilterOpen, setIsMobileFilterOpen] = useState(false);
const [filteredProducts, setFilteredProducts] = useState<Product[]>([]); const [filteredProducts, setFilteredProducts] = useState<Product[]>([]);
const [page, setPage] = useState(1); const [page, setPage] = useState(1);
const [meta, setMeta] = useState({ total: 0, lastPage: 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="min-h-screen bg-medical-gray-50 pb-20 px-4 pt-10 font-vazir" dir="rtl">
<div className="max-w-7xl mx-auto"> <div className="max-w-7xl mx-auto">
{/* Mobile Navigation & Breadcrumbs */} {/* Mobile Header & Filter Trigger */}
<div className="lg:hidden mb-10 space-y-4"> <div className="lg:hidden mb-6 space-y-4">
<button <div className="flex items-center justify-between">
onClick={() => router.back()} <button
className="flex items-center gap-2 text-medical-gray-500 font-bold hover:text-canina-blue transition-colors" onClick={() => router.back()}
> className="flex items-center gap-1 text-sm font-bold text-medical-gray-600"
<ChevronRight className="w-5 h-5 font-vazir" /> >
<span>بازگشت</span> <ChevronRight className="w-4 h-4 font-vazir" />
</button> <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> <span className="cursor-pointer hover:text-canina-blue" onClick={() => router.push('/')}>کانینا</span>
<ChevronLeft className="w-2.5 h-2.5" /> <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>
</div> </div>
{/* Desktop Breadcrumbs */} {/* 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> <span className="cursor-pointer hover:text-canina-blue" onClick={() => router.push('/')}>خانه</span>
<ChevronLeft className="w-2.5 h-2.5" /> <ChevronLeft className="w-2.5 h-2.5" />
<span className="cursor-pointer hover:text-canina-blue" onClick={() => { setSelectedCategory("all"); }}>کاتالوگ</span> <span className="cursor-pointer hover:text-canina-blue" onClick={() => { setSelectedCategory("all"); }}>کاتالوگ</span>
@ -354,14 +405,22 @@ export default function ArchivePage({
)} )}
</div> </div>
<div className="flex flex-col lg:flex-row gap-10"> <div className="flex flex-col lg:flex-row gap-8">
{/* Sidebar Filters */} {/* Sidebar Filters - Collapsible on Mobile */}
<aside className="lg:w-72 flex-shrink-0 space-y-8"> <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="bg-white rounded-[2rem] p-6 border border-medical-gray-200 shadow-sm">
<div className="flex items-center gap-2 mb-6"> <div className="flex items-center justify-between mb-6">
<Filter className="w-5 h-5 text-canina-blue" /> <div className="flex items-center gap-2">
<h3 className="font-black text-medical-gray-900">فیلترهای تخصصی</h3> <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>
<div className="space-y-6"> <div className="space-y-6">
@ -393,7 +452,7 @@ export default function ArchivePage({
{categories.map(cat => ( {categories.map(cat => (
<button <button
key={cat.id} 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'}`} 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} {cat.icon}

View File

@ -258,21 +258,21 @@ export default function BlogPage({ blogs = [] }: { blogs: BlogPost[] }) {
))} ))}
{/* Newsletter / CTA Box */} {/* Newsletter / CTA Box */}
<div className="bg-canina-blue rounded-[3rem] p-10 text-white relative overflow-hidden flex flex-col justify-center"> <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"> <div className="absolute top-0 right-0 p-8 opacity-20 pointer-events-none">
<Sparkles className="w-24 h-24" /> <Sparkles className="w-24 h-24" />
</div> </div>
<h3 className="text-3xl font-black mb-4 italic">مشترک خبرنامه علمی شوید</h3> <h3 className="text-2xl sm:text-3xl font-black mb-4 italic font-lalezar">مشترک خبرنامه علمی شوید</h3>
<p className="text-white/80 mb-8 font-medium leading-relaxed"> <p className="text-white/80 mb-6 font-medium leading-relaxed text-xs sm:text-sm font-shabnam">
ماهانه یک ایمیل حاوی مهم‌ترین نکات سلامت پت‌ها و کدهای تخفیف اختصاصی دریافت کنید. ماهانه یک ایمیل حاوی مهم‌ترین نکات سلامت پت‌ها و کدهای تخفیف اختصاصی دریافت کنید.
</p> </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 <input
type="email" type="email"
placeholder="آدرس ایمیل شما" 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> </button>
</div> </div>

View File

@ -147,121 +147,112 @@ export default function CheckoutPage() {
<span className="text-canina-blue">درگاه پرداخت امن و نهایی‌سازی</span> <span className="text-canina-blue">درگاه پرداخت امن و نهایی‌سازی</span>
</div> </div>
<div className="grid lg:grid-cols-12 gap-12"> <div className="grid lg:grid-cols-12 gap-8 lg:gap-12">
{/* Main Form */} {/* 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 */} {/* Step 1: Shipping */}
<section className="bg-white rounded-[3rem] border border-medical-gray-200 p-10 overflow-hidden relative"> <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-3 h-full bg-canina-blue opacity-20" /> <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-4 mb-10"> <div className="flex items-center gap-3 sm:gap-4 mb-6 sm:mb-10">
<div className="w-12 h-12 bg-medical-gray-900 text-white rounded-2xl flex items-center justify-center font-black">۱</div> <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-2xl font-black text-medical-gray-900 italic">اطلاعات ارسال</h2> <h2 className="text-xl sm:text-2xl font-black text-medical-gray-900 italic">اطلاعات ارسال</h2>
</div> </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"> <div className="space-y-2">
<label className="text-[10px] font-black text-medical-gray-400 uppercase tracking-widest block">نام و نام خانوادگی</label> <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>
<div className="space-y-2"> <div className="space-y-2">
<label className="text-[10px] font-black text-medical-gray-400 uppercase tracking-widest block">شماره تماس</label> <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>
<div className="md:col-span-2 space-y-2"> <div className="md:col-span-2 space-y-2">
<label className="text-[10px] font-black text-medical-gray-400 uppercase tracking-widest block">آدرس دقیق پستی</label> <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>
</div> </div>
</section> </section>
{/* Step 2: Payment */} {/* Step 2: Payment */}
<section className="bg-white rounded-[3rem] border border-medical-gray-200 p-10 overflow-hidden relative"> <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-3 h-full bg-medical-gray-900 opacity-20" /> <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-4 mb-10"> <div className="flex items-center gap-3 sm:gap-4 mb-6 sm:mb-10">
<div className="w-12 h-12 bg-medical-gray-900 text-white rounded-2xl flex items-center justify-center font-black">۲</div> <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-2xl font-black text-medical-gray-900 italic">شیوه پرداخت</h2> <h2 className="text-xl sm:text-2xl font-black text-medical-gray-900 italic">شیوه پرداخت</h2>
</div> </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: 'online', label: 'پرداخت آنلاین', desc: 'کارت‌های بانکی', icon: <CreditCard className="w-5 h-5 sm:w-6 sm:h-6" /> },
{ id: 'wallet', label: 'اعتبار حساب', desc: 'شارژ شده اختصاصی', icon: <Wallet className="w-6 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-6 h-6" /> } { id: 'cod', label: 'پرداخت در محل', desc: 'فقط تهران', icon: <Truck className="w-5 h-5 sm:w-6 sm:h-6" /> }
].map((pay) => ( ].map((pay) => (
<div <div
key={pay.id} key={pay.id}
onClick={async () => { onClick={async () => {
setPaymentMethod(pay.id); 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} {pay.icon}
</div> </div>
<h4 className="font-black text-sm text-medical-gray-900 mb-1">{pay.label}</h4> <div>
<p className="text-[10px] text-medical-gray-400 font-bold">{pay.desc}</p> <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>
))} ))}
</div> </div>
</section> </section>
{/* Step 3: Charity Section */} {/* Step 3: Charity Section */}
<section className="bg-white rounded-[3rem] border border-medical-gray-200 p-10 overflow-hidden relative"> <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-3 h-full bg-pink-500 opacity-20" /> <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-8"> <div className="flex items-center justify-between mb-6 sm:mb-8">
<div className="flex items-center gap-4"> <div className="flex items-center gap-3 sm:gap-4">
<div className="w-12 h-12 bg-pink-500 text-white rounded-2xl flex items-center justify-center"> <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-6 h-6 fill-white" /> <Heart className="w-5 h-5 sm:w-6 sm:h-6 fill-white" />
</div> </div>
<div> <div>
<h2 className="text-2xl font-black text-medical-gray-900 italic">ردپای مهربانی</h2> <h2 className="text-xl sm:text-2xl font-black text-medical-gray-900 italic">ردپای مهربانی</h2>
<p className="text-xs font-bold text-pink-500 mt-1">سهم شما در حمایت از حیوانات بی‌پناه</p> <p className="text-[10px] sm:text-xs font-bold text-pink-500 mt-0.5">سهم شما در حمایت از حیوانات بی‌پناه</p>
</div> </div>
</div> </div>
</div> </div>
<div className="bg-pink-50 rounded-[2.5rem] p-8 border border-pink-100"> <div className="bg-pink-50 rounded-[2rem] sm:rounded-[2.5rem] p-5 sm:p-8 border border-pink-100">
<div className="flex flex-wrap items-center justify-between gap-6"> <div className="flex flex-col sm:flex-row items-start sm:items-center justify-between gap-4 sm:gap-6">
<div className="flex-1 min-w-[280px]"> <div className="flex-1">
<h4 className="text-lg font-black text-medical-gray-900 italic mb-2">رند کردن مبلغ و کمک به پناهگاه</h4> <h4 className="text-base sm:text-lg font-black text-medical-gray-900 italic mb-1 sm:mb-2">رند کردن مبلغ و کمک به پناهگاه</h4>
<p className="text-sm text-medical-gray-600 leading-relaxed font-medium"> با انتخاب این گزینه، مابقی مبلغ تا ده هزار تومان بعدی یا ۱٪ از خرید شما (هر کدام بیشتر باشد) صرف تامین غذا و دارو برای حیوانات بی-سرپرست تحت حمایت کانینا می‌شود.</p> <p className="text-xs sm: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> </div>
<button <button
onClick={handleCharityToggle} onClick={handleCharityToggle}
className={cn( 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" 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> </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>
)}
</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> <p className="mt-6 text-[10px] text-center text-medical-gray-400 font-bold">«با خرید این محصول، شما هم در درمان یک حیوان پناهگاهی سهیم شدید.»</p>
</section> </section>
</div> </div>
{/* Sidebar Summary */} {/* Sidebar Summary */}

View File

@ -130,39 +130,37 @@ export default function Header({
</div> </div>
<header className="sticky top-0 z-50 bg-white/95 backdrop-blur-md border-b border-medical-gray-100 shadow-sm"> <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 */} {/* 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-1.5 sm:gap-2 min-w-0">
<div className="flex items-center gap-2"> {/* Mobile Menu Toggle */}
{/* Mobile Menu Toggle (visible below 800px) */} <button
<button onClick={() => setIsMobileMenuOpen(!isMobileMenuOpen)}
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"
className="min-[800px]:hidden p-2 rounded-xl text-medical-gray-600 hover:bg-medical-gray-50 transition-all flex-shrink-0" aria-label="منو"
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" />}
{isMobileMenuOpen ? <X className="w-6 h-6" /> : <Menu className="w-6 h-6" />} </button>
</button>
{/* Logo Section */} {/* Logo Section */}
<Link <Link
href="/" href="/"
className="flex items-center gap-2 sm:gap-3 cursor-pointer group" className="flex items-center gap-1.5 sm:gap-3 cursor-pointer group min-w-0"
onClick={() => setIsMobileMenuOpen(false)} 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="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 gap-0.5 sm:gap-1"> <div className="flex flex-col justify-center min-w-0">
<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"> <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 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"> <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', "ایران")} {getText('brand_name_fa', "ایران")}
</span>
</span> </span>
<span className="text-[8px] sm:text-[9px] text-medical-gray-400 font-bold uppercase tracking-wider font-vazir leading-none whitespace-nowrap"> </span>
{getText('brand_subtitle', "نماینده رسمی Canina Pharma GmbH آلمان")} <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> نماینده رسمی <span className="block sm:inline text-[6px] sm:text-[9px]">CANINA PHARMA GMBH</span>
</div> </span>
</Link> </div>
</div> </Link>
</div> </div>
{/* Navigation Items: Centered on XL screens (1224px+) */} {/* Navigation Items: Centered on XL screens (1224px+) */}

View File

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

View File

@ -167,22 +167,8 @@ export default function ProductPage({ productSlug }: { productSlug: string }) {
return ( return (
<div className="min-h-screen bg-medical-gray-50 pt-2 pb-20 px-4 md:px-0" dir="rtl"> <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"> <div className="max-w-7xl mx-auto">
{/* Mobile Header with Back Button */} {/* Breadcrumbs for Mobile and Desktop */}
<div className="flex items-center justify-between mb-6 md:hidden"> <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.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 <button
onClick={() => router.push('/')} onClick={() => router.push('/')}
className="hover:text-canina-blue transition-colors font-vazir cursor-pointer" className="hover:text-canina-blue transition-colors font-vazir cursor-pointer"
@ -197,7 +183,7 @@ export default function ProductPage({ productSlug }: { productSlug: string }) {
{product.category} {product.category}
</button> </button>
<ChevronLeft className="w-3.5 h-3.5 flex-shrink-0 text-medical-gray-300" /> <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> </nav>
{/* Global Single Grid Layout - Aligns Sticky Buy Box at the Top */} {/* Global Single Grid Layout - Aligns Sticky Buy Box at the Top */}
@ -769,6 +755,45 @@ export default function ProductPage({ productSlug }: { productSlug: string }) {
</div> </div>
)} )}
</AnimatePresence> </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> </div>
); );
} }