Compare commits
23 Commits
0d805b0eb9
...
27ef5979aa
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
27ef5979aa | ||
|
|
51b661542a | ||
|
|
3683a768a8 | ||
|
|
85b542e8b4 | ||
|
|
13a3b1f405 | ||
|
|
54ef14f006 | ||
|
|
1a1d828358 | ||
|
|
cd52ac2b7d | ||
|
|
6cd5e747de | ||
|
|
5b07ddbf8f | ||
|
|
078f9ba1f2 | ||
|
|
f367499a5c | ||
|
|
c7b944f5c4 | ||
|
|
00a217ee02 | ||
|
|
e1da54f2f5 | ||
|
|
5005f0e68f | ||
|
|
12265c88e8 | ||
|
|
0fa2b8c1d9 | ||
|
|
72a4073113 | ||
|
|
1c93aec1c9 | ||
|
|
19c86c9955 | ||
|
|
913317809f | ||
|
|
1340a2be87 |
@ -88,6 +88,6 @@
|
|||||||
"testEnvironment": "node"
|
"testEnvironment": "node"
|
||||||
},
|
},
|
||||||
"prisma": {
|
"prisma": {
|
||||||
"seed": "ts-node prisma/seed.ts && ts-node prisma/seed-products.ts && ts-node prisma/seed-home.ts"
|
"seed": "ts-node prisma/seed.ts"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -255,7 +255,10 @@ async function main() {
|
|||||||
|
|
||||||
// 2. Seed Scientific Terms
|
// 2. Seed Scientific Terms
|
||||||
console.log('Seeding Scientific Terms...');
|
console.log('Seeding Scientific Terms...');
|
||||||
const termsFilePath = path.join(process.cwd() + "/prisma", '..', '..', 'frontend', 'application', 'lib', 'data', 'scientificTerms.ts');
|
let termsFilePath = path.join(process.cwd() + "/prisma", '..', '..', 'frontend', 'application', 'lib', 'data', 'scientificTerms.ts');
|
||||||
|
if (!fs.existsSync(termsFilePath)) {
|
||||||
|
termsFilePath = path.join(process.cwd(), 'prisma', 'scientificTerms.ts');
|
||||||
|
}
|
||||||
if (fs.existsSync(termsFilePath)) {
|
if (fs.existsSync(termsFilePath)) {
|
||||||
const termsContent = fs.readFileSync(termsFilePath, 'utf-8');
|
const termsContent = fs.readFileSync(termsFilePath, 'utf-8');
|
||||||
const termsJsCode = ts.transpile(termsContent, {
|
const termsJsCode = ts.transpile(termsContent, {
|
||||||
@ -290,7 +293,25 @@ async function main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('Seeding completed successfully!');
|
// 3. Seed Products & Categories
|
||||||
|
console.log('Seeding Products & Categories...');
|
||||||
|
try {
|
||||||
|
const { main: seedProducts } = await import('./seed-products');
|
||||||
|
await seedProducts();
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Failed to seed products:', err);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. Seed Home Components & Testimonials
|
||||||
|
console.log('Seeding Home Components...');
|
||||||
|
try {
|
||||||
|
const { main: seedHome } = await import('./seed-home');
|
||||||
|
await seedHome();
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Failed to seed home components:', err);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('All Seeding completed successfully!');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -35,17 +35,7 @@ export default function ClientLayout({ children }: { children: React.ReactNode }
|
|||||||
}
|
}
|
||||||
}, [fetchProfile, fetchSettings]);
|
}, [fetchProfile, fetchSettings]);
|
||||||
|
|
||||||
if (!isInitialized) {
|
// Remove full-page blocking screen to allow immediate render
|
||||||
return (
|
|
||||||
<div className="min-h-screen bg-medical-gray-50 flex flex-col items-center justify-center font-sans" dir="rtl">
|
|
||||||
<div className="flex flex-col items-center gap-4 text-center">
|
|
||||||
<div className="w-12 h-12 border-4 border-canina-blue border-t-transparent rounded-full animate-spin" />
|
|
||||||
<h2 className="text-xl font-black text-medical-gray-900 font-lalezar tracking-wide">در حال بارگذاری اطلاعات سایت...</h2>
|
|
||||||
<p className="text-sm text-medical-gray-500 font-shabnam">لطفاً شکیبا باشید</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Derived currentView from pathname for Header
|
// Derived currentView from pathname for Header
|
||||||
let currentView = "home";
|
let currentView = "home";
|
||||||
@ -114,7 +104,7 @@ export default function ClientLayout({ children }: { children: React.ReactNode }
|
|||||||
petName={advisorData?.name}
|
petName={advisorData?.name}
|
||||||
isAdvisorContext={!!advisorData}
|
isAdvisorContext={!!advisorData}
|
||||||
/>
|
/>
|
||||||
<Toaster position="top-center" expand={true} richColors />
|
<Toaster position="top-center" expand={true} richColors closeButton />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -104,7 +104,7 @@
|
|||||||
|
|
||||||
html, body, #root {
|
html, body, #root {
|
||||||
font-family: "Vazirmatn" !important;
|
font-family: "Vazirmatn" !important;
|
||||||
@apply bg-medical-gray-50 text-medical-gray-900 antialiased overflow-x-hidden max-w-[100vw];
|
@apply bg-medical-gray-50 text-medical-gray-900 antialiased max-w-[100vw];
|
||||||
font-feature-settings: "ss01", "ss02", "cv01", "cv11";
|
font-feature-settings: "ss01", "ss02", "cv01", "cv11";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
import { Suspense } from "react";
|
||||||
import IngredientWiki from "../../components/IngredientWiki";
|
import IngredientWiki from "../../components/IngredientWiki";
|
||||||
import type { Metadata } from 'next';
|
import type { Metadata } from 'next';
|
||||||
|
|
||||||
@ -18,5 +19,9 @@ export const metadata: Metadata = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default function WikiPage() {
|
export default function WikiPage() {
|
||||||
return <IngredientWiki />;
|
return (
|
||||||
|
<Suspense fallback={<div className="min-h-screen flex items-center justify-center font-vazir text-sm">در حال بارگذاری دانشنامه...</div>}>
|
||||||
|
<IngredientWiki />
|
||||||
|
</Suspense>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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>
|
||||||
|
{(() => {
|
||||||
|
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
|
<button
|
||||||
onClick={handleAddToCart}
|
onClick={handleAddToCart}
|
||||||
disabled={isAdding}
|
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"
|
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-4 h-4 animate-spin" /> : <Plus className="w-4 h-4" />}
|
{isAdding ? <Loader2 className="w-3.5 h-3.5 animate-spin" /> : <Plus className="w-3.5 h-3.5" />}
|
||||||
|
<span>خرید</span>
|
||||||
</button>
|
</button>
|
||||||
|
);
|
||||||
|
})()}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Link>
|
</Link>
|
||||||
@ -195,10 +234,12 @@ 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 });
|
||||||
|
|
||||||
|
const [symptomSearch, setSymptomSearch] = useState("");
|
||||||
const [categories, setCategories] = useState<{ id: string; label: string; icon: React.ReactNode }[]>([]);
|
const [categories, setCategories] = useState<{ id: string; label: string; icon: React.ReactNode }[]>([]);
|
||||||
const [symptoms, setSymptoms] = useState<string[]>([]);
|
const [symptoms, setSymptoms] = useState<string[]>([]);
|
||||||
|
|
||||||
@ -324,45 +365,55 @@ 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 */}
|
{/* Standard Breadcrumb Navigation & Integrated Back Button */}
|
||||||
<div className="lg:hidden mb-10 space-y-4">
|
<div className="flex items-center justify-between mb-8 pb-4 border-b border-medical-gray-200/60 font-vazir">
|
||||||
<button
|
<div className="flex items-center gap-2 text-xs font-bold text-medical-gray-400 whitespace-nowrap">
|
||||||
onClick={() => router.back()}
|
<span className="cursor-pointer hover:text-canina-blue transition-colors" onClick={() => router.push('/')}>خانه</span>
|
||||||
className="flex items-center gap-2 text-medical-gray-500 font-bold hover:text-canina-blue transition-colors"
|
<ChevronLeft className="w-3 h-3 text-medical-gray-300" />
|
||||||
>
|
<span className="cursor-pointer hover:text-canina-blue transition-colors" onClick={() => { setSelectedCategory("all"); }}>کاتالوگ</span>
|
||||||
<ChevronRight className="w-5 h-5 font-vazir" />
|
|
||||||
<span>بازگشت</span>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<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">فروشگاه تخصصی</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">
|
|
||||||
<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>
|
|
||||||
{selectedCategory !== "all" && (
|
{selectedCategory !== "all" && (
|
||||||
<>
|
<>
|
||||||
<ChevronLeft className="w-2.5 h-2.5" />
|
<ChevronLeft className="w-3 h-3 text-medical-gray-300" />
|
||||||
<span className="text-canina-blue">{CATEGORY_LABELS[selectedCategory] || selectedCategory}</span>
|
<span className="text-canina-blue font-black">{CATEGORY_LABELS[selectedCategory] || selectedCategory}</span>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex flex-col lg:flex-row gap-10">
|
<div className="flex items-center gap-2">
|
||||||
|
<button
|
||||||
|
onClick={() => setIsMobileFilterOpen(!isMobileFilterOpen)}
|
||||||
|
className="lg:hidden flex items-center gap-1.5 bg-canina-blue text-white px-3 py-1.5 rounded-lg text-xs font-bold shadow-xs"
|
||||||
|
>
|
||||||
|
<Filter className="w-3.5 h-3.5" />
|
||||||
|
<span>فیلترها {activeSymptoms.length > 0 || selectedPet !== "all" || selectedCategory !== "all" ? "•" : ""}</span>
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={() => router.push('/')}
|
||||||
|
className="px-3.5 py-1.5 bg-white border border-medical-gray-200 rounded-lg text-medical-gray-600 shadow-xs flex items-center gap-1.5 font-bold text-xs hover:border-canina-blue hover:text-canina-blue transition-all whitespace-nowrap"
|
||||||
|
>
|
||||||
|
<ChevronRight className="w-3.5 h-3.5" />
|
||||||
|
<span>بازگشت</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
{/* Sidebar Filters */}
|
<div className="flex flex-col lg:flex-row gap-8">
|
||||||
<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="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">
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
<Filter className="w-5 h-5 text-canina-blue" />
|
<Filter className="w-5 h-5 text-canina-blue" />
|
||||||
<h3 className="font-black text-medical-gray-900">فیلترهای تخصصی</h3>
|
<h3 className="font-black text-medical-gray-900">فیلترهای تخصصی</h3>
|
||||||
</div>
|
</div>
|
||||||
|
<button
|
||||||
|
onClick={() => setIsMobileFilterOpen(false)}
|
||||||
|
className="lg:hidden text-xs text-medical-gray-400 font-bold"
|
||||||
|
>
|
||||||
|
بستن ✕
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="space-y-6">
|
<div className="space-y-6">
|
||||||
{/* Pet Type */}
|
{/* Pet Type */}
|
||||||
@ -393,7 +444,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}
|
||||||
@ -403,7 +454,7 @@ export default function ArchivePage({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Symptoms Pill Tags */}
|
{/* Symptoms Pill Tags with Search Field */}
|
||||||
<div>
|
<div>
|
||||||
<div className="flex items-center justify-between mb-3">
|
<div className="flex items-center justify-between mb-3">
|
||||||
<span className="text-[10px] font-black text-medical-gray-400 uppercase tracking-widest">جستجو بر اساس علائم</span>
|
<span className="text-[10px] font-black text-medical-gray-400 uppercase tracking-widest">جستجو بر اساس علائم</span>
|
||||||
@ -416,10 +467,21 @@ export default function ArchivePage({
|
|||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-wrap gap-1.5 max-h-52 overflow-y-auto scrollbar-thin scrollbar-thumb-medical-gray-200 scrollbar-track-transparent pr-0.5">
|
<div className="relative mb-3">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
placeholder="جستجوی علائم..."
|
||||||
|
value={symptomSearch}
|
||||||
|
onChange={(e) => setSymptomSearch(e.target.value)}
|
||||||
|
className="w-full bg-medical-gray-50 border border-medical-gray-200 rounded-xl py-2 px-3 text-xs outline-none focus:border-canina-blue font-vazir"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-wrap gap-1.5 max-h-48 overflow-y-auto scrollbar-thin scrollbar-thumb-medical-gray-200 scrollbar-track-transparent pr-0.5">
|
||||||
{symptoms.length === 0 ? (
|
{symptoms.length === 0 ? (
|
||||||
<span className="text-[10px] text-medical-gray-400">در حال بارگذاری...</span>
|
<span className="text-[10px] text-medical-gray-400">در حال بارگذاری...</span>
|
||||||
) : symptoms.map(s => (
|
) : symptoms
|
||||||
|
.filter(s => s.toLowerCase().includes(symptomSearch.toLowerCase()))
|
||||||
|
.map(s => (
|
||||||
<button
|
<button
|
||||||
key={s}
|
key={s}
|
||||||
onClick={() => toggleSymptom(s)}
|
onClick={() => toggleSymptom(s)}
|
||||||
@ -447,7 +509,7 @@ export default function ArchivePage({
|
|||||||
|
|
||||||
{/* Main Content */}
|
{/* Main Content */}
|
||||||
<main className="flex-1 relative">
|
<main className="flex-1 relative">
|
||||||
<div className="flex flex-col md:flex-row items-center justify-between mb-8 gap-4">
|
<div className="flex flex-col md:flex-row items-center justify-between mb-6 gap-4">
|
||||||
<h2 className="text-3xl font-black text-medical-gray-900">کاتولوگ دارویی <span className="text-canina-blue">Canina</span></h2>
|
<h2 className="text-3xl font-black text-medical-gray-900">کاتولوگ دارویی <span className="text-canina-blue">Canina</span></h2>
|
||||||
<div className="relative w-full md:w-80">
|
<div className="relative w-full md:w-80">
|
||||||
<Search className="absolute right-4 top-1/2 -translate-y-1/2 w-4 h-4 text-medical-gray-400" />
|
<Search className="absolute right-4 top-1/2 -translate-y-1/2 w-4 h-4 text-medical-gray-400" />
|
||||||
@ -461,6 +523,43 @@ export default function ArchivePage({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* Active Filters Bar with X Dismiss Cross Buttons */}
|
||||||
|
{(selectedCategory !== "all" || selectedPet !== "all" || activeSymptoms.length > 0 || searchQuery) && (
|
||||||
|
<div className="flex flex-wrap items-center gap-2 mb-6 bg-white p-4 rounded-2xl border border-medical-gray-200 shadow-sm font-vazir" dir="rtl">
|
||||||
|
<span className="text-xs font-black text-medical-gray-400 ml-2">فیلترهای فعال:</span>
|
||||||
|
{selectedCategory !== "all" && (
|
||||||
|
<span className="inline-flex items-center gap-1.5 px-3 py-1 bg-canina-blue/10 text-canina-blue rounded-xl text-xs font-black border border-canina-blue/20">
|
||||||
|
{CATEGORY_LABELS[selectedCategory] || selectedCategory}
|
||||||
|
<button onClick={() => setSelectedCategory("all")} className="hover:text-red-500 text-sm leading-none">✕</button>
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
{selectedPet !== "all" && (
|
||||||
|
<span className="inline-flex items-center gap-1.5 px-3 py-1 bg-canina-blue/10 text-canina-blue rounded-xl text-xs font-black border border-canina-blue/20">
|
||||||
|
پت: {selectedPet}
|
||||||
|
<button onClick={() => setSelectedPet("all")} className="hover:text-red-500 text-sm leading-none">✕</button>
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
{activeSymptoms.map(sym => (
|
||||||
|
<span key={sym} className="inline-flex items-center gap-1.5 px-3 py-1 bg-canina-blue/10 text-canina-blue rounded-xl text-xs font-black border border-canina-blue/20">
|
||||||
|
علائم: {sym}
|
||||||
|
<button onClick={() => toggleSymptom(sym)} className="hover:text-red-500 text-sm leading-none">✕</button>
|
||||||
|
</span>
|
||||||
|
))}
|
||||||
|
{searchQuery && (
|
||||||
|
<span className="inline-flex items-center gap-1.5 px-3 py-1 bg-canina-blue/10 text-canina-blue rounded-xl text-xs font-black border border-canina-blue/20">
|
||||||
|
جستجو: {searchQuery}
|
||||||
|
<button onClick={() => setSearchQuery("")} className="hover:text-red-500 text-sm leading-none">✕</button>
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
<button
|
||||||
|
onClick={() => { setSelectedCategory("all"); setSelectedPet("all"); setActiveSymptoms([]); setSearchQuery(""); }}
|
||||||
|
className="text-xs font-bold text-red-500 hover:underline mr-auto"
|
||||||
|
>
|
||||||
|
حذف همه فیلترها
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
<AnimatePresence mode="wait">
|
<AnimatePresence mode="wait">
|
||||||
{isUpdating ? (
|
{isUpdating ? (
|
||||||
<div key="skeleton" className="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-4 gap-6">
|
<div key="skeleton" className="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-4 gap-6">
|
||||||
|
|||||||
@ -1,7 +1,8 @@
|
|||||||
"use client";
|
"use client";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { motion } from "motion/react";
|
import { motion } from "motion/react";
|
||||||
import { ChevronRight, Calendar, User, ArrowLeft, Sparkles, BookOpen } from "lucide-react";
|
import { ChevronRight, Calendar, User, ArrowLeft, Sparkles, BookOpen, Mail, Check } from "lucide-react";
|
||||||
|
import { toast } from "sonner";
|
||||||
import { Product } from "../lib/data/products";
|
import { Product } from "../lib/data/products";
|
||||||
import { productService } from "../lib/services/productService";
|
import { productService } from "../lib/services/productService";
|
||||||
|
|
||||||
@ -31,13 +32,23 @@ export default function BlogPage({ blogs = [] }: { blogs: BlogPost[] }) {
|
|||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-medical-gray-50 pt-8 pb-20 px-4 font-vazir" dir="rtl">
|
<div className="min-h-screen bg-medical-gray-50 pt-8 pb-20 px-4 font-vazir" dir="rtl">
|
||||||
<div className="max-w-7xl mx-auto">
|
<div className="max-w-7xl mx-auto">
|
||||||
{/* Breadcrumbs */}
|
{/* Standard Breadcrumb Navigation & Integrated Back Button */}
|
||||||
<div className="flex items-center gap-2 text-[10px] font-black text-medical-gray-400 uppercase tracking-widest mb-10">
|
<div className="flex items-center justify-between mb-8 pb-4 border-b border-medical-gray-200/60 font-vazir" dir="rtl">
|
||||||
<span className="cursor-pointer hover:text-canina-blue" onClick={() => router.push('/')}>خانه</span>
|
<div className="flex items-center gap-2 text-xs font-bold text-medical-gray-400 whitespace-nowrap">
|
||||||
<ChevronRight className="w-2.5 h-2.5" />
|
<span className="cursor-pointer hover:text-canina-blue transition-colors" onClick={() => router.push('/')}>خانه</span>
|
||||||
<span className="cursor-pointer hover:text-canina-blue" onClick={() => setSelectedPost(null)}>مجله سلامت</span>
|
<ChevronRight className="w-3 h-3 text-medical-gray-300" />
|
||||||
<ChevronRight className="w-2.5 h-2.5" />
|
<span className="cursor-pointer hover:text-canina-blue transition-colors" onClick={() => setSelectedPost(null)}>مجله سلامت</span>
|
||||||
<span className="text-canina-blue">{selectedPost.title}</span>
|
<ChevronRight className="w-3 h-3 text-medical-gray-300" />
|
||||||
|
<span className="text-canina-blue font-black">{selectedPost.title}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button
|
||||||
|
onClick={() => setSelectedPost(null)}
|
||||||
|
className="px-3.5 py-1.5 bg-white border border-medical-gray-200 rounded-lg text-medical-gray-600 shadow-xs flex items-center gap-1.5 font-bold text-xs hover:border-canina-blue hover:text-canina-blue transition-all whitespace-nowrap"
|
||||||
|
>
|
||||||
|
<ChevronRight className="w-3.5 h-3.5" />
|
||||||
|
<span>بازگشت</span>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="grid lg:grid-cols-12 gap-12">
|
<div className="grid lg:grid-cols-12 gap-12">
|
||||||
@ -144,29 +155,37 @@ export default function BlogPage({ blogs = [] }: { blogs: BlogPost[] }) {
|
|||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-medical-gray-50 pt-8 pb-20 px-4 font-vazir" dir="rtl">
|
<div className="min-h-screen bg-medical-gray-50 pt-8 pb-20 px-4 font-vazir" dir="rtl">
|
||||||
<div className="max-w-7xl mx-auto">
|
<div className="max-w-7xl mx-auto">
|
||||||
{/* Header */}
|
{/* Breadcrumb Navigation & Integrated Back Button */}
|
||||||
<div className="flex flex-col md:flex-row items-center justify-between mb-16 gap-6">
|
<div className="flex items-center justify-between mb-8 pb-4 border-b border-medical-gray-200/60 font-vazir">
|
||||||
<div className="text-right">
|
<div className="flex items-center gap-2 text-xs font-bold text-medical-gray-400">
|
||||||
<div className="inline-flex items-center gap-2 px-3 py-1 bg-canina-blue/10 text-canina-blue rounded-full text-[10px] font-black uppercase tracking-widest mb-4">
|
<span className="cursor-pointer hover:text-canina-blue transition-colors" onClick={() => router.push('/')}>خانه</span>
|
||||||
<BookOpen className="w-3 h-3" />
|
<ChevronRight className="w-3 h-3 text-medical-gray-300" />
|
||||||
Canina Science Blog
|
<span className="text-canina-blue font-black">مجله سلامت</span>
|
||||||
</div>
|
|
||||||
<h1 className="text-4xl lg:text-6xl font-black text-medical-gray-900 italic leading-tight">
|
|
||||||
مجله تخصصی <span className="text-canina-blue">سلامت پتها</span>
|
|
||||||
</h1>
|
|
||||||
<p className="text-lg text-medical-gray-500 font-medium mt-4 max-w-xl">
|
|
||||||
آخرین یافتههای علمی محققین کانینا آلمان در مورد تغذیه و سلامت پتها.
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
onClick={() => router.push('/')}
|
onClick={() => router.push('/')}
|
||||||
className="px-8 py-3 bg-white border border-medical-gray-200 rounded-2xl text-medical-gray-700 shadow-sm flex items-center gap-2 font-black hover:bg-medical-gray-50 transition-all"
|
className="px-3.5 py-1.5 bg-white border border-medical-gray-200 rounded-lg text-medical-gray-600 shadow-xs flex items-center gap-1.5 font-bold text-xs hover:border-canina-blue hover:text-canina-blue transition-all whitespace-nowrap"
|
||||||
>
|
>
|
||||||
<ChevronRight className="w-5 h-5" />
|
<ChevronRight className="w-3.5 h-3.5" />
|
||||||
بازگشت به خانه
|
<span>بازگشت</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* Header */}
|
||||||
|
<div className="mb-10 text-right">
|
||||||
|
<div className="inline-flex items-center gap-2 px-3 py-1 bg-canina-blue/10 text-canina-blue rounded-full text-xs font-black uppercase tracking-widest mb-3">
|
||||||
|
<BookOpen className="w-3.5 h-3.5" />
|
||||||
|
<span>Canina Science Blog</span>
|
||||||
|
</div>
|
||||||
|
<h1 className="text-3xl sm:text-4xl lg:text-5xl font-black text-medical-gray-900 leading-tight">
|
||||||
|
مجله تخصصی <span className="text-canina-blue">سلامت پتها</span>
|
||||||
|
</h1>
|
||||||
|
<p className="text-sm sm:text-base text-medical-gray-500 font-medium mt-3 max-w-xl leading-relaxed">
|
||||||
|
آخرین یافتههای علمی محققین کانینا آلمان در مورد تغذیه و سلامت پتها.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
{/* Featured Post */}
|
{/* Featured Post */}
|
||||||
{blogs.length > 0 && (
|
{blogs.length > 0 && (
|
||||||
<div className="mb-20">
|
<div className="mb-20">
|
||||||
@ -257,26 +276,79 @@ export default function BlogPage({ blogs = [] }: { blogs: BlogPost[] }) {
|
|||||||
</motion.div>
|
</motion.div>
|
||||||
))}
|
))}
|
||||||
|
|
||||||
{/* Newsletter / CTA Box */}
|
{/* Ultra-Premium Redesigned Newsletter / CTA Box */}
|
||||||
<div className="bg-canina-blue rounded-[3rem] p-10 text-white relative overflow-hidden flex flex-col justify-center">
|
<motion.div
|
||||||
<div className="absolute top-0 right-0 p-8 opacity-20">
|
initial={{ opacity: 0, y: 30 }}
|
||||||
<Sparkles className="w-24 h-24" />
|
whileInView={{ opacity: 1, y: 0 }}
|
||||||
|
viewport={{ once: true }}
|
||||||
|
transition={{ duration: 0.7 }}
|
||||||
|
className="bg-gradient-to-br from-canina-blue via-canina-blue/95 to-medical-gray-900 rounded-[3rem] p-8 sm:p-14 text-white relative overflow-hidden font-vazir shadow-2xl border border-white/10"
|
||||||
|
dir="rtl"
|
||||||
|
>
|
||||||
|
{/* Decorative Glassmorphic Background Elements */}
|
||||||
|
<div className="absolute top-0 right-0 w-96 h-96 bg-canina-teal/15 rounded-full blur-[100px] pointer-events-none" />
|
||||||
|
<div className="absolute bottom-0 left-0 w-80 h-80 bg-canina-gold/10 rounded-full blur-[90px] pointer-events-none" />
|
||||||
|
<div className="absolute -top-12 -left-12 opacity-5 pointer-events-none select-none">
|
||||||
|
<span className="text-[180px] font-black italic tracking-tighter font-sans text-white">CANINA</span>
|
||||||
</div>
|
</div>
|
||||||
<h3 className="text-3xl font-black mb-4 italic">مشترک خبرنامه علمی شوید</h3>
|
|
||||||
<p className="text-white/80 mb-8 font-medium leading-relaxed">
|
<div className="relative z-10 max-w-4xl mx-auto flex flex-col items-center text-center space-y-8">
|
||||||
ماهانه یک ایمیل حاوی مهمترین نکات سلامت پتها و کدهای تخفیف اختصاصی دریافت کنید.
|
|
||||||
|
{/* Top Premium Badge */}
|
||||||
|
<div className="inline-flex items-center gap-2.5 px-4 py-2 bg-white/10 backdrop-blur-md rounded-full border border-white/20 shadow-inner">
|
||||||
|
<div className="w-6 h-6 rounded-lg bg-canina-gold text-canina-dark flex items-center justify-center font-black text-xs italic shadow-md">
|
||||||
|
C
|
||||||
|
</div>
|
||||||
|
<span className="text-xs font-black text-white/90 tracking-wider font-vazir">
|
||||||
|
خبرنامه اختصاصی پژوهشگاه کانینا آلمان
|
||||||
|
</span>
|
||||||
|
<Sparkles className="w-3.5 h-3.5 text-canina-gold animate-pulse" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Headline & Description */}
|
||||||
|
<div className="space-y-4 max-w-2xl">
|
||||||
|
<h3 className="text-3xl sm:text-4xl lg:text-5xl font-black font-vazir text-white leading-tight">
|
||||||
|
مشترک <span className="text-transparent bg-clip-text bg-gradient-to-r from-canina-gold via-white to-canina-teal">خبرنامه علمی</span> شوید
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm sm:text-base text-white/80 font-medium font-vazir leading-relaxed">
|
||||||
|
ماهانه یک ایمیل حاوی تازهترین یافتـههای پزشکی، کاتالوگهای درمانی اختصاصی کانینا و کدهای تخفیف ویژه برای شما ارسال میشود.
|
||||||
</p>
|
</p>
|
||||||
<div className="flex gap-2">
|
</div>
|
||||||
|
|
||||||
|
{/* Main Interactive Floating Input Bar */}
|
||||||
|
<div className="w-full max-w-xl">
|
||||||
|
<form onSubmit={(e) => { e.preventDefault(); toast.success("عضویت شما در خبرنامه علمی با موفقیت ثبت شد!"); }} className="w-full bg-white/15 backdrop-blur-xl border border-white/25 p-2 rounded-2xl sm:rounded-full flex flex-col sm:flex-row items-stretch sm:items-center gap-2 sm:gap-3 shadow-2xl hover:border-canina-gold/40 transition-all group" dir="ltr">
|
||||||
<input
|
<input
|
||||||
type="email"
|
type="email"
|
||||||
placeholder="آدرس ایمیل شما"
|
required
|
||||||
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"
|
placeholder="آدرس ایمیل شما (name@domain.com)..."
|
||||||
|
className="flex-1 bg-transparent border-none text-xs sm:text-sm outline-none text-white placeholder:text-white/45 px-3 sm:px-4 py-2.5 sm:py-0 font-sans text-left"
|
||||||
/>
|
/>
|
||||||
<button className="bg-white text-canina-blue px-6 py-3 rounded-xl font-black">
|
<button
|
||||||
عضویت
|
type="submit"
|
||||||
|
className="bg-canina-gold hover:bg-white text-canina-dark px-6 sm:px-8 py-3.5 rounded-xl sm:rounded-full font-black text-xs sm:text-sm transition-all duration-300 whitespace-nowrap shadow-xl hover:scale-105 flex items-center justify-center gap-2 font-vazir cursor-pointer flex-shrink-0"
|
||||||
|
dir="rtl"
|
||||||
|
>
|
||||||
|
<span>عضویت آنی</span>
|
||||||
|
<Mail className="w-4 h-4" />
|
||||||
</button>
|
</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Bottom Feature Micro Badges */}
|
||||||
|
<div className="pt-2 flex flex-wrap items-center justify-center gap-6 text-xs text-white/70 font-bold font-vazir border-t border-white/10 w-full max-w-xl">
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<Check className="w-4 h-4 text-canina-gold" />
|
||||||
|
<span>بدون اسپم (حداکثر ۱ ایمیل در ماه)</span>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<Check className="w-4 h-4 text-canina-gold" />
|
||||||
|
<span>امکان لغو عضویت با یک کلیک</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</motion.div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Synergy Products Cross-sell */}
|
{/* Synergy Products Cross-sell */}
|
||||||
|
|||||||
@ -147,107 +147,99 @@ 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>
|
||||||
|
<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>
|
<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>
|
||||||
|
</div>
|
||||||
{useRoundUp && (
|
{useRoundUp && (
|
||||||
<motion.div
|
<motion.div
|
||||||
initial={{ opacity: 0, y: 10 }}
|
initial={{ opacity: 0, y: 10 }}
|
||||||
@ -258,7 +250,6 @@ export default function CheckoutPage() {
|
|||||||
<span className="text-lg font-black font-vazir text-pink-500">{toPersian(charityDonation.toLocaleString())} تومان</span>
|
<span className="text-lg font-black font-vazir text-pink-500">{toPersian(charityDonation.toLocaleString())} تومان</span>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
)}
|
)}
|
||||||
</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>
|
||||||
|
|||||||
@ -29,7 +29,7 @@ export default function Footer({ onNavigate, onShopNavigate, onB2BOpen }: {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<footer className="bg-medical-gray-900 text-white pt-24 pb-12 font-shabnam relative" dir="rtl">
|
<footer className="bg-medical-gray-900 text-white pt-24 pb-36 sm:pb-12 font-shabnam relative" dir="rtl">
|
||||||
{/* Floating Back-to-Top Button */}
|
{/* Floating Back-to-Top Button */}
|
||||||
{showScroll && (
|
{showScroll && (
|
||||||
<button
|
<button
|
||||||
|
|||||||
@ -124,46 +124,45 @@ export default function Header({
|
|||||||
<>
|
<>
|
||||||
<AuthModal isOpen={isAuthModalOpen} onClose={() => setIsAuthModalOpen(false)} />
|
<AuthModal isOpen={isAuthModalOpen} onClose={() => setIsAuthModalOpen(false)} />
|
||||||
|
|
||||||
<div className="bg-canina-gold text-canina-dark text-xs font-black py-2.5 text-center font-vazir tracking-wider flex items-center justify-center gap-2">
|
<div className="sticky top-0 z-50 w-full shadow-sm">
|
||||||
|
<div className="bg-canina-gold text-canina-dark text-xs font-black py-2 text-center font-vazir tracking-wider flex items-center justify-center gap-2">
|
||||||
<span>🚚</span>
|
<span>🚚</span>
|
||||||
<span>{getText('shipping_notice', "ارسال رایگان برای سفارشهای بالای ۱۵۰ هزار تومان")}</span>
|
<span>{getText('shipping_notice', "ارسال رایگان برای سفارشهای بالای ۱۵۰ هزار تومان")}</span>
|
||||||
</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="bg-white/95 backdrop-blur-md border-b border-medical-gray-100">
|
||||||
<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-2 rounded-xl text-medical-gray-600 hover:bg-medical-gray-50 transition-all flex-shrink-0"
|
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="منو"
|
aria-label="منو"
|
||||||
>
|
>
|
||||||
{isMobileMenuOpen ? <X className="w-6 h-6" /> : <Menu className="w-6 h-6" />}
|
{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>
|
</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>
|
||||||
<span className="text-[8px] sm:text-[9px] text-medical-gray-400 font-bold uppercase tracking-wider font-vazir leading-none whitespace-nowrap">
|
<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">
|
||||||
{getText('brand_subtitle', "نماینده رسمی Canina Pharma GmbH آلمان")}
|
نماینده رسمی <span className="block sm:inline text-[6px] sm:text-[9px]">CANINA PHARMA GMBH</span>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Navigation Items: Centered on XL screens (1224px+) */}
|
{/* Navigation Items: Centered on XL screens (1224px+) */}
|
||||||
<nav className="hidden xl:flex items-center gap-1 flex-grow justify-center h-full">
|
<nav className="hidden xl:flex items-center gap-1 flex-grow justify-center h-full">
|
||||||
@ -249,15 +248,17 @@ export default function Header({
|
|||||||
<div className="flex items-center gap-2 sm:gap-4 flex-shrink-0 justify-end h-auto md:h-16 pl-1 sm:pl-2">
|
<div className="flex items-center gap-2 sm:gap-4 flex-shrink-0 justify-end h-auto md:h-16 pl-1 sm:pl-2">
|
||||||
|
|
||||||
{/* Elastic Search */}
|
{/* Elastic Search */}
|
||||||
<div className="relative flex items-center justify-end z-20">
|
{/* Elastic Search */}
|
||||||
|
<div className="relative flex items-center justify-end z-30">
|
||||||
<AnimatePresence>
|
<AnimatePresence>
|
||||||
{isSearchFocused && (
|
{isSearchFocused && (
|
||||||
<motion.div
|
<motion.div
|
||||||
initial={{ width: 0, opacity: 0 }}
|
initial={{ width: 0, opacity: 0 }}
|
||||||
animate={{ width: 260, opacity: 1 }}
|
animate={{ width: 220, opacity: 1 }}
|
||||||
exit={{ width: 0, opacity: 0 }}
|
exit={{ width: 0, opacity: 0 }}
|
||||||
transition={{ type: "spring", damping: 25, stiffness: 220 }}
|
transition={{ type: "spring", damping: 25, stiffness: 220 }}
|
||||||
className="absolute right-0 top-1/2 -translate-y-1/2 bg-white border border-canina-blue/30 border-l rounded-2xl shadow-xl shadow-canina-blue/5 overflow-hidden h-10 sm:h-12 flex items-center pr-10 pl-3 z-25"
|
className="absolute left-full sm:right-0 top-1/2 -translate-y-1/2 bg-white border border-canina-blue/30 rounded-2xl shadow-2xl overflow-hidden h-10 sm:h-12 flex items-center pr-10 pl-3 z-30"
|
||||||
|
style={{ transformOrigin: "right center" }}
|
||||||
>
|
>
|
||||||
<form onSubmit={handleSearch} className="w-full flex items-center">
|
<form onSubmit={handleSearch} className="w-full flex items-center">
|
||||||
<input
|
<input
|
||||||
@ -510,6 +511,7 @@ export default function Header({
|
|||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
</div>
|
||||||
|
|
||||||
{/* Mobile Drawer Menu */}
|
{/* Mobile Drawer Menu */}
|
||||||
<AnimatePresence>
|
<AnimatePresence>
|
||||||
|
|||||||
@ -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]);
|
||||||
@ -75,28 +77,21 @@ export default function IngredientWiki() {
|
|||||||
<div className="bg-white py-12 px-4 overflow-hidden font-vazir" dir="rtl">
|
<div className="bg-white py-12 px-4 overflow-hidden font-vazir" dir="rtl">
|
||||||
<div className="max-w-7xl mx-auto">
|
<div className="max-w-7xl mx-auto">
|
||||||
|
|
||||||
{/* Mobile Navigation & Breadcrumbs */}
|
{/* Standard Breadcrumb Navigation & Integrated Back Button */}
|
||||||
<div className="lg:hidden mb-12 space-y-4">
|
<div className="flex items-center justify-between mb-8 pb-4 border-b border-medical-gray-200/60 font-vazir" dir="rtl">
|
||||||
|
<div className="flex items-center gap-2 text-xs font-bold text-medical-gray-400 whitespace-nowrap">
|
||||||
|
<span className="cursor-pointer hover:text-canina-blue transition-colors" onClick={() => router.push('/')}>خانه</span>
|
||||||
|
<ChevronLeft className="w-3 h-3 text-medical-gray-300" />
|
||||||
|
<span className="text-canina-blue font-black">دانشنامه مواد نایاب و ارگانیک</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
onClick={() => router.back()}
|
onClick={() => router.push('/')}
|
||||||
className="flex items-center gap-2 text-medical-gray-500 font-bold hover:text-canina-blue transition-colors"
|
className="px-3.5 py-1.5 bg-white border border-medical-gray-200 rounded-lg text-medical-gray-600 shadow-xs flex items-center gap-1.5 font-bold text-xs hover:border-canina-blue hover:text-canina-blue transition-all whitespace-nowrap"
|
||||||
>
|
>
|
||||||
<ChevronRight className="w-5 h-5" />
|
<ChevronRight className="w-3.5 h-3.5" />
|
||||||
<span>بازگشت</span>
|
<span>بازگشت</span>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<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">دانشنامه علمی</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-12">
|
|
||||||
<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>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex flex-col items-center text-center mb-20">
|
<div className="flex flex-col items-center text-center mb-20">
|
||||||
@ -229,21 +224,29 @@ export default function IngredientWiki() {
|
|||||||
initial={{ opacity: 0, scale: 0.9 }}
|
initial={{ opacity: 0, scale: 0.9 }}
|
||||||
whileInView={{ opacity: 1, scale: 1 }}
|
whileInView={{ opacity: 1, scale: 1 }}
|
||||||
viewport={{ once: true }}
|
viewport={{ once: true }}
|
||||||
className="bg-medical-gray-100 rounded-[4rem] p-12 relative overflow-hidden"
|
className="bg-medical-gray-100/80 rounded-[3rem] p-8 sm:p-10 border border-medical-gray-200/60 relative overflow-hidden"
|
||||||
>
|
>
|
||||||
<div className="absolute top-0 right-0 p-8">
|
<div className="flex items-center justify-between mb-8 pb-4 border-b border-medical-gray-200/60">
|
||||||
<div className="text-[10px] font-black text-medical-gray-400 uppercase tracking-[0.3em]">موجود در محصولات</div>
|
<div className="flex items-center gap-2">
|
||||||
|
<span className="w-2.5 h-2.5 rounded-full bg-canina-blue animate-pulse" />
|
||||||
|
<h4 className="text-xs sm:text-sm font-black text-medical-gray-900 font-vazir">موجود در محصولات کاتالوگ</h4>
|
||||||
|
</div>
|
||||||
|
<span className="text-[10px] font-black text-canina-blue bg-canina-blue/10 px-3 py-1 rounded-full font-vazir">
|
||||||
|
{hasIngredient.length} محصول
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6 relative z-10">
|
<div className="grid grid-cols-1 sm:grid-cols-2 gap-5 relative z-10">
|
||||||
{hasIngredient.length > 0 ? hasIngredient.map(p => (
|
{hasIngredient.length > 0 ? hasIngredient.map(p => (
|
||||||
<Link
|
<Link
|
||||||
key={p.id}
|
key={p.id}
|
||||||
href={`/shop/${p.slug || p.id}`}
|
href={`/shop/${p.slug || p.id}`}
|
||||||
className="bg-white rounded-[2.5rem] p-6 shadow-xl hover:scale-105 transition-transform cursor-pointer group block"
|
className="bg-white rounded-[2rem] p-5 shadow-lg border border-medical-gray-200/70 hover:border-canina-blue/40 hover:shadow-xl hover:scale-[1.03] transition-all cursor-pointer group flex flex-col justify-between"
|
||||||
>
|
>
|
||||||
<img src={p.image} alt={p.name} className="w-24 h-24 object-contain mx-auto mb-4" referrerPolicy="no-referrer" />
|
<div className="aspect-square bg-medical-gray-50 rounded-2xl p-4 mb-4 flex items-center justify-center">
|
||||||
<h4 className="text-sm font-black text-center text-medical-gray-900 group-hover:text-canina-blue transition-colors px-2">{p.name}</h4>
|
<img src={p.image} alt={p.name} className="max-h-24 w-auto object-contain group-hover:scale-110 transition-transform duration-500" referrerPolicy="no-referrer" />
|
||||||
|
</div>
|
||||||
|
<h4 className="text-xs font-black text-center text-medical-gray-900 group-hover:text-canina-blue transition-colors px-1 leading-snug font-vazir">{p.name}</h4>
|
||||||
</Link>
|
</Link>
|
||||||
)) : (
|
)) : (
|
||||||
<div className="col-span-full py-8 text-center">
|
<div className="col-span-full py-8 text-center">
|
||||||
|
|||||||
@ -161,66 +161,66 @@ export default function ProductPage({ productSlug }: { productSlug: string }) {
|
|||||||
setItemQuantity(suggestedQty);
|
setItemQuantity(suggestedQty);
|
||||||
}, [calculation?.duration]);
|
}, [calculation?.duration]);
|
||||||
|
|
||||||
if (isLoading) return <div className="min-h-screen flex items-center justify-center">Loading...</div>;
|
if (isLoading) return (
|
||||||
|
<div className="min-h-screen bg-medical-gray-50 p-6 max-w-7xl mx-auto font-vazir" dir="rtl">
|
||||||
|
<div className="animate-pulse space-y-6">
|
||||||
|
<div className="h-8 bg-medical-gray-200 rounded-2xl w-48" />
|
||||||
|
<div className="grid md:grid-cols-12 gap-8">
|
||||||
|
<div className="md:col-span-5 h-80 bg-white border border-medical-gray-200 rounded-[2.5rem]" />
|
||||||
|
<div className="md:col-span-7 space-y-4">
|
||||||
|
<div className="h-10 bg-medical-gray-200 rounded-2xl w-3/4" />
|
||||||
|
<div className="h-6 bg-medical-gray-100 rounded-xl w-1/2" />
|
||||||
|
<div className="h-24 bg-medical-gray-100 rounded-2xl w-full" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
if (!product || !fullProduct || !calculation) return <div className="min-h-screen flex items-center justify-center">محصول یافت نشد</div>;
|
if (!product || !fullProduct || !calculation) return <div className="min-h-screen flex items-center justify-center">محصول یافت نشد</div>;
|
||||||
|
|
||||||
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-36 sm:pb-20 px-4 sm:px-6 lg:px-8 font-vazir" dir="rtl">
|
||||||
<div className="max-w-7xl mx-auto">
|
<div className="max-w-7xl mx-auto w-full">
|
||||||
{/* Mobile Header with Back Button */}
|
{/* Standard Breadcrumb Navigation & Integrated Back Button */}
|
||||||
<div className="flex items-center justify-between mb-6 md:hidden">
|
<div className="flex items-center justify-between mb-8 pb-4 border-b border-medical-gray-200/60 font-vazir" dir="rtl">
|
||||||
|
<div className="flex items-center gap-2 text-xs font-bold text-medical-gray-400 whitespace-nowrap">
|
||||||
|
<span className="cursor-pointer hover:text-canina-blue transition-colors" onClick={() => router.push('/')}>خانه</span>
|
||||||
|
<ChevronLeft className="w-3 h-3 text-medical-gray-300" />
|
||||||
|
<span className="cursor-pointer hover:text-canina-blue transition-colors" onClick={() => router.push('/shop')}>فروشگاه</span>
|
||||||
|
<ChevronLeft className="w-3 h-3 text-medical-gray-300" />
|
||||||
|
<span className="text-canina-blue font-black">{product.nameFa || product.name}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
onClick={() => router.back()}
|
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"
|
className="px-3.5 py-1.5 bg-white border border-medical-gray-200 rounded-lg text-medical-gray-600 shadow-xs flex items-center gap-1.5 font-bold text-xs hover:border-canina-blue hover:text-canina-blue transition-all whitespace-nowrap"
|
||||||
>
|
>
|
||||||
<ChevronRight className="w-5 h-5" />
|
<ChevronRight className="w-3.5 h-3.5" />
|
||||||
بازگشت
|
<span>بازگشت</span>
|
||||||
</button>
|
</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>
|
||||||
</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"
|
|
||||||
>
|
|
||||||
خانه
|
|
||||||
</button>
|
|
||||||
<ChevronLeft className="w-3.5 h-3.5 flex-shrink-0 text-medical-gray-300" />
|
|
||||||
<button
|
|
||||||
onClick={() => router.push(`/shop?category=${product.categorySlug}`)}
|
|
||||||
className="hover:text-canina-blue cursor-pointer font-vazir"
|
|
||||||
>
|
|
||||||
{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>
|
|
||||||
</nav>
|
|
||||||
|
|
||||||
{/* Global Single Grid Layout - Aligns Sticky Buy Box at the Top */}
|
{/* Global Single Grid Layout - Aligns Sticky Buy Box at the Top */}
|
||||||
<div className="grid lg:grid-cols-12 gap-12 items-start">
|
<div className="grid grid-cols-1 lg:grid-cols-12 gap-12 items-start w-full">
|
||||||
|
|
||||||
{/* Right/Main Content Column (lg:col-span-8) */}
|
{/* Right/Main Content Column (lg:col-span-8) */}
|
||||||
<div className="lg:col-span-8 space-y-12">
|
<div className="w-full lg:col-span-8 space-y-12">
|
||||||
|
|
||||||
{/* Above the Fold Grid */}
|
{/* Above the Fold Grid */}
|
||||||
<div className="grid md:grid-cols-12 gap-12 items-start">
|
<div className="grid grid-cols-1 md:grid-cols-12 gap-8 md:gap-12 items-center md:items-start text-center md:text-right font-vazir w-full" dir="rtl">
|
||||||
{/* Right Column: Product Image Frame (md:col-span-5) */}
|
{/* Right Column: Product Image Frame (md:col-span-5) */}
|
||||||
<div className="md:col-span-5 w-full">
|
<div className="md:col-span-5 w-full mx-auto max-w-sm md:max-w-none">
|
||||||
<motion.div
|
<motion.div
|
||||||
initial={{ opacity: 0, scale: 0.95 }}
|
initial={{ opacity: 0, scale: 0.95 }}
|
||||||
animate={{ opacity: 1, scale: 1 }}
|
animate={{ opacity: 1, scale: 1 }}
|
||||||
className="bg-white rounded-[2.5rem] border border-medical-gray-200 shadow-xl relative group overflow-hidden h-[380px] flex items-center justify-center p-8"
|
className="bg-white rounded-[2.5rem] border border-medical-gray-200 shadow-xl relative group overflow-hidden h-[300px] sm:h-[380px] flex items-center justify-center p-6 sm:p-8"
|
||||||
>
|
>
|
||||||
<div className="absolute top-6 left-6 flex flex-col gap-2 z-10">
|
<div className="absolute top-4 left-4 sm:top-6 sm:left-6 flex flex-col gap-1.5 sm:gap-2 z-10 items-start">
|
||||||
<div className="px-3 py-1 bg-green-500 text-white rounded-full text-[10px] font-black uppercase tracking-widest flex items-center gap-1 font-vazir shadow-sm">
|
<div className="px-2.5 py-1 bg-green-500 text-white rounded-full text-[9px] sm:text-[10px] font-black uppercase tracking-widest flex items-center gap-1 font-vazir shadow-sm">
|
||||||
<CheckCircle2 className="w-3 h-3" />
|
<CheckCircle2 className="w-3 h-3" />
|
||||||
موجود در انبار
|
موجود در انبار
|
||||||
</div>
|
</div>
|
||||||
<div className="px-3 py-1 bg-canina-blue text-white rounded-full text-[10px] font-black uppercase tracking-widest font-vazir whitespace-nowrap shadow-sm">
|
<div className="px-2.5 py-1 bg-canina-blue text-white rounded-full text-[9px] sm:text-[10px] font-black uppercase tracking-widest font-vazir whitespace-nowrap shadow-sm">
|
||||||
گرید دارویی اختصاصی
|
گرید دارویی اختصاصی
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -228,15 +228,15 @@ export default function ProductPage({ productSlug }: { productSlug: string }) {
|
|||||||
src={product.image}
|
src={product.image}
|
||||||
alt={product.name}
|
alt={product.name}
|
||||||
className="w-full h-full"
|
className="w-full h-full"
|
||||||
imgClassName="max-h-[300px] w-auto object-contain drop-shadow-2xl group-hover:scale-105 transition-transform duration-700 mx-auto my-auto"
|
imgClassName="max-h-[240px] sm:max-h-[300px] w-auto object-contain drop-shadow-2xl group-hover:scale-105 transition-transform duration-700 mx-auto my-auto"
|
||||||
/>
|
/>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Left Column: Product Title & Description (md:col-span-7) */}
|
{/* Left Column: Product Title & Description (md:col-span-7) */}
|
||||||
<div className="md:col-span-7 space-y-6">
|
<div className="md:col-span-7 space-y-4 sm:space-y-6 flex flex-col items-center md:items-start">
|
||||||
<div>
|
<div className="w-full flex flex-col items-center md:items-start">
|
||||||
<div className="flex flex-wrap items-center gap-3 mb-4">
|
<div className="flex flex-wrap justify-center md:justify-start items-center gap-2 sm:gap-3 mb-3 sm:mb-4">
|
||||||
<div className="px-3 py-1 bg-canina-blue text-white rounded-full text-[10px] font-black uppercase tracking-widest font-vazir whitespace-nowrap shadow-sm">
|
<div className="px-3 py-1 bg-canina-blue text-white rounded-full text-[10px] font-black uppercase tracking-widest font-vazir whitespace-nowrap shadow-sm">
|
||||||
استاندارد صنعتی آلمان
|
استاندارد صنعتی آلمان
|
||||||
</div>
|
</div>
|
||||||
@ -246,17 +246,17 @@ export default function ProductPage({ productSlug }: { productSlug: string }) {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col gap-2 mb-4">
|
<div className="flex flex-col gap-1.5 mb-4 text-center md:text-right w-full">
|
||||||
<h1 dir="rtl" className="text-2xl md:text-3xl lg:text-4xl font-black text-medical-gray-900 leading-tight font-vazir text-right">
|
<h1 dir="rtl" className="text-xl sm:text-2xl md:text-3xl lg:text-4xl font-black text-medical-gray-900 leading-tight font-vazir">
|
||||||
{product.nameFa || product.name}
|
{product.nameFa || product.name}
|
||||||
</h1>
|
</h1>
|
||||||
{product.nameEn && (
|
{product.nameEn && (
|
||||||
<h2 dir="ltr" className="text-base md:text-lg text-slate-400 font-bold italic font-sans text-left">
|
<h2 dir="ltr" className="text-xs sm:text-base text-slate-400 font-bold italic font-sans text-center md:text-left">
|
||||||
{product.nameEn}
|
{product.nameEn}
|
||||||
</h2>
|
</h2>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<p className="text-xl text-canina-blue font-bold italic opacity-70 leading-relaxed max-w-2xl font-vazir mb-6 text-right" dir="rtl">
|
<p className="text-base sm:text-xl text-canina-blue font-bold italic opacity-80 leading-relaxed max-w-2xl font-vazir mb-4 text-center md:text-right" dir="rtl">
|
||||||
{isMounted && pets.length > 0 ? (
|
{isMounted && pets.length > 0 ? (
|
||||||
product.optimisticTemplate?.replace("[PetName]", activePet?.name || "").replace("[OnSet]", product.onSetOfAction || "به زودی")
|
product.optimisticTemplate?.replace("[PetName]", activePet?.name || "").replace("[OnSet]", product.onSetOfAction || "به زودی")
|
||||||
) : (
|
) : (
|
||||||
@ -264,9 +264,11 @@ export default function ProductPage({ productSlug }: { productSlug: string }) {
|
|||||||
)}
|
)}
|
||||||
</p>
|
</p>
|
||||||
{fullProduct.shortDescription && (
|
{fullProduct.shortDescription && (
|
||||||
<p className="text-lg text-medical-gray-600 font-bold leading-relaxed max-w-3xl font-vazir border-r-4 border-canina-blue pr-6 py-2 bg-canina-blue/5 rounded-l-2xl">
|
<div className="w-full text-right bg-canina-blue/5 border-r-4 border-canina-blue p-4 sm:p-6 rounded-2xl">
|
||||||
|
<p className="text-sm sm:text-lg text-medical-gray-600 font-bold leading-relaxed font-vazir">
|
||||||
{fullProduct.shortDescription}
|
{fullProduct.shortDescription}
|
||||||
</p>
|
</p>
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -379,8 +381,8 @@ export default function ProductPage({ productSlug }: { productSlug: string }) {
|
|||||||
<Clock className="w-6 h-6" />
|
<Clock className="w-6 h-6" />
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<h3 className="text-2xl font-black text-medical-gray-900 italic font-vazir">ماشین حساب هوشمند مصرف</h3>
|
<h3 className="text-lg sm:text-2xl font-black text-medical-gray-900 italic font-vazir whitespace-nowrap">ماشین حساب هوشمند مصرف</h3>
|
||||||
<p className="text-xs text-medical-gray-400 font-bold font-vazir mt-1">تخمین دقیق دوز روزانه و ماندگاری هر بسته بر اساس مشخصات پت شما</p>
|
<p className="text-[11px] sm:text-xs text-medical-gray-400 font-bold font-vazir mt-0.5 sm:mt-1">تخمین دقیق دوز روزانه و ماندگاری هر بسته بر اساس مشخصات پت شما</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -433,18 +435,18 @@ export default function ProductPage({ productSlug }: { productSlug: string }) {
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Ingredients Section */}
|
{/* Ingredients Section */}
|
||||||
<section className="space-y-8">
|
<section className="bg-white rounded-[2.5rem] border border-medical-gray-200 p-8 md:p-10 shadow-md space-y-8">
|
||||||
<div className="flex items-center gap-4">
|
<div className="flex items-center gap-4 border-b border-medical-gray-100 pb-6">
|
||||||
<div className="w-12 h-12 bg-canina-blue text-white rounded-2xl flex items-center justify-center shadow-lg">
|
<div className="w-12 h-12 bg-canina-blue text-white rounded-2xl flex items-center justify-center shadow-lg">
|
||||||
<FlaskConical className="w-6 h-6" />
|
<FlaskConical className="w-6 h-6" />
|
||||||
</div>
|
</div>
|
||||||
<h3 className="text-3xl font-black text-medical-gray-900 italic font-vazir">ترکیبات و آنالیز علمی</h3>
|
<h3 className="text-2xl md:text-3xl font-black text-medical-gray-900 italic font-vazir">ترکیبات و آنالیز علمی</h3>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="space-y-10">
|
<div className="space-y-8">
|
||||||
{/* Ingredients Cards */}
|
{/* Ingredients Cards */}
|
||||||
<div className="bg-white rounded-[2.5rem] p-8 md:p-10 border border-medical-gray-200 shadow-md">
|
<div>
|
||||||
<h4 className="text-xs font-black text-medical-gray-400 uppercase tracking-widest mb-6 font-vazir">مواد تشکیلدهنده برتر</h4>
|
<h4 className="text-xs font-black text-medical-gray-400 uppercase tracking-widest mb-4 font-vazir">مواد تشکیلدهنده برتر</h4>
|
||||||
<div className="flex flex-wrap gap-3">
|
<div className="flex flex-wrap gap-3">
|
||||||
{product.main_ingredients.map((ing, idx) => {
|
{product.main_ingredients.map((ing, idx) => {
|
||||||
const termKey = termKeys.find(key => {
|
const termKey = termKeys.find(key => {
|
||||||
@ -582,8 +584,8 @@ export default function ProductPage({ productSlug }: { productSlug: string }) {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Sticky Sidebar (Clean Buy Box) - Sticky starts at the top, level with the title */}
|
{/* Sticky Sidebar (Clean Buy Box) - Hidden on mobile as mobile floating buy bar is active */}
|
||||||
<div className="lg:col-span-4 lg:sticky lg:top-28 space-y-8">
|
<div className="hidden lg:block lg:col-span-4 lg:sticky lg:top-36 space-y-8">
|
||||||
<div className="bg-white rounded-[2.5rem] border-2 border-medical-gray-100 p-8 shadow-2xl relative overflow-hidden">
|
<div className="bg-white rounded-[2.5rem] border-2 border-medical-gray-100 p-8 shadow-2xl relative overflow-hidden">
|
||||||
<div className="absolute top-0 right-0 w-24 h-24 bg-canina-blue/5 rounded-full -mr-12 -mt-12" />
|
<div className="absolute top-0 right-0 w-24 h-24 bg-canina-blue/5 rounded-full -mr-12 -mt-12" />
|
||||||
|
|
||||||
@ -769,6 +771,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>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -128,51 +128,57 @@ export default function SmartAdvisor({ onComplete, rules = [] }: SmartAdvisorPro
|
|||||||
initial={{ opacity: 0, y: 20 }}
|
initial={{ opacity: 0, y: 20 }}
|
||||||
whileInView={{ opacity: 1, y: 0 }}
|
whileInView={{ opacity: 1, y: 0 }}
|
||||||
viewport={{ once: true }}
|
viewport={{ once: true }}
|
||||||
className="grid md:grid-cols-3 gap-6 mb-12"
|
className="grid grid-cols-1 md:grid-cols-3 gap-4 sm:gap-6 mb-8 sm:mb-12"
|
||||||
>
|
>
|
||||||
<div className="bg-white p-6 rounded-[2.5rem] border border-medical-gray-200/80 shadow-lg hover:shadow-xl transition-all group flex flex-col justify-between">
|
<div className="bg-white p-4 sm:p-6 rounded-2xl sm:rounded-[2.5rem] border border-medical-gray-200/80 shadow-md sm:shadow-lg hover:shadow-xl transition-all group flex flex-col justify-between">
|
||||||
<div>
|
<div>
|
||||||
<div className="w-12 h-12 bg-canina-blue/10 rounded-2xl flex items-center justify-center text-canina-blue mb-4 group-hover:bg-canina-blue group-hover:text-white transition-all shadow-sm">
|
<div className="flex items-center gap-3 sm:block mb-2 sm:mb-0">
|
||||||
<Pill className="w-6 h-6" />
|
<div className="w-9 h-9 sm:w-12 sm:h-12 bg-canina-blue/10 rounded-xl sm:rounded-2xl flex items-center justify-center text-canina-blue sm:mb-4 group-hover:bg-canina-blue group-hover:text-white transition-all shadow-sm flex-shrink-0">
|
||||||
|
<Pill className="w-5 h-5 sm:w-6 sm:h-6" />
|
||||||
|
</div>
|
||||||
|
<h3 className="text-base sm:text-lg font-black text-medical-gray-900 sm:mb-2 font-vazir">چرا ثبت شناسنامه؟</h3>
|
||||||
</div>
|
</div>
|
||||||
<h3 className="text-lg font-black text-medical-gray-900 mb-2 font-vazir">چرا ثبت شناسنامه؟</h3>
|
|
||||||
<p className="text-xs text-medical-gray-500 font-medium leading-relaxed font-vazir">
|
<p className="text-xs text-medical-gray-500 font-medium leading-relaxed font-vazir">
|
||||||
مکملهای دارویی کانینا غلیظ و تخصصی هستند؛ الگوریتم هوشمند ما بر اساس سن، وزن و جثه پت شما، دوز دقیق مصرفی روزانه را محاسبه میکند تا حداکثر اثرگذاری ایجاد شود.
|
مکملهای دارویی کانینا غلیظ و تخصصی هستند؛ الگوریتم هوشمند ما بر اساس سن، وزن و جثه پت شما، دوز دقیق مصرفی روزانه را محاسبه میکند.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="mt-4 pt-4 border-t border-medical-gray-100 text-[10px] font-black text-canina-blue flex items-center gap-1 font-vazir">
|
<div className="mt-3 sm:mt-4 pt-3 sm:pt-4 border-t border-medical-gray-100 text-[10px] font-black text-canina-blue flex items-center gap-1 font-vazir">
|
||||||
<Check className="w-3.5 h-3.5" />
|
<Check className="w-3.5 h-3.5" />
|
||||||
تضمین ایمنی و عدم اوردوز
|
تضمین ایمنی و عدم اوردوز
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="bg-white p-6 rounded-[2.5rem] border border-medical-gray-200/80 shadow-lg hover:shadow-xl transition-all group flex flex-col justify-between">
|
<div className="bg-white p-4 sm:p-6 rounded-2xl sm:rounded-[2.5rem] border border-medical-gray-200/80 shadow-md sm:shadow-lg hover:shadow-xl transition-all group flex flex-col justify-between">
|
||||||
<div>
|
<div>
|
||||||
<div className="w-12 h-12 bg-canina-blue/10 rounded-2xl flex items-center justify-center text-canina-blue mb-4 group-hover:bg-canina-blue group-hover:text-white transition-all shadow-sm">
|
<div className="flex items-center gap-3 sm:block mb-2 sm:mb-0">
|
||||||
<Activity className="w-6 h-6" />
|
<div className="w-9 h-9 sm:w-12 sm:h-12 bg-canina-blue/10 rounded-xl sm:rounded-2xl flex items-center justify-center text-canina-blue sm:mb-4 group-hover:bg-canina-blue group-hover:text-white transition-all shadow-sm flex-shrink-0">
|
||||||
|
<Activity className="w-5 h-5 sm:w-6 sm:h-6" />
|
||||||
|
</div>
|
||||||
|
<h3 className="text-base sm:text-lg font-black text-medical-gray-900 sm:mb-2 font-vazir">تطبیق علائم بالینی</h3>
|
||||||
</div>
|
</div>
|
||||||
<h3 className="text-lg font-black text-medical-gray-900 mb-2 font-vazir">تطبیق علائم بالینی</h3>
|
|
||||||
<p className="text-xs text-medical-gray-500 font-medium leading-relaxed font-vazir">
|
<p className="text-xs text-medical-gray-500 font-medium leading-relaxed font-vazir">
|
||||||
با انتخاب علائمی مثل لنگیدن، ریزش مو، یا اسهال، موتور هوشمند ما دقیقترین راهکار مکمل آلمانی مرتبط را به همراه دلایل علمی به شما پیشنهاد میدهد.
|
با انتخاب علائمی مثل لنگیدن یا ریزش مو، دقیقترین راهکار مکمل آلمانی به همراه دلایل علمی به شما پیشنهاد میشود.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="mt-4 pt-4 border-t border-medical-gray-100 text-[10px] font-black text-canina-blue flex items-center gap-1 font-vazir">
|
<div className="mt-3 sm:mt-4 pt-3 sm:pt-4 border-t border-medical-gray-100 text-[10px] font-black text-canina-blue flex items-center gap-1 font-vazir">
|
||||||
<Check className="w-3.5 h-3.5" />
|
<Check className="w-3.5 h-3.5" />
|
||||||
پیشنهاد هدفمند و تخصصی
|
پیشنهاد هدفمند و تخصصی
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="bg-white p-6 rounded-[2.5rem] border border-medical-gray-200/80 shadow-lg hover:shadow-xl transition-all group flex flex-col justify-between">
|
<div className="bg-white p-4 sm:p-6 rounded-2xl sm:rounded-[2.5rem] border border-medical-gray-200/80 shadow-md sm:shadow-lg hover:shadow-xl transition-all group flex flex-col justify-between">
|
||||||
<div>
|
<div>
|
||||||
<div className="w-12 h-12 bg-canina-blue/10 rounded-2xl flex items-center justify-center text-canina-blue mb-4 group-hover:bg-canina-blue group-hover:text-white transition-all shadow-sm">
|
<div className="flex items-center gap-3 sm:block mb-2 sm:mb-0">
|
||||||
<ShieldCheck className="w-6 h-6" />
|
<div className="w-9 h-9 sm:w-12 sm:h-12 bg-canina-blue/10 rounded-xl sm:rounded-2xl flex items-center justify-center text-canina-blue sm:mb-4 group-hover:bg-canina-blue group-hover:text-white transition-all shadow-sm flex-shrink-0">
|
||||||
|
<ShieldCheck className="w-5 h-5 sm:w-6 sm:h-6" />
|
||||||
|
</div>
|
||||||
|
<h3 className="text-base sm:text-lg font-black text-medical-gray-900 sm:mb-2 font-vazir">پایش موجودی و یادآور</h3>
|
||||||
</div>
|
</div>
|
||||||
<h3 className="text-lg font-black text-medical-gray-900 mb-2 font-vazir">پایش موجودی و یادآور</h3>
|
|
||||||
<p className="text-xs text-medical-gray-500 font-medium leading-relaxed font-vazir">
|
<p className="text-xs text-medical-gray-500 font-medium leading-relaxed font-vazir">
|
||||||
پس از ایجاد شناسنامه، زمانهای مصرف مکملها تنظیم شده و سیستم قبل از اتمام دوره درمانی، پیام هشدار شارژ مجدد به شما ارسال خواهد کرد.
|
زمانهای مصرف مکملها تنظیم شده و سیستم قبل از اتمام دوره درمانی، هشدار شارژ مجدد ارسال خواهد کرد.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="mt-4 pt-4 border-t border-medical-gray-100 text-[10px] font-black text-canina-blue flex items-center gap-1 font-vazir">
|
<div className="mt-3 sm:mt-4 pt-3 sm:pt-4 border-t border-medical-gray-100 text-[10px] font-black text-canina-blue flex items-center gap-1 font-vazir">
|
||||||
<Check className="w-3.5 h-3.5" />
|
<Check className="w-3.5 h-3.5" />
|
||||||
تکمیل منظم دوره درمان
|
تکمیل منظم دوره درمان
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user