fix: resolve seed encoding, search param, and wiki data source issues
- Fix seed-products.ts TS error (implicit any) and BOM handling - Re-run full seed to restore correct Persian encoding in DB - Fix productService query→search param mismatch - Fix IngredientWiki hardcoded port 4000→use settingsStore - Restore seed-products-data.json from git after accidental corruption
@ -1,6 +1,6 @@
|
|||||||
# نقشه جامع اتصال به بکبند (Comprehensive Backend Integration Map) 🏗️
|
# نقشه جامع اتصال به بکبند (Comprehensive Backend Integration Map) 🏗️
|
||||||
|
|
||||||
این سند حاوی معماری دقیق، فهرست کامل نقاط اتصال (API Endpoints)، کامنتهای مکاننما در کد (TODO Markers)، و تعاریف رسمی تمامی تایپهای ورودی (Inputs) و خروجی (Outputs) پلتفرم درمانی و فروشگاهی کانینو ایران است.
|
این سند حاوی معماری دقیق، فهرست کامل نقاط اتصال (API Endpoints)، کامنتهای مکاننما در کد (TODO Markers)، و تعاریف رسمی تمامی تایپهای ورودی (Inputs) و خروجی (Outputs) پلتفرم درمانی و فروشگاهی کانینا ایران است.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
# طرحواره پایگاه داده کانینو ایران (Canino Iran Database Schema) 🗄️
|
# طرحواره پایگاه داده کانینا ایران (Canina Iran Database Schema) 🗄️
|
||||||
|
|
||||||
این سند ساختار دقیق جداول، فیلدها، نوع دادهها (Datatypes)، روابط بین موجودیتها (ERD Relations) و ایندکسهای پیشنهادی را برای راهاندازی پایگاه داده نهایی سیستم کانینو طراحی و ارائه میکند. جهت انعطافپذیری توسعه، پیادهسازی هم بر اساس **پایگاه داده رابطهای (PostgreSQL / MySQL)** و هم **پایگاه داده مستندمحور/سندمراقبتی (NoSQL - MongoDB / Firestore)** مدلسازی شده است.
|
این سند ساختار دقیق جداول، فیلدها، نوع دادهها (Datatypes)، روابط بین موجودیتها (ERD Relations) و ایندکسهای پیشنهادی را برای راهاندازی پایگاه داده نهایی سیستم کانینا طراحی و ارائه میکند. جهت انعطافپذیری توسعه، پیادهسازی هم بر اساس **پایگاه داده رابطهای (PostgreSQL / MySQL)** و هم **پایگاه داده مستندمحور/سندمراقبتی (NoSQL - MongoDB / Firestore)** مدلسازی شده است.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@ -63,7 +63,7 @@ CREATE TABLE wallet_transactions (
|
|||||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
|
||||||
);
|
);
|
||||||
|
|
||||||
-- ۴. جدول کاتالوگ محصولات کانینو (products)
|
-- ۴. جدول کاتالوگ محصولات کانینا (products)
|
||||||
CREATE TABLE products (
|
CREATE TABLE products (
|
||||||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||||
art_no VARCHAR(20) UNIQUE NOT NULL,
|
art_no VARCHAR(20) UNIQUE NOT NULL,
|
||||||
@ -250,7 +250,7 @@ CREATE INDEX idx_reminder_completions_ref ON reminder_completions(reminder_id, c
|
|||||||
"reminders": [
|
"reminders": [
|
||||||
{
|
{
|
||||||
"id": "REM-001",
|
"id": "REM-001",
|
||||||
"productId": "6472f8d38bfcb8234eccb611", // مکمل آرتروفیت کانینو فیزیکی جهت کسر انبار پت
|
"productId": "6472f8d38bfcb8234eccb611", // مکمل آرتروفیت کانینا فیزیکی جهت کسر انبار پت
|
||||||
"title": "مصرف قرص مفصلساز Canhydrox",
|
"title": "مصرف قرص مفصلساز Canhydrox",
|
||||||
"time": "08:30",
|
"time": "08:30",
|
||||||
"frequency": "روزانه",
|
"frequency": "روزانه",
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
# پلتفرم کانینو ایران (Canino Iran Platform) 🐾
|
# پلتفرم کانینا ایران (Canina Iran Platform) 🐾
|
||||||
### لندینگ، فروشگاه تخصصی و پرونده سلامت الکترونیک پت (نمایندگی رسمی دارویی Canina Pharma)
|
### لندینگ، فروشگاه تخصصی و پرونده سلامت الکترونیک پت (نمایندگی رسمی دارویی Canina Pharma)
|
||||||
|
|
||||||
پلتفرم **کانینو ایران** یک برنامه جامع تحت وب (SPA/PWA) مجهز به بردهای تعاملی و ابزارهای بهداشتی-دامپزشکی است که با هدف ارتقای سلامت حیوانات خانگی و دسترسی آسانتر به مکملهای دارویی گرید فوقارگانیک و دارویی کمپانی والای **Canina pharma GmbH آلمان** توسعه یافته است.
|
پلتفرم **کانینا ایران** یک برنامه جامع تحت وب (SPA/PWA) مجهز به بردهای تعاملی و ابزارهای بهداشتی-دامپزشکی است که با هدف ارتقای سلامت حیوانات خانگی و دسترسی آسانتر به مکملهای دارویی گرید فوقارگانیک و دارویی کمپانی والای **Canina pharma GmbH آلمان** توسعه یافته است.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { PrismaClient } from '@prisma/client';
|
import { PrismaClient } from '@prisma/client';
|
||||||
|
|
||||||
const prisma = new PrismaClient();
|
const prisma = new PrismaClient();
|
||||||
|
|
||||||
@ -24,7 +24,7 @@ async function main() {
|
|||||||
'<p>کلسیم یکی از مهمترین مواد معدنی برای رشد ساختار استخوانی است. تولهسگها در ماههای اول زندگی به کلسیم بیشتری نیاز دارند تا اسکلتبندی محکمی داشته باشند.</p>',
|
'<p>کلسیم یکی از مهمترین مواد معدنی برای رشد ساختار استخوانی است. تولهسگها در ماههای اول زندگی به کلسیم بیشتری نیاز دارند تا اسکلتبندی محکمی داشته باشند.</p>',
|
||||||
'',
|
'',
|
||||||
'<h2>نسبت Ca:P (کلسیم به فسفر)</h2>',
|
'<h2>نسبت Ca:P (کلسیم به فسفر)</h2>',
|
||||||
'<p>نسبت ایدهآل کلسیم به فسفر در رژیم تولهسگها <strong>۱.۲:۱ تا ۱.۵:۱</strong> است. عدم تعادل در این نسبت میتواند منجر به ناهنجاریهای استخوانی مانند پاهای پرانتزی و دیسپلازی هیپ شود. <strong>پودر پوسته تخم مرغ کانینو</strong> با ۳۶٪ کلسیم خالص و فسفر ۰.۱٪ بهترین گزینه برای تنظیم این نسبت است.</p>',
|
'<p>نسبت ایدهآل کلسیم به فسفر در رژیم تولهسگها <strong>۱.۲:۱ تا ۱.۵:۱</strong> است. عدم تعادل در این نسبت میتواند منجر به ناهنجاریهای استخوانی مانند پاهای پرانتزی و دیسپلازی هیپ شود. <strong>پودر پوسته تخم مرغ کانینا</strong> با ۳۶٪ کلسیم خالص و فسفر ۰.۱٪ بهترین گزینه برای تنظیم این نسبت است.</p>',
|
||||||
'',
|
'',
|
||||||
'<h2>نقش ویتامین D3 در جذب کلسیم</h2>',
|
'<h2>نقش ویتامین D3 در جذب کلسیم</h2>',
|
||||||
'<p>ویتامین D3 (کولهکلسیفرول) جذب کلسیم از روده را تا ۳۰٪ افزایش میدهد. <strong>مصرف همزمان ویتامین D2 (ارگوکلسیفرول) با D3 مجاز نیست</strong> زیرا این دو با یکدیگر رقابت کرده و جذب مؤثر را کاهش میدهند.</p>',
|
'<p>ویتامین D3 (کولهکلسیفرول) جذب کلسیم از روده را تا ۳۰٪ افزایش میدهد. <strong>مصرف همزمان ویتامین D2 (ارگوکلسیفرول) با D3 مجاز نیست</strong> زیرا این دو با یکدیگر رقابت کرده و جذب مؤثر را کاهش میدهند.</p>',
|
||||||
@ -49,12 +49,12 @@ async function main() {
|
|||||||
'<li><strong>B1 (تیامین):</strong> متابولیسم کربوهیدراتها و عملکرد سیستم عصبی</li>',
|
'<li><strong>B1 (تیامین):</strong> متابولیسم کربوهیدراتها و عملکرد سیستم عصبی</li>',
|
||||||
'<li><strong>B2 (ریبوفلاوین):</strong> تولید انرژی و سلامت پوست</li>',
|
'<li><strong>B2 (ریبوفلاوین):</strong> تولید انرژی و سلامت پوست</li>',
|
||||||
'<li><strong>B6 (پیریدوکسین):</strong> سنتز پروتئین و تولید گلبول قرمز</li>',
|
'<li><strong>B6 (پیریدوکسین):</strong> سنتز پروتئین و تولید گلبول قرمز</li>',
|
||||||
'<li><strong>B7 (بیوتین / ویتامین H):</strong> کراتینسازی مو و پنجه - <strong>Biotin-Tabs کانینو</strong> با ۱ میلیون میکروگرم بیوتین در کیلوگرم، قویترین دوز موجود در بازار است</li>',
|
'<li><strong>B7 (بیوتین / ویتامین H):</strong> کراتینسازی مو و پنجه - <strong>Biotin-Tabs کانینا</strong> با ۱ میلیون میکروگرم بیوتین در کیلوگرم، قویترین دوز موجود در بازار است</li>',
|
||||||
'<li><strong>B12 (کوبالامین):</strong> خونسازی و عملکرد عصبی</li>',
|
'<li><strong>B12 (کوبالامین):</strong> خونسازی و عملکرد عصبی</li>',
|
||||||
'</ul>',
|
'</ul>',
|
||||||
'',
|
'',
|
||||||
'<h2>نقش بیوتین در سلامت پوشش</h2>',
|
'<h2>نقش بیوتین در سلامت پوشش</h2>',
|
||||||
'<p>بیوتین کوآنزیم کربوکسیلازهای مسئول سنتز اسیدهای چرب و گلوکونئوژنز است. <strong>ریزش مو و شکنندگی پنجه</strong> از نشانههای کلاسیک کمبود بیوتین هستند. قرص بیوتین کانینو با تأثیر از هفته چهارم، پوشش براق و پنجههای محکم را تضمین میکند.</p>',
|
'<p>بیوتین کوآنزیم کربوکسیلازهای مسئول سنتز اسیدهای چرب و گلوکونئوژنز است. <strong>ریزش مو و شکنندگی پنجه</strong> از نشانههای کلاسیک کمبود بیوتین هستند. قرص بیوتین کانینا با تأثیر از هفته چهارم، پوشش براق و پنجههای محکم را تضمین میکند.</p>',
|
||||||
'',
|
'',
|
||||||
'<h2>محصولات تقویتکننده پوست و مو</h2>',
|
'<h2>محصولات تقویتکننده پوست و مو</h2>',
|
||||||
'<ul>',
|
'<ul>',
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { PrismaClient } from '@prisma/client';
|
import { PrismaClient } from '@prisma/client';
|
||||||
|
|
||||||
const prisma = new PrismaClient();
|
const prisma = new PrismaClient();
|
||||||
|
|
||||||
@ -39,7 +39,7 @@ async function main() {
|
|||||||
vetName: 'دکتر علیرضا رضایی',
|
vetName: 'دکتر علیرضا رضایی',
|
||||||
clinicName: 'کلینیک دامپزشکی پایتخت',
|
clinicName: 'کلینیک دامپزشکی پایتخت',
|
||||||
imageUrl: '/images/vets/vet1.webp',
|
imageUrl: '/images/vets/vet1.webp',
|
||||||
quote: 'مکملهای مفصلی کانینو از نظر سرعت جذب و اثربخشی در سگهای نژاد بزرگ بینظیر هستند. ما نتایج فوقالعادهای روی دیسپلازی هیپ مشاهده کردیم.',
|
quote: 'مکملهای مفصلی کانینا از نظر سرعت جذب و اثربخشی در سگهای نژاد بزرگ بینظیر هستند. ما نتایج فوقالعادهای روی دیسپلازی هیپ مشاهده کردیم.',
|
||||||
rating: 5,
|
rating: 5,
|
||||||
order: 1,
|
order: 1,
|
||||||
isActive: true,
|
isActive: true,
|
||||||
@ -48,7 +48,7 @@ async function main() {
|
|||||||
vetName: 'دکتر سارا شمس',
|
vetName: 'دکتر سارا شمس',
|
||||||
clinicName: 'بیمارستان دامپزشکی تهران',
|
clinicName: 'بیمارستان دامپزشکی تهران',
|
||||||
imageUrl: '/images/vets/vet2.webp',
|
imageUrl: '/images/vets/vet2.webp',
|
||||||
quote: 'من همیشه برای ریزش مو و مشکلات پوستی گربهها، قرصهای مخمر و بیوتین کانینو را تجویز میکنم. نتایج معمولاً در کمتر از ۳ هفته قابل مشاهده است.',
|
quote: 'من همیشه برای ریزش مو و مشکلات پوستی گربهها، قرصهای مخمر و بیوتین کانینا را تجویز میکنم. نتایج معمولاً در کمتر از ۳ هفته قابل مشاهده است.',
|
||||||
rating: 5,
|
rating: 5,
|
||||||
order: 2,
|
order: 2,
|
||||||
isActive: true,
|
isActive: true,
|
||||||
|
|||||||
@ -13,14 +13,6 @@ function slugify(text: string): string {
|
|||||||
.replace(/^-|-$/g, '');
|
.replace(/^-|-$/g, '');
|
||||||
}
|
}
|
||||||
|
|
||||||
function cleanBrand(text: string): string {
|
|
||||||
return text
|
|
||||||
.replace(/کانینا/g, 'کانینو')
|
|
||||||
.replace(/کانینا/g, 'کانینو')
|
|
||||||
.replace(/Canina/g, 'Canino')
|
|
||||||
.replace(/canina/g, 'canino');
|
|
||||||
}
|
|
||||||
|
|
||||||
function determineSuitableFor(name: string, description: string): string {
|
function determineSuitableFor(name: string, description: string): string {
|
||||||
const text = (name + ' ' + description).toLowerCase();
|
const text = (name + ' ' + description).toLowerCase();
|
||||||
const hasCat = text.includes('گربه') || text.includes('katzen') || text.includes('cat');
|
const hasCat = text.includes('گربه') || text.includes('katzen') || text.includes('cat');
|
||||||
@ -41,22 +33,27 @@ function parseSize(size: string): { unit: string; packageSize: number } {
|
|||||||
return { unit: 'g', packageSize: 100 };
|
return { unit: 'g', packageSize: 100 };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function findOrCreateCategory(slug: string): Promise<{ id: string; slug: string }> {
|
||||||
|
const CATEGORY_NAMES: Record<string, string> = {
|
||||||
|
'joints': 'مفاصل و استخوان',
|
||||||
|
'immune': 'تقویت سیستم ایمنی و گوارش',
|
||||||
|
'energy': 'ویتامینها و انرژیبخشها',
|
||||||
|
'special-care': 'مراقبتهای ویژه (پوست، دندان و چشم)',
|
||||||
|
'general': 'تقویت عمومی',
|
||||||
|
'nutrition': 'تغذیه تخصصی',
|
||||||
|
'supplements': 'مکملهای غذایی و درمانی',
|
||||||
|
};
|
||||||
|
const name = CATEGORY_NAMES[slug] || slug;
|
||||||
|
return await prisma.category.upsert({
|
||||||
|
where: { slug },
|
||||||
|
update: { name },
|
||||||
|
create: { slug, name, description: name },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
console.log('Seeding products from seed-products-data.json...');
|
console.log('Seeding products from seed-products-data.json...');
|
||||||
|
|
||||||
// 1. Create default category
|
|
||||||
const category = await prisma.category.upsert({
|
|
||||||
where: { slug: 'supplements' },
|
|
||||||
update: {},
|
|
||||||
create: {
|
|
||||||
name: 'مکملهای غذایی و درمانی',
|
|
||||||
slug: 'supplements',
|
|
||||||
description: 'انواع مکملهای اورجینال کانینو آلمان',
|
|
||||||
metaTitle: 'خرید مکمل کانینو',
|
|
||||||
metaDescription: 'بهترین مکملهای کانینو'
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// 2. Read JSON data
|
// 2. Read JSON data
|
||||||
const dataPath = path.join(__dirname, 'seed-products-data.json');
|
const dataPath = path.join(__dirname, 'seed-products-data.json');
|
||||||
if (!fs.existsSync(dataPath)) {
|
if (!fs.existsSync(dataPath)) {
|
||||||
@ -64,16 +61,18 @@ async function main() {
|
|||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
const productsData = JSON.parse(fs.readFileSync(dataPath, 'utf-8'));
|
const productsData = JSON.parse(fs.readFileSync(dataPath, 'utf-8').replace(/^\ufeff/, ''));
|
||||||
let variantCount = 0;
|
let variantCount = 0;
|
||||||
|
|
||||||
for (const item of productsData) {
|
for (const item of productsData) {
|
||||||
const baseName = cleanBrand(item.name);
|
const baseName = item.name;
|
||||||
const cleanDesc = cleanBrand(item.description);
|
const cleanDesc = item.description;
|
||||||
const cleanIngredients = item.ingredients ? cleanBrand(item.ingredients) : '';
|
const cleanIngredients = item.ingredients || '';
|
||||||
const cleanDosage = item.usage_and_dosage ? cleanBrand(item.usage_and_dosage) : '';
|
const cleanDosage = item.usage_and_dosage || '';
|
||||||
const suitableFor = determineSuitableFor(baseName, cleanDesc);
|
const suitableFor = determineSuitableFor(baseName, cleanDesc);
|
||||||
const baseSlug = slugify(baseName);
|
const baseSlug = slugify(baseName);
|
||||||
|
const categorySlug = item.category_slug || 'supplements';
|
||||||
|
const category = await findOrCreateCategory(categorySlug);
|
||||||
|
|
||||||
for (const variant of item.variants) {
|
for (const variant of item.variants) {
|
||||||
const artNo = variant.art_no;
|
const artNo = variant.art_no;
|
||||||
@ -135,7 +134,7 @@ async function main() {
|
|||||||
// Seed ingredients (split by '،' or '، ')
|
// Seed ingredients (split by '،' or '، ')
|
||||||
await prisma.productIngredient.deleteMany({ where: { productId: product.id } });
|
await prisma.productIngredient.deleteMany({ where: { productId: product.id } });
|
||||||
if (cleanIngredients) {
|
if (cleanIngredients) {
|
||||||
const parts = cleanIngredients.split(/[،,]/).map(s => s.trim()).filter(Boolean);
|
const parts = cleanIngredients.split(/[،,]/).map((s: string) => s.trim()).filter(Boolean);
|
||||||
// Only take the first meaningful items (up to ~20)
|
// Only take the first meaningful items (up to ~20)
|
||||||
const meaningful = parts.slice(0, 20);
|
const meaningful = parts.slice(0, 20);
|
||||||
for (const ing of meaningful) {
|
for (const ing of meaningful) {
|
||||||
@ -171,16 +170,16 @@ async function main() {
|
|||||||
|
|
||||||
// 3. Seed some Blogs
|
// 3. Seed some Blogs
|
||||||
const blog1Content = [
|
const blog1Content = [
|
||||||
'<p><strong>تغذیه صحیح سگهای بالغ</strong> یکی از مهمترین عوامل در حفظ سلامت و افزایش طول عمر آنهاست. برند کانینو (Canino) با بیش از ۴۰ سال سابقه در تولید مکملهای دامپزشکی در آلمان، استاندارد طلایی تغذیه تکمیلی را تعریف کرده است.</p>',
|
'<p><strong>تغذیه صحیح سگهای بالغ</strong> یکی از مهمترین عوامل در حفظ سلامت و افزایش طول عمر آنهاست. برند کانینا (Canina) با بیش از ۴۰ سال سابقه در تولید مکملهای دامپزشکی در آلمان، استاندارد طلایی تغذیه تکمیلی را تعریف کرده است.</p>',
|
||||||
'',
|
'',
|
||||||
'<h2>اصول تغذیه سگ بالغ</h2>',
|
'<h2>اصول تغذیه سگ بالغ</h2>',
|
||||||
'<p>سگهای بالغ به رژیم غذایی متعادل حاوی پروتئین، چربی، کربوهیدرات، ویتامینها و مواد معدنی نیاز دارند. نسبت Ca:P (کلسیم به فسفر) باید در محدوده ۱.۲:۱ تا ۱.۵:۱ باشد. هرگونه عدم تعادل در این نسبت میتواند منجر به مشکلات کلیوی و استخوانی شود.</p>',
|
'<p>سگهای بالغ به رژیم غذایی متعادل حاوی پروتئین، چربی، کربوهیدرات، ویتامینها و مواد معدنی نیاز دارند. نسبت Ca:P (کلسیم به فسفر) باید در محدوده ۱.۲:۱ تا ۱.۵:۱ باشد. هرگونه عدم تعادل در این نسبت میتواند منجر به مشکلات کلیوی و استخوانی شود.</p>',
|
||||||
'',
|
'',
|
||||||
'<h2>نقش مکملها در رژیم غذایی</h2>',
|
'<h2>نقش مکملها در رژیم غذایی</h2>',
|
||||||
'<p>حتی با بهترین رژیم غذایی، ممکن است برخی مواد مغذی به اندازه کافی تأمین نشوند. محصولات کانینو مانند <strong>Petvital Vitamin-Tabs</strong> (کمپلکس کامل A تا K3) و <strong>Biotin-Tabs</strong> (۱ میلیون میکروگرم بیوتین) نیازهای تغذیهای را پوشش میدهند.</p>',
|
'<p>حتی با بهترین رژیم غذایی، ممکن است برخی مواد مغذی به اندازه کافی تأمین نشوند. محصولات کانینا مانند <strong>Petvital Vitamin-Tabs</strong> (کمپلکس کامل A تا K3) و <strong>Biotin-Tabs</strong> (۱ میلیون میکروگرم بیوتین) نیازهای تغذیهای را پوشش میدهند.</p>',
|
||||||
'',
|
'',
|
||||||
'<h2>اسیدهای چرب ضروری</h2>',
|
'<h2>اسیدهای چرب ضروری</h2>',
|
||||||
'<p>روغن سالمون کانینو (Lachs-Öl) با ۱۴٪ امگا ۳ (EPA/DHA) به روش Cold Press استخراج میشود و تمام ویتامینهای حساس به حرارت را حفظ میکند. EPA پیشماده رزولوینهای ضدالتهابی و DHA ۳۰٪ وزن خشک مغز را تشکیل میدهد.</p>',
|
'<p>روغن سالمون کانینا (Lachs-Öl) با ۱۴٪ امگا ۳ (EPA/DHA) به روش Cold Press استخراج میشود و تمام ویتامینهای حساس به حرارت را حفظ میکند. EPA پیشماده رزولوینهای ضدالتهابی و DHA ۳۰٪ وزن خشک مغز را تشکیل میدهد.</p>',
|
||||||
'',
|
'',
|
||||||
'<h2>مراقبت از مفاصل</h2>',
|
'<h2>مراقبت از مفاصل</h2>',
|
||||||
'<p>با افزایش سن سگ، غضروف مفصلی تحلیل میرود. گلیکوزآمینوگلیکانهای صدف لب سبز (GAG) با جذب مولکولهای آب در ماتریکس غضروفی، خاصیت بافری مفاصل را بازیابی میکنند. <strong>CANHYDROX GAG</strong> و <strong>FLEXAN</strong> حاوی این ترکیبات حیاتی هستند.</p>',
|
'<p>با افزایش سن سگ، غضروف مفصلی تحلیل میرود. گلیکوزآمینوگلیکانهای صدف لب سبز (GAG) با جذب مولکولهای آب در ماتریکس غضروفی، خاصیت بافری مفاصل را بازیابی میکنند. <strong>CANHYDROX GAG</strong> و <strong>FLEXAN</strong> حاوی این ترکیبات حیاتی هستند.</p>',
|
||||||
@ -195,12 +194,12 @@ async function main() {
|
|||||||
].join('\n');
|
].join('\n');
|
||||||
|
|
||||||
const blog2Content = [
|
const blog2Content = [
|
||||||
'<p><strong>کانینو (Canino)</strong> نماینده رسمی برند <strong>Canina pharma GmbH</strong> در ایران است. این شرکت آلمانی در سال ۱۹۸۴ توسط <strong>پتر و کریستین کرشنمایر</strong> در شهر برگیش گلادباخ تأسیس شد و به یکی از پیشگامان تولید مکملهای طبیعی دامپزشکی در اروپا تبدیل شده است.</p>',
|
'<p><strong>کانینا (Canina)</strong> نماینده رسمی برند <strong>Canina pharma GmbH</strong> در ایران است. این شرکت آلمانی در سال ۱۹۸۴ توسط <strong>پتر و کریستین کرشنمایر</strong> در شهر برگیش گلادباخ تأسیس شد و به یکی از پیشگامان تولید مکملهای طبیعی دامپزشکی در اروپا تبدیل شده است.</p>',
|
||||||
'',
|
'',
|
||||||
'<h2>فلسفه Canina: "مادر طبیعت بهترین نسخه را میداند"</h2>',
|
'<h2>فلسفه Canina: "مادر طبیعت بهترین نسخه را میداند"</h2>',
|
||||||
'<p>تمام محصولات کانینا بر پایه مواد اولیه طبیعی و با فرآیندهای پیشرفته تولید میشوند. این شرکت دارای گواهیهای معتبر <strong>IFS (International Featured Standard)</strong> و <strong>HACCP</strong> است و محصولات آن در بیش از ۴۰ کشور جهان توزیع میشود.</p>',
|
'<p>تمام محصولات کانینا بر پایه مواد اولیه طبیعی و با فرآیندهای پیشرفته تولید میشوند. این شرکت دارای گواهیهای معتبر <strong>IFS (International Featured Standard)</strong> و <strong>HACCP</strong> است و محصولات آن در بیش از ۴۰ کشور جهان توزیع میشود.</p>',
|
||||||
'',
|
'',
|
||||||
'<h2>چرا مکملهای کانینو در ایران؟</h2>',
|
'<h2>چرا مکملهای کانینا در ایران؟</h2>',
|
||||||
'<ul>',
|
'<ul>',
|
||||||
'<li><strong>کیفیت آلمانی:</strong> تمام محصولات در کارخانه برگیش گلادباخ تحت نظارت دامپزشکان تولید میشوند</li>',
|
'<li><strong>کیفیت آلمانی:</strong> تمام محصولات در کارخانه برگیش گلادباخ تحت نظارت دامپزشکان تولید میشوند</li>',
|
||||||
'<li><strong>بدون مواد مصنوعی:</strong> فاقد رنگ، طعم و نگهدارنده مصنوعی</li>',
|
'<li><strong>بدون مواد مصنوعی:</strong> فاقد رنگ، طعم و نگهدارنده مصنوعی</li>',
|
||||||
@ -215,7 +214,7 @@ async function main() {
|
|||||||
'<p><strong>قلب و انرژی:</strong> Herz Vital (ال-کارنیتین و زالزالک)، Energy-Gel (ویتامینهای گروه B)</p>',
|
'<p><strong>قلب و انرژی:</strong> Herz Vital (ال-کارنیتین و زالزالک)، Energy-Gel (ویتامینهای گروه B)</p>',
|
||||||
'',
|
'',
|
||||||
'<h2>تعهد به سلامت حیوانات</h2>',
|
'<h2>تعهد به سلامت حیوانات</h2>',
|
||||||
'<p>کانینو به عنوان نماینده رسمی کانینا در ایران، متعهد به ارائه محصولات اصل با ضمانت اصالت و پروانه دامپزشکی است. تمام محصولات دارای بستهبندی اصلی آلمان و بارکد اختصاصی هستند.</p>'
|
'<p>کانینا به عنوان نماینده رسمی کانینا در ایران، متعهد به ارائه محصولات اصل با ضمانت اصالت و پروانه دامپزشکی است. تمام محصولات دارای بستهبندی اصلی آلمان و بارکد اختصاصی هستند.</p>'
|
||||||
].join('\n');
|
].join('\n');
|
||||||
|
|
||||||
const blogs = [
|
const blogs = [
|
||||||
@ -227,7 +226,7 @@ async function main() {
|
|||||||
isPublished: true,
|
isPublished: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'چرا مکملهای کانینو؟',
|
title: 'چرا مکملهای کانینا؟',
|
||||||
slug: 'why-canino-supplements',
|
slug: 'why-canino-supplements',
|
||||||
content: blog2Content,
|
content: blog2Content,
|
||||||
authorId: adminId,
|
authorId: adminId,
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { PrismaClient } from '@prisma/client';
|
import { PrismaClient } from '@prisma/client';
|
||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import * as ts from 'typescript';
|
import * as ts from 'typescript';
|
||||||
@ -47,7 +47,7 @@ async function main() {
|
|||||||
const uiTexts = {
|
const uiTexts = {
|
||||||
hero_badge: "از ۱۹۸۴ در خدمت سلامت حیوانات",
|
hero_badge: "از ۱۹۸۴ در خدمت سلامت حیوانات",
|
||||||
hero_title: "تخصص آلمانی در خدمت\nسلامت پتهای خانگی",
|
hero_title: "تخصص آلمانی در خدمت\nسلامت پتهای خانگی",
|
||||||
hero_desc: "از سال ۱۹۸۴، شرکت Canina pharma GmbH در برگیش گلادباخ آلمان، با بهرهگیری از مواد اولیه طبیعی و فرآیندهای پیشرفته، استاندارد طلایی مکملهای دامپزشکی را تعریف میکند. کانینو نماینده رسمی این برند در ایران است.",
|
hero_desc: "از سال ۱۹۸۴، شرکت Canina pharma GmbH در برگیش گلادباخ آلمان، با بهرهگیری از مواد اولیه طبیعی و فرآیندهای پیشرفته، استاندارد طلایی مکملهای دامپزشکی را تعریف میکند. کانینا نماینده رسمی این برند در ایران است.",
|
||||||
hero_btn_advisor: "دستیار سلامت پت",
|
hero_btn_advisor: "دستیار سلامت پت",
|
||||||
hero_btn_products: "مشاهده محصولات",
|
hero_btn_products: "مشاهده محصولات",
|
||||||
hero_stat_founded: "۱۹۸۴ سال تأسیس",
|
hero_stat_founded: "۱۹۸۴ سال تأسیس",
|
||||||
@ -57,12 +57,12 @@ async function main() {
|
|||||||
hero_image_title: "مکملهای تایید شده دامپزشکی با گواهی IFS",
|
hero_image_title: "مکملهای تایید شده دامپزشکی با گواهی IFS",
|
||||||
hero_quality_standard: "استاندارد کیفی آلمان (IFS & HACCP)",
|
hero_quality_standard: "استاندارد کیفی آلمان (IFS & HACCP)",
|
||||||
cta_title: "میخواهید بدانید کدام محصول برای پت شما مناسبتر است؟",
|
cta_title: "میخواهید بدانید کدام محصول برای پت شما مناسبتر است؟",
|
||||||
cta_subtitle: "تیم متخصص دامپزشکی کانینو ایران آماده پاسخگویی به سوالات شماست. با بیش از ۴۰ محصول تخصصی، راهکار مناسب هر نیاز بالینی را خواهید یافت.",
|
cta_subtitle: "تیم متخصص دامپزشکی کانینا ایران آماده پاسخگویی به سوالات شماست. با بیش از ۴۰ محصول تخصصی، راهکار مناسب هر نیاز بالینی را خواهید یافت.",
|
||||||
cta_btn_free: "دریافت رژیم مکمل رایگان",
|
cta_btn_free: "دریافت رژیم مکمل رایگان",
|
||||||
cta_btn_products: "ورود به محصولات تخصصی",
|
cta_btn_products: "ورود به محصولات تخصصی",
|
||||||
about_teaser_badge: "داستان ما از آلمان",
|
about_teaser_badge: "داستان ما از آلمان",
|
||||||
about_teaser_title: "Canina pharma GmbH – میراثی از ۱۹۸۴",
|
about_teaser_title: "Canina pharma GmbH – میراثی از ۱۹۸۴",
|
||||||
about_teaser_desc: "شرکت Canina pharma GmbH در سال ۱۹۸۴ توسط پتر و کریستین کرشنمایر در شهر برگیش گلادباخ آلمان تأسیس شد. این شرکت با شعار «مادر طبیعت بهترین نسخه را میداند» از مواد اولیه طبیعی و تجدیدپذیر برای تولید مکملهای با گرید دارویی استفاده میکند. امروزه محصولات کانینا در بیش از ۴۰ کشور جهان توزیع میشود و نماینده رسمی آن در ایران با نام کانینو به ارائه محصولات اصل با پروانه دامپزشکی میپردازد.",
|
about_teaser_desc: "شرکت Canina pharma GmbH در سال ۱۹۸۴ توسط پتر و کریستین کرشنمایر در شهر برگیش گلادباخ آلمان تأسیس شد. این شرکت با شعار «مادر طبیعت بهترین نسخه را میداند» از مواد اولیه طبیعی و تجدیدپذیر برای تولید مکملهای با گرید دارویی استفاده میکند. امروزه محصولات کانینا در بیش از ۴۰ کشور جهان توزیع میشود و نماینده رسمی آن در ایران با نام کانینا به ارائه محصولات اصل با پروانه دامپزشکی میپردازد.",
|
||||||
about_teaser_feat1_title: "مواد اولیه نایاب",
|
about_teaser_feat1_title: "مواد اولیه نایاب",
|
||||||
about_teaser_feat1_desc: "استفاده از پودر صدف لبسبز اصل نیوزیلند (Perna canaliculus)، پیت طبیعی آلمان، آغوز و روغنهای گیاهی ارگانیک با گرید دارویی.",
|
about_teaser_feat1_desc: "استفاده از پودر صدف لبسبز اصل نیوزیلند (Perna canaliculus)، پیت طبیعی آلمان، آغوز و روغنهای گیاهی ارگانیک با گرید دارویی.",
|
||||||
about_teaser_feat2_title: "فاقد مواد نگهدارنده",
|
about_teaser_feat2_title: "فاقد مواد نگهدارنده",
|
||||||
@ -125,7 +125,7 @@ async function main() {
|
|||||||
{
|
{
|
||||||
id: "biotin",
|
id: "biotin",
|
||||||
name: "بیوتین (ویتامین H / B7)",
|
name: "بیوتین (ویتامین H / B7)",
|
||||||
description: "کوآنزیم کربوکسیلازهای مسئول سنتز اسیدهای چرب و گلوکونئوژنز. با دوز ۱,۰۰۰,۰۰۰ میکروگرم در کیلوگرم در محصولات کانینو، قویترین دوز موجود در بازار مکملهای دامپزشکی.",
|
description: "کوآنزیم کربوکسیلازهای مسئول سنتز اسیدهای چرب و گلوکونئوژنز. با دوز ۱,۰۰۰,۰۰۰ میکروگرم در کیلوگرم در محصولات کانینا، قویترین دوز موجود در بازار مکملهای دامپزشکی.",
|
||||||
benefits: [
|
benefits: [
|
||||||
"جلوگیری از ریزش مو",
|
"جلوگیری از ریزش مو",
|
||||||
"تقویت رنگدانه پوشش",
|
"تقویت رنگدانه پوشش",
|
||||||
|
|||||||
@ -34,8 +34,8 @@ async function bootstrap() {
|
|||||||
app.useGlobalFilters(new HttpExceptionFilter());
|
app.useGlobalFilters(new HttpExceptionFilter());
|
||||||
|
|
||||||
const config = new DocumentBuilder()
|
const config = new DocumentBuilder()
|
||||||
.setTitle('Canino Iran API')
|
.setTitle('Canina Iran API')
|
||||||
.setDescription('API Documentation for Canino Iran Pet Health & Supplement Platform')
|
.setDescription('API Documentation for Canina Iran Pet Health & Supplement Platform')
|
||||||
.setVersion('1.0.0')
|
.setVersion('1.0.0')
|
||||||
.addBearerAuth()
|
.addBearerAuth()
|
||||||
.build();
|
.build();
|
||||||
|
|||||||
BIN
backend/uploads/1783765738982-360633697.png
Normal file
|
After Width: | Height: | Size: 33 KiB |
BIN
backend/uploads/1783765761042-126169451.png
Normal file
|
After Width: | Height: | Size: 23 KiB |
BIN
backend/uploads/1783766019136-538342352.png
Normal file
|
After Width: | Height: | Size: 37 KiB |
BIN
backend/uploads/1783766176570-259772529.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
backend/uploads/1783766236883-149191779.png
Normal file
|
After Width: | Height: | Size: 39 KiB |
BIN
backend/uploads/1783766312952-814581776.png
Normal file
|
After Width: | Height: | Size: 32 KiB |
BIN
backend/uploads/1783766352024-429505659.png
Normal file
|
After Width: | Height: | Size: 46 KiB |
@ -1,7 +1,7 @@
|
|||||||
# معرفی پروژه کانینو ایران (Canino Iran)
|
# معرفی پروژه کانینا ایران (Canina Iran)
|
||||||
|
|
||||||
## این پروژه چیست؟
|
## این پروژه چیست؟
|
||||||
سامانه «کانینو ایران» پلتفرم تخصصی معرفی، فروش و مدیریت مکملهای درمانی حیوانات خانگی با گرید دارویی است. این سامانه به عنوان درگاه آنلاین نماینده انحصاری کانینو آلمان در ایران فعالیت میکند. هدف اصلی پروژه، ارائه یک تجربه کاربری (UX) بسیار غنی، سریع و در کلاس جهانی برای خریداران، کلینیکهای دامپزشکی (مشتریان B2B) و همچنین فراهمکردن ابزارهای هوشمند (مانند مشاوره هوشمند و دانشنامه ترکیبات دارویی) است.
|
سامانه «کانینا ایران» پلتفرم تخصصی معرفی، فروش و مدیریت مکملهای درمانی حیوانات خانگی با گرید دارویی است. این سامانه به عنوان درگاه آنلاین نماینده انحصاری کانینا آلمان در ایران فعالیت میکند. هدف اصلی پروژه، ارائه یک تجربه کاربری (UX) بسیار غنی، سریع و در کلاس جهانی برای خریداران، کلینیکهای دامپزشکی (مشتریان B2B) و همچنین فراهمکردن ابزارهای هوشمند (مانند مشاوره هوشمند و دانشنامه ترکیبات دارویی) است.
|
||||||
|
|
||||||
## قابلیتهای کلیدی سامانه
|
## قابلیتهای کلیدی سامانه
|
||||||
سامانه به گونهای طراحی شده تا تمام نیازهای یک کسبوکار مدرن e-commerce را در کنار قابلیتهای تخصصی حوزه سلامت حیوانات برآورده کند:
|
سامانه به گونهای طراحی شده تا تمام نیازهای یک کسبوکار مدرن e-commerce را در کنار قابلیتهای تخصصی حوزه سلامت حیوانات برآورده کند:
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
# راهنمای کاربری سیستم (User Guide)
|
# راهنمای کاربری سیستم (User Guide)
|
||||||
|
|
||||||
سیستم کانینو از نظر نوع مخاطب به دو دسته کلی B2C (مشتریان عادی) و B2B (کلینیکها و فروشگاهها) تقسیم میشود. علاوه بر این، نقش «ادمین» برای مدیریت سیستم وجود دارد.
|
سیستم کانینا از نظر نوع مخاطب به دو دسته کلی B2C (مشتریان عادی) و B2B (کلینیکها و فروشگاهها) تقسیم میشود. علاوه بر این، نقش «ادمین» برای مدیریت سیستم وجود دارد.
|
||||||
|
|
||||||
## ۱. مشتریان عادی (B2C Users)
|
## ۱. مشتریان عادی (B2C Users)
|
||||||
مشتری عادی کسی است که وارد سایت میشود تا برای حیوان خانگی خود مکمل خریداری کند یا اطلاعات کسب کند.
|
مشتری عادی کسی است که وارد سایت میشود تا برای حیوان خانگی خود مکمل خریداری کند یا اطلاعات کسب کند.
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
# مستندات توسعهدهندگان (Developer Documentation)
|
# مستندات توسعهدهندگان (Developer Documentation)
|
||||||
|
|
||||||
به مستندات رسمی سامانه «کانینو ایران» خوش آمدید. این مستندات به منظور راهنمایی توسعهدهندگان، مهندسین دواپس و تیم فنی شرکت نوشته شده است و نباید در دسترس کاربران عمومی قرار گیرد.
|
به مستندات رسمی سامانه «کانینا ایران» خوش آمدید. این مستندات به منظور راهنمایی توسعهدهندگان، مهندسین دواپس و تیم فنی شرکت نوشته شده است و نباید در دسترس کاربران عمومی قرار گیرد.
|
||||||
|
|
||||||
در این دایرکتوری تمامی ساختارها، معماریها، قوانین کدنویسی و مراحل انتشار (Deployment) به دقت تدوین شدهاند تا سرعت 온بوردینگ (Onboarding) توسعهدهندگان جدید افزایش یافته و نگهداری کدهای قدیمی با کمترین ریسک انجام شود.
|
در این دایرکتوری تمامی ساختارها، معماریها، قوانین کدنویسی و مراحل انتشار (Deployment) به دقت تدوین شدهاند تا سرعت 온بوردینگ (Onboarding) توسعهدهندگان جدید افزایش یافته و نگهداری کدهای قدیمی با کمترین ریسک انجام شود.
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { Link, useLocation, useNavigate } from 'react-router-dom';
|
import { Link, useLocation, useNavigate } from 'react-router-dom';
|
||||||
import { Home, Users, ShoppingBag, ShoppingCart, Tag, Settings, LogOut, TrendingUp, FolderTree, FileText, BookOpen, Heart, Package, LayoutDashboard } from 'lucide-react';
|
import { Home, Users, ShoppingBag, ShoppingCart, Tag, Settings, LogOut, TrendingUp, FolderTree, FileText, BookOpen, Heart, Package, LayoutDashboard } from 'lucide-react';
|
||||||
|
|
||||||
const menuGroups = [
|
const menuGroups = [
|
||||||
@ -67,7 +67,7 @@ export default function Sidebar({ isOpen, setIsOpen }: SidebarProps) {
|
|||||||
<aside className={`w-64 bg-white border-l border-gray-200 h-screen fixed lg:sticky top-0 flex flex-col font-vazir shadow-sm z-50 transform transition-transform duration-300 ease-in-out ${isOpen ? 'translate-x-0' : 'translate-x-full lg:translate-x-0'
|
<aside className={`w-64 bg-white border-l border-gray-200 h-screen fixed lg:sticky top-0 flex flex-col font-vazir shadow-sm z-50 transform transition-transform duration-300 ease-in-out ${isOpen ? 'translate-x-0' : 'translate-x-full lg:translate-x-0'
|
||||||
}`}>
|
}`}>
|
||||||
<div className="h-16 flex items-center justify-center border-b border-gray-200 shrink-0">
|
<div className="h-16 flex items-center justify-center border-b border-gray-200 shrink-0">
|
||||||
<h1 className="text-xl font-black text-purple-600">کانینو | ادمینپنل</h1>
|
<h1 className="text-xl font-black text-purple-600">کانینا | ادمینپنل</h1>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<nav className="flex-1 overflow-y-auto py-4 px-3 space-y-6">
|
<nav className="flex-1 overflow-y-auto py-4 px-3 space-y-6">
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { useState, useEffect } from 'react';
|
import { useState, useEffect } from 'react';
|
||||||
import { DollarSign, ShoppingCart, Users, Activity } from 'lucide-react';
|
import { DollarSign, ShoppingCart, Users, Activity } from 'lucide-react';
|
||||||
import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer, PieChart, Pie, Cell } from 'recharts';
|
import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer, PieChart, Pie, Cell } from 'recharts';
|
||||||
import api from '../services/api';
|
import api from '../services/api';
|
||||||
@ -53,7 +53,7 @@ export default function Dashboard() {
|
|||||||
<div className="space-y-6">
|
<div className="space-y-6">
|
||||||
<div>
|
<div>
|
||||||
<h2 className="text-2xl font-black text-gray-900">داشبورد</h2>
|
<h2 className="text-2xl font-black text-gray-900">داشبورد</h2>
|
||||||
<p className="text-gray-500 font-medium mt-1">خلاصهای از وضعیت فروشگاه کانینو</p>
|
<p className="text-gray-500 font-medium mt-1">خلاصهای از وضعیت فروشگاه کانینا</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import { Lock, Mail, ChevronLeft } from 'lucide-react';
|
import { Lock, Mail, ChevronLeft } from 'lucide-react';
|
||||||
import api from '../services/api';
|
import api from '../services/api';
|
||||||
@ -36,7 +36,7 @@ export default function Login() {
|
|||||||
ورود به پنل مدیریت
|
ورود به پنل مدیریت
|
||||||
</h2>
|
</h2>
|
||||||
<p className="mt-2 text-center text-sm text-gray-600 font-bold">
|
<p className="mt-2 text-center text-sm text-gray-600 font-bold">
|
||||||
کانینو | لابراتوار تخصصی مکملهای درمانی حیوانات
|
کانینا | لابراتوار تخصصی مکملهای درمانی حیوانات
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { useState, useEffect } from 'react';
|
import { useState, useEffect } from 'react';
|
||||||
import { Settings as SettingsIcon, Save, Truck, ShieldAlert, Percent, AlertCircle } from 'lucide-react';
|
import { Settings as SettingsIcon, Save, Truck, ShieldAlert, Percent, AlertCircle } from 'lucide-react';
|
||||||
import api from '../services/api';
|
import api from '../services/api';
|
||||||
import Spinner from '../components/ui/Spinner';
|
import Spinner from '../components/ui/Spinner';
|
||||||
@ -57,7 +57,7 @@ export default function Settings() {
|
|||||||
<SettingsIcon className="w-6 h-6 text-purple-600" />
|
<SettingsIcon className="w-6 h-6 text-purple-600" />
|
||||||
تنظیمات فروشگاه
|
تنظیمات فروشگاه
|
||||||
</h2>
|
</h2>
|
||||||
<p className="text-gray-500 font-medium mt-1">مدیریت پارامترهای اصلی و سیستمی کانینو</p>
|
<p className="text-gray-500 font-medium mt-1">مدیریت پارامترهای اصلی و سیستمی کانینا</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { useState, useEffect } from 'react';
|
import { useState, useEffect } from 'react';
|
||||||
import { Search, Plus, Edit2, Trash2, BookOpen, XCircle } from 'lucide-react';
|
import { Search, Plus, Edit2, Trash2, BookOpen, XCircle } from 'lucide-react';
|
||||||
import api from '../services/api';
|
import api from '../services/api';
|
||||||
import Spinner from '../components/ui/Spinner';
|
import Spinner from '../components/ui/Spinner';
|
||||||
@ -100,7 +100,7 @@ export default function Wiki() {
|
|||||||
<div>
|
<div>
|
||||||
<h2 className="text-2xl font-black text-gray-900 flex items-center gap-2">
|
<h2 className="text-2xl font-black text-gray-900 flex items-center gap-2">
|
||||||
<BookOpen className="w-6 h-6 text-purple-600" />
|
<BookOpen className="w-6 h-6 text-purple-600" />
|
||||||
دانشنامه کانینو (Wiki)
|
دانشنامه کانینا (Wiki)
|
||||||
</h2>
|
</h2>
|
||||||
<p className="text-gray-500 font-medium mt-1">مدیریت اصطلاحات علمی، مواد تشکیلدهنده و خواص درمانی</p>
|
<p className="text-gray-500 font-medium mt-1">مدیریت اصطلاحات علمی، مواد تشکیلدهنده و خواص درمانی</p>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -3,3 +3,9 @@
|
|||||||
|
|
||||||
This version has breaking changes — APIs, conventions, and file structure may all differ from your training data. Read the relevant guide in `node_modules/next/dist/docs/` before writing any code. Heed deprecation notices.
|
This version has breaking changes — APIs, conventions, and file structure may all differ from your training data. Read the relevant guide in `node_modules/next/dist/docs/` before writing any code. Heed deprecation notices.
|
||||||
<!-- END:nextjs-agent-rules -->
|
<!-- END:nextjs-agent-rules -->
|
||||||
|
|
||||||
|
# Brand Name
|
||||||
|
نام برند رسمی «**کانینا**» / «**Canina**» است (نه «کانینو» / «Canino»). در سرتاسر پروژه باید از Canina / کانینا استفاده شود.
|
||||||
|
- CSS class names: `canina-blue`, `canina-gold`, `canina-teal`, `canina-dark`
|
||||||
|
- Store/cookie names: `canina-user`, `canina-cart`, `canina-pets`
|
||||||
|
- URL `https://canino-iran.com` (domain name, بدون تغییر میماند)
|
||||||
|
|||||||
@ -15,7 +15,7 @@ async function getBlog(slug: string) {
|
|||||||
excerpt: b.metaDescription || b.content.substring(0, 150).replace(/<[^>]+>/g, '') + '...',
|
excerpt: b.metaDescription || b.content.substring(0, 150).replace(/<[^>]+>/g, '') + '...',
|
||||||
image: b.imageUrl,
|
image: b.imageUrl,
|
||||||
date: new Date(b.createdAt).toLocaleDateString('fa-IR'),
|
date: new Date(b.createdAt).toLocaleDateString('fa-IR'),
|
||||||
author: b.author ? `${b.author.firstName} ${b.author.lastName}` : 'نویسنده کانینو',
|
author: b.author ? `${b.author.firstName} ${b.author.lastName}` : 'نویسنده کانینا',
|
||||||
content: b.content
|
content: b.content
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@ -41,7 +41,7 @@ export default async function BlogPostPage({ params }: { params: { slug: string
|
|||||||
return (
|
return (
|
||||||
<div className="min-h-[50vh] flex flex-col items-center justify-center font-vazir text-center" dir="rtl">
|
<div className="min-h-[50vh] flex flex-col items-center justify-center font-vazir text-center" dir="rtl">
|
||||||
<h1 className="text-3xl font-black text-medical-gray-900 mb-4">مقالهای یافت نشد</h1>
|
<h1 className="text-3xl font-black text-medical-gray-900 mb-4">مقالهای یافت نشد</h1>
|
||||||
<Link href="/blog" className="text-canino-blue font-bold flex items-center gap-2">
|
<Link href="/blog" className="text-canina-blue font-bold flex items-center gap-2">
|
||||||
<ChevronRight className="w-4 h-4" />
|
<ChevronRight className="w-4 h-4" />
|
||||||
بازگشت به مجله سلامت
|
بازگشت به مجله سلامت
|
||||||
</Link>
|
</Link>
|
||||||
@ -54,11 +54,11 @@ export default async function BlogPostPage({ params }: { params: { slug: string
|
|||||||
<div className="max-w-7xl mx-auto">
|
<div className="max-w-7xl mx-auto">
|
||||||
{/* Breadcrumbs */}
|
{/* Breadcrumbs */}
|
||||||
<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 gap-2 text-[10px] font-black text-medical-gray-400 uppercase tracking-widest mb-10">
|
||||||
<Link href="/" className="hover:text-canino-blue transition-colors">خانه</Link>
|
<Link href="/" className="hover:text-canina-blue transition-colors">خانه</Link>
|
||||||
<ChevronRight className="w-2.5 h-2.5" />
|
<ChevronRight className="w-2.5 h-2.5" />
|
||||||
<Link href="/blog" className="hover:text-canino-blue transition-colors">مجله سلامت</Link>
|
<Link href="/blog" className="hover:text-canina-blue transition-colors">مجله سلامت</Link>
|
||||||
<ChevronRight className="w-2.5 h-2.5" />
|
<ChevronRight className="w-2.5 h-2.5" />
|
||||||
<span className="text-canino-blue">{selectedPost.title}</span>
|
<span className="text-canina-blue">{selectedPost.title}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="grid lg:grid-cols-12 gap-12">
|
<div className="grid lg:grid-cols-12 gap-12">
|
||||||
@ -68,8 +68,8 @@ export default async function BlogPostPage({ params }: { params: { slug: string
|
|||||||
<img src={selectedPost.image} alt={selectedPost.title} className="w-full h-full object-cover" />
|
<img src={selectedPost.image} alt={selectedPost.title} className="w-full h-full object-cover" />
|
||||||
</div>
|
</div>
|
||||||
<div className="p-12">
|
<div className="p-12">
|
||||||
<div className="flex items-center gap-4 text-xs font-bold text-canino-blue mb-8">
|
<div className="flex items-center gap-4 text-xs font-bold text-canina-blue mb-8">
|
||||||
<div className="bg-canino-blue/10 px-4 py-1.5 rounded-full uppercase tracking-widest">تحقیق بالینی</div>
|
<div className="bg-canina-blue/10 px-4 py-1.5 rounded-full uppercase tracking-widest">تحقیق بالینی</div>
|
||||||
<div className="flex items-center gap-1">
|
<div className="flex items-center gap-1">
|
||||||
<Calendar className="w-4 h-4" />
|
<Calendar className="w-4 h-4" />
|
||||||
{selectedPost.date}
|
{selectedPost.date}
|
||||||
@ -79,7 +79,7 @@ export default async function BlogPostPage({ params }: { params: { slug: string
|
|||||||
{selectedPost.title}
|
{selectedPost.title}
|
||||||
</h1>
|
</h1>
|
||||||
<div className="prose prose-lg max-w-none text-medical-gray-600 leading-[2] text-justify space-y-6">
|
<div className="prose prose-lg max-w-none text-medical-gray-600 leading-[2] text-justify space-y-6">
|
||||||
<p className="font-bold text-medical-gray-900 italic text-xl border-r-4 border-canino-blue pr-6 py-2">
|
<p className="font-bold text-medical-gray-900 italic text-xl border-r-4 border-canina-blue pr-6 py-2">
|
||||||
{selectedPost.excerpt}
|
{selectedPost.excerpt}
|
||||||
</p>
|
</p>
|
||||||
<div className="whitespace-pre-line" dangerouslySetInnerHTML={{ __html: selectedPost.content }} />
|
<div className="whitespace-pre-line" dangerouslySetInnerHTML={{ __html: selectedPost.content }} />
|
||||||
@ -92,11 +92,11 @@ export default async function BlogPostPage({ params }: { params: { slug: string
|
|||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<div className="font-black text-medical-gray-900 text-lg">{selectedPost.author}</div>
|
<div className="font-black text-medical-gray-900 text-lg">{selectedPost.author}</div>
|
||||||
<div className="font-bold text-medical-gray-400">نویسنده کانینو</div>
|
<div className="font-bold text-medical-gray-400">نویسنده کانینا</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex gap-4">
|
<div className="flex gap-4">
|
||||||
<button className="p-4 bg-medical-gray-100 rounded-2xl hover:bg-canino-blue hover:text-white transition-all text-medical-gray-400">
|
<button className="p-4 bg-medical-gray-100 rounded-2xl hover:bg-canina-blue hover:text-white transition-all text-medical-gray-400">
|
||||||
<Sparkles className="w-6 h-6" />
|
<Sparkles className="w-6 h-6" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@ -106,7 +106,7 @@ export default async function BlogPostPage({ params }: { params: { slug: string
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="lg:col-span-4 space-y-10">
|
<div className="lg:col-span-4 space-y-10">
|
||||||
<div className="bg-canino-blue rounded-[3rem] p-10 text-white shadow-2xl relative overflow-hidden">
|
<div className="bg-canina-blue rounded-[3rem] p-10 text-white shadow-2xl relative overflow-hidden">
|
||||||
<div className="absolute top-0 left-0 p-8 opacity-10">
|
<div className="absolute top-0 left-0 p-8 opacity-10">
|
||||||
<Sparkles className="w-20 h-20" />
|
<Sparkles className="w-20 h-20" />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import BlogPage from "../../components/BlogPage";
|
import BlogPage from "../../components/BlogPage";
|
||||||
import type { Metadata } from 'next';
|
import type { Metadata } from 'next';
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export const metadata: Metadata = {
|
||||||
@ -19,7 +19,7 @@ async function getBlogs() {
|
|||||||
excerpt: b.metaDescription || b.content.substring(0, 150).replace(/<[^>]+>/g, '') + '...',
|
excerpt: b.metaDescription || b.content.substring(0, 150).replace(/<[^>]+>/g, '') + '...',
|
||||||
image: b.imageUrl,
|
image: b.imageUrl,
|
||||||
date: new Date(b.createdAt).toLocaleDateString('fa-IR'),
|
date: new Date(b.createdAt).toLocaleDateString('fa-IR'),
|
||||||
author: b.author ? `${b.author.firstName} ${b.author.lastName}` : 'نویسنده کانینو',
|
author: b.author ? `${b.author.firstName} ${b.author.lastName}` : 'نویسنده کانینا',
|
||||||
content: b.content
|
content: b.content
|
||||||
}));
|
}));
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@ -7,10 +7,10 @@
|
|||||||
--font-inter: "Inter", sans-serif;
|
--font-inter: "Inter", sans-serif;
|
||||||
|
|
||||||
/* Brand Colors */
|
/* Brand Colors */
|
||||||
--color-canino-blue: #1E4053;
|
--color-canina-blue: #1E4053;
|
||||||
--color-canino-gold: #F1B646;
|
--color-canina-gold: #F1B646;
|
||||||
--color-canino-teal: #9BC8CC;
|
--color-canina-teal: #9BC8CC;
|
||||||
--color-canino-dark: #060709;
|
--color-canina-dark: #060709;
|
||||||
|
|
||||||
/* Core UI color mappings (harmonies based on brand palette) */
|
/* Core UI color mappings (harmonies based on brand palette) */
|
||||||
--color-medical-gray-50: #FFFFFF; /* pure white main background */
|
--color-medical-gray-50: #FFFFFF; /* pure white main background */
|
||||||
@ -80,5 +80,5 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
::-webkit-scrollbar-thumb:hover {
|
::-webkit-scrollbar-thumb:hover {
|
||||||
background: var(--color-canino-blue);
|
background: var(--color-canina-blue);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,35 +1,35 @@
|
|||||||
import type { Metadata } from 'next';
|
import type { Metadata } from 'next';
|
||||||
import './globals.css';
|
import './globals.css';
|
||||||
import ClientLayout from './ClientLayout';
|
import ClientLayout from './ClientLayout';
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export const metadata: Metadata = {
|
||||||
metadataBase: new URL(process.env.NEXT_PUBLIC_SITE_URL || 'https://canino-iran.com'),
|
metadataBase: new URL(process.env.NEXT_PUBLIC_SITE_URL || 'https://canino-iran.com'),
|
||||||
title: {
|
title: {
|
||||||
template: '%s | کانینو ایران',
|
template: '%s | کانینا ایران',
|
||||||
default: 'کانینو ایران - مکملهای درمانی حیوانات خانگی',
|
default: 'کانینا ایران - مکملهای درمانی حیوانات خانگی',
|
||||||
},
|
},
|
||||||
description: 'تدارک هوشمندانه سلامت برای همراهان وفادار شما. کانینو ایران واردکننده انحصاری مکملهای درمانی با گرید دارویی اختصاصی از آلمان.',
|
description: 'تدارک هوشمندانه سلامت برای همراهان وفادار شما. کانینا ایران واردکننده انحصاری مکملهای درمانی با گرید دارویی اختصاصی از آلمان.',
|
||||||
keywords: ['مکمل حیوانات خانگی', 'مکمل سگ', 'مکمل گربه', 'کانینو', 'داروی حیوانات', 'Canino Iran'],
|
keywords: ['مکمل حیوانات خانگی', 'مکمل سگ', 'مکمل گربه', 'کانینا', 'داروی حیوانات', 'Canina Iran'],
|
||||||
authors: [{ name: 'Canino Iran' }],
|
authors: [{ name: 'Canina Iran' }],
|
||||||
creator: 'Canino Iran',
|
creator: 'Canina Iran',
|
||||||
publisher: 'Canino Iran',
|
publisher: 'Canina Iran',
|
||||||
formatDetection: {
|
formatDetection: {
|
||||||
email: false,
|
email: false,
|
||||||
address: false,
|
address: false,
|
||||||
telephone: false,
|
telephone: false,
|
||||||
},
|
},
|
||||||
openGraph: {
|
openGraph: {
|
||||||
title: 'کانینو ایران - مکملهای درمانی حیوانات خانگی',
|
title: 'کانینا ایران - مکملهای درمانی حیوانات خانگی',
|
||||||
description: 'واردکننده انحصاری مکملهای درمانی با گرید دارویی اختصاصی از آلمان',
|
description: 'واردکننده انحصاری مکملهای درمانی با گرید دارویی اختصاصی از آلمان',
|
||||||
url: 'https://canino-iran.com',
|
url: 'https://canino-iran.com',
|
||||||
siteName: 'کانینو ایران',
|
siteName: 'کانینا ایران',
|
||||||
locale: 'fa_IR',
|
locale: 'fa_IR',
|
||||||
type: 'website',
|
type: 'website',
|
||||||
},
|
},
|
||||||
twitter: {
|
twitter: {
|
||||||
card: 'summary_large_image',
|
card: 'summary_large_image',
|
||||||
title: 'کانینو ایران',
|
title: 'کانینا ایران',
|
||||||
description: 'مکملهای درمانی حیوانات خانگی کانینو',
|
description: 'مکملهای درمانی حیوانات خانگی کانینا',
|
||||||
},
|
},
|
||||||
robots: {
|
robots: {
|
||||||
index: true,
|
index: true,
|
||||||
@ -52,7 +52,7 @@ export default function RootLayout({
|
|||||||
const jsonLd = {
|
const jsonLd = {
|
||||||
'@context': 'https://schema.org',
|
'@context': 'https://schema.org',
|
||||||
'@type': 'Organization',
|
'@type': 'Organization',
|
||||||
name: 'کانینو ایران',
|
name: 'کانینا ایران',
|
||||||
url: 'https://canino-iran.com',
|
url: 'https://canino-iran.com',
|
||||||
logo: 'https://canina.de/media/fb/d5/47/1683116813/Logo.png',
|
logo: 'https://canina.de/media/fb/d5/47/1683116813/Logo.png',
|
||||||
contactPoint: {
|
contactPoint: {
|
||||||
|
|||||||
@ -36,9 +36,9 @@ export default async function Home() {
|
|||||||
href="/shop"
|
href="/shop"
|
||||||
className="bg-white p-12 rounded-[3.5rem] border border-medical-gray-200 shadow-sm hover:shadow-2xl hover:-translate-y-2 transition-all cursor-pointer group block"
|
className="bg-white p-12 rounded-[3.5rem] border border-medical-gray-200 shadow-sm hover:shadow-2xl hover:-translate-y-2 transition-all cursor-pointer group block"
|
||||||
>
|
>
|
||||||
<h3 className="text-3xl font-black text-medical-gray-900 mb-4 group-hover:text-canino-blue transition-colors italic">فروشگاه تخصصی</h3>
|
<h3 className="text-3xl font-black text-medical-gray-900 mb-4 group-hover:text-canina-blue transition-colors italic">فروشگاه تخصصی</h3>
|
||||||
<p className="text-medical-gray-500 mb-8 leading-relaxed">دسترسی به تمامی محصولات بر اساس علائم بالینی و نیازهای پت شما.</p>
|
<p className="text-medical-gray-500 mb-8 leading-relaxed">دسترسی به تمامی محصولات بر اساس علائم بالینی و نیازهای پت شما.</p>
|
||||||
<div className="flex items-center gap-2 text-canino-blue font-black tracking-widest uppercase text-xs">
|
<div className="flex items-center gap-2 text-canina-blue font-black tracking-widest uppercase text-xs">
|
||||||
کاتالوگ کامل محصولات
|
کاتالوگ کامل محصولات
|
||||||
<span className="text-lg">←</span>
|
<span className="text-lg">←</span>
|
||||||
</div>
|
</div>
|
||||||
@ -47,9 +47,9 @@ export default async function Home() {
|
|||||||
href="/wiki"
|
href="/wiki"
|
||||||
className="bg-medical-gray-900 p-12 rounded-[3.5rem] text-white hover:shadow-2xl hover:-translate-y-2 transition-all cursor-pointer group block"
|
className="bg-medical-gray-900 p-12 rounded-[3.5rem] text-white hover:shadow-2xl hover:-translate-y-2 transition-all cursor-pointer group block"
|
||||||
>
|
>
|
||||||
<h3 className="text-3xl font-black mb-4 group-hover:text-canino-blue transition-colors italic">دانشنامه علمی</h3>
|
<h3 className="text-3xl font-black mb-4 group-hover:text-canina-blue transition-colors italic">دانشنامه علمی</h3>
|
||||||
<p className="text-white/60 mb-8 leading-relaxed">آشنایی با ترکیبات نایاب و استانداردهای دارویی محصولات آلمانی کانینو.</p>
|
<p className="text-white/60 mb-8 leading-relaxed">آشنایی با ترکیبات نایاب و استانداردهای دارویی محصولات آلمانی کانینا.</p>
|
||||||
<div className="flex items-center gap-2 text-canino-blue font-black tracking-widest uppercase text-xs">
|
<div className="flex items-center gap-2 text-canina-blue font-black tracking-widest uppercase text-xs">
|
||||||
مطالعه مقالات تخصصی
|
مطالعه مقالات تخصصی
|
||||||
<span className="text-lg">←</span>
|
<span className="text-lg">←</span>
|
||||||
</div>
|
</div>
|
||||||
@ -61,21 +61,21 @@ export default async function Home() {
|
|||||||
<section className="py-24 bg-white overflow-hidden">
|
<section className="py-24 bg-white overflow-hidden">
|
||||||
<div className="max-w-7xl mx-auto px-4 grid lg:grid-cols-2 gap-16 lg:gap-24 items-center">
|
<div className="max-w-7xl mx-auto px-4 grid lg:grid-cols-2 gap-16 lg:gap-24 items-center">
|
||||||
<div className="relative">
|
<div className="relative">
|
||||||
<div className="absolute -top-10 -right-10 w-40 h-40 bg-canino-blue/5 rounded-full blur-3xl" />
|
<div className="absolute -top-10 -right-10 w-40 h-40 bg-canina-blue/5 rounded-full blur-3xl" />
|
||||||
<img
|
<img
|
||||||
src="/assets/images/regenerated_image_1779109861747.png"
|
src="/assets/images/regenerated_image_1779109861747.png"
|
||||||
alt="Laboratory"
|
alt="Laboratory"
|
||||||
className="rounded-[3rem] shadow-2xl relative z-10 grayscale-[10%]"
|
className="rounded-[3rem] shadow-2xl relative z-10 grayscale-[10%]"
|
||||||
/>
|
/>
|
||||||
<div className="absolute -bottom-6 -left-6 bg-canino-blue text-white p-8 rounded-3xl shadow-xl z-20">
|
<div className="absolute -bottom-6 -left-6 bg-canina-blue text-white p-8 rounded-3xl shadow-xl z-20">
|
||||||
<div className="text-4xl font-black mb-1 italic">کیفیت</div>
|
<div className="text-4xl font-black mb-1 italic">کیفیت</div>
|
||||||
<div className="text-xs uppercase tracking-widest font-bold opacity-80">استانداردهای فوقدارویی</div>
|
<div className="text-xs uppercase tracking-widest font-bold opacity-80">استانداردهای فوقدارویی</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<div className="text-canino-blue text-xs font-bold uppercase tracking-[0.2em] mb-4">میراث ما از آلمان</div>
|
<div className="text-canina-blue text-xs font-bold uppercase tracking-[0.2em] mb-4">میراث ما از آلمان</div>
|
||||||
<h2 className="text-3xl lg:text-5xl font-black text-medical-gray-900 leading-[1.2] mb-12">
|
<h2 className="text-3xl lg:text-5xl font-black text-medical-gray-900 leading-[1.2] mb-12">
|
||||||
چرا برند آلمانی Canino مرجع دامپزشکان است؟
|
چرا برند آلمانی Canina مرجع دامپزشکان است؟
|
||||||
</h2>
|
</h2>
|
||||||
<div className="space-y-6">
|
<div className="space-y-6">
|
||||||
{[
|
{[
|
||||||
@ -84,7 +84,7 @@ export default async function Home() {
|
|||||||
{ title: 'تاییدیه اروپا', desc: 'مطابق با سختگیرانهترین استانداردهای ایمنی مواد غذایی و دارویی در اتحادیه اروپا.' }
|
{ title: 'تاییدیه اروپا', desc: 'مطابق با سختگیرانهترین استانداردهای ایمنی مواد غذایی و دارویی در اتحادیه اروپا.' }
|
||||||
].map((item, idx) => (
|
].map((item, idx) => (
|
||||||
<div key={idx} className="flex gap-4 items-center">
|
<div key={idx} className="flex gap-4 items-center">
|
||||||
<div className="w-12 h-12 rounded-2xl bg-medical-gray-50 flex items-center justify-center flex-shrink-0 text-canino-blue font-bold">
|
<div className="w-12 h-12 rounded-2xl bg-medical-gray-50 flex items-center justify-center flex-shrink-0 text-canina-blue font-bold">
|
||||||
{toPersian(idx + 1)}
|
{toPersian(idx + 1)}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
@ -99,7 +99,7 @@ export default async function Home() {
|
|||||||
</section>
|
</section>
|
||||||
|
|
||||||
{/* Call to Action */}
|
{/* Call to Action */}
|
||||||
<section className="bg-canino-blue py-20 relative overflow-hidden">
|
<section className="bg-canina-blue py-20 relative overflow-hidden">
|
||||||
<div className="absolute inset-0 opacity-10">
|
<div className="absolute inset-0 opacity-10">
|
||||||
<div className="grid grid-cols-10 h-full w-full">
|
<div className="grid grid-cols-10 h-full w-full">
|
||||||
{Array.from({length: 100}).map((_, i) => (
|
{Array.from({length: 100}).map((_, i) => (
|
||||||
@ -112,15 +112,15 @@ export default async function Home() {
|
|||||||
میخواهید بدانید کدام محصول برای پت شما مناسبتر است؟
|
میخواهید بدانید کدام محصول برای پت شما مناسبتر است؟
|
||||||
</h2>
|
</h2>
|
||||||
<p className="text-white/80 text-lg mb-10 leading-relaxed">
|
<p className="text-white/80 text-lg mb-10 leading-relaxed">
|
||||||
تیم متخصص دامپزشکی کانینو ایران آماده پاسخگویی به سوالات شماست.
|
تیم متخصص دامپزشکی کانینا ایران آماده پاسخگویی به سوالات شماست.
|
||||||
</p>
|
</p>
|
||||||
<div className="flex flex-wrap justify-center gap-4">
|
<div className="flex flex-wrap justify-center gap-4">
|
||||||
<button className="bg-white text-canino-blue px-12 py-5 rounded-full font-black text-xl hover:scale-105 transition-transform shadow-2xl shadow-black/20">
|
<button className="bg-white text-canina-blue px-12 py-5 rounded-full font-black text-xl hover:scale-105 transition-transform shadow-2xl shadow-black/20">
|
||||||
دریافت رژیم مکمل رایگان
|
دریافت رژیم مکمل رایگان
|
||||||
</button>
|
</button>
|
||||||
<Link
|
<Link
|
||||||
href="/shop"
|
href="/shop"
|
||||||
className="bg-transparent border-2 border-white text-white px-12 py-5 rounded-full font-black text-xl hover:bg-white hover:text-canino-blue transition-all"
|
className="bg-transparent border-2 border-white text-white px-12 py-5 rounded-full font-black text-xl hover:bg-white hover:text-canina-blue transition-all"
|
||||||
>
|
>
|
||||||
پروانه دامپزشکی و اصالت کالا
|
پروانه دامپزشکی و اصالت کالا
|
||||||
</Link>
|
</Link>
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
import SearchResultsPage from "../../components/SearchResultsPage";
|
import SearchResultsPage from "../../components/SearchResultsPage";
|
||||||
import type { Metadata } from 'next';
|
import type { Metadata } from 'next';
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export const metadata: Metadata = {
|
||||||
title: 'جستجوی محصولات',
|
title: 'جستجوی محصولات',
|
||||||
description: 'جستجوی مکملهای درمانی حیوانات خانگی، داروها و مقالات سلامت در کانینو ایران.',
|
description: 'جستجوی مکملهای درمانی حیوانات خانگی، داروها و مقالات سلامت در کانینا ایران.',
|
||||||
};
|
};
|
||||||
|
|
||||||
export default async function SearchPage({ searchParams }: { searchParams: Promise<{ q?: string }> }) {
|
export default async function SearchPage({ searchParams }: { searchParams: Promise<{ q?: string }> }) {
|
||||||
|
|||||||
@ -54,7 +54,7 @@ export default async function ShopProductPage({ params }: { params: Promise<{ sl
|
|||||||
sku: product.artNo,
|
sku: product.artNo,
|
||||||
brand: {
|
brand: {
|
||||||
'@type': 'Brand',
|
'@type': 'Brand',
|
||||||
name: 'Canino'
|
name: 'Canina'
|
||||||
},
|
},
|
||||||
offers: {
|
offers: {
|
||||||
'@type': 'Offer',
|
'@type': 'Offer',
|
||||||
|
|||||||
@ -30,7 +30,7 @@ export default async function BlogPage({ params }: { params: { slug: string } })
|
|||||||
return (
|
return (
|
||||||
<div className="min-h-[50vh] flex flex-col items-center justify-center font-vazir text-center" dir="rtl">
|
<div className="min-h-[50vh] flex flex-col items-center justify-center font-vazir text-center" dir="rtl">
|
||||||
<h1 className="text-3xl font-black text-medical-gray-900 mb-4">مقالهای یافت نشد</h1>
|
<h1 className="text-3xl font-black text-medical-gray-900 mb-4">مقالهای یافت نشد</h1>
|
||||||
<Link href="/wiki" className="text-canino-blue font-bold flex items-center gap-2">
|
<Link href="/wiki" className="text-canina-blue font-bold flex items-center gap-2">
|
||||||
<ChevronRight className="w-4 h-4" />
|
<ChevronRight className="w-4 h-4" />
|
||||||
بازگشت به دانشنامه
|
بازگشت به دانشنامه
|
||||||
</Link>
|
</Link>
|
||||||
@ -41,7 +41,7 @@ export default async function BlogPage({ params }: { params: { slug: string } })
|
|||||||
return (
|
return (
|
||||||
<div className="bg-white py-20 px-4 font-vazir" dir="rtl">
|
<div className="bg-white py-20 px-4 font-vazir" dir="rtl">
|
||||||
<div className="max-w-4xl mx-auto">
|
<div className="max-w-4xl mx-auto">
|
||||||
<Link href="/wiki" className="inline-flex items-center gap-2 text-medical-gray-400 hover:text-canino-blue transition-colors font-bold mb-8">
|
<Link href="/wiki" className="inline-flex items-center gap-2 text-medical-gray-400 hover:text-canina-blue transition-colors font-bold mb-8">
|
||||||
<ChevronRight className="w-5 h-5" />
|
<ChevronRight className="w-5 h-5" />
|
||||||
بازگشت به مقالات
|
بازگشت به مقالات
|
||||||
</Link>
|
</Link>
|
||||||
@ -67,7 +67,7 @@ export default async function BlogPage({ params }: { params: { slug: string } })
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
className="prose prose-lg prose-medical-gray max-w-none prose-headings:font-black prose-p:leading-relaxed prose-a:text-canino-blue"
|
className="prose prose-lg prose-medical-gray max-w-none prose-headings:font-black prose-p:leading-relaxed prose-a:text-canina-blue"
|
||||||
dangerouslySetInnerHTML={{ __html: blog.content }}
|
dangerouslySetInnerHTML={{ __html: blog.content }}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
import IngredientWiki from "../../components/IngredientWiki";
|
import IngredientWiki from "../../components/IngredientWiki";
|
||||||
import type { Metadata } from 'next';
|
import type { Metadata } from 'next';
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export const metadata: Metadata = {
|
||||||
title: 'دانشنامه ترکیبات دارویی',
|
title: 'دانشنامه ترکیبات دارویی',
|
||||||
description: 'اطلاعات کامل در مورد مواد موثره، ویتامینها و ترکیبات گیاهی به کار رفته در محصولات تخصصی کانینو ایران.',
|
description: 'اطلاعات کامل در مورد مواد موثره، ویتامینها و ترکیبات گیاهی به کار رفته در محصولات تخصصی کانینا ایران.',
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function WikiPage() {
|
export default function WikiPage() {
|
||||||
|
|||||||
@ -134,7 +134,7 @@ export default function AddressModal({ isOpen, onClose, onSave, editingAddress }
|
|||||||
>
|
>
|
||||||
<div className="bg-medical-gray-50 px-8 py-6 border-b border-medical-gray-100 flex items-center justify-between">
|
<div className="bg-medical-gray-50 px-8 py-6 border-b border-medical-gray-100 flex items-center justify-between">
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
<div className="w-10 h-10 bg-canino-blue rounded-xl flex items-center justify-center text-white">
|
<div className="w-10 h-10 bg-canina-blue rounded-xl flex items-center justify-center text-white">
|
||||||
<MapPin className="w-5 h-5" />
|
<MapPin className="w-5 h-5" />
|
||||||
</div>
|
</div>
|
||||||
<h3 className="text-xl font-black text-medical-gray-900 italic">
|
<h3 className="text-xl font-black text-medical-gray-900 italic">
|
||||||
@ -159,7 +159,7 @@ export default function AddressModal({ isOpen, onClose, onSave, editingAddress }
|
|||||||
type="text"
|
type="text"
|
||||||
value={formData.title}
|
value={formData.title}
|
||||||
onChange={e => setFormData({...formData, title: e.target.value})}
|
onChange={e => setFormData({...formData, title: e.target.value})}
|
||||||
className={cn("w-full bg-medical-gray-50 border rounded-2xl py-3 px-5 outline-none font-bold transition-all focus:ring-2 focus:ring-canino-blue/20", errors.title ? "border-red-300" : "border-medical-gray-100")}
|
className={cn("w-full bg-medical-gray-50 border rounded-2xl py-3 px-5 outline-none font-bold transition-all focus:ring-2 focus:ring-canina-blue/20", errors.title ? "border-red-300" : "border-medical-gray-100")}
|
||||||
placeholder="مثال: منزل اصلی"
|
placeholder="مثال: منزل اصلی"
|
||||||
/>
|
/>
|
||||||
{errors.title && <p className="text-[10px] text-red-500 font-bold pr-2">{errors.title}</p>}
|
{errors.title && <p className="text-[10px] text-red-500 font-bold pr-2">{errors.title}</p>}
|
||||||
@ -173,7 +173,7 @@ export default function AddressModal({ isOpen, onClose, onSave, editingAddress }
|
|||||||
type="text"
|
type="text"
|
||||||
value={formData.receptorName}
|
value={formData.receptorName}
|
||||||
onChange={e => setFormData({...formData, receptorName: e.target.value})}
|
onChange={e => setFormData({...formData, receptorName: e.target.value})}
|
||||||
className={cn("w-full bg-medical-gray-50 border rounded-2xl py-3 px-5 outline-none font-bold transition-all focus:ring-2 focus:ring-canino-blue/20", errors.receptorName ? "border-red-300" : "border-medical-gray-100")}
|
className={cn("w-full bg-medical-gray-50 border rounded-2xl py-3 px-5 outline-none font-bold transition-all focus:ring-2 focus:ring-canina-blue/20", errors.receptorName ? "border-red-300" : "border-medical-gray-100")}
|
||||||
placeholder="نام و نامخانوادگی..."
|
placeholder="نام و نامخانوادگی..."
|
||||||
/>
|
/>
|
||||||
{errors.receptorName && <p className="text-[10px] text-red-500 font-bold pr-2">{errors.receptorName}</p>}
|
{errors.receptorName && <p className="text-[10px] text-red-500 font-bold pr-2">{errors.receptorName}</p>}
|
||||||
@ -184,7 +184,7 @@ export default function AddressModal({ isOpen, onClose, onSave, editingAddress }
|
|||||||
type="text"
|
type="text"
|
||||||
value={formData.phone}
|
value={formData.phone}
|
||||||
onChange={e => setFormData({...formData, phone: e.target.value})}
|
onChange={e => setFormData({...formData, phone: e.target.value})}
|
||||||
className={cn("w-full bg-medical-gray-50 border rounded-2xl py-3 px-5 outline-none font-bold transition-all focus:ring-2 focus:ring-canino-blue/20 text-left", errors.phone ? "border-red-300" : "border-medical-gray-100")}
|
className={cn("w-full bg-medical-gray-50 border rounded-2xl py-3 px-5 outline-none font-bold transition-all focus:ring-2 focus:ring-canina-blue/20 text-left", errors.phone ? "border-red-300" : "border-medical-gray-100")}
|
||||||
placeholder="09120000000"
|
placeholder="09120000000"
|
||||||
dir="ltr"
|
dir="ltr"
|
||||||
/>
|
/>
|
||||||
@ -200,7 +200,7 @@ export default function AddressModal({ isOpen, onClose, onSave, editingAddress }
|
|||||||
type="text"
|
type="text"
|
||||||
value={formData.province}
|
value={formData.province}
|
||||||
onChange={e => setFormData({...formData, province: e.target.value})}
|
onChange={e => setFormData({...formData, province: e.target.value})}
|
||||||
className={cn("w-full bg-medical-gray-50 border rounded-2xl py-3 px-5 outline-none font-bold transition-all focus:ring-2 focus:ring-canino-blue/20", errors.province ? "border-red-300" : "border-medical-gray-100")}
|
className={cn("w-full bg-medical-gray-50 border rounded-2xl py-3 px-5 outline-none font-bold transition-all focus:ring-2 focus:ring-canina-blue/20", errors.province ? "border-red-300" : "border-medical-gray-100")}
|
||||||
placeholder="نام استان..."
|
placeholder="نام استان..."
|
||||||
/>
|
/>
|
||||||
{errors.province && <p className="text-[10px] text-red-500 font-bold pr-2">{errors.province}</p>}
|
{errors.province && <p className="text-[10px] text-red-500 font-bold pr-2">{errors.province}</p>}
|
||||||
@ -211,7 +211,7 @@ export default function AddressModal({ isOpen, onClose, onSave, editingAddress }
|
|||||||
type="text"
|
type="text"
|
||||||
value={formData.city}
|
value={formData.city}
|
||||||
onChange={e => setFormData({...formData, city: e.target.value})}
|
onChange={e => setFormData({...formData, city: e.target.value})}
|
||||||
className={cn("w-full bg-medical-gray-50 border rounded-2xl py-3 px-5 outline-none font-bold transition-all focus:ring-2 focus:ring-canino-blue/20", errors.city ? "border-red-300" : "border-medical-gray-100")}
|
className={cn("w-full bg-medical-gray-50 border rounded-2xl py-3 px-5 outline-none font-bold transition-all focus:ring-2 focus:ring-canina-blue/20", errors.city ? "border-red-300" : "border-medical-gray-100")}
|
||||||
placeholder="نام شهر..."
|
placeholder="نام شهر..."
|
||||||
/>
|
/>
|
||||||
{errors.city && <p className="text-[10px] text-red-500 font-bold pr-2">{errors.city}</p>}
|
{errors.city && <p className="text-[10px] text-red-500 font-bold pr-2">{errors.city}</p>}
|
||||||
@ -225,7 +225,7 @@ export default function AddressModal({ isOpen, onClose, onSave, editingAddress }
|
|||||||
rows={2}
|
rows={2}
|
||||||
value={formData.detail}
|
value={formData.detail}
|
||||||
onChange={e => setFormData({...formData, detail: e.target.value})}
|
onChange={e => setFormData({...formData, detail: e.target.value})}
|
||||||
className={cn("w-full bg-medical-gray-50 border rounded-2xl py-3 px-5 outline-none font-bold transition-all focus:ring-2 focus:ring-canino-blue/20 resize-none", errors.detail ? "border-red-300" : "border-medical-gray-100")}
|
className={cn("w-full bg-medical-gray-50 border rounded-2xl py-3 px-5 outline-none font-bold transition-all focus:ring-2 focus:ring-canina-blue/20 resize-none", errors.detail ? "border-red-300" : "border-medical-gray-100")}
|
||||||
placeholder="خیابان، کوچه، پلاک، واحد..."
|
placeholder="خیابان، کوچه، پلاک، واحد..."
|
||||||
/>
|
/>
|
||||||
{errors.detail && <p className="text-[10px] text-red-500 font-bold pr-2">{errors.detail}</p>}
|
{errors.detail && <p className="text-[10px] text-red-500 font-bold pr-2">{errors.detail}</p>}
|
||||||
@ -238,7 +238,7 @@ export default function AddressModal({ isOpen, onClose, onSave, editingAddress }
|
|||||||
type="text"
|
type="text"
|
||||||
value={formData.zipCode}
|
value={formData.zipCode}
|
||||||
onChange={e => setFormData({...formData, zipCode: e.target.value})}
|
onChange={e => setFormData({...formData, zipCode: e.target.value})}
|
||||||
className={cn("w-full bg-medical-gray-50 border rounded-2xl py-3 px-5 outline-none font-bold transition-all focus:ring-2 focus:ring-canino-blue/20 text-left", errors.zipCode ? "border-red-300" : "border-medical-gray-100")}
|
className={cn("w-full bg-medical-gray-50 border rounded-2xl py-3 px-5 outline-none font-bold transition-all focus:ring-2 focus:ring-canina-blue/20 text-left", errors.zipCode ? "border-red-300" : "border-medical-gray-100")}
|
||||||
placeholder="1234567890"
|
placeholder="1234567890"
|
||||||
dir="ltr"
|
dir="ltr"
|
||||||
/>
|
/>
|
||||||
@ -252,7 +252,7 @@ export default function AddressModal({ isOpen, onClose, onSave, editingAddress }
|
|||||||
onClick={() => setFormData({...formData, isDefault: !formData.isDefault})}
|
onClick={() => setFormData({...formData, isDefault: !formData.isDefault})}
|
||||||
className={cn(
|
className={cn(
|
||||||
"w-6 h-6 rounded-lg border-2 flex items-center justify-center transition-all",
|
"w-6 h-6 rounded-lg border-2 flex items-center justify-center transition-all",
|
||||||
formData.isDefault ? "bg-canino-blue border-canino-blue text-white" : "border-medical-gray-200 text-transparent"
|
formData.isDefault ? "bg-canina-blue border-canina-blue text-white" : "border-medical-gray-200 text-transparent"
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<Check className="w-4 h-4" />
|
<Check className="w-4 h-4" />
|
||||||
@ -272,7 +272,7 @@ export default function AddressModal({ isOpen, onClose, onSave, editingAddress }
|
|||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
disabled={isSubmitting}
|
disabled={isSubmitting}
|
||||||
className="flex-[2] py-4 bg-canino-blue text-white rounded-2xl font-black text-sm flex items-center justify-center gap-3 hover:bg-medical-gray-900 transition-all shadow-lg shadow-canino-blue/20 disabled:opacity-50 disabled:cursor-wait"
|
className="flex-[2] py-4 bg-canina-blue text-white rounded-2xl font-black text-sm flex items-center justify-center gap-3 hover:bg-medical-gray-900 transition-all shadow-lg shadow-canina-blue/20 disabled:opacity-50 disabled:cursor-wait"
|
||||||
>
|
>
|
||||||
{isSubmitting ? (
|
{isSubmitting ? (
|
||||||
<div className="w-5 h-5 border-2 border-white/30 border-t-white rounded-full animate-spin" />
|
<div className="w-5 h-5 border-2 border-white/30 border-t-white rounded-full animate-spin" />
|
||||||
|
|||||||
@ -104,7 +104,7 @@ const ArchiveProductCard: React.FC<{ product: Product, onClick: (p: Product) =>
|
|||||||
className="group bg-white rounded-[2.5rem] border border-medical-gray-200 overflow-hidden hover:shadow-2xl transition-all cursor-pointer flex flex-col h-full relative"
|
className="group bg-white rounded-[2.5rem] border border-medical-gray-200 overflow-hidden hover:shadow-2xl transition-all cursor-pointer flex flex-col h-full relative"
|
||||||
>
|
>
|
||||||
{product.specialBadge && (
|
{product.specialBadge && (
|
||||||
<div className="absolute top-4 right-4 z-10 bg-canino-blue text-white text-[9px] font-black uppercase tracking-widest px-3 py-1 rounded-full shadow-lg">
|
<div className="absolute top-4 right-4 z-10 bg-canina-blue text-white text-[9px] font-black uppercase tracking-widest px-3 py-1 rounded-full shadow-lg">
|
||||||
{product.specialBadge}
|
{product.specialBadge}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@ -120,7 +120,7 @@ const ArchiveProductCard: React.FC<{ product: Product, onClick: (p: Product) =>
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
<div className="aspect-square bg-medical-gray-50 flex items-center justify-center p-8 overflow-hidden relative">
|
<div className="aspect-square bg-medical-gray-50 flex items-center justify-center p-8 overflow-hidden relative">
|
||||||
<SafeImage src={product.image} alt={product.name} className="w-full h-full object-contain group-hover:scale-110 transition-transform duration-700" />
|
<SafeImage src={product.image} alt={product.name} className="w-full h-full group-hover:scale-110 transition-transform duration-700" imgClassName="object-contain" />
|
||||||
<div className="absolute bottom-4 left-4 flex gap-2">
|
<div className="absolute bottom-4 left-4 flex gap-2">
|
||||||
{(product.suitableFor === "سگ" || product.suitableFor === "هر دو") && (
|
{(product.suitableFor === "سگ" || product.suitableFor === "هر دو") && (
|
||||||
<div className="w-7 h-7 bg-white rounded-lg flex items-center justify-center text-medical-gray-400 border border-medical-gray-100 shadow-sm">
|
<div className="w-7 h-7 bg-white rounded-lg flex items-center justify-center text-medical-gray-400 border border-medical-gray-100 shadow-sm">
|
||||||
@ -136,8 +136,8 @@ const ArchiveProductCard: React.FC<{ product: Product, onClick: (p: Product) =>
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="p-6 flex flex-col flex-1">
|
<div className="p-6 flex flex-col flex-1">
|
||||||
<div className="text-[10px] font-bold text-canino-blue uppercase tracking-widest mb-2">{product.category}</div>
|
<div className="text-[10px] font-bold text-canina-blue uppercase tracking-widest mb-2">{product.category}</div>
|
||||||
<h3 className="text-lg font-black text-medical-gray-900 group-hover:text-canino-blue transition-colors mb-3 leading-tight">{product.name}</h3>
|
<h3 className="text-lg font-black text-medical-gray-900 group-hover:text-canina-blue transition-colors mb-3 leading-tight">{product.name}</h3>
|
||||||
|
|
||||||
<div className="flex flex-wrap gap-1 mb-6">
|
<div className="flex flex-wrap gap-1 mb-6">
|
||||||
{product.symptoms.slice(0, 2).map((s, i) => (
|
{product.symptoms.slice(0, 2).map((s, i) => (
|
||||||
@ -152,7 +152,7 @@ const ArchiveProductCard: React.FC<{ product: Product, onClick: (p: Product) =>
|
|||||||
<button
|
<button
|
||||||
onClick={handleAddToCart}
|
onClick={handleAddToCart}
|
||||||
disabled={isAdding}
|
disabled={isAdding}
|
||||||
className="w-10 h-10 rounded-xl bg-medical-gray-50 text-canino-blue flex items-center justify-center group-hover:bg-canino-blue group-hover:text-white transition-all disabled:opacity-50"
|
className="w-10 h-10 rounded-xl bg-medical-gray-50 text-canina-blue flex items-center justify-center group-hover:bg-canina-blue group-hover:text-white transition-all disabled:opacity-50"
|
||||||
>
|
>
|
||||||
{isAdding ? <Loader2 className="w-4 h-4 animate-spin" /> : <Plus className="w-4 h-4" />}
|
{isAdding ? <Loader2 className="w-4 h-4 animate-spin" /> : <Plus className="w-4 h-4" />}
|
||||||
</button>
|
</button>
|
||||||
@ -263,24 +263,24 @@ export default function ArchivePage({
|
|||||||
<div className="lg:hidden mb-10 space-y-4">
|
<div className="lg:hidden mb-10 space-y-4">
|
||||||
<button
|
<button
|
||||||
onClick={() => router.back()}
|
onClick={() => router.back()}
|
||||||
className="flex items-center gap-2 text-medical-gray-500 font-bold hover:text-canino-blue transition-colors"
|
className="flex items-center gap-2 text-medical-gray-500 font-bold hover:text-canina-blue transition-colors"
|
||||||
>
|
>
|
||||||
<ChevronRight className="w-5 h-5 font-vazir" />
|
<ChevronRight className="w-5 h-5 font-vazir" />
|
||||||
<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">
|
<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-canino-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-canino-blue">فروشگاه تخصصی</span>
|
<span className="text-canina-blue">فروشگاه تخصصی</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Desktop Breadcrumbs */}
|
{/* Desktop Breadcrumbs */}
|
||||||
<div className="hidden lg:flex items-center gap-2 text-[10px] font-black text-medical-gray-400 uppercase tracking-widest mb-10">
|
<div className="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-canino-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-canino-blue">کاتالوگ کامل محصولات</span>
|
<span className="text-canina-blue">کاتالوگ کامل محصولات</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex flex-col lg:flex-row gap-10">
|
<div className="flex flex-col lg:flex-row gap-10">
|
||||||
@ -289,7 +289,7 @@ export default function ArchivePage({
|
|||||||
<aside className="lg:w-72 flex-shrink-0 space-y-8">
|
<aside className="lg:w-72 flex-shrink-0 space-y-8">
|
||||||
<div className="bg-white rounded-[2rem] p-6 border border-medical-gray-200 shadow-sm">
|
<div className="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 gap-2 mb-6">
|
||||||
<Filter className="w-5 h-5 text-canino-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>
|
||||||
|
|
||||||
@ -306,7 +306,7 @@ export default function ArchivePage({
|
|||||||
<button
|
<button
|
||||||
key={pet.id}
|
key={pet.id}
|
||||||
onClick={() => setSelectedPet(pet.id as any)}
|
onClick={() => setSelectedPet(pet.id as any)}
|
||||||
className={`py-2 rounded-xl text-[10px] font-black border transition-all flex flex-col items-center gap-1 ${selectedPet === pet.id ? 'bg-canino-blue border-canino-blue text-white shadow-lg shadow-canino-blue/20' : 'bg-white border-medical-gray-200 text-medical-gray-400'}`}
|
className={`py-2 rounded-xl text-[10px] font-black border transition-all flex flex-col items-center gap-1 ${selectedPet === pet.id ? 'bg-canina-blue border-canina-blue text-white shadow-lg shadow-canina-blue/20' : 'bg-white border-medical-gray-200 text-medical-gray-400'}`}
|
||||||
>
|
>
|
||||||
{pet.icon}
|
{pet.icon}
|
||||||
{pet.label}
|
{pet.label}
|
||||||
@ -323,7 +323,7 @@ export default function ArchivePage({
|
|||||||
<button
|
<button
|
||||||
key={cat.id}
|
key={cat.id}
|
||||||
onClick={() => setSelectedCategory(cat.id)}
|
onClick={() => setSelectedCategory(cat.id)}
|
||||||
className={`flex items-center gap-3 px-4 py-3 rounded-2xl text-xs font-bold transition-all border ${selectedCategory === cat.id ? 'bg-canino-blue border-canino-blue text-white' : 'bg-white border-medical-gray-100 text-medical-gray-600 hover:border-canino-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}
|
||||||
{cat.label}
|
{cat.label}
|
||||||
@ -352,8 +352,8 @@ export default function ArchivePage({
|
|||||||
|
|
||||||
{/* Promo Card */}
|
{/* Promo Card */}
|
||||||
<div className="bg-medical-gray-900 rounded-[2rem] p-6 text-white relative overflow-hidden group">
|
<div className="bg-medical-gray-900 rounded-[2rem] p-6 text-white relative overflow-hidden group">
|
||||||
<div className="absolute -top-10 -left-10 w-32 h-32 bg-canino-blue rounded-full blur-3xl opacity-20 group-hover:opacity-40 transition-opacity" />
|
<div className="absolute -top-10 -left-10 w-32 h-32 bg-canina-blue rounded-full blur-3xl opacity-20 group-hover:opacity-40 transition-opacity" />
|
||||||
<h4 className="text-lg font-black italic mb-4 relative z-10 underline decoration-canino-blue underline-offset-8">مشاوره رایگان</h4>
|
<h4 className="text-lg font-black italic mb-4 relative z-10 underline decoration-canina-blue underline-offset-8">مشاوره رایگان</h4>
|
||||||
<p className="text-xs text-white/60 leading-relaxed mb-6 relative z-10">اگر نمیدانید کدام ترکیب برای پت شما مناسب است، همین حالا با دامپزشکان ما تماس بگیرید.</p>
|
<p className="text-xs text-white/60 leading-relaxed mb-6 relative z-10">اگر نمیدانید کدام ترکیب برای پت شما مناسب است، همین حالا با دامپزشکان ما تماس بگیرید.</p>
|
||||||
<a href="tel:0218888" className="w-full bg-white text-medical-gray-900 py-3 rounded-xl text-xs font-black hover:scale-105 transition-transform relative z-10 flex items-center justify-center">شماره تماس: ۰۲۱-۸۸۸۸</a>
|
<a href="tel:0218888" className="w-full bg-white text-medical-gray-900 py-3 rounded-xl text-xs font-black hover:scale-105 transition-transform relative z-10 flex items-center justify-center">شماره تماس: ۰۲۱-۸۸۸۸</a>
|
||||||
</div>
|
</div>
|
||||||
@ -362,7 +362,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-8 gap-4">
|
||||||
<h2 className="text-3xl font-black text-medical-gray-900">کاتولوگ دارویی <span className="text-canino-blue">Canino</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" />
|
||||||
<input
|
<input
|
||||||
@ -370,20 +370,20 @@ export default function ArchivePage({
|
|||||||
placeholder="جستجوی محصول..."
|
placeholder="جستجوی محصول..."
|
||||||
value={searchQuery}
|
value={searchQuery}
|
||||||
onChange={(e) => setSearchQuery(e.target.value)}
|
onChange={(e) => setSearchQuery(e.target.value)}
|
||||||
className="w-full bg-white border border-medical-gray-200 rounded-full py-3 pr-11 pl-4 text-sm focus:outline-none focus:ring-2 focus:ring-canino-blue/20"
|
className="w-full bg-white border border-medical-gray-200 rounded-full py-3 pr-11 pl-4 text-sm focus:outline-none focus:ring-2 focus:ring-canina-blue/20"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<AnimatePresence mode="wait">
|
<AnimatePresence mode="wait">
|
||||||
{isUpdating ? (
|
{isUpdating ? (
|
||||||
<div key="skeleton" className="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-6">
|
<div key="skeleton" className="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-4 gap-6">
|
||||||
{Array.from({ length: 6 }).map((_, i) => (
|
{Array.from({ length: 8 }).map((_, i) => (
|
||||||
<ProductCardSkeleton key={i} />
|
<ProductCardSkeleton key={i} />
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
) : filteredProducts.length > 0 ? (
|
) : filteredProducts.length > 0 ? (
|
||||||
<div key="grid" className="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-6">
|
<div key="grid" className="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-4 gap-6">
|
||||||
<AnimatePresence mode="popLayout">
|
<AnimatePresence mode="popLayout">
|
||||||
{filteredProducts.map((p: Product) => (
|
{filteredProducts.map((p: Product) => (
|
||||||
<ArchiveProductCard key={p.id} product={p} onClick={(p) => router.push(`/shop/${p.slug || p.id}`)} />
|
<ArchiveProductCard key={p.id} product={p} onClick={(p) => router.push(`/shop/${p.slug || p.id}`)} />
|
||||||
@ -405,7 +405,7 @@ export default function ArchivePage({
|
|||||||
setActiveSymptoms([]);
|
setActiveSymptoms([]);
|
||||||
setSearchQuery("");
|
setSearchQuery("");
|
||||||
}}
|
}}
|
||||||
className="bg-canino-blue text-white px-8 py-3 rounded-xl font-black text-sm hover:scale-105 transition-transform shadow-lg shadow-canino-blue/20"
|
className="bg-canina-blue text-white px-8 py-3 rounded-xl font-black text-sm hover:scale-105 transition-transform shadow-lg shadow-canina-blue/20"
|
||||||
>
|
>
|
||||||
پاک کردن همه فیلترها و نمایش همه
|
پاک کردن همه فیلترها و نمایش همه
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@ -181,7 +181,7 @@ export default function AuthModal({ isOpen, onClose }: AuthModalProps) {
|
|||||||
dir="rtl"
|
dir="rtl"
|
||||||
>
|
>
|
||||||
{/* Top highlight bar */}
|
{/* Top highlight bar */}
|
||||||
<div className="absolute top-0 left-0 w-full h-2 bg-gradient-to-r from-canino-blue to-indigo-500" />
|
<div className="absolute top-0 left-0 w-full h-2 bg-gradient-to-r from-canina-blue to-indigo-500" />
|
||||||
|
|
||||||
<div className="p-8 relative">
|
<div className="p-8 relative">
|
||||||
{/* Close Button */}
|
{/* Close Button */}
|
||||||
@ -194,11 +194,11 @@ export default function AuthModal({ isOpen, onClose }: AuthModalProps) {
|
|||||||
|
|
||||||
{/* Title Header */}
|
{/* Title Header */}
|
||||||
<div className="flex flex-col items-center text-center mb-8 pt-4">
|
<div className="flex flex-col items-center text-center mb-8 pt-4">
|
||||||
<div className="w-20 h-20 bg-canino-blue/10 rounded-3xl flex items-center justify-center mb-4 shadow-inner">
|
<div className="w-20 h-20 bg-canina-blue/10 rounded-3xl flex items-center justify-center mb-4 shadow-inner">
|
||||||
<ShieldCheck className="w-10 h-10 text-canino-blue" />
|
<ShieldCheck className="w-10 h-10 text-canina-blue" />
|
||||||
</div>
|
</div>
|
||||||
<h2 className="text-3xl font-black text-medical-gray-900 mb-2 italic">
|
<h2 className="text-3xl font-black text-medical-gray-900 mb-2 italic">
|
||||||
ورود به دنیای کانینو
|
ورود به دنیای کانینا
|
||||||
</h2>
|
</h2>
|
||||||
<p className="text-medical-gray-500 text-sm font-bold max-w-[280px]">
|
<p className="text-medical-gray-500 text-sm font-bold max-w-[280px]">
|
||||||
{view === "otp"
|
{view === "otp"
|
||||||
@ -227,7 +227,7 @@ export default function AuthModal({ isOpen, onClose }: AuthModalProps) {
|
|||||||
value={phoneNumber}
|
value={phoneNumber}
|
||||||
onChange={(e) => setPhoneNumber(e.target.value.replace(/[^0-9]/g, ''))}
|
onChange={(e) => setPhoneNumber(e.target.value.replace(/[^0-9]/g, ''))}
|
||||||
disabled={isLoading}
|
disabled={isLoading}
|
||||||
className="w-full bg-medical-gray-50 border border-medical-gray-200 rounded-xl py-3 px-4 focus:ring-2 focus:ring-canino-blue/20 outline-none font-bold text-left tracking-widest"
|
className="w-full bg-medical-gray-50 border border-medical-gray-200 rounded-xl py-3 px-4 focus:ring-2 focus:ring-canina-blue/20 outline-none font-bold text-left tracking-widest"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
@ -238,7 +238,7 @@ export default function AuthModal({ isOpen, onClose }: AuthModalProps) {
|
|||||||
value={password}
|
value={password}
|
||||||
onChange={(e) => setPassword(e.target.value)}
|
onChange={(e) => setPassword(e.target.value)}
|
||||||
disabled={isLoading}
|
disabled={isLoading}
|
||||||
className="w-full bg-medical-gray-50 border border-medical-gray-200 rounded-xl py-3 px-4 focus:ring-2 focus:ring-canino-blue/20 outline-none text-left"
|
className="w-full bg-medical-gray-50 border border-medical-gray-200 rounded-xl py-3 px-4 focus:ring-2 focus:ring-canina-blue/20 outline-none text-left"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -246,14 +246,14 @@ export default function AuthModal({ isOpen, onClose }: AuthModalProps) {
|
|||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => setView("otp-phone")}
|
onClick={() => setView("otp-phone")}
|
||||||
className="text-xs font-bold text-canino-blue hover:underline"
|
className="text-xs font-bold text-canina-blue hover:underline"
|
||||||
>
|
>
|
||||||
ورود با کد یکبار مصرف (OTP)
|
ورود با کد یکبار مصرف (OTP)
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => setView("register")}
|
onClick={() => setView("register")}
|
||||||
className="text-xs font-bold text-canino-blue hover:underline"
|
className="text-xs font-bold text-canina-blue hover:underline"
|
||||||
>
|
>
|
||||||
حساب ندارید؟ ثبتنام
|
حساب ندارید؟ ثبتنام
|
||||||
</button>
|
</button>
|
||||||
@ -262,7 +262,7 @@ export default function AuthModal({ isOpen, onClose }: AuthModalProps) {
|
|||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
disabled={isLoading || !phoneNumber || !password}
|
disabled={isLoading || !phoneNumber || !password}
|
||||||
className="w-full py-4 mt-4 bg-canino-blue text-white rounded-xl font-black hover:bg-indigo-700 disabled:opacity-50 transition-all shadow-lg shadow-canino-blue/20 flex items-center justify-center gap-2 cursor-pointer"
|
className="w-full py-4 mt-4 bg-canina-blue text-white rounded-xl font-black hover:bg-indigo-700 disabled:opacity-50 transition-all shadow-lg shadow-canina-blue/20 flex items-center justify-center gap-2 cursor-pointer"
|
||||||
>
|
>
|
||||||
{isLoading ? <RefreshCw className="w-5 h-5 animate-spin" /> : <>ورود به حساب</>}
|
{isLoading ? <RefreshCw className="w-5 h-5 animate-spin" /> : <>ورود به حساب</>}
|
||||||
</button>
|
</button>
|
||||||
@ -286,7 +286,7 @@ export default function AuthModal({ isOpen, onClose }: AuthModalProps) {
|
|||||||
value={firstName}
|
value={firstName}
|
||||||
onChange={(e) => setFirstName(e.target.value)}
|
onChange={(e) => setFirstName(e.target.value)}
|
||||||
disabled={isLoading}
|
disabled={isLoading}
|
||||||
className="w-full bg-medical-gray-50 border border-medical-gray-200 rounded-xl py-2 px-3 focus:ring-2 focus:ring-canino-blue/20 outline-none text-sm"
|
className="w-full bg-medical-gray-50 border border-medical-gray-200 rounded-xl py-2 px-3 focus:ring-2 focus:ring-canina-blue/20 outline-none text-sm"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="space-y-1">
|
<div className="space-y-1">
|
||||||
@ -296,7 +296,7 @@ export default function AuthModal({ isOpen, onClose }: AuthModalProps) {
|
|||||||
value={lastName}
|
value={lastName}
|
||||||
onChange={(e) => setLastName(e.target.value)}
|
onChange={(e) => setLastName(e.target.value)}
|
||||||
disabled={isLoading}
|
disabled={isLoading}
|
||||||
className="w-full bg-medical-gray-50 border border-medical-gray-200 rounded-xl py-2 px-3 focus:ring-2 focus:ring-canino-blue/20 outline-none text-sm"
|
className="w-full bg-medical-gray-50 border border-medical-gray-200 rounded-xl py-2 px-3 focus:ring-2 focus:ring-canina-blue/20 outline-none text-sm"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -309,7 +309,7 @@ export default function AuthModal({ isOpen, onClose }: AuthModalProps) {
|
|||||||
value={phoneNumber}
|
value={phoneNumber}
|
||||||
onChange={(e) => setPhoneNumber(e.target.value.replace(/[^0-9]/g, ''))}
|
onChange={(e) => setPhoneNumber(e.target.value.replace(/[^0-9]/g, ''))}
|
||||||
disabled={isLoading}
|
disabled={isLoading}
|
||||||
className="w-full bg-medical-gray-50 border border-medical-gray-200 rounded-xl py-2 px-3 focus:ring-2 focus:ring-canino-blue/20 outline-none text-left tracking-widest text-sm"
|
className="w-full bg-medical-gray-50 border border-medical-gray-200 rounded-xl py-2 px-3 focus:ring-2 focus:ring-canina-blue/20 outline-none text-left tracking-widest text-sm"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -320,7 +320,7 @@ export default function AuthModal({ isOpen, onClose }: AuthModalProps) {
|
|||||||
value={email}
|
value={email}
|
||||||
onChange={(e) => setEmail(e.target.value)}
|
onChange={(e) => setEmail(e.target.value)}
|
||||||
disabled={isLoading}
|
disabled={isLoading}
|
||||||
className="w-full bg-medical-gray-50 border border-medical-gray-200 rounded-xl py-2 px-3 focus:ring-2 focus:ring-canino-blue/20 outline-none text-left text-sm"
|
className="w-full bg-medical-gray-50 border border-medical-gray-200 rounded-xl py-2 px-3 focus:ring-2 focus:ring-canina-blue/20 outline-none text-left text-sm"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -331,7 +331,7 @@ export default function AuthModal({ isOpen, onClose }: AuthModalProps) {
|
|||||||
value={password}
|
value={password}
|
||||||
onChange={(e) => setPassword(e.target.value)}
|
onChange={(e) => setPassword(e.target.value)}
|
||||||
disabled={isLoading}
|
disabled={isLoading}
|
||||||
className="w-full bg-medical-gray-50 border border-medical-gray-200 rounded-xl py-2 px-3 focus:ring-2 focus:ring-canino-blue/20 outline-none text-left text-sm"
|
className="w-full bg-medical-gray-50 border border-medical-gray-200 rounded-xl py-2 px-3 focus:ring-2 focus:ring-canina-blue/20 outline-none text-left text-sm"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -339,7 +339,7 @@ export default function AuthModal({ isOpen, onClose }: AuthModalProps) {
|
|||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => setView("login")}
|
onClick={() => setView("login")}
|
||||||
className="text-xs font-bold text-canino-blue hover:underline"
|
className="text-xs font-bold text-canina-blue hover:underline"
|
||||||
>
|
>
|
||||||
بازگشت به ورود
|
بازگشت به ورود
|
||||||
</button>
|
</button>
|
||||||
@ -348,7 +348,7 @@ export default function AuthModal({ isOpen, onClose }: AuthModalProps) {
|
|||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
disabled={isLoading || !phoneNumber || !password || !firstName || !lastName}
|
disabled={isLoading || !phoneNumber || !password || !firstName || !lastName}
|
||||||
className="w-full py-3 mt-2 bg-canino-blue text-white rounded-xl font-black hover:bg-indigo-700 disabled:opacity-50 transition-all flex items-center justify-center gap-2 cursor-pointer"
|
className="w-full py-3 mt-2 bg-canina-blue text-white rounded-xl font-black hover:bg-indigo-700 disabled:opacity-50 transition-all flex items-center justify-center gap-2 cursor-pointer"
|
||||||
>
|
>
|
||||||
{isLoading ? <RefreshCw className="w-4 h-4 animate-spin" /> : <>ثبتنام</>}
|
{isLoading ? <RefreshCw className="w-4 h-4 animate-spin" /> : <>ثبتنام</>}
|
||||||
</button>
|
</button>
|
||||||
@ -370,7 +370,7 @@ export default function AuthModal({ isOpen, onClose }: AuthModalProps) {
|
|||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => setView("login")}
|
onClick={() => setView("login")}
|
||||||
className="text-[10px] font-black text-canino-blue hover:underline"
|
className="text-[10px] font-black text-canina-blue hover:underline"
|
||||||
>
|
>
|
||||||
برگشت به صفحه ورود
|
برگشت به صفحه ورود
|
||||||
</button>
|
</button>
|
||||||
@ -385,7 +385,7 @@ export default function AuthModal({ isOpen, onClose }: AuthModalProps) {
|
|||||||
value={phoneNumber}
|
value={phoneNumber}
|
||||||
onChange={(e) => setPhoneNumber(e.target.value.replace(/[^0-9]/g, ''))}
|
onChange={(e) => setPhoneNumber(e.target.value.replace(/[^0-9]/g, ''))}
|
||||||
disabled={isLoading}
|
disabled={isLoading}
|
||||||
className="w-full bg-medical-gray-50 border border-medical-gray-200 rounded-2xl py-4 pr-12 pl-4 focus:ring-2 focus:ring-canino-blue/20 outline-none font-bold text-lg text-left tracking-widest"
|
className="w-full bg-medical-gray-50 border border-medical-gray-200 rounded-2xl py-4 pr-12 pl-4 focus:ring-2 focus:ring-canina-blue/20 outline-none font-bold text-lg text-left tracking-widest"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -393,7 +393,7 @@ export default function AuthModal({ isOpen, onClose }: AuthModalProps) {
|
|||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
disabled={isLoading || phoneNumber.length < 11}
|
disabled={isLoading || phoneNumber.length < 11}
|
||||||
className="w-full py-5 bg-canino-blue text-white rounded-2xl font-black text-xl hover:bg-indigo-700 disabled:opacity-50 transition-all shadow-xl shadow-canino-blue/20 flex items-center justify-center gap-3 cursor-pointer"
|
className="w-full py-5 bg-canina-blue text-white rounded-2xl font-black text-xl hover:bg-indigo-700 disabled:opacity-50 transition-all shadow-xl shadow-canina-blue/20 flex items-center justify-center gap-3 cursor-pointer"
|
||||||
>
|
>
|
||||||
{isLoading ? (
|
{isLoading ? (
|
||||||
<RefreshCw className="w-6 h-6 animate-spin" />
|
<RefreshCw className="w-6 h-6 animate-spin" />
|
||||||
@ -422,7 +422,7 @@ export default function AuthModal({ isOpen, onClose }: AuthModalProps) {
|
|||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => setView("otp-phone")}
|
onClick={() => setView("otp-phone")}
|
||||||
className="text-[10px] font-black text-canino-blue flex items-center gap-1 hover:underline"
|
className="text-[10px] font-black text-canina-blue flex items-center gap-1 hover:underline"
|
||||||
>
|
>
|
||||||
<ArrowRight className="w-3 h-3" />
|
<ArrowRight className="w-3 h-3" />
|
||||||
تغییر شماره
|
تغییر شماره
|
||||||
@ -438,7 +438,7 @@ export default function AuthModal({ isOpen, onClose }: AuthModalProps) {
|
|||||||
value={otpCode}
|
value={otpCode}
|
||||||
onChange={(e) => setOtpCode(e.target.value.replace(/[^0-9]/g, ''))}
|
onChange={(e) => setOtpCode(e.target.value.replace(/[^0-9]/g, ''))}
|
||||||
disabled={isLoading}
|
disabled={isLoading}
|
||||||
className="w-full bg-medical-gray-50 border border-medical-gray-200 rounded-2xl py-4 pr-12 pl-4 focus:ring-2 focus:ring-canino-blue/20 outline-none font-black text-2xl text-center tracking-[0.5em]"
|
className="w-full bg-medical-gray-50 border border-medical-gray-200 rounded-2xl py-4 pr-12 pl-4 focus:ring-2 focus:ring-canina-blue/20 outline-none font-black text-2xl text-center tracking-[0.5em]"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -453,7 +453,7 @@ export default function AuthModal({ isOpen, onClose }: AuthModalProps) {
|
|||||||
type="button"
|
type="button"
|
||||||
onClick={handleResendOtp}
|
onClick={handleResendOtp}
|
||||||
disabled={isLoading}
|
disabled={isLoading}
|
||||||
className="text-xs font-black text-canino-blue hover:underline flex items-center gap-1.5 justify-center mx-auto"
|
className="text-xs font-black text-canina-blue hover:underline flex items-center gap-1.5 justify-center mx-auto"
|
||||||
>
|
>
|
||||||
<RefreshCw className="w-3.5 h-3.5" />
|
<RefreshCw className="w-3.5 h-3.5" />
|
||||||
ارسال مجدد کد تایید
|
ارسال مجدد کد تایید
|
||||||
@ -464,7 +464,7 @@ export default function AuthModal({ isOpen, onClose }: AuthModalProps) {
|
|||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
disabled={isLoading || otpCode.length < 5}
|
disabled={isLoading || otpCode.length < 5}
|
||||||
className="w-full py-5 bg-canino-blue text-white rounded-2xl font-black text-xl hover:bg-indigo-700 disabled:opacity-50 transition-all shadow-xl shadow-canino-blue/20 flex items-center justify-center gap-3 cursor-pointer"
|
className="w-full py-5 bg-canina-blue text-white rounded-2xl font-black text-xl hover:bg-indigo-700 disabled:opacity-50 transition-all shadow-xl shadow-canina-blue/20 flex items-center justify-center gap-3 cursor-pointer"
|
||||||
>
|
>
|
||||||
{isLoading ? (
|
{isLoading ? (
|
||||||
<RefreshCw className="w-6 h-6 animate-spin" />
|
<RefreshCw className="w-6 h-6 animate-spin" />
|
||||||
|
|||||||
@ -79,7 +79,7 @@ export default function B2BPortal({ onClose }: { onClose: () => void }) {
|
|||||||
</button>
|
</button>
|
||||||
|
|
||||||
{/* Sidebar Info */}
|
{/* Sidebar Info */}
|
||||||
<div className="w-full md:w-80 bg-canino-blue p-10 text-white flex flex-col">
|
<div className="w-full md:w-80 bg-canina-blue p-10 text-white flex flex-col">
|
||||||
<div className="mb-10">
|
<div className="mb-10">
|
||||||
<div className="w-16 h-16 bg-white/20 rounded-2xl flex items-center justify-center mb-6">
|
<div className="w-16 h-16 bg-white/20 rounded-2xl flex items-center justify-center mb-6">
|
||||||
<Building2 className="w-8 h-8" />
|
<Building2 className="w-8 h-8" />
|
||||||
@ -113,14 +113,14 @@ export default function B2BPortal({ onClose }: { onClose: () => void }) {
|
|||||||
placeholder="جستجوی کد کالا یا نام محصول..."
|
placeholder="جستجوی کد کالا یا نام محصول..."
|
||||||
value={searchQuery}
|
value={searchQuery}
|
||||||
onChange={e => setSearchQuery(e.target.value)}
|
onChange={e => setSearchQuery(e.target.value)}
|
||||||
className="w-full bg-medical-gray-50 border border-medical-gray-200 rounded-2xl py-3 pr-11 pl-4 text-sm focus:outline-none focus:ring-2 focus:ring-canino-blue/20"
|
className="w-full bg-medical-gray-50 border border-medical-gray-200 rounded-2xl py-3 pr-11 pl-4 text-sm focus:outline-none focus:ring-2 focus:ring-canina-blue/20"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
onClick={handleAddAll}
|
onClick={handleAddAll}
|
||||||
disabled={totalItems === 0}
|
disabled={totalItems === 0}
|
||||||
className="bg-medical-gray-900 text-white px-8 py-3 rounded-2xl font-black text-sm flex items-center gap-2 hover:bg-canino-blue transition-colors disabled:opacity-30"
|
className="bg-medical-gray-900 text-white px-8 py-3 rounded-2xl font-black text-sm flex items-center gap-2 hover:bg-canina-blue transition-colors disabled:opacity-30"
|
||||||
>
|
>
|
||||||
<ShoppingCart className="w-4 h-4" />
|
<ShoppingCart className="w-4 h-4" />
|
||||||
افزودن کلی ({totalItems} عدد)
|
افزودن کلی ({totalItems} عدد)
|
||||||
@ -143,7 +143,7 @@ export default function B2BPortal({ onClose }: { onClose: () => void }) {
|
|||||||
{filteredProducts.map(product => (
|
{filteredProducts.map(product => (
|
||||||
<tr key={product.id} className="hover:bg-medical-gray-50/50 transition-colors">
|
<tr key={product.id} className="hover:bg-medical-gray-50/50 transition-colors">
|
||||||
<td className="px-6 py-4">
|
<td className="px-6 py-4">
|
||||||
<SafeImage src={product.image} className="w-12 h-12 object-contain" alt={product.name} />
|
<SafeImage src={product.image} className="w-12 h-12" imgClassName="object-contain" alt={product.name} />
|
||||||
</td>
|
</td>
|
||||||
<td className="px-6 py-4">
|
<td className="px-6 py-4">
|
||||||
<div className="font-black text-medical-gray-900">{product.name}</div>
|
<div className="font-black text-medical-gray-900">{product.name}</div>
|
||||||
@ -162,7 +162,7 @@ export default function B2BPortal({ onClose }: { onClose: () => void }) {
|
|||||||
value={quantities[product.id] || ""}
|
value={quantities[product.id] || ""}
|
||||||
onChange={(e) => handleQuantityChange(product.id, e.target.value)}
|
onChange={(e) => handleQuantityChange(product.id, e.target.value)}
|
||||||
placeholder="0"
|
placeholder="0"
|
||||||
className="w-20 bg-medical-gray-50 border border-medical-gray-200 rounded-xl py-2 px-3 text-center font-mono font-bold focus:ring-2 focus:ring-canino-blue/20 outline-none"
|
className="w-20 bg-medical-gray-50 border border-medical-gray-200 rounded-xl py-2 px-3 text-center font-mono font-bold focus:ring-2 focus:ring-canina-blue/20 outline-none"
|
||||||
/>
|
/>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
@ -33,11 +33,11 @@ export default function BlogPage({ blogs = [] }: { blogs: BlogPost[] }) {
|
|||||||
<div className="max-w-7xl mx-auto">
|
<div className="max-w-7xl mx-auto">
|
||||||
{/* Breadcrumbs */}
|
{/* Breadcrumbs */}
|
||||||
<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 gap-2 text-[10px] font-black text-medical-gray-400 uppercase tracking-widest mb-10">
|
||||||
<span className="cursor-pointer hover:text-canino-blue" onClick={() => router.push('/')}>خانه</span>
|
<span className="cursor-pointer hover:text-canina-blue" onClick={() => router.push('/')}>خانه</span>
|
||||||
<ChevronRight className="w-2.5 h-2.5" />
|
<ChevronRight className="w-2.5 h-2.5" />
|
||||||
<span className="cursor-pointer hover:text-canino-blue" onClick={() => setSelectedPost(null)}>مجله سلامت</span>
|
<span className="cursor-pointer hover:text-canina-blue" onClick={() => setSelectedPost(null)}>مجله سلامت</span>
|
||||||
<ChevronRight className="w-2.5 h-2.5" />
|
<ChevronRight className="w-2.5 h-2.5" />
|
||||||
<span className="text-canino-blue">{selectedPost.title}</span>
|
<span className="text-canina-blue">{selectedPost.title}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="grid lg:grid-cols-12 gap-12">
|
<div className="grid lg:grid-cols-12 gap-12">
|
||||||
@ -51,8 +51,8 @@ export default function BlogPage({ blogs = [] }: { blogs: BlogPost[] }) {
|
|||||||
<img src={selectedPost.image} alt={selectedPost.title} className="w-full h-full object-cover" />
|
<img src={selectedPost.image} alt={selectedPost.title} className="w-full h-full object-cover" />
|
||||||
</div>
|
</div>
|
||||||
<div className="p-12">
|
<div className="p-12">
|
||||||
<div className="flex items-center gap-4 text-xs font-bold text-canino-blue mb-8">
|
<div className="flex items-center gap-4 text-xs font-bold text-canina-blue mb-8">
|
||||||
<div className="bg-canino-blue/10 px-4 py-1.5 rounded-full uppercase tracking-widest">تحقیق بالینی</div>
|
<div className="bg-canina-blue/10 px-4 py-1.5 rounded-full uppercase tracking-widest">تحقیق بالینی</div>
|
||||||
<div className="flex items-center gap-1">
|
<div className="flex items-center gap-1">
|
||||||
<Calendar className="w-4 h-4" />
|
<Calendar className="w-4 h-4" />
|
||||||
{selectedPost.date}
|
{selectedPost.date}
|
||||||
@ -62,7 +62,7 @@ export default function BlogPage({ blogs = [] }: { blogs: BlogPost[] }) {
|
|||||||
{selectedPost.title}
|
{selectedPost.title}
|
||||||
</h1>
|
</h1>
|
||||||
<div className="prose prose-lg max-w-none text-medical-gray-600 leading-[2] text-justify space-y-6">
|
<div className="prose prose-lg max-w-none text-medical-gray-600 leading-[2] text-justify space-y-6">
|
||||||
<p className="font-bold text-medical-gray-900 italic text-xl border-r-4 border-canino-blue pr-6 py-2">
|
<p className="font-bold text-medical-gray-900 italic text-xl border-r-4 border-canina-blue pr-6 py-2">
|
||||||
{selectedPost.excerpt}
|
{selectedPost.excerpt}
|
||||||
</p>
|
</p>
|
||||||
<div className="whitespace-pre-line">
|
<div className="whitespace-pre-line">
|
||||||
@ -77,11 +77,11 @@ export default function BlogPage({ blogs = [] }: { blogs: BlogPost[] }) {
|
|||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<div className="font-black text-medical-gray-900 text-lg">{selectedPost.author}</div>
|
<div className="font-black text-medical-gray-900 text-lg">{selectedPost.author}</div>
|
||||||
<div className="font-bold text-medical-gray-400">تیم تحقیق و توسعه کانینو آلمان</div>
|
<div className="font-bold text-medical-gray-400">تیم تحقیق و توسعه کانینا آلمان</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex gap-4">
|
<div className="flex gap-4">
|
||||||
<button className="p-4 bg-medical-gray-100 rounded-2xl hover:bg-canino-blue hover:text-white transition-all text-medical-gray-400">
|
<button className="p-4 bg-medical-gray-100 rounded-2xl hover:bg-canina-blue hover:text-white transition-all text-medical-gray-400">
|
||||||
<Sparkles className="w-6 h-6" />
|
<Sparkles className="w-6 h-6" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@ -91,7 +91,7 @@ export default function BlogPage({ blogs = [] }: { blogs: BlogPost[] }) {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="lg:col-span-4 space-y-10">
|
<div className="lg:col-span-4 space-y-10">
|
||||||
<div className="bg-canino-blue rounded-[3rem] p-10 text-white shadow-2xl relative overflow-hidden">
|
<div className="bg-canina-blue rounded-[3rem] p-10 text-white shadow-2xl relative overflow-hidden">
|
||||||
<div className="absolute top-0 left-0 p-8 opacity-10">
|
<div className="absolute top-0 left-0 p-8 opacity-10">
|
||||||
<Sparkles className="w-20 h-20" />
|
<Sparkles className="w-20 h-20" />
|
||||||
</div>
|
</div>
|
||||||
@ -127,7 +127,7 @@ export default function BlogPage({ blogs = [] }: { blogs: BlogPost[] }) {
|
|||||||
<div className="w-16 h-16 rounded-2xl overflow-hidden shrink-0">
|
<div className="w-16 h-16 rounded-2xl overflow-hidden shrink-0">
|
||||||
<img src={p.image} className="w-full h-full object-cover group-hover:scale-110 transition-transform" />
|
<img src={p.image} className="w-full h-full object-cover group-hover:scale-110 transition-transform" />
|
||||||
</div>
|
</div>
|
||||||
<div className="text-sm font-black text-medical-gray-900 group-hover:text-canino-blue transition-colors line-clamp-2">
|
<div className="text-sm font-black text-medical-gray-900 group-hover:text-canina-blue transition-colors line-clamp-2">
|
||||||
{p.title}
|
{p.title}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -147,15 +147,15 @@ export default function BlogPage({ blogs = [] }: { blogs: BlogPost[] }) {
|
|||||||
{/* Header */}
|
{/* Header */}
|
||||||
<div className="flex flex-col md:flex-row items-center justify-between mb-16 gap-6">
|
<div className="flex flex-col md:flex-row items-center justify-between mb-16 gap-6">
|
||||||
<div className="text-right">
|
<div className="text-right">
|
||||||
<div className="inline-flex items-center gap-2 px-3 py-1 bg-canino-blue/10 text-canino-blue rounded-full text-[10px] font-black uppercase tracking-widest mb-4">
|
<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">
|
||||||
<BookOpen className="w-3 h-3" />
|
<BookOpen className="w-3 h-3" />
|
||||||
Canino Science Blog
|
Canina Science Blog
|
||||||
</div>
|
</div>
|
||||||
<h1 className="text-4xl lg:text-6xl font-black text-medical-gray-900 italic leading-tight">
|
<h1 className="text-4xl lg:text-6xl font-black text-medical-gray-900 italic leading-tight">
|
||||||
مجله تخصصی <span className="text-canino-blue">سلامت پتها</span>
|
مجله تخصصی <span className="text-canina-blue">سلامت پتها</span>
|
||||||
</h1>
|
</h1>
|
||||||
<p className="text-lg text-medical-gray-500 font-medium mt-4 max-w-xl">
|
<p className="text-lg text-medical-gray-500 font-medium mt-4 max-w-xl">
|
||||||
آخرین یافتههای علمی محققین کانینو آلمان در مورد تغذیه و سلامت پتها.
|
آخرین یافتههای علمی محققین کانینا آلمان در مورد تغذیه و سلامت پتها.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
@ -184,14 +184,14 @@ export default function BlogPage({ blogs = [] }: { blogs: BlogPost[] }) {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="lg:w-1/2 p-12 flex flex-col justify-center">
|
<div className="lg:w-1/2 p-12 flex flex-col justify-center">
|
||||||
<div className="flex items-center gap-4 text-xs font-bold text-canino-blue mb-6">
|
<div className="flex items-center gap-4 text-xs font-bold text-canina-blue mb-6">
|
||||||
<div className="bg-canino-blue/10 px-3 py-1 rounded-full uppercase tracking-widest">تخصصی</div>
|
<div className="bg-canina-blue/10 px-3 py-1 rounded-full uppercase tracking-widest">تخصصی</div>
|
||||||
<div className="flex items-center gap-1">
|
<div className="flex items-center gap-1">
|
||||||
<Calendar className="w-3 h-3" />
|
<Calendar className="w-3 h-3" />
|
||||||
{blogs[0].date}
|
{blogs[0].date}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<h2 className="text-3xl lg:text-4xl font-black text-medical-gray-900 mb-6 leading-tight group-hover:text-canino-blue transition-colors">
|
<h2 className="text-3xl lg:text-4xl font-black text-medical-gray-900 mb-6 leading-tight group-hover:text-canina-blue transition-colors">
|
||||||
{blogs[0].title}
|
{blogs[0].title}
|
||||||
</h2>
|
</h2>
|
||||||
<p className="text-lg text-medical-gray-500 mb-8 leading-relaxed italic">
|
<p className="text-lg text-medical-gray-500 mb-8 leading-relaxed italic">
|
||||||
@ -204,10 +204,10 @@ export default function BlogPage({ blogs = [] }: { blogs: BlogPost[] }) {
|
|||||||
</div>
|
</div>
|
||||||
<div className="text-sm">
|
<div className="text-sm">
|
||||||
<div className="font-black text-medical-gray-900">{blogs[0].author}</div>
|
<div className="font-black text-medical-gray-900">{blogs[0].author}</div>
|
||||||
<div className="font-bold text-medical-gray-400">نویسنده کانینو</div>
|
<div className="font-bold text-medical-gray-400">نویسنده کانینا</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center gap-2 text-canino-blue font-black">
|
<div className="flex items-center gap-2 text-canina-blue font-black">
|
||||||
ادامه مطلب
|
ادامه مطلب
|
||||||
<ArrowLeft className="w-5 h-5 group-hover:-translate-x-2 transition-transform" />
|
<ArrowLeft className="w-5 h-5 group-hover:-translate-x-2 transition-transform" />
|
||||||
</div>
|
</div>
|
||||||
@ -237,13 +237,13 @@ export default function BlogPage({ blogs = [] }: { blogs: BlogPost[] }) {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="p-8">
|
<div className="p-8">
|
||||||
<div className="flex items-center gap-4 text-[10px] font-bold text-canino-blue mb-4">
|
<div className="flex items-center gap-4 text-[10px] font-bold text-canina-blue mb-4">
|
||||||
<div className="flex items-center gap-1">
|
<div className="flex items-center gap-1">
|
||||||
<Calendar className="w-3 h-3" />
|
<Calendar className="w-3 h-3" />
|
||||||
{post.date}
|
{post.date}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<h3 className="text-xl font-black text-medical-gray-900 mb-4 group-hover:text-canino-blue transition-colors">
|
<h3 className="text-xl font-black text-medical-gray-900 mb-4 group-hover:text-canina-blue transition-colors">
|
||||||
{post.title}
|
{post.title}
|
||||||
</h3>
|
</h3>
|
||||||
<p className="text-sm text-medical-gray-500 mb-8 leading-relaxed line-clamp-2">
|
<p className="text-sm text-medical-gray-500 mb-8 leading-relaxed line-clamp-2">
|
||||||
@ -258,7 +258,7 @@ export default function BlogPage({ blogs = [] }: { blogs: BlogPost[] }) {
|
|||||||
))}
|
))}
|
||||||
|
|
||||||
{/* Newsletter / CTA Box */}
|
{/* Newsletter / CTA Box */}
|
||||||
<div className="bg-canino-blue rounded-[3rem] p-10 text-white relative overflow-hidden flex flex-col justify-center">
|
<div className="bg-canina-blue rounded-[3rem] p-10 text-white relative overflow-hidden flex flex-col justify-center">
|
||||||
<div className="absolute top-0 right-0 p-8 opacity-20">
|
<div className="absolute top-0 right-0 p-8 opacity-20">
|
||||||
<Sparkles className="w-24 h-24" />
|
<Sparkles className="w-24 h-24" />
|
||||||
</div>
|
</div>
|
||||||
@ -272,7 +272,7 @@ export default function BlogPage({ blogs = [] }: { blogs: BlogPost[] }) {
|
|||||||
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 outline-none focus:bg-white/20 placeholder:text-white/40"
|
||||||
/>
|
/>
|
||||||
<button className="bg-white text-canino-blue px-6 py-3 rounded-xl font-black">
|
<button className="bg-white text-canina-blue px-6 py-3 rounded-xl font-black">
|
||||||
عضویت
|
عضویت
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@ -280,7 +280,7 @@ export default function BlogPage({ blogs = [] }: { blogs: BlogPost[] }) {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Synergy Products Cross-sell */}
|
{/* Synergy Products Cross-sell */}
|
||||||
<section className="mt-32 p-12 bg-canino-blue rounded-[4rem] text-white overflow-hidden relative shadow-2xl">
|
<section className="mt-32 p-12 bg-canina-blue rounded-[4rem] text-white overflow-hidden relative shadow-2xl">
|
||||||
<div className="absolute inset-0 opacity-20 pointer-events-none">
|
<div className="absolute inset-0 opacity-20 pointer-events-none">
|
||||||
<div className="grid grid-cols-6 h-full w-full">
|
<div className="grid grid-cols-6 h-full w-full">
|
||||||
{Array.from({ length: 36 }).map((_, i) => (
|
{Array.from({ length: 36 }).map((_, i) => (
|
||||||
@ -292,11 +292,11 @@ export default function BlogPage({ blogs = [] }: { blogs: BlogPost[] }) {
|
|||||||
<div className="flex-1">
|
<div className="flex-1">
|
||||||
<h3 className="text-3xl lg:text-4xl font-black italic mb-6">علم آلمانی در خدمت سلامت پت شما</h3>
|
<h3 className="text-3xl lg:text-4xl font-black italic mb-6">علم آلمانی در خدمت سلامت پت شما</h3>
|
||||||
<p className="text-white/80 mb-8 leading-relaxed max-w-xl">
|
<p className="text-white/80 mb-8 leading-relaxed max-w-xl">
|
||||||
تمامی مقالات این وبلاگ بر اساس کاتالوگهای رسمی و نتایج آزمایشگاهی کمپانی کانینو آلمان تدوین شده است.
|
تمامی مقالات این وبلاگ بر اساس کاتالوگهای رسمی و نتایج آزمایشگاهی کمپانی کانینا آلمان تدوین شده است.
|
||||||
</p>
|
</p>
|
||||||
<button
|
<button
|
||||||
onClick={() => router.push('/shop')}
|
onClick={() => router.push('/shop')}
|
||||||
className="bg-white text-canino-blue px-8 py-4 rounded-2xl font-black hover:scale-105 transition-transform"
|
className="bg-white text-canina-blue px-8 py-4 rounded-2xl font-black hover:scale-105 transition-transform"
|
||||||
>
|
>
|
||||||
مشاهده محصولات تخصصی
|
مشاهده محصولات تخصصی
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@ -69,7 +69,7 @@ export default function CartDrawer({ isOpen, onClose, onCheckout, onShopNavigate
|
|||||||
{/* Header */}
|
{/* Header */}
|
||||||
<div className="p-6 border-b border-medical-gray-100 flex items-center justify-between">
|
<div className="p-6 border-b border-medical-gray-100 flex items-center justify-between">
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
<div className="w-10 h-10 bg-medical-gray-50 rounded-xl flex items-center justify-center text-canino-blue">
|
<div className="w-10 h-10 bg-medical-gray-50 rounded-xl flex items-center justify-center text-canina-blue">
|
||||||
<ShoppingBag className="w-6 h-6" />
|
<ShoppingBag className="w-6 h-6" />
|
||||||
</div>
|
</div>
|
||||||
<h3 className="text-xl font-black text-medical-gray-900 italic">سبد خرید</h3>
|
<h3 className="text-xl font-black text-medical-gray-900 italic">سبد خرید</h3>
|
||||||
@ -92,7 +92,7 @@ export default function CartDrawer({ isOpen, onClose, onCheckout, onShopNavigate
|
|||||||
onClose();
|
onClose();
|
||||||
onShopNavigate?.();
|
onShopNavigate?.();
|
||||||
}}
|
}}
|
||||||
className="text-canino-blue font-black text-sm border-b-2 border-canino-blue pb-1 font-vazir"
|
className="text-canina-blue font-black text-sm border-b-2 border-canina-blue pb-1 font-vazir"
|
||||||
>
|
>
|
||||||
مشاهده محصولات تخصصی
|
مشاهده محصولات تخصصی
|
||||||
</button>
|
</button>
|
||||||
@ -103,16 +103,16 @@ export default function CartDrawer({ isOpen, onClose, onCheckout, onShopNavigate
|
|||||||
{items.map((item) => (
|
{items.map((item) => (
|
||||||
<div key={item.product.id} className="flex gap-4 p-4 bg-medical-gray-50 rounded-3xl border border-medical-gray-100 group">
|
<div key={item.product.id} className="flex gap-4 p-4 bg-medical-gray-50 rounded-3xl border border-medical-gray-100 group">
|
||||||
<div className="w-20 h-20 bg-white rounded-2xl p-2 flex-shrink-0 flex items-center justify-center shadow-sm">
|
<div className="w-20 h-20 bg-white rounded-2xl p-2 flex-shrink-0 flex items-center justify-center shadow-sm">
|
||||||
<SafeImage src={item.product.image} alt={item.product.name} className="w-full h-full object-contain" />
|
<SafeImage src={item.product.image} alt={item.product.name} className="w-full h-full" imgClassName="object-contain" />
|
||||||
</div>
|
</div>
|
||||||
<div className="flex-1 min-w-0">
|
<div className="flex-1 min-w-0">
|
||||||
<h4 className="text-sm font-black text-medical-gray-900 truncate mb-1">{item.product.name}</h4>
|
<h4 className="text-sm font-black text-medical-gray-900 truncate mb-1">{item.product.name}</h4>
|
||||||
<p className="text-[10px] text-canino-blue font-bold mb-3">{item.product.category}</p>
|
<p className="text-[10px] text-canina-blue font-bold mb-3">{item.product.category}</p>
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<div className="flex items-center gap-2 bg-white rounded-lg border border-medical-gray-200 p-1">
|
<div className="flex items-center gap-2 bg-white rounded-lg border border-medical-gray-200 p-1">
|
||||||
<button
|
<button
|
||||||
onClick={() => updateQuantity(item.product.id, item.quantity - 1)}
|
onClick={() => updateQuantity(item.product.id, item.quantity - 1)}
|
||||||
className="p-1 hover:text-canino-blue transition-colors"
|
className="p-1 hover:text-canina-blue transition-colors"
|
||||||
data-testid="minus-btn"
|
data-testid="minus-btn"
|
||||||
>
|
>
|
||||||
<Minus className="w-3 h-3" />
|
<Minus className="w-3 h-3" />
|
||||||
@ -120,7 +120,7 @@ export default function CartDrawer({ isOpen, onClose, onCheckout, onShopNavigate
|
|||||||
<span className="text-xs font-black min-w-[20px] text-center font-vazir">{toPersian(item.quantity)}</span>
|
<span className="text-xs font-black min-w-[20px] text-center font-vazir">{toPersian(item.quantity)}</span>
|
||||||
<button
|
<button
|
||||||
onClick={() => updateQuantity(item.product.id, item.quantity + 1)}
|
onClick={() => updateQuantity(item.product.id, item.quantity + 1)}
|
||||||
className="p-1 hover:text-canino-blue transition-colors"
|
className="p-1 hover:text-canina-blue transition-colors"
|
||||||
data-testid="plus-btn"
|
data-testid="plus-btn"
|
||||||
>
|
>
|
||||||
<Plus className="w-3 h-3" />
|
<Plus className="w-3 h-3" />
|
||||||
@ -184,15 +184,15 @@ export default function CartDrawer({ isOpen, onClose, onCheckout, onShopNavigate
|
|||||||
<motion.div
|
<motion.div
|
||||||
initial={{ opacity: 0, y: 20 }}
|
initial={{ opacity: 0, y: 20 }}
|
||||||
animate={{ opacity: 1, y: 0 }}
|
animate={{ opacity: 1, y: 0 }}
|
||||||
className="p-5 bg-gradient-to-br from-canino-blue/5 to-transparent border border-canino-blue/10 rounded-3xl"
|
className="p-5 bg-gradient-to-br from-canina-blue/5 to-transparent border border-canina-blue/10 rounded-3xl"
|
||||||
>
|
>
|
||||||
<div className="flex items-center gap-2 mb-4">
|
<div className="flex items-center gap-2 mb-4">
|
||||||
<Sparkles className="w-4 h-4 text-canino-blue animate-pulse" />
|
<Sparkles className="w-4 h-4 text-canina-blue animate-pulse" />
|
||||||
<span className="text-xs font-black text-medical-gray-900">پیشنهاد هوشمند برای جذب بهتر</span>
|
<span className="text-xs font-black text-medical-gray-900">پیشنهاد هوشمند برای جذب بهتر</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center gap-4">
|
<div className="flex items-center gap-4">
|
||||||
<div className="w-16 h-16 bg-white rounded-2xl p-2 shrink-0 shadow-sm border border-canino-blue/5">
|
<div className="w-16 h-16 bg-white rounded-2xl p-2 shrink-0 shadow-sm border border-canina-blue/5">
|
||||||
<SafeImage src={suggestedProduct.image} alt="" className="w-full h-full object-contain" />
|
<SafeImage src={suggestedProduct.image} alt="" className="w-full h-full" imgClassName="object-contain" />
|
||||||
</div>
|
</div>
|
||||||
<div className="flex-1">
|
<div className="flex-1">
|
||||||
<h5 className="text-[10px] font-black text-medical-gray-900 mb-1">{suggestedProduct.name}</h5>
|
<h5 className="text-[10px] font-black text-medical-gray-900 mb-1">{suggestedProduct.name}</h5>
|
||||||
@ -200,7 +200,7 @@ export default function CartDrawer({ isOpen, onClose, onCheckout, onShopNavigate
|
|||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
onClick={() => addItem(suggestedProduct, 1)}
|
onClick={() => addItem(suggestedProduct, 1)}
|
||||||
className="bg-canino-blue text-white w-8 h-8 rounded-full flex items-center justify-center hover:scale-110 transition-transform shadow-lg shadow-canino-blue/20"
|
className="bg-canina-blue text-white w-8 h-8 rounded-full flex items-center justify-center hover:scale-110 transition-transform shadow-lg shadow-canina-blue/20"
|
||||||
>
|
>
|
||||||
<Plus className="w-4 h-4" />
|
<Plus className="w-4 h-4" />
|
||||||
</button>
|
</button>
|
||||||
@ -226,11 +226,11 @@ export default function CartDrawer({ isOpen, onClose, onCheckout, onShopNavigate
|
|||||||
placeholder="CANINO2024"
|
placeholder="CANINO2024"
|
||||||
value={couponCode}
|
value={couponCode}
|
||||||
onChange={(e) => setCouponCode(e.target.value)}
|
onChange={(e) => setCouponCode(e.target.value)}
|
||||||
className={`w-full bg-white border ${couponStatus === 'error' ? 'border-red-300' : 'border-medical-gray-200'} rounded-2xl py-3 px-4 pr-10 text-sm font-bold focus:outline-none focus:ring-2 focus:ring-canino-blue/20 transition-all`}
|
className={`w-full bg-white border ${couponStatus === 'error' ? 'border-red-300' : 'border-medical-gray-200'} rounded-2xl py-3 px-4 pr-10 text-sm font-bold focus:outline-none focus:ring-2 focus:ring-canina-blue/20 transition-all`}
|
||||||
/>
|
/>
|
||||||
<button
|
<button
|
||||||
onClick={handleApplyCoupon}
|
onClick={handleApplyCoupon}
|
||||||
className={`absolute left-2 top-1/2 -translate-y-1/2 px-4 py-1.5 rounded-xl text-[10px] font-black transition-all ${couponStatus === 'success' ? 'bg-green-600 text-white' : 'bg-medical-gray-900 text-white hover:bg-canino-blue'}`}
|
className={`absolute left-2 top-1/2 -translate-y-1/2 px-4 py-1.5 rounded-xl text-[10px] font-black transition-all ${couponStatus === 'success' ? 'bg-green-600 text-white' : 'bg-medical-gray-900 text-white hover:bg-canina-blue'}`}
|
||||||
>
|
>
|
||||||
{couponStatus === 'success' ? <CheckCircle2 className="w-3 h-3" /> : 'اعمال'}
|
{couponStatus === 'success' ? <CheckCircle2 className="w-3 h-3" /> : 'اعمال'}
|
||||||
</button>
|
</button>
|
||||||
@ -257,17 +257,17 @@ export default function CartDrawer({ isOpen, onClose, onCheckout, onShopNavigate
|
|||||||
{/* Subscription Toggle */}
|
{/* Subscription Toggle */}
|
||||||
<div
|
<div
|
||||||
onClick={toggleSubscription}
|
onClick={toggleSubscription}
|
||||||
className={`p-4 rounded-2xl border-2 transition-all cursor-pointer ${isSubscribed ? 'bg-canino-blue/5 border-canino-blue' : 'bg-white border-medical-gray-100 hover:border-canino-blue/30'}`}
|
className={`p-4 rounded-2xl border-2 transition-all cursor-pointer ${isSubscribed ? 'bg-canina-blue/5 border-canina-blue' : 'bg-white border-medical-gray-100 hover:border-canina-blue/30'}`}
|
||||||
>
|
>
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
<div className={`w-10 h-10 rounded-xl flex items-center justify-center transition-colors ${isSubscribed ? 'bg-canino-blue text-white' : 'bg-medical-gray-50 text-medical-gray-300'}`}>
|
<div className={`w-10 h-10 rounded-xl flex items-center justify-center transition-colors ${isSubscribed ? 'bg-canina-blue text-white' : 'bg-medical-gray-50 text-medical-gray-300'}`}>
|
||||||
<ShieldCheck className="w-6 h-6" />
|
<ShieldCheck className="w-6 h-6" />
|
||||||
</div>
|
</div>
|
||||||
<div className="flex-1">
|
<div className="flex-1">
|
||||||
<h5 className="text-xs font-black text-medical-gray-900">فعالسازی سرویس تمدید خودکار (Refill)</h5>
|
<h5 className="text-xs font-black text-medical-gray-900">فعالسازی سرویس تمدید خودکار (Refill)</h5>
|
||||||
<p className="text-[10px] text-medical-gray-500 font-medium">۵٪ تخفیف روی تمام فاکتور + ارسال اولویتدار</p>
|
<p className="text-[10px] text-medical-gray-500 font-medium">۵٪ تخفیف روی تمام فاکتور + ارسال اولویتدار</p>
|
||||||
</div>
|
</div>
|
||||||
<div className={`w-5 h-5 rounded-full border-2 flex items-center justify-center ${isSubscribed ? 'bg-canino-blue border-canino-blue' : 'border-medical-gray-200'}`}>
|
<div className={`w-5 h-5 rounded-full border-2 flex items-center justify-center ${isSubscribed ? 'bg-canina-blue border-canina-blue' : 'border-medical-gray-200'}`}>
|
||||||
{isSubscribed && <X className="w-3 h-3 text-white" />}
|
{isSubscribed && <X className="w-3 h-3 text-white" />}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -287,7 +287,7 @@ export default function CartDrawer({ isOpen, onClose, onCheckout, onShopNavigate
|
|||||||
<div className="flex items-center justify-between border-t border-medical-gray-200 pt-4 px-2">
|
<div className="flex items-center justify-between border-t border-medical-gray-200 pt-4 px-2">
|
||||||
<span className="text-lg font-black text-medical-gray-900 italic">مجموع قابل پرداخت</span>
|
<span className="text-lg font-black text-medical-gray-900 italic">مجموع قابل پرداخت</span>
|
||||||
<div className="text-left">
|
<div className="text-left">
|
||||||
<p className="text-2xl font-black text-canino-blue tracking-tighter leading-none font-vazir">{toPersian(getTotal().toLocaleString())}</p>
|
<p className="text-2xl font-black text-canina-blue tracking-tighter leading-none font-vazir">{toPersian(getTotal().toLocaleString())}</p>
|
||||||
<p className="text-[10px] text-medical-gray-400 font-bold">تومان</p>
|
<p className="text-[10px] text-medical-gray-400 font-bold">تومان</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -295,7 +295,7 @@ export default function CartDrawer({ isOpen, onClose, onCheckout, onShopNavigate
|
|||||||
|
|
||||||
<button
|
<button
|
||||||
onClick={onCheckout}
|
onClick={onCheckout}
|
||||||
className="w-full bg-canino-blue text-white py-5 rounded-[2.5rem] font-black text-lg hover:shadow-2xl hover:shadow-canino-blue/20 transition-all flex items-center justify-center gap-3 group"
|
className="w-full bg-canina-blue text-white py-5 rounded-[2.5rem] font-black text-lg hover:shadow-2xl hover:shadow-canina-blue/20 transition-all flex items-center justify-center gap-3 group"
|
||||||
>
|
>
|
||||||
ثبت نهایی و تسویه حساب
|
ثبت نهایی و تسویه حساب
|
||||||
<ArrowLeft className="w-5 h-5 group-hover:translate-x-[-4px] transition-transform" />
|
<ArrowLeft className="w-5 h-5 group-hover:translate-x-[-4px] transition-transform" />
|
||||||
|
|||||||
@ -113,7 +113,7 @@ export default function CheckoutPage() {
|
|||||||
<ShieldCheck className="w-12 h-12" />
|
<ShieldCheck className="w-12 h-12" />
|
||||||
</div>
|
</div>
|
||||||
<h2 className="text-2xl font-black text-medical-gray-900 italic">سبد خرید شما خالی است</h2>
|
<h2 className="text-2xl font-black text-medical-gray-900 italic">سبد خرید شما خالی است</h2>
|
||||||
<button onClick={() => router.push('/shop')} className="text-canino-blue font-black underline underline-offset-8">بازگشت به فروشگاه</button>
|
<button onClick={() => router.push('/shop')} className="text-canina-blue font-black underline underline-offset-8">بازگشت به فروشگاه</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@ -127,24 +127,24 @@ export default function CheckoutPage() {
|
|||||||
<div className="lg:hidden mb-10 space-y-4">
|
<div className="lg:hidden mb-10 space-y-4">
|
||||||
<button
|
<button
|
||||||
onClick={() => router.back()}
|
onClick={() => router.back()}
|
||||||
className="flex items-center gap-2 text-medical-gray-500 font-bold hover:text-canino-blue transition-colors"
|
className="flex items-center gap-2 text-medical-gray-500 font-bold hover:text-canina-blue transition-colors"
|
||||||
>
|
>
|
||||||
<ChevronRight className="w-5 h-5" />
|
<ChevronRight className="w-5 h-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">
|
<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-canino-blue" onClick={() => router.push('/shop')}>سبد خرید</span>
|
<span className="cursor-pointer hover:text-canina-blue" onClick={() => router.push('/shop')}>سبد خرید</span>
|
||||||
<ChevronLeft className="w-2.5 h-2.5" />
|
<ChevronLeft className="w-2.5 h-2.5" />
|
||||||
<span className="text-canino-blue">نهاییسازی سفارش</span>
|
<span className="text-canina-blue">نهاییسازی سفارش</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Desktop Breadcrumbs (Hidden on Mobile) */}
|
{/* Desktop Breadcrumbs (Hidden on Mobile) */}
|
||||||
<div className="hidden lg: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-canino-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-canino-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-12">
|
||||||
@ -152,7 +152,7 @@ export default function CheckoutPage() {
|
|||||||
<div className="lg:col-span-8 space-y-8">
|
<div className="lg:col-span-8 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-[3rem] border border-medical-gray-200 p-10 overflow-hidden relative">
|
||||||
<div className="absolute top-0 right-0 w-3 h-full bg-canino-blue opacity-20" />
|
<div className="absolute top-0 right-0 w-3 h-full bg-canina-blue opacity-20" />
|
||||||
<div className="flex items-center gap-4 mb-10">
|
<div className="flex items-center gap-4 mb-10">
|
||||||
<div className="w-12 h-12 bg-medical-gray-900 text-white rounded-2xl flex items-center justify-center font-black">۱</div>
|
<div className="w-12 h-12 bg-medical-gray-900 text-white rounded-2xl flex items-center justify-center font-black">۱</div>
|
||||||
<h2 className="text-2xl font-black text-medical-gray-900 italic">اطلاعات ارسال</h2>
|
<h2 className="text-2xl font-black text-medical-gray-900 italic">اطلاعات ارسال</h2>
|
||||||
@ -161,15 +161,15 @@ export default function CheckoutPage() {
|
|||||||
<div className="grid md:grid-cols-2 gap-6">
|
<div className="grid md:grid-cols-2 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-canino-blue/20" placeholder="مثلاً: پارسا آقایی" />
|
<input type="text" className="w-full bg-medical-gray-50 border border-medical-gray-200 rounded-2xl py-4 px-6 text-sm focus:outline-none focus:ring-2 focus:ring-canina-blue/20" placeholder="مثلاً: پارسا آقایی" />
|
||||||
</div>
|
</div>
|
||||||
<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-canino-blue/20" placeholder="۰۹۱۲XXXXXXX" />
|
<input type="text" className="w-full bg-medical-gray-50 border border-medical-gray-200 rounded-2xl py-4 px-6 text-sm focus:outline-none focus:ring-2 focus:ring-canina-blue/20" placeholder="۰۹۱۲XXXXXXX" />
|
||||||
</div>
|
</div>
|
||||||
<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-canino-blue/20 h-32" placeholder="استان، شهر، خیابان..." />
|
<textarea className="w-full bg-medical-gray-50 border border-medical-gray-200 rounded-2xl py-4 px-6 text-sm focus:outline-none focus:ring-2 focus:ring-canina-blue/20 h-32" placeholder="استان، شهر، خیابان..." />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
@ -199,9 +199,9 @@ export default function CheckoutPage() {
|
|||||||
console.error("Payment init failed");
|
console.error("Payment init failed");
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
className={cn("p-6 rounded-3xl border-2 cursor-pointer transition-all group", paymentMethod === pay.id ? "border-canino-blue bg-canino-blue/5" : "border-medical-gray-100 hover:border-canino-blue")}
|
className={cn("p-6 rounded-3xl border-2 cursor-pointer transition-all group", paymentMethod === pay.id ? "border-canina-blue bg-canina-blue/5" : "border-medical-gray-100 hover:border-canina-blue")}
|
||||||
>
|
>
|
||||||
<div className="w-12 h-12 bg-medical-gray-50 rounded-2xl flex items-center justify-center text-medical-gray-400 group-hover:text-canino-blue group-hover:bg-canino-blue/10 mb-4 transition-all">
|
<div className="w-12 h-12 bg-medical-gray-50 rounded-2xl flex items-center justify-center text-medical-gray-400 group-hover:text-canina-blue group-hover:bg-canina-blue/10 mb-4 transition-all">
|
||||||
{pay.icon}
|
{pay.icon}
|
||||||
</div>
|
</div>
|
||||||
<h4 className="font-black text-sm text-medical-gray-900 mb-1">{pay.label}</h4>
|
<h4 className="font-black text-sm text-medical-gray-900 mb-1">{pay.label}</h4>
|
||||||
@ -230,7 +230,7 @@ export default function CheckoutPage() {
|
|||||||
<div className="flex flex-wrap items-center justify-between gap-6">
|
<div className="flex flex-wrap items-center justify-between gap-6">
|
||||||
<div className="flex-1 min-w-[280px]">
|
<div className="flex-1 min-w-[280px]">
|
||||||
<h4 className="text-lg font-black text-medical-gray-900 italic mb-2">رند کردن مبلغ و کمک به پناهگاه</h4>
|
<h4 className="text-lg font-black text-medical-gray-900 italic mb-2">رند کردن مبلغ و کمک به پناهگاه</h4>
|
||||||
<p className="text-sm text-medical-gray-600 leading-relaxed font-medium"> با انتخاب این گزینه، مابقی مبلغ تا ده هزار تومان بعدی یا ۱٪ از خرید شما (هر کدام بیشتر باشد) صرف تامین غذا و دارو برای حیوانات بی-سرپرست تحت حمایت کانینو میشود.</p>
|
<p className="text-sm text-medical-gray-600 leading-relaxed font-medium"> با انتخاب این گزینه، مابقی مبلغ تا ده هزار تومان بعدی یا ۱٪ از خرید شما (هر کدام بیشتر باشد) صرف تامین غذا و دارو برای حیوانات بی-سرپرست تحت حمایت کانینا میشود.</p>
|
||||||
<div className="mt-4 flex items-center gap-3 text-pink-600">
|
<div className="mt-4 flex items-center gap-3 text-pink-600">
|
||||||
<ShieldCheck className="w-4 h-4" />
|
<ShieldCheck className="w-4 h-4" />
|
||||||
<span className="text-[10px] font-black uppercase tracking-widest">گزارش شفاف هزینهکرد در داشبورد شما</span>
|
<span className="text-[10px] font-black uppercase tracking-widest">گزارش شفاف هزینهکرد در داشبورد شما</span>
|
||||||
@ -305,7 +305,7 @@ export default function CheckoutPage() {
|
|||||||
<div className="flex justify-between items-end pt-4">
|
<div className="flex justify-between items-end pt-4">
|
||||||
<span className="text-xl font-black italic">مبلغ نهایی</span>
|
<span className="text-xl font-black italic">مبلغ نهایی</span>
|
||||||
<div className="text-left">
|
<div className="text-left">
|
||||||
<p className="text-3xl font-black text-canino-blue leading-none font-vazir">{toPersian(getTotal().toLocaleString())}</p>
|
<p className="text-3xl font-black text-canina-blue leading-none font-vazir">{toPersian(getTotal().toLocaleString())}</p>
|
||||||
<p className="text-[10px] text-white/30 font-bold mt-1">تومان</p>
|
<p className="text-[10px] text-white/30 font-bold mt-1">تومان</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -330,7 +330,7 @@ export default function CheckoutPage() {
|
|||||||
name="coupon"
|
name="coupon"
|
||||||
type="text"
|
type="text"
|
||||||
placeholder="کد تخفیف (مثلاً: CANINO2024)"
|
placeholder="کد تخفیف (مثلاً: CANINO2024)"
|
||||||
className="flex-1 bg-white/5 border border-white/10 rounded-xl px-4 py-3 text-xs focus:ring-1 focus:ring-canino-blue outline-none"
|
className="flex-1 bg-white/5 border border-white/10 rounded-xl px-4 py-3 text-xs focus:ring-1 focus:ring-canina-blue outline-none"
|
||||||
/>
|
/>
|
||||||
<button type="submit" className="bg-white/10 px-4 py-3 rounded-xl text-[10px] font-black uppercase tracking-widest hover:bg-white/20 transition-all">اعمال</button>
|
<button type="submit" className="bg-white/10 px-4 py-3 rounded-xl text-[10px] font-black uppercase tracking-widest hover:bg-white/20 transition-all">اعمال</button>
|
||||||
</form>
|
</form>
|
||||||
@ -339,7 +339,7 @@ export default function CheckoutPage() {
|
|||||||
{/* Refill Estimates */}
|
{/* Refill Estimates */}
|
||||||
<div className="mt-10 p-6 bg-white/5 rounded-3xl border border-white/10 space-y-4">
|
<div className="mt-10 p-6 bg-white/5 rounded-3xl border border-white/10 space-y-4">
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
<Clock className="w-5 h-5 text-canino-blue" />
|
<Clock className="w-5 h-5 text-canina-blue" />
|
||||||
<h4 className="text-xs font-black uppercase tracking-widest font-vazir">تخمین اتمام مصرف (هوش مصنوعی)</h4>
|
<h4 className="text-xs font-black uppercase tracking-widest font-vazir">تخمین اتمام مصرف (هوش مصنوعی)</h4>
|
||||||
</div>
|
</div>
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
@ -353,7 +353,7 @@ export default function CheckoutPage() {
|
|||||||
return (
|
return (
|
||||||
<div key={item.product.id} className="flex items-center justify-between text-[10px] font-medium font-vazir">
|
<div key={item.product.id} className="flex items-center justify-between text-[10px] font-medium font-vazir">
|
||||||
<span className="text-white/40">{item.product.name}</span>
|
<span className="text-white/40">{item.product.name}</span>
|
||||||
<span className="text-canino-blue">~ {toPersian(days)} روز دیگر</span>
|
<span className="text-canina-blue">~ {toPersian(days)} روز دیگر</span>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
@ -363,7 +363,7 @@ export default function CheckoutPage() {
|
|||||||
<button
|
<button
|
||||||
onClick={handleFinalize}
|
onClick={handleFinalize}
|
||||||
disabled={loading}
|
disabled={loading}
|
||||||
className="w-full bg-canino-blue text-white py-6 rounded-2xl font-black text-xl mt-10 hover:scale-[1.02] transition-all shadow-xl shadow-canino-blue/20 flex items-center justify-center gap-3 disabled:opacity-50 disabled:cursor-not-allowed"
|
className="w-full bg-canina-blue text-white py-6 rounded-2xl font-black text-xl mt-10 hover:scale-[1.02] transition-all shadow-xl shadow-canina-blue/20 flex items-center justify-center gap-3 disabled:opacity-50 disabled:cursor-not-allowed"
|
||||||
>
|
>
|
||||||
{loading ? (
|
{loading ? (
|
||||||
<>
|
<>
|
||||||
|
|||||||
@ -52,14 +52,14 @@ export class ErrorBoundary extends React.Component<Props, State> {
|
|||||||
|
|
||||||
<button
|
<button
|
||||||
onClick={this.handleRetry}
|
onClick={this.handleRetry}
|
||||||
className="w-full bg-canino-blue text-white py-5 rounded-2xl font-black flex items-center justify-center gap-3 hover:scale-105 transition-all shadow-xl shadow-canino-blue/20"
|
className="w-full bg-canina-blue text-white py-5 rounded-2xl font-black flex items-center justify-center gap-3 hover:scale-105 transition-all shadow-xl shadow-canina-blue/20"
|
||||||
>
|
>
|
||||||
<RefreshCcw className="w-5 h-5" />
|
<RefreshCcw className="w-5 h-5" />
|
||||||
تلاش مجدد
|
تلاش مجدد
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<div className="mt-8 pt-8 border-t border-medical-gray-50 flex items-center justify-center gap-2">
|
<div className="mt-8 pt-8 border-t border-medical-gray-50 flex items-center justify-center gap-2">
|
||||||
<div className="w-8 h-8 bg-canino-blue rounded-xl flex items-center justify-center text-white font-bold text-xs italic">C</div>
|
<div className="w-8 h-8 bg-canina-blue rounded-xl flex items-center justify-center text-white font-bold text-xs italic">C</div>
|
||||||
<span className="text-[10px] font-black text-medical-gray-300 uppercase tracking-widest">Canina Pharma Support</span>
|
<span className="text-[10px] font-black text-medical-gray-300 uppercase tracking-widest">Canina Pharma Support</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -13,7 +13,7 @@ export const NotFoundPage = () => {
|
|||||||
<div className="text-[15rem] font-black text-medical-gray-100 leading-none select-none">۴۰۴</div>
|
<div className="text-[15rem] font-black text-medical-gray-100 leading-none select-none">۴۰۴</div>
|
||||||
<div className="absolute inset-0 flex items-center justify-center">
|
<div className="absolute inset-0 flex items-center justify-center">
|
||||||
<div className="w-32 h-32 bg-white rounded-[3rem] shadow-2xl flex items-center justify-center">
|
<div className="w-32 h-32 bg-white rounded-[3rem] shadow-2xl flex items-center justify-center">
|
||||||
<FileQuestion className="w-16 h-16 text-canino-blue" />
|
<FileQuestion className="w-16 h-16 text-canina-blue" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -25,7 +25,7 @@ export const NotFoundPage = () => {
|
|||||||
|
|
||||||
<button
|
<button
|
||||||
onClick={() => router.push('/')}
|
onClick={() => router.push('/')}
|
||||||
className="bg-medical-gray-900 text-white px-10 py-5 rounded-2xl font-black flex items-center justify-center gap-3 mx-auto hover:bg-canino-blue transition-all shadow-2xl shadow-medical-gray-900/10"
|
className="bg-medical-gray-900 text-white px-10 py-5 rounded-2xl font-black flex items-center justify-center gap-3 mx-auto hover:bg-canina-blue transition-all shadow-2xl shadow-medical-gray-900/10"
|
||||||
>
|
>
|
||||||
<Home className="w-5 h-5" />
|
<Home className="w-5 h-5" />
|
||||||
بازگشت به خانه
|
بازگشت به خانه
|
||||||
@ -45,13 +45,13 @@ export const ServerErrorPage = ({ onRetry }: { onRetry: () => void }) => {
|
|||||||
|
|
||||||
<h1 className="text-4xl font-black text-medical-gray-900 mb-4">خطای داخلی سیستم</h1>
|
<h1 className="text-4xl font-black text-medical-gray-900 mb-4">خطای داخلی سیستم</h1>
|
||||||
<p className="text-medical-gray-500 mb-12 font-bold text-lg">
|
<p className="text-medical-gray-500 mb-12 font-bold text-lg">
|
||||||
ارتباط با دیتابیس کانینو با مشکل مواجه شده است. در حال بررسی موضوع هستیم.
|
ارتباط با دیتابیس کانینا با مشکل مواجه شده است. در حال بررسی موضوع هستیم.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div className="flex flex-col sm:flex-row gap-4 justify-center">
|
<div className="flex flex-col sm:flex-row gap-4 justify-center">
|
||||||
<button
|
<button
|
||||||
onClick={onRetry}
|
onClick={onRetry}
|
||||||
className="bg-canino-blue text-white px-10 py-5 rounded-2xl font-black flex items-center justify-center gap-3 hover:scale-105 transition-all shadow-xl shadow-canino-blue/20"
|
className="bg-canina-blue text-white px-10 py-5 rounded-2xl font-black flex items-center justify-center gap-3 hover:scale-105 transition-all shadow-xl shadow-canina-blue/20"
|
||||||
>
|
>
|
||||||
<RefreshCw className="w-5 h-5" />
|
<RefreshCw className="w-5 h-5" />
|
||||||
تلاش مجدد
|
تلاش مجدد
|
||||||
|
|||||||
@ -29,7 +29,7 @@ function ProductCard({ product, onClick }: { product: Product; key?: string | nu
|
|||||||
viewport={{ once: true }}
|
viewport={{ once: true }}
|
||||||
transition={{ duration: 0.5 }}
|
transition={{ duration: 0.5 }}
|
||||||
onClick={() => onClick(product)}
|
onClick={() => onClick(product)}
|
||||||
className="group bg-white rounded-3xl border border-medical-gray-200 overflow-hidden hover:shadow-2xl hover:shadow-canino-blue/10 transition-all duration-500 flex flex-col h-full cursor-pointer relative"
|
className="group bg-white rounded-3xl border border-medical-gray-200 overflow-hidden hover:shadow-2xl hover:shadow-canina-blue/10 transition-all duration-500 flex flex-col h-full cursor-pointer relative"
|
||||||
>
|
>
|
||||||
{compatibility && (
|
{compatibility && (
|
||||||
<div className={`absolute top-16 right-4 z-10 text-[8px] font-black uppercase tracking-widest px-3 py-1 rounded-full shadow-md flex items-center gap-1 ${
|
<div className={`absolute top-16 right-4 z-10 text-[8px] font-black uppercase tracking-widest px-3 py-1 rounded-full shadow-md flex items-center gap-1 ${
|
||||||
@ -45,7 +45,8 @@ function ProductCard({ product, onClick }: { product: Product; key?: string | nu
|
|||||||
<SafeImage
|
<SafeImage
|
||||||
src={product.image}
|
src={product.image}
|
||||||
alt={product.name}
|
alt={product.name}
|
||||||
className="w-full h-full object-contain group-hover:scale-105 transition-transform duration-500 drop-shadow-2xl"
|
className="w-full h-full group-hover:scale-105 transition-transform duration-500 drop-shadow-2xl"
|
||||||
|
imgClassName="object-contain"
|
||||||
/>
|
/>
|
||||||
<div className="absolute top-4 right-4 px-3 py-1 bg-white/80 backdrop-blur-md rounded-full border border-medical-gray-200 text-[10px] font-bold text-medical-gray-500 uppercase tracking-widest">
|
<div className="absolute top-4 right-4 px-3 py-1 bg-white/80 backdrop-blur-md rounded-full border border-medical-gray-200 text-[10px] font-bold text-medical-gray-500 uppercase tracking-widest">
|
||||||
{product.category}
|
{product.category}
|
||||||
@ -53,11 +54,11 @@ function ProductCard({ product, onClick }: { product: Product; key?: string | nu
|
|||||||
|
|
||||||
{/* Hover Actions */}
|
{/* Hover Actions */}
|
||||||
<Link href={`/shop/${product.slug || product.id}`} className="absolute inset-0 z-10" />
|
<Link href={`/shop/${product.slug || product.id}`} className="absolute inset-0 z-10" />
|
||||||
<div className="absolute inset-0 bg-canino-blue/60 opacity-0 group-hover:opacity-100 backdrop-blur-sm transition-all duration-300 flex items-center justify-center gap-4">
|
<div className="absolute inset-0 bg-canina-blue/60 opacity-0 group-hover:opacity-100 backdrop-blur-sm transition-all duration-300 flex items-center justify-center gap-4">
|
||||||
<div className="w-12 h-12 rounded-full bg-white text-canino-blue flex items-center justify-center hover:scale-110 transition-transform shadow-lg">
|
<div className="w-12 h-12 rounded-full bg-white text-canina-blue flex items-center justify-center hover:scale-110 transition-transform shadow-lg">
|
||||||
<Eye className="w-5 h-5" />
|
<Eye className="w-5 h-5" />
|
||||||
</div>
|
</div>
|
||||||
<div className="w-12 h-12 rounded-full bg-canino-blue text-white flex items-center justify-center hover:scale-110 transition-transform shadow-lg border border-white/20">
|
<div className="w-12 h-12 rounded-full bg-canina-blue text-white flex items-center justify-center hover:scale-110 transition-transform shadow-lg border border-white/20">
|
||||||
<ShoppingCart className="w-5 h-5" />
|
<ShoppingCart className="w-5 h-5" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -66,10 +67,10 @@ function ProductCard({ product, onClick }: { product: Product; key?: string | nu
|
|||||||
{/* Content Area */}
|
{/* Content Area */}
|
||||||
<div className="p-8 flex flex-col flex-1">
|
<div className="p-8 flex flex-col flex-1">
|
||||||
<div className="flex items-start justify-between mb-4 gap-2">
|
<div className="flex items-start justify-between mb-4 gap-2">
|
||||||
<h3 className="text-xl font-black text-medical-gray-900 group-hover:text-canino-blue transition-colors leading-tight">
|
<h3 className="text-xl font-black text-medical-gray-900 group-hover:text-canina-blue transition-colors leading-tight">
|
||||||
{product.name}
|
{product.name}
|
||||||
</h3>
|
</h3>
|
||||||
<ShieldCheck className="w-6 h-6 text-canino-blue flex-shrink-0" />
|
<ShieldCheck className="w-6 h-6 text-canina-blue flex-shrink-0" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p className="text-sm text-medical-gray-500 leading-relaxed mb-6 flex-1">
|
<p className="text-sm text-medical-gray-500 leading-relaxed mb-6 flex-1">
|
||||||
@ -78,13 +79,13 @@ function ProductCard({ product, onClick }: { product: Product; key?: string | nu
|
|||||||
|
|
||||||
<div className="space-y-4 pt-4 border-t border-medical-gray-100">
|
<div className="space-y-4 pt-4 border-t border-medical-gray-100">
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
<div className="w-1 h-1 rounded-full bg-canino-blue" />
|
<div className="w-1 h-1 rounded-full bg-canina-blue" />
|
||||||
<span className="text-xs font-semibold text-medical-gray-700 italic">{product.benefits}</span>
|
<span className="text-xs font-semibold text-medical-gray-700 italic">{product.benefits}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<div className="text-xl font-black text-medical-gray-900 font-vazir">{product.price}</div>
|
<div className="text-xl font-black text-medical-gray-900 font-vazir">{product.price}</div>
|
||||||
<button className="text-xs font-black text-canino-blue uppercase tracking-widest border-b-2 border-canino-blue pb-1 hover:text-medical-gray-900 hover:border-medical-gray-900 transition-all">
|
<button className="text-xs font-black text-canina-blue uppercase tracking-widest border-b-2 border-canina-blue pb-1 hover:text-medical-gray-900 hover:border-medical-gray-900 transition-all">
|
||||||
مشاهده جزییات
|
مشاهده جزییات
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@ -122,19 +123,19 @@ export default function FeaturedProducts() {
|
|||||||
<div className="max-w-7xl mx-auto px-4">
|
<div className="max-w-7xl mx-auto px-4">
|
||||||
<div className="flex flex-col lg:flex-row items-end justify-between mb-16 gap-6">
|
<div className="flex flex-col lg:flex-row items-end justify-between mb-16 gap-6">
|
||||||
<div className="lg:w-2/3">
|
<div className="lg:w-2/3">
|
||||||
<div className="text-canino-blue text-xs font-bold uppercase tracking-[0.2em] mb-4 font-vazir">بیشترین انتخاب توسط دامپزشکان</div>
|
<div className="text-canina-blue text-xs font-bold uppercase tracking-[0.2em] mb-4 font-vazir">بیشترین انتخاب توسط دامپزشکان</div>
|
||||||
<h2 className="text-3xl lg:text-5xl font-black text-medical-gray-900 leading-[1.2]">
|
<h2 className="text-3xl lg:text-5xl font-black text-medical-gray-900 leading-[1.2]">
|
||||||
محصولات برگزیده و راهکارهای <br />
|
محصولات برگزیده و راهکارهای <br />
|
||||||
<span className="italic text-canino-blue">درمان تخصصی</span>
|
<span className="italic text-canina-blue">درمان تخصصی</span>
|
||||||
</h2>
|
</h2>
|
||||||
</div>
|
</div>
|
||||||
<div className="lg:w-1/3 text-left lg:text-right">
|
<div className="lg:w-1/3 text-left lg:text-right">
|
||||||
<p className="text-medical-gray-500 text-sm leading-relaxed mb-4">
|
<p className="text-medical-gray-500 text-sm leading-relaxed mb-4">
|
||||||
محصولات دارویی کانینو با استفاده از دانش پیشرفته بیوتکنولوژی و مواد اولیه ارگانیک نایاب فرآوری شدهاند.
|
محصولات دارویی کانینا با استفاده از دانش پیشرفته بیوتکنولوژی و مواد اولیه ارگانیک نایاب فرآوری شدهاند.
|
||||||
</p>
|
</p>
|
||||||
<button
|
<button
|
||||||
onClick={() => router.push('/shop')}
|
onClick={() => router.push('/shop')}
|
||||||
className="inline-flex items-center gap-2 text-canino-blue font-bold text-sm hover:translate-x-1 transition-transform rtl:hover:-translate-x-1"
|
className="inline-flex items-center gap-2 text-canina-blue font-bold text-sm hover:translate-x-1 transition-transform rtl:hover:-translate-x-1"
|
||||||
>
|
>
|
||||||
مشاهده تمامی محصولات
|
مشاهده تمامی محصولات
|
||||||
<span className="text-lg">←</span>
|
<span className="text-lg">←</span>
|
||||||
@ -142,7 +143,7 @@ export default function FeaturedProducts() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-10">
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-10">
|
||||||
{isLoading ? (
|
{isLoading ? (
|
||||||
Array.from({ length: 3 }).map((_, i) => <ProductCardSkeleton key={i} />)
|
Array.from({ length: 3 }).map((_, i) => <ProductCardSkeleton key={i} />)
|
||||||
) : products.length > 0 ? (
|
) : products.length > 0 ? (
|
||||||
@ -151,7 +152,7 @@ export default function FeaturedProducts() {
|
|||||||
))
|
))
|
||||||
) : (
|
) : (
|
||||||
<div className="col-span-full py-16 px-8 flex flex-col items-center justify-center text-center bg-white rounded-[2.5rem] border border-medical-gray-200 shadow-xl max-w-lg mx-auto">
|
<div className="col-span-full py-16 px-8 flex flex-col items-center justify-center text-center bg-white rounded-[2.5rem] border border-medical-gray-200 shadow-xl max-w-lg mx-auto">
|
||||||
<AlertCircle className="w-12 h-12 text-canino-teal mb-4" />
|
<AlertCircle className="w-12 h-12 text-canina-teal mb-4" />
|
||||||
<h3 className="text-xl font-black text-medical-gray-900 mb-2 font-vazir">هیچ محصولی یافت نشد</h3>
|
<h3 className="text-xl font-black text-medical-gray-900 mb-2 font-vazir">هیچ محصولی یافت نشد</h3>
|
||||||
<p className="text-sm text-medical-gray-500 font-medium font-vazir leading-relaxed">
|
<p className="text-sm text-medical-gray-500 font-medium font-vazir leading-relaxed">
|
||||||
در حال حاضر هیچ محصول برجستهای برای نمایش وجود ندارد. لطفاً در پنل ادمین محصولات برگزیده را تنظیم کنید.
|
در حال حاضر هیچ محصول برجستهای برای نمایش وجود ندارد. لطفاً در پنل ادمین محصولات برگزیده را تنظیم کنید.
|
||||||
|
|||||||
@ -16,10 +16,10 @@ export default function Footer({ onNavigate, onShopNavigate, onB2BOpen }: {
|
|||||||
<div className="space-y-8">
|
<div className="space-y-8">
|
||||||
<div className="flex items-center gap-4 cursor-pointer group" onClick={() => onNavigate("home")}>
|
<div className="flex items-center gap-4 cursor-pointer group" onClick={() => onNavigate("home")}>
|
||||||
<div className="w-16 h-16 bg-white rounded-2xl flex items-center justify-center p-2 group-hover:scale-105 transition-transform">
|
<div className="w-16 h-16 bg-white rounded-2xl flex items-center justify-center p-2 group-hover:scale-105 transition-transform">
|
||||||
<img src="https://canina.de/media/fb/d5/47/1683116813/Logo.png" alt="Canino Logo" className="w-full h-auto" referrerPolicy="no-referrer" />
|
<img src="https://canina.de/media/fb/d5/47/1683116813/Logo.png" alt="Canina Logo" className="w-full h-auto" referrerPolicy="no-referrer" />
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<h3 className="text-2xl font-black italic tracking-tighter">کانینو ایران</h3>
|
<h3 className="text-2xl font-black italic tracking-tighter">کانینا ایران</h3>
|
||||||
<p className="text-[10px] text-white/40 font-bold uppercase tracking-widest">نماینده رسمی در ایران</p>
|
<p className="text-[10px] text-white/40 font-bold uppercase tracking-widest">نماینده رسمی در ایران</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -28,7 +28,7 @@ export default function Footer({ onNavigate, onShopNavigate, onB2BOpen }: {
|
|||||||
</p>
|
</p>
|
||||||
<div className="flex gap-4">
|
<div className="flex gap-4">
|
||||||
{[Instagram, Globe].map((Icon, i) => (
|
{[Instagram, Globe].map((Icon, i) => (
|
||||||
<a key={i} href="#" className="w-10 h-10 bg-white/5 rounded-xl flex items-center justify-center hover:bg-canino-blue hover:text-white transition-all text-white/40">
|
<a key={i} href="#" className="w-10 h-10 bg-white/5 rounded-xl flex items-center justify-center hover:bg-canina-blue hover:text-white transition-all text-white/40">
|
||||||
<Icon className="w-5 h-5" />
|
<Icon className="w-5 h-5" />
|
||||||
</a>
|
</a>
|
||||||
))}
|
))}
|
||||||
@ -37,26 +37,26 @@ export default function Footer({ onNavigate, onShopNavigate, onB2BOpen }: {
|
|||||||
|
|
||||||
{/* Quick Links */}
|
{/* Quick Links */}
|
||||||
<div className="space-y-8">
|
<div className="space-y-8">
|
||||||
<h4 className="text-lg font-black text-canino-blue italic underline decoration-white/20 underline-offset-8">دسترسی سریع</h4>
|
<h4 className="text-lg font-black text-canina-blue italic underline decoration-white/20 underline-offset-8">دسترسی سریع</h4>
|
||||||
<ul className="space-y-4 text-sm font-bold text-white/60">
|
<ul className="space-y-4 text-sm font-bold text-white/60">
|
||||||
<li onClick={() => onShopNavigate()} className="hover:text-white hover:translate-x-[-4px] transition-all cursor-pointer flex items-center gap-2 group">
|
<li onClick={() => onShopNavigate()} className="hover:text-white hover:translate-x-[-4px] transition-all cursor-pointer flex items-center gap-2 group">
|
||||||
<div className="w-1.5 h-1.5 rounded-full bg-canino-blue group-hover:w-4 transition-all" />
|
<div className="w-1.5 h-1.5 rounded-full bg-canina-blue group-hover:w-4 transition-all" />
|
||||||
محصولات تخصصی ۲۰۲۴
|
محصولات تخصصی ۲۰۲۴
|
||||||
</li>
|
</li>
|
||||||
<li onClick={() => onNavigate("blog")} className="hover:text-white hover:translate-x-[-4px] transition-all cursor-pointer flex items-center gap-2 group">
|
<li onClick={() => onNavigate("blog")} className="hover:text-white hover:translate-x-[-4px] transition-all cursor-pointer flex items-center gap-2 group">
|
||||||
<div className="w-1.5 h-1.5 rounded-full bg-canino-blue group-hover:w-4 transition-all" />
|
<div className="w-1.5 h-1.5 rounded-full bg-canina-blue group-hover:w-4 transition-all" />
|
||||||
مجله سلامت پت (وبلاگ)
|
مجله سلامت پت (وبلاگ)
|
||||||
</li>
|
</li>
|
||||||
<li onClick={() => onNavigate("profile")} className="hover:text-white hover:translate-x-[-4px] transition-all cursor-pointer flex items-center gap-2 group">
|
<li onClick={() => onNavigate("profile")} className="hover:text-white hover:translate-x-[-4px] transition-all cursor-pointer flex items-center gap-2 group">
|
||||||
<div className="w-1.5 h-1.5 rounded-full bg-canino-blue group-hover:w-4 transition-all" />
|
<div className="w-1.5 h-1.5 rounded-full bg-canina-blue group-hover:w-4 transition-all" />
|
||||||
شناسنامه پتها
|
شناسنامه پتها
|
||||||
</li>
|
</li>
|
||||||
<li onClick={() => onNavigate("wiki")} className="hover:text-white hover:translate-x-[-4px] transition-all cursor-pointer flex items-center gap-2 group">
|
<li onClick={() => onNavigate("wiki")} className="hover:text-white hover:translate-x-[-4px] transition-all cursor-pointer flex items-center gap-2 group">
|
||||||
<div className="w-1.5 h-1.5 rounded-full bg-canino-blue group-hover:w-4 transition-all" />
|
<div className="w-1.5 h-1.5 rounded-full bg-canina-blue group-hover:w-4 transition-all" />
|
||||||
دانشنامه ترکیبات
|
دانشنامه ترکیبات
|
||||||
</li>
|
</li>
|
||||||
<li onClick={onB2BOpen} className="hover:text-canino-blue hover:translate-x-[-4px] transition-all cursor-pointer flex items-center gap-2 group text-blue-300">
|
<li onClick={onB2BOpen} className="hover:text-canina-blue hover:translate-x-[-4px] transition-all cursor-pointer flex items-center gap-2 group text-blue-300">
|
||||||
<div className="w-1.5 h-1.5 rounded-full bg-canino-blue group-hover:w-4 transition-all" />
|
<div className="w-1.5 h-1.5 rounded-full bg-canina-blue group-hover:w-4 transition-all" />
|
||||||
پنل سفارش عمده (B2B)
|
پنل سفارش عمده (B2B)
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
@ -64,11 +64,11 @@ export default function Footer({ onNavigate, onShopNavigate, onB2BOpen }: {
|
|||||||
|
|
||||||
{/* Location & Contact */}
|
{/* Location & Contact */}
|
||||||
<div className="space-y-8 lg:col-span-2">
|
<div className="space-y-8 lg:col-span-2">
|
||||||
<h4 className="text-lg font-black text-canino-blue italic underline decoration-white/20 underline-offset-8">اطلاعات تماس نمایندگی</h4>
|
<h4 className="text-lg font-black text-canina-blue italic underline decoration-white/20 underline-offset-8">اطلاعات تماس نمایندگی</h4>
|
||||||
<div className="grid md:grid-cols-2 gap-8">
|
<div className="grid md:grid-cols-2 gap-8">
|
||||||
<div className="space-y-6">
|
<div className="space-y-6">
|
||||||
<div className="flex gap-4 group">
|
<div className="flex gap-4 group">
|
||||||
<div className="w-12 h-12 bg-white/5 rounded-2xl flex items-center justify-center text-canino-blue group-hover:scale-110 transition-transform flex-shrink-0">
|
<div className="w-12 h-12 bg-white/5 rounded-2xl flex items-center justify-center text-canina-blue group-hover:scale-110 transition-transform flex-shrink-0">
|
||||||
<Phone className="w-6 h-6" />
|
<Phone className="w-6 h-6" />
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
@ -77,7 +77,7 @@ export default function Footer({ onNavigate, onShopNavigate, onB2BOpen }: {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex gap-4 group">
|
<div className="flex gap-4 group">
|
||||||
<div className="w-12 h-12 bg-white/5 rounded-2xl flex items-center justify-center text-canino-blue group-hover:scale-110 transition-transform flex-shrink-0">
|
<div className="w-12 h-12 bg-white/5 rounded-2xl flex items-center justify-center text-canina-blue group-hover:scale-110 transition-transform flex-shrink-0">
|
||||||
<Mail className="w-6 h-6" />
|
<Mail className="w-6 h-6" />
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
@ -88,12 +88,12 @@ export default function Footer({ onNavigate, onShopNavigate, onB2BOpen }: {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex gap-4 group">
|
<div className="flex gap-4 group">
|
||||||
<div className="w-12 h-12 bg-white/5 rounded-2xl flex items-center justify-center text-canino-blue group-hover:scale-110 transition-transform flex-shrink-0">
|
<div className="w-12 h-12 bg-white/5 rounded-2xl flex items-center justify-center text-canina-blue group-hover:scale-110 transition-transform flex-shrink-0">
|
||||||
<MapPin className="w-6 h-6" />
|
<MapPin className="w-6 h-6" />
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<p className="text-[10px] text-white/40 font-black uppercase mb-1">دفتر مرکزی</p>
|
<p className="text-[10px] text-white/40 font-black uppercase mb-1">دفتر مرکزی</p>
|
||||||
<p className="text-sm font-bold leading-relaxed">تهران، جردن، خیابان سعیدی، ساختمان کانینو، طبقه ۵، واحد ۱۹</p>
|
<p className="text-sm font-bold leading-relaxed">تهران، جردن، خیابان سعیدی، ساختمان کانینا، طبقه ۵، واحد ۱۹</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -108,14 +108,14 @@ export default function Footer({ onNavigate, onShopNavigate, onB2BOpen }: {
|
|||||||
<p className="text-[10px] text-white/40 font-bold">تمامی محصولات دارای لیبل اصالت وزارت بهداشت و QR Code اختصاصی هستند.</p>
|
<p className="text-[10px] text-white/40 font-bold">تمامی محصولات دارای لیبل اصالت وزارت بهداشت و QR Code اختصاصی هستند.</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="text-xs font-black italic text-white/20">اصالت آلمانی کانینو</div>
|
<div className="text-xs font-black italic text-white/20">اصالت آلمانی کانینا</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="pt-12 border-t border-white/5 flex flex-col md:flex-row items-center justify-between gap-6 text-[10px] font-black text-white/20 uppercase tracking-[0.3em]">
|
<div className="pt-12 border-t border-white/5 flex flex-col md:flex-row items-center justify-between gap-6 text-[10px] font-black text-white/20 uppercase tracking-[0.3em]">
|
||||||
<div>© ۲۰۲۶ کانینو ایران. تمامی حقوق محفوظ است.</div>
|
<div>© ۲۰۲۶ کانینا ایران. تمامی حقوق محفوظ است.</div>
|
||||||
<div className="flex gap-8 font-vazir">
|
<div className="flex gap-8 font-vazir">
|
||||||
<button onClick={() => onNavigate("home")} className="hover:text-white transition-colors">درباره ما</button>
|
<button onClick={() => onNavigate("home")} className="hover:text-white transition-colors">درباره ما</button>
|
||||||
<button onClick={() => onNavigate("home")} className="hover:text-white transition-colors">تماس با ما</button>
|
<button onClick={() => onNavigate("home")} className="hover:text-white transition-colors">تماس با ما</button>
|
||||||
|
|||||||
@ -90,7 +90,7 @@ export default function Header({
|
|||||||
<>
|
<>
|
||||||
<AuthModal isOpen={isAuthModalOpen} onClose={() => setIsAuthModalOpen(false)} />
|
<AuthModal isOpen={isAuthModalOpen} onClose={() => setIsAuthModalOpen(false)} />
|
||||||
|
|
||||||
<div className="bg-canino-gold text-canino-dark text-xs font-black py-2.5 text-center font-vazir tracking-wider flex items-center justify-center gap-2">
|
<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">
|
||||||
<span>🚚</span>
|
<span>🚚</span>
|
||||||
<span>ارسال رایگان برای سفارشهای بالای ۱۵۰ هزار تومان</span>
|
<span>ارسال رایگان برای سفارشهای بالای ۱۵۰ هزار تومان</span>
|
||||||
</div>
|
</div>
|
||||||
@ -115,9 +115,9 @@ export default function Header({
|
|||||||
setIsMobileMenuOpen(false);
|
setIsMobileMenuOpen(false);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className="w-12 h-12 bg-canino-blue rounded-2xl flex items-center justify-center text-white font-bold text-2xl group-hover:bg-medical-gray-900 transition-all shadow-xl shadow-canino-blue/20 italic">C</div>
|
<div className="w-12 h-12 bg-canina-blue rounded-2xl flex items-center justify-center text-white font-bold text-2xl group-hover:bg-medical-gray-900 transition-all shadow-xl shadow-canina-blue/20 italic">C</div>
|
||||||
<div className="flex flex-col">
|
<div className="flex flex-col">
|
||||||
<span className="text-canino-blue font-black text-2xl tracking-tighter leading-none italic font-inter">Canino <span className="text-sm not-italic font-medium border-l-2 border-medical-gray-100 pl-2 ml-2 font-vazir">ایران</span></span>
|
<span className="text-canina-blue font-black text-2xl tracking-tighter leading-none italic font-inter">Canina <span className="text-sm not-italic font-medium border-l-2 border-medical-gray-100 pl-2 ml-2 font-vazir">ایران</span></span>
|
||||||
<span className="text-[10px] text-medical-gray-400 font-bold uppercase tracking-widest leading-none mt-1.5 font-vazir">نماینده رسمی Canina Pharma GmbH آلمان</span>
|
<span className="text-[10px] text-medical-gray-400 font-bold uppercase tracking-widest leading-none mt-1.5 font-vazir">نماینده رسمی Canina Pharma GmbH آلمان</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -130,7 +130,7 @@ export default function Header({
|
|||||||
onMouseEnter={() => setIsMegaMenuOpen(true)}
|
onMouseEnter={() => setIsMegaMenuOpen(true)}
|
||||||
onMouseLeave={() => setIsMegaMenuOpen(false)}
|
onMouseLeave={() => setIsMegaMenuOpen(false)}
|
||||||
>
|
>
|
||||||
<button className={`flex items-center justify-center gap-1.5 px-4 py-3 rounded-xl text-sm font-black transition-all whitespace-nowrap focus-visible:ring-4 focus-visible:ring-canino-blue/30 focus-visible:outline-none min-h-[48px] ${isMegaMenuOpen ? 'bg-medical-gray-50 text-canino-blue' : 'text-medical-gray-600 hover:bg-medical-gray-50 hover:text-canino-blue'} font-vazir`}>
|
<button className={`flex items-center justify-center gap-1.5 px-4 py-3 rounded-xl text-sm font-black transition-all whitespace-nowrap focus-visible:ring-4 focus-visible:ring-canina-blue/30 focus-visible:outline-none min-h-[48px] ${isMegaMenuOpen ? 'bg-medical-gray-50 text-canina-blue' : 'text-medical-gray-600 hover:bg-medical-gray-50 hover:text-canina-blue'} font-vazir`}>
|
||||||
راهکارهای درمانی
|
راهکارهای درمانی
|
||||||
<ChevronDown className={`w-4 h-4 transition-transform duration-300 ${isMegaMenuOpen ? 'rotate-180' : ''}`} />
|
<ChevronDown className={`w-4 h-4 transition-transform duration-300 ${isMegaMenuOpen ? 'rotate-180' : ''}`} />
|
||||||
</button>
|
</button>
|
||||||
@ -153,7 +153,7 @@ export default function Header({
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className="flex items-center gap-4 mb-4">
|
<div className="flex items-center gap-4 mb-4">
|
||||||
<div className="p-3 bg-medical-gray-50 rounded-2xl text-canino-blue group-hover/item:bg-canino-blue group-hover/item:text-white transition-all shadow-sm">
|
<div className="p-3 bg-medical-gray-50 rounded-2xl text-canina-blue group-hover/item:bg-canina-blue group-hover/item:text-white transition-all shadow-sm">
|
||||||
{item.icon}
|
{item.icon}
|
||||||
</div>
|
</div>
|
||||||
<h4 className="font-black text-medical-gray-900 text-sm font-vazir whitespace-nowrap">{item.title}</h4>
|
<h4 className="font-black text-medical-gray-900 text-sm font-vazir whitespace-nowrap">{item.title}</h4>
|
||||||
@ -162,7 +162,7 @@ export default function Header({
|
|||||||
{item.solutions.map((sol, sIdx) => (
|
{item.solutions.map((sol, sIdx) => (
|
||||||
<li
|
<li
|
||||||
key={sIdx}
|
key={sIdx}
|
||||||
className="text-[12px] text-medical-gray-400 hover:text-canino-blue hover:translate-x-[-4px] transition-all font-bold cursor-pointer font-vazir whitespace-nowrap"
|
className="text-[12px] text-medical-gray-400 hover:text-canina-blue hover:translate-x-[-4px] transition-all font-bold cursor-pointer font-vazir whitespace-nowrap"
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
onShopNavigate(item.id, sol);
|
onShopNavigate(item.id, sol);
|
||||||
@ -189,7 +189,7 @@ export default function Header({
|
|||||||
<button
|
<button
|
||||||
key={item.id}
|
key={item.id}
|
||||||
onClick={item.action}
|
onClick={item.action}
|
||||||
className={`px-4 py-3 rounded-xl text-sm font-black transition-all font-vazir whitespace-nowrap focus-visible:ring-4 focus-visible:ring-canino-blue/30 focus-visible:outline-none min-h-[48px] ${currentView === item.id ? 'bg-canino-blue/5 text-canino-blue' : 'text-medical-gray-600 hover:bg-medical-gray-50 hover:text-canino-blue'}`}
|
className={`px-4 py-3 rounded-xl text-sm font-black transition-all font-vazir whitespace-nowrap focus-visible:ring-4 focus-visible:ring-canina-blue/30 focus-visible:outline-none min-h-[48px] ${currentView === item.id ? 'bg-canina-blue/5 text-canina-blue' : 'text-medical-gray-600 hover:bg-medical-gray-50 hover:text-canina-blue'}`}
|
||||||
>
|
>
|
||||||
{item.label}
|
{item.label}
|
||||||
</button>
|
</button>
|
||||||
@ -208,7 +208,7 @@ export default function Header({
|
|||||||
animate={{ width: 350, opacity: 1 }}
|
animate={{ width: 350, opacity: 1 }}
|
||||||
exit={{ width: 0, opacity: 0 }}
|
exit={{ width: 0, opacity: 0 }}
|
||||||
transition={{ type: "spring", damping: 20, stiffness: 200 }}
|
transition={{ type: "spring", damping: 20, stiffness: 200 }}
|
||||||
className="absolute right-0 top-1/2 -translate-y-1/2 bg-white border-2 border-canino-blue rounded-2xl shadow-xl overflow-hidden h-12 flex items-center pr-10"
|
className="absolute right-0 top-1/2 -translate-y-1/2 bg-white border-2 border-canina-blue rounded-2xl shadow-xl overflow-hidden h-12 flex items-center pr-10"
|
||||||
>
|
>
|
||||||
<form onSubmit={handleSearch} className="w-full flex items-center">
|
<form onSubmit={handleSearch} className="w-full flex items-center">
|
||||||
<input
|
<input
|
||||||
@ -220,7 +220,7 @@ export default function Header({
|
|||||||
placeholder="جستجوی محصولات، مقالات سلامت و..."
|
placeholder="جستجوی محصولات، مقالات سلامت و..."
|
||||||
className="w-full bg-transparent px-4 py-2 text-[12px] font-bold outline-none font-vazir text-medical-gray-900"
|
className="w-full bg-transparent px-4 py-2 text-[12px] font-bold outline-none font-vazir text-medical-gray-900"
|
||||||
/>
|
/>
|
||||||
<button type="submit" className="px-4 py-2 bg-canino-blue text-white text-[10px] font-black hover:bg-medical-gray-900 transition-colors">
|
<button type="submit" className="px-4 py-2 bg-canina-blue text-white text-[10px] font-black hover:bg-medical-gray-900 transition-colors">
|
||||||
جستجو
|
جستجو
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
@ -230,7 +230,7 @@ export default function Header({
|
|||||||
|
|
||||||
<HeaderButton
|
<HeaderButton
|
||||||
variant={isSearchFocused ? "primary" : "secondary"}
|
variant={isSearchFocused ? "primary" : "secondary"}
|
||||||
className={cn("w-12 h-12 transition-all duration-300", isSearchFocused ? "z-30 bg-canino-blue text-white" : "")}
|
className={cn("w-12 h-12 transition-all duration-300", isSearchFocused ? "z-30 bg-canina-blue text-white" : "")}
|
||||||
onClick={() => setIsSearchFocused(!isSearchFocused)}
|
onClick={() => setIsSearchFocused(!isSearchFocused)}
|
||||||
>
|
>
|
||||||
<Search className="w-5 h-5" />
|
<Search className="w-5 h-5" />
|
||||||
@ -245,7 +245,7 @@ export default function Header({
|
|||||||
className="flex items-center gap-2.5 px-4 py-2 hover:bg-white rounded-2xl cursor-pointer transition-all border border-transparent hover:border-medical-gray-200"
|
className="flex items-center gap-2.5 px-4 py-2 hover:bg-white rounded-2xl cursor-pointer transition-all border border-transparent hover:border-medical-gray-200"
|
||||||
onClick={() => onNavigate("user-dashboard")}
|
onClick={() => onNavigate("user-dashboard")}
|
||||||
>
|
>
|
||||||
<User className="w-5 h-5 text-canino-blue" />
|
<User className="w-5 h-5 text-canina-blue" />
|
||||||
<span className="text-[14px] font-black font-vazir text-medical-gray-900 leading-none">
|
<span className="text-[14px] font-black font-vazir text-medical-gray-900 leading-none">
|
||||||
{profile.firstName}
|
{profile.firstName}
|
||||||
</span>
|
</span>
|
||||||
@ -259,16 +259,16 @@ export default function Header({
|
|||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
"flex items-center gap-2.5 px-4 py-2 rounded-2xl transition-all cursor-pointer",
|
"flex items-center gap-2.5 px-4 py-2 rounded-2xl transition-all cursor-pointer",
|
||||||
isPetSwitcherOpen ? "bg-canino-blue text-white shadow-lg shadow-canino-blue/20" : "text-canino-blue hover:bg-white"
|
isPetSwitcherOpen ? "bg-canina-blue text-white shadow-lg shadow-canina-blue/20" : "text-canina-blue hover:bg-white"
|
||||||
)}
|
)}
|
||||||
onClick={() => setIsPetSwitcherOpen(!isPetSwitcherOpen)}
|
onClick={() => setIsPetSwitcherOpen(!isPetSwitcherOpen)}
|
||||||
>
|
>
|
||||||
{activePet?.type === "گربه" ? (
|
{activePet?.type === "گربه" ? (
|
||||||
<Cat className={cn("w-5 h-5", isPetSwitcherOpen ? "text-white" : "text-canino-blue/60")} />
|
<Cat className={cn("w-5 h-5", isPetSwitcherOpen ? "text-white" : "text-canina-blue/60")} />
|
||||||
) : (
|
) : (
|
||||||
<Dog className={cn("w-5 h-5", isPetSwitcherOpen ? "text-white" : "text-canino-blue/60")} />
|
<Dog className={cn("w-5 h-5", isPetSwitcherOpen ? "text-white" : "text-canina-blue/60")} />
|
||||||
)}
|
)}
|
||||||
<span className={cn("text-[14px] font-black font-vazir leading-none", isPetSwitcherOpen ? "text-white" : "text-canino-blue")}>
|
<span className={cn("text-[14px] font-black font-vazir leading-none", isPetSwitcherOpen ? "text-white" : "text-canina-blue")}>
|
||||||
{activePet?.name || "بدون پت"}
|
{activePet?.name || "بدون پت"}
|
||||||
</span>
|
</span>
|
||||||
<ChevronDown className={cn("w-4 h-4 transition-transform", isPetSwitcherOpen ? "rotate-180" : "")} />
|
<ChevronDown className={cn("w-4 h-4 transition-transform", isPetSwitcherOpen ? "rotate-180" : "")} />
|
||||||
@ -289,7 +289,7 @@ export default function Header({
|
|||||||
key={pet.id}
|
key={pet.id}
|
||||||
className={cn(
|
className={cn(
|
||||||
"w-full flex items-center justify-between p-3 rounded-xl transition-all group/item",
|
"w-full flex items-center justify-between p-3 rounded-xl transition-all group/item",
|
||||||
activePetId === pet.id ? "bg-canino-blue/5 text-canino-blue" : "hover:bg-medical-gray-50 text-medical-gray-600"
|
activePetId === pet.id ? "bg-canina-blue/5 text-canina-blue" : "hover:bg-medical-gray-50 text-medical-gray-600"
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
@ -302,7 +302,7 @@ export default function Header({
|
|||||||
>
|
>
|
||||||
<div className={cn(
|
<div className={cn(
|
||||||
"w-8 h-8 rounded-lg flex items-center justify-center text-[11px] font-black transition-colors",
|
"w-8 h-8 rounded-lg flex items-center justify-center text-[11px] font-black transition-colors",
|
||||||
activePetId === pet.id ? "bg-canino-blue text-white" : "bg-medical-gray-100 text-medical-gray-400 group-hover/item:bg-medical-gray-200"
|
activePetId === pet.id ? "bg-canina-blue text-white" : "bg-medical-gray-100 text-medical-gray-400 group-hover/item:bg-medical-gray-200"
|
||||||
)}>
|
)}>
|
||||||
{pet.name[0]}
|
{pet.name[0]}
|
||||||
</div>
|
</div>
|
||||||
@ -318,7 +318,7 @@ export default function Header({
|
|||||||
onNavigate({ view: "profile", subview: "detail" });
|
onNavigate({ view: "profile", subview: "detail" });
|
||||||
setIsPetSwitcherOpen(false);
|
setIsPetSwitcherOpen(false);
|
||||||
}}
|
}}
|
||||||
className="p-1.5 rounded-lg hover:bg-canino-blue hover:text-white transition-all text-medical-gray-300 hover:shadow-lg"
|
className="p-1.5 rounded-lg hover:bg-canina-blue hover:text-white transition-all text-medical-gray-300 hover:shadow-lg"
|
||||||
title="مشاهده شناسنامه سلامت"
|
title="مشاهده شناسنامه سلامت"
|
||||||
>
|
>
|
||||||
<FileHeart className="w-4 h-4" />
|
<FileHeart className="w-4 h-4" />
|
||||||
@ -331,7 +331,7 @@ export default function Header({
|
|||||||
<div className="pt-4 border-t border-medical-gray-100 space-y-1">
|
<div className="pt-4 border-t border-medical-gray-100 space-y-1">
|
||||||
<button
|
<button
|
||||||
onClick={() => { onNavigate({ view: "profile", subview: "add" }); setIsPetSwitcherOpen(false); }}
|
onClick={() => { onNavigate({ view: "profile", subview: "add" }); setIsPetSwitcherOpen(false); }}
|
||||||
className="w-full flex items-center gap-3 p-3 text-canino-blue hover:bg-canino-blue/5 rounded-xl transition-all text-[12px] font-black font-vazir"
|
className="w-full flex items-center gap-3 p-3 text-canina-blue hover:bg-canina-blue/5 rounded-xl transition-all text-[12px] font-black font-vazir"
|
||||||
>
|
>
|
||||||
<PlusCircle className="w-5 h-5" />
|
<PlusCircle className="w-5 h-5" />
|
||||||
ثبت همدم (Pet) جدید
|
ثبت همدم (Pet) جدید
|
||||||
@ -348,7 +348,7 @@ export default function Header({
|
|||||||
className="w-full flex items-center gap-3 p-3 text-red-500 hover:bg-red-50 rounded-xl transition-all text-[12px] font-bold font-vazir mt-1"
|
className="w-full flex items-center gap-3 p-3 text-red-500 hover:bg-red-50 rounded-xl transition-all text-[12px] font-bold font-vazir mt-1"
|
||||||
>
|
>
|
||||||
<LogOut className="w-5 h-5" />
|
<LogOut className="w-5 h-5" />
|
||||||
خروج از حساب کانینو
|
خروج از حساب کانینا
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
@ -404,8 +404,8 @@ export default function Header({
|
|||||||
>
|
>
|
||||||
<div className="flex items-center justify-between border-b border-medical-gray-100 pb-4">
|
<div className="flex items-center justify-between border-b border-medical-gray-100 pb-4">
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
<div className="w-10 h-10 bg-canino-blue rounded-xl flex items-center justify-center text-white font-bold text-xl italic">C</div>
|
<div className="w-10 h-10 bg-canina-blue rounded-xl flex items-center justify-center text-white font-bold text-xl italic">C</div>
|
||||||
<span className="text-canino-blue font-black text-xl italic font-inter">Canino</span>
|
<span className="text-canina-blue font-black text-xl italic font-inter">Canina</span>
|
||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
onClick={() => setIsMobileMenuOpen(false)}
|
onClick={() => setIsMobileMenuOpen(false)}
|
||||||
@ -437,20 +437,20 @@ export default function Header({
|
|||||||
{MENU_ITEMS.map((item, idx) => (
|
{MENU_ITEMS.map((item, idx) => (
|
||||||
<div key={idx} className="py-1">
|
<div key={idx} className="py-1">
|
||||||
<div
|
<div
|
||||||
className="text-[13px] font-bold text-medical-gray-800 font-vazir hover:text-canino-blue cursor-pointer flex items-center gap-2"
|
className="text-[13px] font-bold text-medical-gray-800 font-vazir hover:text-canina-blue cursor-pointer flex items-center gap-2"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
onShopNavigate(item.id);
|
onShopNavigate(item.id);
|
||||||
setIsMobileMenuOpen(false);
|
setIsMobileMenuOpen(false);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<span className="text-canino-blue/80">{item.icon}</span>
|
<span className="text-canina-blue/80">{item.icon}</span>
|
||||||
<span>{item.title}</span>
|
<span>{item.title}</span>
|
||||||
</div>
|
</div>
|
||||||
<ul className="mt-1 space-y-1 mr-6">
|
<ul className="mt-1 space-y-1 mr-6">
|
||||||
{item.solutions.map((sol, sIdx) => (
|
{item.solutions.map((sol, sIdx) => (
|
||||||
<li
|
<li
|
||||||
key={sIdx}
|
key={sIdx}
|
||||||
className="text-[11px] text-medical-gray-500 hover:text-canino-blue cursor-pointer py-1 font-vazir"
|
className="text-[11px] text-medical-gray-500 hover:text-canina-blue cursor-pointer py-1 font-vazir"
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
onShopNavigate(item.id, sol);
|
onShopNavigate(item.id, sol);
|
||||||
@ -481,7 +481,7 @@ export default function Header({
|
|||||||
setIsMobileMenuOpen(false);
|
setIsMobileMenuOpen(false);
|
||||||
}}
|
}}
|
||||||
className={`w-full text-right px-4 py-3 rounded-xl text-sm font-black transition-all font-vazir ${currentView === item.id
|
className={`w-full text-right px-4 py-3 rounded-xl text-sm font-black transition-all font-vazir ${currentView === item.id
|
||||||
? 'bg-canino-blue/5 text-canino-blue'
|
? 'bg-canina-blue/5 text-canina-blue'
|
||||||
: 'text-medical-gray-600 hover:bg-medical-gray-50'
|
: 'text-medical-gray-600 hover:bg-medical-gray-50'
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
|
|||||||
@ -20,13 +20,13 @@ export default function HeaderButton({
|
|||||||
badge,
|
badge,
|
||||||
icon
|
icon
|
||||||
}: HeaderButtonProps) {
|
}: HeaderButtonProps) {
|
||||||
const baseStyles = "relative flex flex-col items-center justify-center rounded-xl transition-all duration-300 font-vazir select-none cursor-pointer overflow-visible focus-visible:ring-4 focus-visible:ring-canino-blue/30 focus-visible:outline-none";
|
const baseStyles = "relative flex flex-col items-center justify-center rounded-xl transition-all duration-300 font-vazir select-none cursor-pointer overflow-visible focus-visible:ring-4 focus-visible:ring-canina-blue/30 focus-visible:outline-none";
|
||||||
|
|
||||||
const variants = {
|
const variants = {
|
||||||
primary: "bg-canino-blue text-white hover:bg-medical-gray-900 shadow-lg shadow-canino-blue/20",
|
primary: "bg-canina-blue text-white hover:bg-medical-gray-900 shadow-lg shadow-canina-blue/20",
|
||||||
secondary: "bg-medical-gray-50 text-medical-gray-600 hover:bg-medical-gray-100",
|
secondary: "bg-medical-gray-50 text-medical-gray-600 hover:bg-medical-gray-100",
|
||||||
outline: "border-2 border-medical-gray-100 text-medical-gray-700 hover:border-canino-blue hover:text-canino-blue",
|
outline: "border-2 border-medical-gray-100 text-medical-gray-700 hover:border-canina-blue hover:text-canina-blue",
|
||||||
ghost: "text-medical-gray-600 hover:bg-medical-gray-50 hover:text-canino-blue"
|
ghost: "text-medical-gray-600 hover:bg-medical-gray-50 hover:text-canina-blue"
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@ -22,7 +22,7 @@ function StatCounter({ target }: { target: number }) {
|
|||||||
initial={{ scale: 0.8, opacity: 0 }}
|
initial={{ scale: 0.8, opacity: 0 }}
|
||||||
animate={{ scale: 1, opacity: 1 }}
|
animate={{ scale: 1, opacity: 1 }}
|
||||||
transition={{ duration: 2.5, ease: "easeOut" }}
|
transition={{ duration: 2.5, ease: "easeOut" }}
|
||||||
className="text-4xl lg:text-6xl font-black text-canino-blue font-vazir origin-right flex items-center"
|
className="text-4xl lg:text-6xl font-black text-canina-blue font-vazir origin-right flex items-center"
|
||||||
>
|
>
|
||||||
<motion.span
|
<motion.span
|
||||||
animate={{ scale: [1, 1.1, 1] }}
|
animate={{ scale: [1, 1.1, 1] }}
|
||||||
@ -47,13 +47,13 @@ function Typewriter({ text }: { text: string }) {
|
|||||||
}, [text]);
|
}, [text]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="text-4xl lg:text-6xl font-black text-canino-blue font-vazir flex flex-row-reverse items-center">
|
<div className="text-4xl lg:text-6xl font-black text-canina-blue font-vazir flex flex-row-reverse items-center">
|
||||||
<span className="relative">
|
<span className="relative">
|
||||||
{toPersian(displayText)}
|
{toPersian(displayText)}
|
||||||
<motion.span
|
<motion.span
|
||||||
animate={{ opacity: [0, 1, 0] }}
|
animate={{ opacity: [0, 1, 0] }}
|
||||||
transition={{ duration: 0.8, repeat: Infinity }}
|
transition={{ duration: 0.8, repeat: Infinity }}
|
||||||
className="absolute -left-1 top-0 h-full w-[3px] bg-canino-blue"
|
className="absolute -left-1 top-0 h-full w-[3px] bg-canina-blue"
|
||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
@ -68,7 +68,7 @@ export default function Hero({ banners = [] }: { banners?: any[] }) {
|
|||||||
const title = banners.length > 0 ? banners[0].title : getText('hero_title', "تخصص آلمانی در خدمت\nسلامت پتهای خانگی");
|
const title = banners.length > 0 ? banners[0].title : getText('hero_title', "تخصص آلمانی در خدمت\nسلامت پتهای خانگی");
|
||||||
const subtitle = banners.length > 0 ? banners[0].subtitle : getText(
|
const subtitle = banners.length > 0 ? banners[0].subtitle : getText(
|
||||||
'hero_desc',
|
'hero_desc',
|
||||||
'بیش از <span className="font-bold text-canino-blue">۴۰ سال</span> تجربه نوآورانه در تولید مکملهای درمانی با بالاترین استاندارد کیفی «گرید دارویی اختصاصی». راهکار هوشمند برای هر نیاز بالینی.'
|
'بیش از <span className="font-bold text-canina-blue">۴۰ سال</span> تجربه نوآورانه در تولید مکملهای درمانی با بالاترین استاندارد کیفی «گرید دارویی اختصاصی». راهکار هوشمند برای هر نیاز بالینی.'
|
||||||
);
|
);
|
||||||
const titleParts = title.split('\n');
|
const titleParts = title.split('\n');
|
||||||
|
|
||||||
@ -76,7 +76,7 @@ export default function Hero({ banners = [] }: { banners?: any[] }) {
|
|||||||
<section className="relative overflow-hidden bg-white py-20 lg:py-32 border-b border-medical-gray-100">
|
<section className="relative overflow-hidden bg-white py-20 lg:py-32 border-b border-medical-gray-100">
|
||||||
{/* Background patterns */}
|
{/* Background patterns */}
|
||||||
<div className="absolute top-0 left-0 w-full h-full opacity-[0.03] pointer-events-none select-none overflow-hidden">
|
<div className="absolute top-0 left-0 w-full h-full opacity-[0.03] pointer-events-none select-none overflow-hidden">
|
||||||
<div className="absolute top-0 right-0 w-[800px] h-[800px] bg-canino-blue rounded-full blur-[120px] -mr-96 -mt-96" />
|
<div className="absolute top-0 right-0 w-[800px] h-[800px] bg-canina-blue rounded-full blur-[120px] -mr-96 -mt-96" />
|
||||||
<div className="absolute bottom-0 left-0 w-[600px] h-[600px] bg-medical-gray-500 rounded-full blur-[100px] -ml-40 -mb-40" />
|
<div className="absolute bottom-0 left-0 w-[600px] h-[600px] bg-medical-gray-500 rounded-full blur-[100px] -ml-40 -mb-40" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -88,14 +88,14 @@ export default function Hero({ banners = [] }: { banners?: any[] }) {
|
|||||||
animate={{ opacity: 1, y: 0 }}
|
animate={{ opacity: 1, y: 0 }}
|
||||||
transition={{ duration: 0.6 }}
|
transition={{ duration: 0.6 }}
|
||||||
>
|
>
|
||||||
<div className="inline-flex items-center gap-2 px-3 py-1 bg-canino-blue/5 border border-canino-blue/10 rounded-full mb-6">
|
<div className="inline-flex items-center gap-2 px-3 py-1 bg-canina-blue/5 border border-canina-blue/10 rounded-full mb-6">
|
||||||
<span className="w-2 h-2 rounded-full bg-canino-blue animate-pulse" />
|
<span className="w-2 h-2 rounded-full bg-canina-blue animate-pulse" />
|
||||||
<span className="text-canino-blue text-xs font-bold uppercase tracking-widest leading-none">{getText('hero_badge', "تخصص دارویی از آلمان")}</span>
|
<span className="text-canina-blue text-xs font-bold uppercase tracking-widest leading-none">{getText('hero_badge', "تخصص دارویی از آلمان")}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h1 className="text-4xl lg:text-7xl font-black text-medical-gray-900 leading-[1.1] mb-6">
|
<h1 className="text-4xl lg:text-7xl font-black text-medical-gray-900 leading-[1.1] mb-6">
|
||||||
{titleParts[0]} <br />
|
{titleParts[0]} <br />
|
||||||
{titleParts[1] && <span className="text-canino-blue font-vazir">{titleParts[1]}</span>}
|
{titleParts[1] && <span className="text-canina-blue font-vazir">{titleParts[1]}</span>}
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
<p
|
<p
|
||||||
@ -113,14 +113,14 @@ export default function Hero({ banners = [] }: { banners?: any[] }) {
|
|||||||
element.scrollIntoView({ behavior: 'smooth' });
|
element.scrollIntoView({ behavior: 'smooth' });
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
className="bg-medical-gray-900 text-white px-10 py-5 rounded-full font-bold text-lg hover:bg-canino-blue hover:shadow-2xl focus-visible:ring-4 focus-visible:ring-canino-blue/30 focus-visible:outline-none transition-all flex items-center gap-2 group font-vazir min-h-[48px]"
|
className="bg-medical-gray-900 text-white px-10 py-5 rounded-full font-bold text-lg hover:bg-canina-blue hover:shadow-2xl focus-visible:ring-4 focus-visible:ring-canina-blue/30 focus-visible:outline-none transition-all flex items-center gap-2 group font-vazir min-h-[48px]"
|
||||||
>
|
>
|
||||||
{getText('hero_btn_advisor', "دستیار سلامت پت")}
|
{getText('hero_btn_advisor', "دستیار سلامت پت")}
|
||||||
<ChevronLeft className="w-5 h-5 group-hover:-translate-x-1 transition-transform" />
|
<ChevronLeft className="w-5 h-5 group-hover:-translate-x-1 transition-transform" />
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => router.push('/shop')}
|
onClick={() => router.push('/shop')}
|
||||||
className="bg-white border-2 border-medical-gray-200 text-medical-gray-700 px-10 py-5 rounded-full font-bold text-lg hover:border-canino-blue hover:text-canino-blue focus-visible:ring-4 focus-visible:ring-canino-blue/30 focus-visible:outline-none transition-all font-vazir min-h-[48px]"
|
className="bg-white border-2 border-medical-gray-200 text-medical-gray-700 px-10 py-5 rounded-full font-bold text-lg hover:border-canina-blue hover:text-canina-blue focus-visible:ring-4 focus-visible:ring-canina-blue/30 focus-visible:outline-none transition-all font-vazir min-h-[48px]"
|
||||||
>
|
>
|
||||||
{getText('hero_btn_products', "مشاهده محصولات")}
|
{getText('hero_btn_products', "مشاهده محصولات")}
|
||||||
</button>
|
</button>
|
||||||
@ -153,10 +153,10 @@ export default function Hero({ banners = [] }: { banners?: any[] }) {
|
|||||||
<motion.div
|
<motion.div
|
||||||
animate={{ rotate: 360 }}
|
animate={{ rotate: 360 }}
|
||||||
transition={{ duration: 20, repeat: Infinity, ease: "linear" }}
|
transition={{ duration: 20, repeat: Infinity, ease: "linear" }}
|
||||||
className="absolute top-6 right-6 lg:top-8 lg:right-8 z-20 w-24 h-24 lg:w-28 lg:h-28 bg-white shadow-2xl rounded-full p-2 border-2 border-dashed border-canino-blue flex items-center justify-center text-center"
|
className="absolute top-6 right-6 lg:top-8 lg:right-8 z-20 w-24 h-24 lg:w-28 lg:h-28 bg-white shadow-2xl rounded-full p-2 border-2 border-dashed border-canina-blue flex items-center justify-center text-center"
|
||||||
>
|
>
|
||||||
<div className="flex flex-col items-center">
|
<div className="flex flex-col items-center">
|
||||||
<span className="text-xl lg:text-2xl font-black text-canino-blue leading-none tracking-tighter">DE</span>
|
<span className="text-xl lg:text-2xl font-black text-canina-blue leading-none tracking-tighter">DE</span>
|
||||||
<span className="text-[7px] lg:text-[8px] font-bold text-medical-gray-500 uppercase tracking-widest mt-0.5 leading-tight">{getText('hero_quality_standard', "استاندارد کیفی آلمان")}</span>
|
<span className="text-[7px] lg:text-[8px] font-bold text-medical-gray-500 uppercase tracking-widest mt-0.5 leading-tight">{getText('hero_quality_standard', "استاندارد کیفی آلمان")}</span>
|
||||||
</div>
|
</div>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
@ -183,7 +183,7 @@ export default function Hero({ banners = [] }: { banners?: any[] }) {
|
|||||||
<div className="flex flex-col items-center justify-center text-center">
|
<div className="flex flex-col items-center justify-center text-center">
|
||||||
<div className="relative overflow-hidden group">
|
<div className="relative overflow-hidden group">
|
||||||
<motion.div
|
<motion.div
|
||||||
className="text-4xl lg:text-6xl font-black text-canino-blue font-vazir relative z-10"
|
className="text-4xl lg:text-6xl font-black text-canina-blue font-vazir relative z-10"
|
||||||
>
|
>
|
||||||
۱۰۰٪
|
۱۰۰٪
|
||||||
</motion.div>
|
</motion.div>
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
"use client";
|
"use client";
|
||||||
import { useMemo, useState, useEffect } from "react";
|
import { useState, useEffect } from "react";
|
||||||
import { Product, IngredientInfo } from "../lib/data/products";
|
import { Product, IngredientInfo } from "../lib/data/products";
|
||||||
import { motion } from "motion/react";
|
import { motion } from "motion/react";
|
||||||
import { FlaskConical, CheckCircle2, ChevronRight, ChevronLeft, Beaker } from "lucide-react";
|
import { FlaskConical, CheckCircle2, ChevronRight, ChevronLeft, Beaker } from "lucide-react";
|
||||||
@ -16,21 +16,27 @@ export default function IngredientWiki() {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
productService.getProducts().then(data => setProducts(data));
|
productService.getProducts().then(data => setProducts(data));
|
||||||
|
|
||||||
fetch('http://localhost:4000/api/wiki')
|
|
||||||
.then(res => res.json())
|
|
||||||
.then(data => {
|
|
||||||
const mapped = data.map((item: any) => ({
|
|
||||||
id: item.key,
|
|
||||||
name: item.term,
|
|
||||||
description: item.definition,
|
|
||||||
benefits: item.keywords ? JSON.parse(item.keywords) : []
|
|
||||||
}));
|
|
||||||
setIngredientsWiki(mapped);
|
|
||||||
})
|
|
||||||
.catch(err => console.error("Failed to fetch wiki:", err));
|
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const raw = texts.ingredients_wiki || texts.ingredients_wiki_text;
|
||||||
|
if (raw) {
|
||||||
|
try {
|
||||||
|
const parsed = typeof raw === 'string' ? JSON.parse(raw) : raw;
|
||||||
|
if (Array.isArray(parsed)) {
|
||||||
|
setIngredientsWiki(parsed.map((item: any) => ({
|
||||||
|
id: item.id,
|
||||||
|
name: item.name,
|
||||||
|
description: item.description,
|
||||||
|
benefits: Array.isArray(item.benefits) ? item.benefits : []
|
||||||
|
})));
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error("Failed to parse ingredients_wiki:", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [texts]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<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">
|
||||||
@ -39,33 +45,33 @@ export default function IngredientWiki() {
|
|||||||
<div className="lg:hidden mb-12 space-y-4">
|
<div className="lg:hidden mb-12 space-y-4">
|
||||||
<button
|
<button
|
||||||
onClick={() => router.back()}
|
onClick={() => router.back()}
|
||||||
className="flex items-center gap-2 text-medical-gray-500 font-bold hover:text-canino-blue transition-colors"
|
className="flex items-center gap-2 text-medical-gray-500 font-bold hover:text-canina-blue transition-colors"
|
||||||
>
|
>
|
||||||
<ChevronRight className="w-5 h-5" />
|
<ChevronRight className="w-5 h-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">
|
<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-canino-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-canino-blue">دانشنامه علمی</span>
|
<span className="text-canina-blue">دانشنامه علمی</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Desktop Breadcrumbs */}
|
{/* Desktop Breadcrumbs */}
|
||||||
<div className="hidden lg:flex items-center gap-2 text-[10px] font-black text-medical-gray-400 uppercase tracking-widest mb-12">
|
<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-canino-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-canino-blue">دانشنامه مواد نایاب و ارگانیک</span>
|
<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">
|
||||||
<div className="inline-flex items-center gap-2 px-4 py-2 bg-canino-blue/5 border border-canino-blue/10 rounded-full text-canino-blue text-xs font-black uppercase tracking-widest mb-6">
|
<div className="inline-flex items-center gap-2 px-4 py-2 bg-canina-blue/5 border border-canina-blue/10 rounded-full text-canina-blue text-xs font-black uppercase tracking-widest mb-6">
|
||||||
<FlaskConical className="w-4 h-4" />
|
<FlaskConical className="w-4 h-4" />
|
||||||
علم در خدمت کیفیت
|
علم در خدمت کیفیت
|
||||||
</div>
|
</div>
|
||||||
<h2 className="text-4xl lg:text-6xl font-black text-medical-gray-900 leading-tight md:max-w-4xl">
|
<h2 className="text-4xl lg:text-6xl font-black text-medical-gray-900 leading-tight md:max-w-4xl">
|
||||||
دانشنامه مواد <span className="text-canino-blue italic">نایاب و ارگانیک</span> کانینو
|
دانشنامه مواد <span className="text-canina-blue italic">نایاب و ارگانیک</span> کانینا
|
||||||
</h2>
|
</h2>
|
||||||
<p className="mt-6 text-lg text-medical-gray-500 max-w-2xl leading-relaxed">
|
<p className="mt-6 text-lg text-medical-gray-500 max-w-2xl leading-relaxed">
|
||||||
ما از مواد اولیهای استفاده میکنیم که در سطح دارویی فرآوری شدهاند. در اینجا با قدرت بیولوژیک این ترکیبات آشنا شوید.
|
ما از مواد اولیهای استفاده میکنیم که در سطح دارویی فرآوری شدهاند. در اینجا با قدرت بیولوژیک این ترکیبات آشنا شوید.
|
||||||
@ -103,7 +109,7 @@ export default function IngredientWiki() {
|
|||||||
<div className="grid grid-cols-1 gap-4 mb-10">
|
<div className="grid grid-cols-1 gap-4 mb-10">
|
||||||
{ing.benefits.map((benefit, bIdx) => (
|
{ing.benefits.map((benefit, bIdx) => (
|
||||||
<div key={bIdx} className="flex items-start gap-4 p-4 bg-medical-gray-50 rounded-2xl border border-medical-gray-100">
|
<div key={bIdx} className="flex items-start gap-4 p-4 bg-medical-gray-50 rounded-2xl border border-medical-gray-100">
|
||||||
<CheckCircle2 className="w-6 h-6 text-canino-blue flex-shrink-0" />
|
<CheckCircle2 className="w-6 h-6 text-canina-blue flex-shrink-0" />
|
||||||
<span className="text-sm font-bold text-medical-gray-700">{benefit}</span>
|
<span className="text-sm font-bold text-medical-gray-700">{benefit}</span>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
@ -131,7 +137,7 @@ export default function IngredientWiki() {
|
|||||||
className="bg-white rounded-[2.5rem] p-6 shadow-xl hover:scale-105 transition-transform cursor-pointer group"
|
className="bg-white rounded-[2.5rem] p-6 shadow-xl hover:scale-105 transition-transform cursor-pointer group"
|
||||||
>
|
>
|
||||||
<img src={p.image} alt={p.name} className="w-24 h-24 object-contain mx-auto mb-4" referrerPolicy="no-referrer" />
|
<img src={p.image} alt={p.name} className="w-24 h-24 object-contain mx-auto mb-4" referrerPolicy="no-referrer" />
|
||||||
<h4 className="text-sm font-black text-center text-medical-gray-900 group-hover:text-canino-blue transition-colors px-2">{p.name}</h4>
|
<h4 className="text-sm font-black text-center text-medical-gray-900 group-hover:text-canina-blue transition-colors px-2">{p.name}</h4>
|
||||||
</div>
|
</div>
|
||||||
)) : (
|
)) : (
|
||||||
<div className="col-span-full py-12 text-center text-medical-gray-400 font-bold italic">
|
<div className="col-span-full py-12 text-center text-medical-gray-400 font-bold italic">
|
||||||
@ -141,7 +147,7 @@ export default function IngredientWiki() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Decorative backdrop */}
|
{/* Decorative backdrop */}
|
||||||
<div className="absolute -bottom-20 -left-20 w-80 h-80 bg-canino-blue rounded-full blur-[100px] opacity-10" />
|
<div className="absolute -bottom-20 -left-20 w-80 h-80 bg-canina-blue rounded-full blur-[100px] opacity-10" />
|
||||||
</motion.div>
|
</motion.div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -159,11 +165,11 @@ export default function IngredientWiki() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="relative z-10 max-w-3xl mx-auto">
|
<div className="relative z-10 max-w-3xl mx-auto">
|
||||||
<h3 className="text-3xl lg:text-5xl font-black mb-8 leading-tight italic">تمام مواد اولیه ما دارای گواهینامه <br /> <span className="text-canino-blue">گرید دارویی اختصاصی</span> هستند.</h3>
|
<h3 className="text-3xl lg:text-5xl font-black mb-8 leading-tight italic">تمام مواد اولیه ما دارای گواهینامه <br /> <span className="text-canina-blue">گرید دارویی اختصاصی</span> هستند.</h3>
|
||||||
<p className="text-white/60 text-lg mb-10">این یعنی استانداردی فراتر از مکملهای معمولی، مشابه استانداردهای تولید دارو در اتحادیه اروپا.</p>
|
<p className="text-white/60 text-lg mb-10">این یعنی استانداردی فراتر از مکملهای معمولی، مشابه استانداردهای تولید دارو در اتحادیه اروپا.</p>
|
||||||
<div className="flex justify-center gap-12">
|
<div className="flex justify-center gap-12">
|
||||||
<div className="flex flex-col items-center">
|
<div className="flex flex-col items-center">
|
||||||
<div className="text-2xl font-black font-vazir text-canino-blue">۱۰۰٪</div>
|
<div className="text-2xl font-black font-vazir text-canina-blue">۱۰۰٪</div>
|
||||||
<div className="text-[10px] font-bold uppercase tracking-widest text-white/40 mt-1">تست آزمایشگاهی</div>
|
<div className="text-[10px] font-bold uppercase tracking-widest text-white/40 mt-1">تست آزمایشگاهی</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col items-center">
|
<div className="flex flex-col items-center">
|
||||||
|
|||||||
@ -137,7 +137,7 @@ export default function LoginModal({ isOpen, onClose, onLogin, petName, isAdviso
|
|||||||
dir="rtl"
|
dir="rtl"
|
||||||
>
|
>
|
||||||
{/* Top color indicator */}
|
{/* Top color indicator */}
|
||||||
<div className="absolute top-0 left-0 w-full h-2 bg-gradient-to-r from-canino-blue to-indigo-500" />
|
<div className="absolute top-0 left-0 w-full h-2 bg-gradient-to-r from-canina-blue to-indigo-500" />
|
||||||
|
|
||||||
{/* Close Button */}
|
{/* Close Button */}
|
||||||
<button
|
<button
|
||||||
@ -149,15 +149,15 @@ export default function LoginModal({ isOpen, onClose, onLogin, petName, isAdviso
|
|||||||
|
|
||||||
{/* Header info */}
|
{/* Header info */}
|
||||||
<div className="text-center mb-8">
|
<div className="text-center mb-8">
|
||||||
<div className="w-20 h-20 bg-canino-blue/10 rounded-[2.5rem] flex items-center justify-center mx-auto mb-6 shadow-inner">
|
<div className="w-20 h-20 bg-canina-blue/10 rounded-[2.5rem] flex items-center justify-center mx-auto mb-6 shadow-inner">
|
||||||
<ShieldCheck className="w-10 h-10 text-canino-blue" />
|
<ShieldCheck className="w-10 h-10 text-canina-blue" />
|
||||||
</div>
|
</div>
|
||||||
<h3 className="text-3xl font-black text-medical-gray-900 mb-2 italic">
|
<h3 className="text-3xl font-black text-medical-gray-900 mb-2 italic">
|
||||||
ورود به کانینو
|
ورود به کانینا
|
||||||
</h3>
|
</h3>
|
||||||
{isAdvisorContext ? (
|
{isAdvisorContext ? (
|
||||||
<p className="text-medical-gray-500 font-bold leading-relaxed px-2 text-sm">
|
<p className="text-medical-gray-500 font-bold leading-relaxed px-2 text-sm">
|
||||||
تحلیل سلامت <span className="text-canino-blue">{petName || "همدم شما"}</span> آماده است! برای مشاهده رژیم مکمل پیشنهادی و ذخیره شناسنامه، وارد شوید.
|
تحلیل سلامت <span className="text-canina-blue">{petName || "همدم شما"}</span> آماده است! برای مشاهده رژیم مکمل پیشنهادی و ذخیره شناسنامه، وارد شوید.
|
||||||
</p>
|
</p>
|
||||||
) : (
|
) : (
|
||||||
<p className="text-medical-gray-500 font-bold text-sm">برای دسترسی به پنل مدیریت سلامت، وارد شوید</p>
|
<p className="text-medical-gray-500 font-bold text-sm">برای دسترسی به پنل مدیریت سلامت، وارد شوید</p>
|
||||||
@ -187,7 +187,7 @@ export default function LoginModal({ isOpen, onClose, onLogin, petName, isAdviso
|
|||||||
value={phoneNumber}
|
value={phoneNumber}
|
||||||
onChange={(e) => setPhoneNumber(e.target.value.replace(/[^0-9]/g, ''))}
|
onChange={(e) => setPhoneNumber(e.target.value.replace(/[^0-9]/g, ''))}
|
||||||
disabled={isLoading}
|
disabled={isLoading}
|
||||||
className="w-full bg-medical-gray-50 border border-medical-gray-200 rounded-2xl py-4 pr-12 pl-4 focus:ring-2 focus:ring-canino-blue/20 focus:border-canino-blue outline-none font-bold text-lg text-left tracking-widest"
|
className="w-full bg-medical-gray-50 border border-medical-gray-200 rounded-2xl py-4 pr-12 pl-4 focus:ring-2 focus:ring-canina-blue/20 focus:border-canina-blue outline-none font-bold text-lg text-left tracking-widest"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -195,7 +195,7 @@ export default function LoginModal({ isOpen, onClose, onLogin, petName, isAdviso
|
|||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
disabled={isLoading || phoneNumber.length < 11}
|
disabled={isLoading || phoneNumber.length < 11}
|
||||||
className="w-full py-5 bg-canino-blue text-white rounded-2xl font-black text-xl hover:bg-indigo-700 disabled:opacity-50 disabled:cursor-not-allowed transition-all shadow-xl shadow-canino-blue/20 flex items-center justify-center gap-3 cursor-pointer"
|
className="w-full py-5 bg-canina-blue text-white rounded-2xl font-black text-xl hover:bg-indigo-700 disabled:opacity-50 disabled:cursor-not-allowed transition-all shadow-xl shadow-canina-blue/20 flex items-center justify-center gap-3 cursor-pointer"
|
||||||
>
|
>
|
||||||
{isLoading ? (
|
{isLoading ? (
|
||||||
<RefreshCw className="w-6 h-6 animate-spin" />
|
<RefreshCw className="w-6 h-6 animate-spin" />
|
||||||
@ -222,7 +222,7 @@ export default function LoginModal({ isOpen, onClose, onLogin, petName, isAdviso
|
|||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => setStep("phone")}
|
onClick={() => setStep("phone")}
|
||||||
className="text-[10px] font-black text-canino-blue flex items-center gap-1 hover:underline"
|
className="text-[10px] font-black text-canina-blue flex items-center gap-1 hover:underline"
|
||||||
>
|
>
|
||||||
<ArrowRight className="w-3 h-3" />
|
<ArrowRight className="w-3 h-3" />
|
||||||
ویرایش شماره
|
ویرایش شماره
|
||||||
@ -238,7 +238,7 @@ export default function LoginModal({ isOpen, onClose, onLogin, petName, isAdviso
|
|||||||
value={otpCode}
|
value={otpCode}
|
||||||
onChange={(e) => setOtpCode(e.target.value.replace(/[^0-9]/g, ''))}
|
onChange={(e) => setOtpCode(e.target.value.replace(/[^0-9]/g, ''))}
|
||||||
disabled={isLoading}
|
disabled={isLoading}
|
||||||
className="w-full bg-medical-gray-50 border border-medical-gray-200 rounded-2xl py-4 pr-12 pl-4 focus:ring-2 focus:ring-canino-blue/20 focus:border-canino-blue outline-none font-black text-2xl text-center tracking-[0.5em]"
|
className="w-full bg-medical-gray-50 border border-medical-gray-200 rounded-2xl py-4 pr-12 pl-4 focus:ring-2 focus:ring-canina-blue/20 focus:border-canina-blue outline-none font-black text-2xl text-center tracking-[0.5em]"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<p className="text-[10px] text-medical-gray-400 font-bold text-center mt-2">
|
<p className="text-[10px] text-medical-gray-400 font-bold text-center mt-2">
|
||||||
@ -256,7 +256,7 @@ export default function LoginModal({ isOpen, onClose, onLogin, petName, isAdviso
|
|||||||
type="button"
|
type="button"
|
||||||
onClick={handleResendOtp}
|
onClick={handleResendOtp}
|
||||||
disabled={isLoading}
|
disabled={isLoading}
|
||||||
className="text-xs font-black text-canino-blue hover:underline flex items-center gap-1.5"
|
className="text-xs font-black text-canina-blue hover:underline flex items-center gap-1.5"
|
||||||
>
|
>
|
||||||
<RefreshCw className="w-3.5 h-3.5" />
|
<RefreshCw className="w-3.5 h-3.5" />
|
||||||
ارسال مجدد کد تایید
|
ارسال مجدد کد تایید
|
||||||
@ -267,7 +267,7 @@ export default function LoginModal({ isOpen, onClose, onLogin, petName, isAdviso
|
|||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
disabled={isLoading || otpCode.length < 5}
|
disabled={isLoading || otpCode.length < 5}
|
||||||
className="w-full py-5 bg-canino-blue text-white rounded-2xl font-black text-xl hover:bg-indigo-700 disabled:opacity-50 disabled:cursor-not-allowed transition-all shadow-xl shadow-canino-blue/20 flex items-center justify-center gap-3 cursor-pointer"
|
className="w-full py-5 bg-canina-blue text-white rounded-2xl font-black text-xl hover:bg-indigo-700 disabled:opacity-50 disabled:cursor-not-allowed transition-all shadow-xl shadow-canina-blue/20 flex items-center justify-center gap-3 cursor-pointer"
|
||||||
>
|
>
|
||||||
{isLoading ? (
|
{isLoading ? (
|
||||||
<RefreshCw className="w-6 h-6 animate-spin" />
|
<RefreshCw className="w-6 h-6 animate-spin" />
|
||||||
|
|||||||
@ -62,7 +62,7 @@ export default function OrderDetailsModal({ isOpen, onClose, order }: OrderDetai
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="header">
|
<div class="header">
|
||||||
<div class="logo">CANINO | کانینو</div>
|
<div class="logo">CANINO | کانینا</div>
|
||||||
<div>تاریخ: ${toPersian(new Date(order.date).toLocaleDateString('fa-IR'))}</div>
|
<div>تاریخ: ${toPersian(new Date(order.date).toLocaleDateString('fa-IR'))}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="info">
|
<div class="info">
|
||||||
@ -139,7 +139,7 @@ export default function OrderDetailsModal({ isOpen, onClose, order }: OrderDetai
|
|||||||
{/* Header */}
|
{/* Header */}
|
||||||
<div className="bg-medical-gray-50 px-10 py-8 flex items-center justify-between border-b border-medical-gray-100">
|
<div className="bg-medical-gray-50 px-10 py-8 flex items-center justify-between border-b border-medical-gray-100">
|
||||||
<div className="flex items-center gap-4">
|
<div className="flex items-center gap-4">
|
||||||
<div className="w-14 h-14 bg-canino-blue rounded-2xl flex items-center justify-center text-white shadow-lg">
|
<div className="w-14 h-14 bg-canina-blue rounded-2xl flex items-center justify-center text-white shadow-lg">
|
||||||
<Package className="w-7 h-7" />
|
<Package className="w-7 h-7" />
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
@ -168,7 +168,7 @@ export default function OrderDetailsModal({ isOpen, onClose, order }: OrderDetai
|
|||||||
</div>
|
</div>
|
||||||
<div className="bg-medical-gray-50 p-4 rounded-2xl">
|
<div className="bg-medical-gray-50 p-4 rounded-2xl">
|
||||||
<div className="text-[9px] font-black text-medical-gray-400 uppercase tracking-widest mb-1">کد رهگیری</div>
|
<div className="text-[9px] font-black text-medical-gray-400 uppercase tracking-widest mb-1">کد رهگیری</div>
|
||||||
<div className="text-sm font-mono font-bold text-canino-blue">{toPersian(order.trackingNumber)}</div>
|
<div className="text-sm font-mono font-bold text-canina-blue">{toPersian(order.trackingNumber)}</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="bg-medical-gray-50 p-4 rounded-2xl">
|
<div className="bg-medical-gray-50 p-4 rounded-2xl">
|
||||||
<div className="text-[9px] font-black text-medical-gray-400 uppercase tracking-widest mb-1">زمان ثبت</div>
|
<div className="text-[9px] font-black text-medical-gray-400 uppercase tracking-widest mb-1">زمان ثبت</div>
|
||||||
@ -182,12 +182,12 @@ export default function OrderDetailsModal({ isOpen, onClose, order }: OrderDetai
|
|||||||
{/* Items List */}
|
{/* Items List */}
|
||||||
<div>
|
<div>
|
||||||
<h4 className="text-sm font-black text-medical-gray-900 mb-6 flex items-center gap-2">
|
<h4 className="text-sm font-black text-medical-gray-900 mb-6 flex items-center gap-2">
|
||||||
<ShoppingBag className="w-4 h-4 text-canino-blue" />
|
<ShoppingBag className="w-4 h-4 text-canina-blue" />
|
||||||
سبد محصولات خریده شده
|
سبد محصولات خریده شده
|
||||||
</h4>
|
</h4>
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
{(order.items || []).map((item: any) => (
|
{(order.items || []).map((item: any) => (
|
||||||
<div key={item.product.id} className="flex items-center justify-between p-4 border border-medical-gray-100 rounded-2xl hover:border-canino-blue transition-all">
|
<div key={item.product.id} className="flex items-center justify-between p-4 border border-medical-gray-100 rounded-2xl hover:border-canina-blue transition-all">
|
||||||
<div className="flex items-center gap-4">
|
<div className="flex items-center gap-4">
|
||||||
<div className="w-16 h-16 bg-medical-gray-50 rounded-xl p-2 flex items-center justify-center shrink-0">
|
<div className="w-16 h-16 bg-medical-gray-50 rounded-xl p-2 flex items-center justify-center shrink-0">
|
||||||
<SafeImage
|
<SafeImage
|
||||||
@ -203,7 +203,7 @@ export default function OrderDetailsModal({ isOpen, onClose, order }: OrderDetai
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="text-left">
|
<div className="text-left">
|
||||||
<div className="text-lg font-black text-canino-blue italic">{toPersian((item.product.priceValue * item.quantity).toLocaleString())} <span className="text-[10px] not-italic">تومان</span></div>
|
<div className="text-lg font-black text-canina-blue italic">{toPersian((item.product.priceValue * item.quantity).toLocaleString())} <span className="text-[10px] not-italic">تومان</span></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
@ -214,7 +214,7 @@ export default function OrderDetailsModal({ isOpen, onClose, order }: OrderDetai
|
|||||||
<div className="grid md:grid-cols-2 gap-8 pt-6 border-t border-medical-gray-100">
|
<div className="grid md:grid-cols-2 gap-8 pt-6 border-t border-medical-gray-100">
|
||||||
<div>
|
<div>
|
||||||
<h4 className="text-sm font-black text-medical-gray-900 mb-4 flex items-center gap-2">
|
<h4 className="text-sm font-black text-medical-gray-900 mb-4 flex items-center gap-2">
|
||||||
<MapPin className="w-4 h-4 text-canino-blue" />
|
<MapPin className="w-4 h-4 text-canina-blue" />
|
||||||
اطلاعات ارسال
|
اطلاعات ارسال
|
||||||
</h4>
|
</h4>
|
||||||
<p className="text-xs font-bold text-medical-gray-500 leading-relaxed">
|
<p className="text-xs font-bold text-medical-gray-500 leading-relaxed">
|
||||||
@ -223,7 +223,7 @@ export default function OrderDetailsModal({ isOpen, onClose, order }: OrderDetai
|
|||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<h4 className="text-sm font-black text-medical-gray-900 mb-4 flex items-center gap-2">
|
<h4 className="text-sm font-black text-medical-gray-900 mb-4 flex items-center gap-2">
|
||||||
<CreditCard className="w-4 h-4 text-canino-blue" />
|
<CreditCard className="w-4 h-4 text-canina-blue" />
|
||||||
جزئیات پرداخت
|
جزئیات پرداخت
|
||||||
</h4>
|
</h4>
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
@ -253,7 +253,7 @@ export default function OrderDetailsModal({ isOpen, onClose, order }: OrderDetai
|
|||||||
<Download className="w-5 h-5" />
|
<Download className="w-5 h-5" />
|
||||||
دانلود فاکتور رسمی
|
دانلود فاکتور رسمی
|
||||||
</button>
|
</button>
|
||||||
<button className="flex items-center justify-center w-14 h-14 bg-medical-gray-900 text-white rounded-2xl hover:bg-canino-blue transition-all shadow-lg shadow-black/10">
|
<button className="flex items-center justify-center w-14 h-14 bg-medical-gray-900 text-white rounded-2xl hover:bg-canina-blue transition-all shadow-lg shadow-black/10">
|
||||||
<Printer className="w-6 h-6" />
|
<Printer className="w-6 h-6" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -35,33 +35,33 @@ export default function OrderSuccess({ orderId }: { orderId: string }) {
|
|||||||
className="bg-white rounded-[4rem] border border-medical-gray-200 p-12 text-center shadow-2xl relative overflow-hidden"
|
className="bg-white rounded-[4rem] border border-medical-gray-200 p-12 text-center shadow-2xl relative overflow-hidden"
|
||||||
>
|
>
|
||||||
{/* Confetti-like background elements */}
|
{/* Confetti-like background elements */}
|
||||||
<div className="absolute top-0 left-0 w-full h-2 bg-gradient-to-r from-canino-blue via-green-500 to-canino-blue" />
|
<div className="absolute top-0 left-0 w-full h-2 bg-gradient-to-r from-canina-blue via-green-500 to-canina-blue" />
|
||||||
|
|
||||||
<div className="w-24 h-24 bg-green-50 text-green-600 rounded-full flex items-center justify-center mx-auto mb-10 shadow-inner">
|
<div className="w-24 h-24 bg-green-50 text-green-600 rounded-full flex items-center justify-center mx-auto mb-10 shadow-inner">
|
||||||
<CheckCircle2 className="w-12 h-12" />
|
<CheckCircle2 className="w-12 h-12" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h2 className="text-4xl font-black text-medical-gray-900 italic mb-4">سفارش شما با موفقیت ثبت شد!</h2>
|
<h2 className="text-4xl font-black text-medical-gray-900 italic mb-4">سفارش شما با موفقیت ثبت شد!</h2>
|
||||||
<p className="text-medical-gray-500 font-bold mb-10">شماره سفارش: <span className="text-canino-blue font-mono">{order.id}</span></p>
|
<p className="text-medical-gray-500 font-bold mb-10">شماره سفارش: <span className="text-canina-blue font-mono">{order.id}</span></p>
|
||||||
|
|
||||||
{/* Empathetic Message */}
|
{/* Empathetic Message */}
|
||||||
<motion.div
|
<motion.div
|
||||||
initial={{ opacity: 0, y: 20 }}
|
initial={{ opacity: 0, y: 20 }}
|
||||||
animate={{ opacity: 1, y: 0 }}
|
animate={{ opacity: 1, y: 0 }}
|
||||||
transition={{ delay: 0.3 }}
|
transition={{ delay: 0.3 }}
|
||||||
className="p-8 bg-canino-blue/5 border border-canino-blue/10 rounded-[3rem] mb-12 text-right relative"
|
className="p-8 bg-canina-blue/5 border border-canina-blue/10 rounded-[3rem] mb-12 text-right relative"
|
||||||
>
|
>
|
||||||
<Sparkles className="absolute top-6 left-6 w-8 h-8 text-canino-blue opacity-20" />
|
<Sparkles className="absolute top-6 left-6 w-8 h-8 text-canina-blue opacity-20" />
|
||||||
<div className="flex items-center gap-4 mb-4">
|
<div className="flex items-center gap-4 mb-4">
|
||||||
<div className="w-10 h-10 bg-white rounded-2xl flex items-center justify-center text-canino-blue shadow-sm">
|
<div className="w-10 h-10 bg-white rounded-2xl flex items-center justify-center text-canina-blue shadow-sm">
|
||||||
<Heart className="w-6 h-6 fill-current" />
|
<Heart className="w-6 h-6 fill-current" />
|
||||||
</div>
|
</div>
|
||||||
<h4 className="text-lg font-black text-canino-blue italic">خیالت راحت باشه!</h4>
|
<h4 className="text-lg font-black text-canina-blue italic">خیالت راحت باشه!</h4>
|
||||||
</div>
|
</div>
|
||||||
<p className="text-sm font-bold text-canino-blue/80 leading-relaxed">
|
<p className="text-sm font-bold text-canina-blue/80 leading-relaxed">
|
||||||
{activePet ? (
|
{activePet ? (
|
||||||
<>
|
<>
|
||||||
انتخاب درستی برای <span className="text-canino-blue font-black">{activePet.name}</span> کردی.
|
انتخاب درستی برای <span className="text-canina-blue font-black">{activePet.name}</span> کردی.
|
||||||
{hasCanhydrox ? (
|
{hasCanhydrox ? (
|
||||||
` مکمل Canhydrox با فرمول آلمانیاش دقیقاً همون چیزیه که استخوانهای ${activePet.name} برای بازیگوشی دوباره بهش نیاز دارن.`
|
` مکمل Canhydrox با فرمول آلمانیاش دقیقاً همون چیزیه که استخوانهای ${activePet.name} برای بازیگوشی دوباره بهش نیاز دارن.`
|
||||||
) : (
|
) : (
|
||||||
@ -94,13 +94,13 @@ export default function OrderSuccess({ orderId }: { orderId: string }) {
|
|||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<button
|
<button
|
||||||
onClick={() => router.push('/track')}
|
onClick={() => router.push('/track')}
|
||||||
className="w-full bg-medical-gray-900 text-white py-5 rounded-2xl font-black text-lg hover:bg-canino-blue transition-all"
|
className="w-full bg-medical-gray-900 text-white py-5 rounded-2xl font-black text-lg hover:bg-canina-blue transition-all"
|
||||||
>
|
>
|
||||||
مشاهده و پیگیری زنده سفارش
|
مشاهده و پیگیری زنده سفارش
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => router.push('/shop')}
|
onClick={() => router.push('/shop')}
|
||||||
className="flex items-center justify-center gap-2 w-full text-medical-gray-400 font-bold hover:text-canino-blue transition-colors"
|
className="flex items-center justify-center gap-2 w-full text-medical-gray-400 font-bold hover:text-canina-blue transition-colors"
|
||||||
>
|
>
|
||||||
<ChevronLeft className="w-4 h-4" />
|
<ChevronLeft className="w-4 h-4" />
|
||||||
بازگشت به فروشگاه
|
بازگشت به فروشگاه
|
||||||
|
|||||||
@ -44,24 +44,24 @@ export default function OrderTracking() {
|
|||||||
<div className="lg:hidden mb-12 space-y-4">
|
<div className="lg:hidden mb-12 space-y-4">
|
||||||
<button
|
<button
|
||||||
onClick={() => router.back()}
|
onClick={() => router.back()}
|
||||||
className="flex items-center gap-2 text-medical-gray-500 font-bold hover:text-canino-blue transition-colors"
|
className="flex items-center gap-2 text-medical-gray-500 font-bold hover:text-canina-blue transition-colors"
|
||||||
>
|
>
|
||||||
<ChevronRight className="w-5 h-5 font-vazir" />
|
<ChevronRight className="w-5 h-5 font-vazir" />
|
||||||
<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">
|
<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-canino-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-canino-blue">پیگیری سفارش</span>
|
<span className="text-canina-blue">پیگیری سفارش</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Desktop Breadcrumbs */}
|
{/* Desktop Breadcrumbs */}
|
||||||
<div className="hidden lg:flex items-center gap-2 text-[10px] font-black text-medical-gray-400 uppercase tracking-widest mb-12">
|
<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-canino-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-canino-blue">رهگیری هوشمند محموله</span>
|
<span className="text-canina-blue">رهگیری هوشمند محموله</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex items-center justify-between mb-12">
|
<div className="flex items-center justify-between mb-12">
|
||||||
@ -78,12 +78,12 @@ export default function OrderTracking() {
|
|||||||
placeholder="شماره سفارش (CN-XXXXX) یا کد رهگیری پستی را وارد کنید..."
|
placeholder="شماره سفارش (CN-XXXXX) یا کد رهگیری پستی را وارد کنید..."
|
||||||
value={searchId}
|
value={searchId}
|
||||||
onChange={(e) => setSearchId(e.target.value)}
|
onChange={(e) => setSearchId(e.target.value)}
|
||||||
className="w-full bg-medical-gray-50 border border-medical-gray-200 rounded-2xl py-4 pr-12 pl-6 text-sm focus:ring-2 focus:ring-canino-blue/20 outline-none font-mono"
|
className="w-full bg-medical-gray-50 border border-medical-gray-200 rounded-2xl py-4 pr-12 pl-6 text-sm focus:ring-2 focus:ring-canina-blue/20 outline-none font-mono"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
onClick={handleSearch}
|
onClick={handleSearch}
|
||||||
className="bg-medical-gray-900 text-white px-10 py-4 rounded-2xl font-black italic hover:bg-canino-blue transition-all"
|
className="bg-medical-gray-900 text-white px-10 py-4 rounded-2xl font-black italic hover:bg-canina-blue transition-all"
|
||||||
>
|
>
|
||||||
رهگیری آنی
|
رهگیری آنی
|
||||||
</button>
|
</button>
|
||||||
@ -97,7 +97,7 @@ export default function OrderTracking() {
|
|||||||
<div className="flex items-center justify-between mb-12">
|
<div className="flex items-center justify-between mb-12">
|
||||||
<div>
|
<div>
|
||||||
<p className="text-[10px] font-black text-medical-gray-400 uppercase tracking-widest mb-1">کد رهگیری پستی</p>
|
<p className="text-[10px] font-black text-medical-gray-400 uppercase tracking-widest mb-1">کد رهگیری پستی</p>
|
||||||
<p className="text-sm font-mono font-bold text-canino-blue">{activeOrder.trackingNumber}</p>
|
<p className="text-sm font-mono font-bold text-canina-blue">{activeOrder.trackingNumber}</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="text-left">
|
<div className="text-left">
|
||||||
<p className="text-[10px] font-black text-medical-gray-400 uppercase tracking-widest mb-1">تاریخ ثبت</p>
|
<p className="text-[10px] font-black text-medical-gray-400 uppercase tracking-widest mb-1">تاریخ ثبت</p>
|
||||||
@ -110,7 +110,7 @@ export default function OrderTracking() {
|
|||||||
|
|
||||||
{steps.map((step, i) => (
|
{steps.map((step, i) => (
|
||||||
<div key={i} className={`relative flex items-center gap-8 ${step.status === 'pending' ? 'opacity-30' : ''}`}>
|
<div key={i} className={`relative flex items-center gap-8 ${step.status === 'pending' ? 'opacity-30' : ''}`}>
|
||||||
<div className={`w-12 h-12 rounded-2xl flex items-center justify-center z-10 shadow-sm transition-all ${step.status === 'completed' ? 'bg-green-600 text-white' : step.status === 'active' ? 'bg-canino-blue text-white ring-8 ring-canino-blue/10 scale-110' : 'bg-medical-gray-50 text-medical-gray-300 border border-medical-gray-100'}`}>
|
<div className={`w-12 h-12 rounded-2xl flex items-center justify-center z-10 shadow-sm transition-all ${step.status === 'completed' ? 'bg-green-600 text-white' : step.status === 'active' ? 'bg-canina-blue text-white ring-8 ring-canina-blue/10 scale-110' : 'bg-medical-gray-50 text-medical-gray-300 border border-medical-gray-100'}`}>
|
||||||
{step.status === 'completed' ? <CheckCircle2 className="w-6 h-6" /> : step.icon}
|
{step.status === 'completed' ? <CheckCircle2 className="w-6 h-6" /> : step.icon}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
@ -136,13 +136,13 @@ export default function OrderTracking() {
|
|||||||
</div>
|
</div>
|
||||||
<div className="mt-8 pt-6 border-t border-white/10 flex justify-between items-center font-black">
|
<div className="mt-8 pt-6 border-t border-white/10 flex justify-between items-center font-black">
|
||||||
<span className="text-xs italic">مجموع فاکتور</span>
|
<span className="text-xs italic">مجموع فاکتور</span>
|
||||||
<span className="text-lg text-canino-blue">{activeOrder.total.toLocaleString()} تومان</span>
|
<span className="text-lg text-canina-blue">{activeOrder.total.toLocaleString()} تومان</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="bg-white rounded-[2rem] p-6 border border-medical-gray-200">
|
<div className="bg-white rounded-[2rem] p-6 border border-medical-gray-200">
|
||||||
<div className="flex items-center gap-3 mb-4">
|
<div className="flex items-center gap-3 mb-4">
|
||||||
<div className="w-10 h-10 bg-canino-blue/10 text-canino-blue rounded-xl flex items-center justify-center">
|
<div className="w-10 h-10 bg-canina-blue/10 text-canina-blue rounded-xl flex items-center justify-center">
|
||||||
<MapPin className="w-5 h-5" />
|
<MapPin className="w-5 h-5" />
|
||||||
</div>
|
</div>
|
||||||
<h4 className="text-xs font-black italic">آدرس تحویل</h4>
|
<h4 className="text-xs font-black italic">آدرس تحویل</h4>
|
||||||
|
|||||||
@ -285,7 +285,7 @@ export default function PetProfile({ initialView, advisorNeed }: {
|
|||||||
setView("add");
|
setView("add");
|
||||||
setStep(1);
|
setStep(1);
|
||||||
}}
|
}}
|
||||||
className="bg-canino-blue text-white px-8 py-4 rounded-[2rem] font-black shadow-xl shadow-canino-blue/20 hover:scale-105 transition-all flex items-center gap-3"
|
className="bg-canina-blue text-white px-8 py-4 rounded-[2rem] font-black shadow-xl shadow-canina-blue/20 hover:scale-105 transition-all flex items-center gap-3"
|
||||||
>
|
>
|
||||||
<Plus className="w-5 h-5" />
|
<Plus className="w-5 h-5" />
|
||||||
صدور شناسنامه جدید
|
صدور شناسنامه جدید
|
||||||
@ -299,7 +299,7 @@ export default function PetProfile({ initialView, advisorNeed }: {
|
|||||||
whileHover={{ y: -5 }}
|
whileHover={{ y: -5 }}
|
||||||
className="bg-white rounded-[3rem] border border-medical-gray-200 p-8 shadow-sm hover:shadow-2xl transition-all relative group"
|
className="bg-white rounded-[3rem] border border-medical-gray-200 p-8 shadow-sm hover:shadow-2xl transition-all relative group"
|
||||||
>
|
>
|
||||||
<div className="w-24 h-24 bg-medical-gray-50 rounded-[2rem] flex items-center justify-center text-canino-blue mb-6 group-hover:bg-canino-blue group-hover:text-white transition-all shadow-inner">
|
<div className="w-24 h-24 bg-medical-gray-50 rounded-[2rem] flex items-center justify-center text-canina-blue mb-6 group-hover:bg-canina-blue group-hover:text-white transition-all shadow-inner">
|
||||||
{pet.type === "سگ" ? <Dog className="w-12 h-12" /> : <Cat className="w-12 h-12" />}
|
{pet.type === "سگ" ? <Dog className="w-12 h-12" /> : <Cat className="w-12 h-12" />}
|
||||||
</div>
|
</div>
|
||||||
<h3 className="text-2xl font-black text-medical-gray-900 mb-1">{pet.name}</h3>
|
<h3 className="text-2xl font-black text-medical-gray-900 mb-1">{pet.name}</h3>
|
||||||
@ -318,7 +318,7 @@ export default function PetProfile({ initialView, advisorNeed }: {
|
|||||||
|
|
||||||
<button
|
<button
|
||||||
onClick={() => { setActivePet(pet.id); setView("detail"); }}
|
onClick={() => { setActivePet(pet.id); setView("detail"); }}
|
||||||
className="w-full py-4 bg-medical-gray-900 text-white rounded-2xl font-black hover:bg-canino-blue transition-all flex items-center justify-center gap-2 group-hover:shadow-lg"
|
className="w-full py-4 bg-medical-gray-900 text-white rounded-2xl font-black hover:bg-canina-blue transition-all flex items-center justify-center gap-2 group-hover:shadow-lg"
|
||||||
>
|
>
|
||||||
مشاهده شناسنامه سلامت
|
مشاهده شناسنامه سلامت
|
||||||
<ChevronLeft className="w-4 h-4" />
|
<ChevronLeft className="w-4 h-4" />
|
||||||
@ -390,7 +390,7 @@ export default function PetProfile({ initialView, advisorNeed }: {
|
|||||||
{/* Progress Bar */}
|
{/* Progress Bar */}
|
||||||
<div className="absolute top-0 left-0 w-full h-1.5 bg-medical-gray-100 font-vazir">
|
<div className="absolute top-0 left-0 w-full h-1.5 bg-medical-gray-100 font-vazir">
|
||||||
<motion.div
|
<motion.div
|
||||||
className="h-full bg-canino-blue"
|
className="h-full bg-canina-blue"
|
||||||
initial={{ width: "0%" }}
|
initial={{ width: "0%" }}
|
||||||
animate={{ width: `${(step / 3) * 100}%` }}
|
animate={{ width: `${(step / 3) * 100}%` }}
|
||||||
/>
|
/>
|
||||||
@ -401,7 +401,7 @@ export default function PetProfile({ initialView, advisorNeed }: {
|
|||||||
<h2 className="text-3xl font-black text-medical-gray-900">{view === "edit" ? "ویرایش شناسنامه" : "صدور شناسنامه سلامت"}</h2>
|
<h2 className="text-3xl font-black text-medical-gray-900">{view === "edit" ? "ویرایش شناسنامه" : "صدور شناسنامه سلامت"}</h2>
|
||||||
<p className="text-medical-gray-500 mt-2 font-medium">مرحله {toPersian(step)} از {toPersian(3)}: بروزرسانی اطلاعات تخصصی</p>
|
<p className="text-medical-gray-500 mt-2 font-medium">مرحله {toPersian(step)} از {toPersian(3)}: بروزرسانی اطلاعات تخصصی</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="w-16 h-16 bg-canino-blue/10 rounded-2xl flex items-center justify-center text-canino-blue">
|
<div className="w-16 h-16 bg-canina-blue/10 rounded-2xl flex items-center justify-center text-canina-blue">
|
||||||
<ClipboardList className="w-8 h-8" />
|
<ClipboardList className="w-8 h-8" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -422,7 +422,7 @@ export default function PetProfile({ initialView, advisorNeed }: {
|
|||||||
type="text"
|
type="text"
|
||||||
value={formData.name}
|
value={formData.name}
|
||||||
onChange={e => setFormData({ ...formData, name: e.target.value })}
|
onChange={e => setFormData({ ...formData, name: e.target.value })}
|
||||||
className="w-full bg-medical-gray-50 border border-medical-gray-200 rounded-2xl py-4 px-6 focus:ring-2 focus:ring-canino-blue/20 outline-none font-black text-lg"
|
className="w-full bg-medical-gray-50 border border-medical-gray-200 rounded-2xl py-4 px-6 focus:ring-2 focus:ring-canina-blue/20 outline-none font-black text-lg"
|
||||||
placeholder="مثلاً: لوسی"
|
placeholder="مثلاً: لوسی"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@ -431,14 +431,14 @@ export default function PetProfile({ initialView, advisorNeed }: {
|
|||||||
<div className="grid grid-cols-2 gap-4">
|
<div className="grid grid-cols-2 gap-4">
|
||||||
<button
|
<button
|
||||||
onClick={() => setFormData({ ...formData, type: "سگ" })}
|
onClick={() => setFormData({ ...formData, type: "سگ" })}
|
||||||
className={`flex items-center justify-center gap-3 py-4 border-2 rounded-2xl transition-all ${formData.type === "سگ" ? 'border-canino-blue bg-canino-blue/5 text-canino-blue font-black' : 'border-medical-gray-200 text-medical-gray-400 font-bold'}`}
|
className={`flex items-center justify-center gap-3 py-4 border-2 rounded-2xl transition-all ${formData.type === "سگ" ? 'border-canina-blue bg-canina-blue/5 text-canina-blue font-black' : 'border-medical-gray-200 text-medical-gray-400 font-bold'}`}
|
||||||
>
|
>
|
||||||
<Dog className="w-6 h-6" />
|
<Dog className="w-6 h-6" />
|
||||||
سگ
|
سگ
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => setFormData({ ...formData, type: "گربه" })}
|
onClick={() => setFormData({ ...formData, type: "گربه" })}
|
||||||
className={`flex items-center justify-center gap-3 py-4 border-2 rounded-2xl transition-all ${formData.type === "گربه" ? 'border-canino-blue bg-canino-blue/5 text-canino-blue font-black' : 'border-medical-gray-200 text-medical-gray-400 font-bold'}`}
|
className={`flex items-center justify-center gap-3 py-4 border-2 rounded-2xl transition-all ${formData.type === "گربه" ? 'border-canina-blue bg-canina-blue/5 text-canina-blue font-black' : 'border-medical-gray-200 text-medical-gray-400 font-bold'}`}
|
||||||
>
|
>
|
||||||
<Cat className="w-6 h-6" />
|
<Cat className="w-6 h-6" />
|
||||||
گربه
|
گربه
|
||||||
@ -451,7 +451,7 @@ export default function PetProfile({ initialView, advisorNeed }: {
|
|||||||
type="text"
|
type="text"
|
||||||
value={formData.breed}
|
value={formData.breed}
|
||||||
onChange={e => setFormData({ ...formData, breed: e.target.value })}
|
onChange={e => setFormData({ ...formData, breed: e.target.value })}
|
||||||
className="w-full bg-medical-gray-50 border border-medical-gray-200 rounded-2xl py-4 px-6 focus:ring-2 focus:ring-canino-blue/20 outline-none font-bold"
|
className="w-full bg-medical-gray-50 border border-medical-gray-200 rounded-2xl py-4 px-6 focus:ring-2 focus:ring-canina-blue/20 outline-none font-bold"
|
||||||
placeholder="آلمانی، پرشین، میکس و..."
|
placeholder="آلمانی، پرشین، میکس و..."
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@ -473,7 +473,7 @@ export default function PetProfile({ initialView, advisorNeed }: {
|
|||||||
type="number"
|
type="number"
|
||||||
value={formData.age || ""}
|
value={formData.age || ""}
|
||||||
onChange={e => setFormData({ ...formData, age: parseInt(e.target.value) })}
|
onChange={e => setFormData({ ...formData, age: parseInt(e.target.value) })}
|
||||||
className="w-full bg-medical-gray-50 border border-medical-gray-200 rounded-2xl py-4 px-6 focus:ring-2 focus:ring-canino-blue/20 outline-none font-black text-lg"
|
className="w-full bg-medical-gray-50 border border-medical-gray-200 rounded-2xl py-4 px-6 focus:ring-2 focus:ring-canina-blue/20 outline-none font-black text-lg"
|
||||||
placeholder="۳"
|
placeholder="۳"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@ -484,7 +484,7 @@ export default function PetProfile({ initialView, advisorNeed }: {
|
|||||||
type="number"
|
type="number"
|
||||||
value={formData.weight || ""}
|
value={formData.weight || ""}
|
||||||
onChange={e => setFormData({ ...formData, weight: parseFloat(e.target.value) })}
|
onChange={e => setFormData({ ...formData, weight: parseFloat(e.target.value) })}
|
||||||
className="w-full bg-medical-gray-50 border border-medical-gray-200 rounded-2xl py-4 pr-6 pl-12 focus:ring-2 focus:ring-canino-blue/20 outline-none font-black text-lg"
|
className="w-full bg-medical-gray-50 border border-medical-gray-200 rounded-2xl py-4 pr-6 pl-12 focus:ring-2 focus:ring-canina-blue/20 outline-none font-black text-lg"
|
||||||
/>
|
/>
|
||||||
<Weight className="absolute left-4 top-1/2 -translate-y-1/2 w-5 h-5 text-medical-gray-400" />
|
<Weight className="absolute left-4 top-1/2 -translate-y-1/2 w-5 h-5 text-medical-gray-400" />
|
||||||
</div>
|
</div>
|
||||||
@ -497,7 +497,7 @@ export default function PetProfile({ initialView, advisorNeed }: {
|
|||||||
<button
|
<button
|
||||||
key={level}
|
key={level}
|
||||||
onClick={() => setFormData({ ...formData, activityLevel: level as any })}
|
onClick={() => setFormData({ ...formData, activityLevel: level as any })}
|
||||||
className={`py-4 border-2 rounded-2xl transition-all text-sm font-black italic ${formData.activityLevel === level ? 'border-canino-blue bg-canino-blue/5 text-canino-blue shadow-lg shadow-canino-blue/10' : 'border-medical-gray-100 text-medical-gray-400'}`}
|
className={`py-4 border-2 rounded-2xl transition-all text-sm font-black italic ${formData.activityLevel === level ? 'border-canina-blue bg-canina-blue/5 text-canina-blue shadow-lg shadow-canina-blue/10' : 'border-medical-gray-100 text-medical-gray-400'}`}
|
||||||
>
|
>
|
||||||
{level}
|
{level}
|
||||||
</button>
|
</button>
|
||||||
@ -536,9 +536,9 @@ export default function PetProfile({ initialView, advisorNeed }: {
|
|||||||
: [...current, condition]
|
: [...current, condition]
|
||||||
})
|
})
|
||||||
}}
|
}}
|
||||||
className={`flex items-center gap-4 p-4 border-2 rounded-2xl transition-all ${formData.medicalConditions.includes(condition) ? 'border-canino-blue bg-canino-blue/5 text-canino-blue' : 'border-medical-gray-50 text-medical-gray-500'}`}
|
className={`flex items-center gap-4 p-4 border-2 rounded-2xl transition-all ${formData.medicalConditions.includes(condition) ? 'border-canina-blue bg-canina-blue/5 text-canina-blue' : 'border-medical-gray-50 text-medical-gray-500'}`}
|
||||||
>
|
>
|
||||||
<div className={`w-6 h-6 rounded-lg flex items-center justify-center border ${formData.medicalConditions.includes(condition) ? 'bg-canino-blue border-canino-blue text-white' : 'border-medical-gray-200'}`}>
|
<div className={`w-6 h-6 rounded-lg flex items-center justify-center border ${formData.medicalConditions.includes(condition) ? 'bg-canina-blue border-canina-blue text-white' : 'border-medical-gray-200'}`}>
|
||||||
{formData.medicalConditions.includes(condition) && <ShieldCheck className="w-3.5 h-3.5" />}
|
{formData.medicalConditions.includes(condition) && <ShieldCheck className="w-3.5 h-3.5" />}
|
||||||
</div>
|
</div>
|
||||||
<span className="font-black text-sm italic">{condition}</span>
|
<span className="font-black text-sm italic">{condition}</span>
|
||||||
@ -556,7 +556,7 @@ export default function PetProfile({ initialView, advisorNeed }: {
|
|||||||
else if (pets.length > 0) setView("index");
|
else if (pets.length > 0) setView("index");
|
||||||
else router.back();
|
else router.back();
|
||||||
}}
|
}}
|
||||||
className="absolute top-8 left-8 text-medical-gray-400 hover:text-canino-blue transition-colors text-[10px] font-black uppercase tracking-widest"
|
className="absolute top-8 left-8 text-medical-gray-400 hover:text-canina-blue transition-colors text-[10px] font-black uppercase tracking-widest"
|
||||||
>
|
>
|
||||||
انصراف
|
انصراف
|
||||||
</button>
|
</button>
|
||||||
@ -572,7 +572,7 @@ export default function PetProfile({ initialView, advisorNeed }: {
|
|||||||
<button
|
<button
|
||||||
onClick={step === 3 ? handleSubmit : handleNext}
|
onClick={step === 3 ? handleSubmit : handleNext}
|
||||||
disabled={step === 1 && (!formData.name || !formData.type)}
|
disabled={step === 1 && (!formData.name || !formData.type)}
|
||||||
className="flex-[2] bg-medical-gray-900 text-white py-4 rounded-2xl font-black flex items-center justify-center gap-2 disabled:opacity-50 hover:bg-canino-blue transition-all"
|
className="flex-[2] bg-medical-gray-900 text-white py-4 rounded-2xl font-black flex items-center justify-center gap-2 disabled:opacity-50 hover:bg-canina-blue transition-all"
|
||||||
>
|
>
|
||||||
{step === 3 ? (view === "edit" ? "ذخیره تغییرات" : "مشاهده پرونده سلامت") : "گام بعدی"}
|
{step === 3 ? (view === "edit" ? "ذخیره تغییرات" : "مشاهده پرونده سلامت") : "گام بعدی"}
|
||||||
<ChevronLeft className="w-5 h-5" />
|
<ChevronLeft className="w-5 h-5" />
|
||||||
@ -594,21 +594,21 @@ export default function PetProfile({ initialView, advisorNeed }: {
|
|||||||
{/* Navigation Bar */}
|
{/* Navigation Bar */}
|
||||||
<div className="flex flex-col md:flex-row justify-between items-start md:items-center gap-6">
|
<div className="flex flex-col md:flex-row justify-between items-start md:items-center gap-6">
|
||||||
<div className="flex items-center gap-2 text-[10px] font-black text-medical-gray-400 uppercase tracking-widest">
|
<div className="flex items-center gap-2 text-[10px] font-black text-medical-gray-400 uppercase tracking-widest">
|
||||||
<span className="cursor-pointer hover:text-canino-blue" onClick={() => setView("index")}>همدمهای من</span>
|
<span className="cursor-pointer hover:text-canina-blue" onClick={() => setView("index")}>همدمهای من</span>
|
||||||
<ChevronLeft className="w-3 h-3" />
|
<ChevronLeft className="w-3 h-3" />
|
||||||
<span className="text-canino-blue">پرونده سلامت {activePet?.name}</span>
|
<span className="text-canina-blue">پرونده سلامت {activePet?.name}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex gap-3">
|
<div className="flex gap-3">
|
||||||
<button
|
<button
|
||||||
onClick={() => setView("index")}
|
onClick={() => setView("index")}
|
||||||
className="px-6 py-2.5 bg-white border border-medical-gray-200 rounded-xl text-[10px] font-black uppercase tracking-widest hover:border-canino-blue transition-all"
|
className="px-6 py-2.5 bg-white border border-medical-gray-200 rounded-xl text-[10px] font-black uppercase tracking-widest hover:border-canina-blue transition-all"
|
||||||
>
|
>
|
||||||
بازگشت به لیست
|
بازگشت به لیست
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={startEdit}
|
onClick={startEdit}
|
||||||
className="px-6 py-2.5 bg-canino-blue text-white rounded-xl text-[10px] font-black uppercase tracking-widest shadow-lg shadow-canino-blue/20 hover:scale-105 transition-all flex items-center gap-2"
|
className="px-6 py-2.5 bg-canina-blue text-white rounded-xl text-[10px] font-black uppercase tracking-widest shadow-lg shadow-canina-blue/20 hover:scale-105 transition-all flex items-center gap-2"
|
||||||
>
|
>
|
||||||
<Edit3 className="w-3.5 h-3.5" />
|
<Edit3 className="w-3.5 h-3.5" />
|
||||||
ویرایش پرونده
|
ویرایش پرونده
|
||||||
@ -619,10 +619,10 @@ export default function PetProfile({ initialView, advisorNeed }: {
|
|||||||
{/* Profile Card */}
|
{/* Profile Card */}
|
||||||
<section className="grid lg:grid-cols-3 gap-8">
|
<section className="grid lg:grid-cols-3 gap-8">
|
||||||
<div className="lg:col-span-2 bg-white rounded-[3.5rem] p-10 border border-medical-gray-200 shadow-xl flex flex-col md:flex-row gap-10 items-center relative overflow-hidden">
|
<div className="lg:col-span-2 bg-white rounded-[3.5rem] p-10 border border-medical-gray-200 shadow-xl flex flex-col md:flex-row gap-10 items-center relative overflow-hidden">
|
||||||
<div className="absolute top-0 left-0 w-32 h-32 bg-canino-blue/5 rounded-full blur-[60px] -translate-x-1/2 -translate-y-1/2" />
|
<div className="absolute top-0 left-0 w-32 h-32 bg-canina-blue/5 rounded-full blur-[60px] -translate-x-1/2 -translate-y-1/2" />
|
||||||
|
|
||||||
<div className="w-44 h-44 rounded-[2.5rem] bg-gradient-to-tr from-canino-blue to-blue-400 p-1 flex-shrink-0 shadow-2xl">
|
<div className="w-44 h-44 rounded-[2.5rem] bg-gradient-to-tr from-canina-blue to-blue-400 p-1 flex-shrink-0 shadow-2xl">
|
||||||
<div className="w-full h-full bg-white rounded-[2.2rem] flex items-center justify-center text-canino-blue">
|
<div className="w-full h-full bg-white rounded-[2.2rem] flex items-center justify-center text-canina-blue">
|
||||||
{activePet.type === "سگ" ? <Dog className="w-24 h-24" /> : <Cat className="w-24 h-24" />}
|
{activePet.type === "سگ" ? <Dog className="w-24 h-24" /> : <Cat className="w-24 h-24" />}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -652,7 +652,7 @@ export default function PetProfile({ initialView, advisorNeed }: {
|
|||||||
|
|
||||||
<div className="flex flex-wrap gap-2">
|
<div className="flex flex-wrap gap-2">
|
||||||
{activePet.medicalConditions.map(c => (
|
{activePet.medicalConditions.map(c => (
|
||||||
<div key={c} className="bg-canino-blue text-white px-4 py-2 rounded-xl text-[10px] font-bold border border-white/10 flex items-center gap-2 shadow-sm">
|
<div key={c} className="bg-canina-blue text-white px-4 py-2 rounded-xl text-[10px] font-bold border border-white/10 flex items-center gap-2 shadow-sm">
|
||||||
<Stethoscope className="w-3 h-3" />
|
<Stethoscope className="w-3 h-3" />
|
||||||
{c}
|
{c}
|
||||||
</div>
|
</div>
|
||||||
@ -661,7 +661,7 @@ export default function PetProfile({ initialView, advisorNeed }: {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="bg-canino-blue rounded-[3.5rem] p-10 text-white flex flex-col justify-between relative overflow-hidden shadow-2xl group">
|
<div className="bg-canina-blue rounded-[3.5rem] p-10 text-white flex flex-col justify-between relative overflow-hidden shadow-2xl group">
|
||||||
<div className="absolute top-0 right-0 p-8 opacity-20 group-hover:rotate-12 transition-transform duration-700">
|
<div className="absolute top-0 right-0 p-8 opacity-20 group-hover:rotate-12 transition-transform duration-700">
|
||||||
<Activity className="w-16 h-16 text-white" />
|
<Activity className="w-16 h-16 text-white" />
|
||||||
</div>
|
</div>
|
||||||
@ -712,10 +712,10 @@ export default function PetProfile({ initialView, advisorNeed }: {
|
|||||||
|
|
||||||
{/* Refill & Stock Tracking */}
|
{/* Refill & Stock Tracking */}
|
||||||
<section className="bg-white rounded-[3.5rem] p-10 border border-medical-gray-200 shadow-sm relative overflow-hidden">
|
<section className="bg-white rounded-[3.5rem] p-10 border border-medical-gray-200 shadow-sm relative overflow-hidden">
|
||||||
<div className="absolute top-0 left-0 w-full h-1 bg-gradient-to-r from-canino-blue to-blue-300" />
|
<div className="absolute top-0 left-0 w-full h-1 bg-gradient-to-r from-canina-blue to-blue-300" />
|
||||||
<div className="flex items-center justify-between mb-8">
|
<div className="flex items-center justify-between mb-8">
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
<Package className="w-8 h-8 text-canino-blue" />
|
<Package className="w-8 h-8 text-canina-blue" />
|
||||||
<h3 className="text-2xl font-black text-medical-gray-900 italic">پایش موجودی مکملها</h3>
|
<h3 className="text-2xl font-black text-medical-gray-900 italic">پایش موجودی مکملها</h3>
|
||||||
</div>
|
</div>
|
||||||
<div className="text-[10px] font-black text-medical-gray-400 uppercase tracking-widest hidden md:block">بروزرسانی لحظهای بر اساس مصرف</div>
|
<div className="text-[10px] font-black text-medical-gray-400 uppercase tracking-widest hidden md:block">بروزرسانی لحظهای بر اساس مصرف</div>
|
||||||
@ -744,7 +744,7 @@ export default function PetProfile({ initialView, advisorNeed }: {
|
|||||||
</div>
|
</div>
|
||||||
<div className={cn(
|
<div className={cn(
|
||||||
"w-12 h-12 rounded-2xl flex items-center justify-center font-black text-xs",
|
"w-12 h-12 rounded-2xl flex items-center justify-center font-black text-xs",
|
||||||
isLow ? "bg-red-50 text-red-500 animate-pulse" : "bg-white text-canino-blue shadow-inner"
|
isLow ? "bg-red-50 text-red-500 animate-pulse" : "bg-white text-canina-blue shadow-inner"
|
||||||
)}>
|
)}>
|
||||||
{toPersian(Math.round(percentage))}%
|
{toPersian(Math.round(percentage))}%
|
||||||
</div>
|
</div>
|
||||||
@ -754,7 +754,7 @@ export default function PetProfile({ initialView, advisorNeed }: {
|
|||||||
<motion.div
|
<motion.div
|
||||||
initial={{ width: 0 }}
|
initial={{ width: 0 }}
|
||||||
animate={{ width: `${Math.min(100, Math.max(0, percentage))}%` }}
|
animate={{ width: `${Math.min(100, Math.max(0, percentage))}%` }}
|
||||||
className={cn("h-full", isLow ? "bg-red-500" : "bg-canino-blue")}
|
className={cn("h-full", isLow ? "bg-red-500" : "bg-canina-blue")}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -783,11 +783,11 @@ export default function PetProfile({ initialView, advisorNeed }: {
|
|||||||
<button
|
<button
|
||||||
key={tab.id}
|
key={tab.id}
|
||||||
onClick={() => setActivePetTab(tab.id as any)}
|
onClick={() => setActivePetTab(tab.id as any)}
|
||||||
className={`pb-4 flex items-center gap-2 text-sm font-black transition-all relative ${activePetTab === tab.id ? "text-canino-blue" : "text-medical-gray-400 hover:text-medical-gray-600"}`}
|
className={`pb-4 flex items-center gap-2 text-sm font-black transition-all relative ${activePetTab === tab.id ? "text-canina-blue" : "text-medical-gray-400 hover:text-medical-gray-600"}`}
|
||||||
>
|
>
|
||||||
{tab.icon}
|
{tab.icon}
|
||||||
{tab.label}
|
{tab.label}
|
||||||
{activePetTab === tab.id && <motion.div layoutId="petTab" className="absolute bottom-0 left-0 right-0 h-1 bg-canino-blue rounded-full" />}
|
{activePetTab === tab.id && <motion.div layoutId="petTab" className="absolute bottom-0 left-0 right-0 h-1 bg-canina-blue rounded-full" />}
|
||||||
</button>
|
</button>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
@ -798,7 +798,7 @@ export default function PetProfile({ initialView, advisorNeed }: {
|
|||||||
<section>
|
<section>
|
||||||
<div className="flex items-center justify-between mb-8 px-4">
|
<div className="flex items-center justify-between mb-8 px-4">
|
||||||
<div className="flex items-center gap-4">
|
<div className="flex items-center gap-4">
|
||||||
<div className="w-12 h-12 bg-white rounded-2xl flex items-center justify-center text-canino-blue shadow-lg border border-medical-gray-100">
|
<div className="w-12 h-12 bg-white rounded-2xl flex items-center justify-center text-canina-blue shadow-lg border border-medical-gray-100">
|
||||||
<Star className="w-6 h-6" />
|
<Star className="w-6 h-6" />
|
||||||
</div>
|
</div>
|
||||||
<h3 className="text-3xl font-black text-medical-gray-900 italic">توصیههای درمانی اختصاصی</h3>
|
<h3 className="text-3xl font-black text-medical-gray-900 italic">توصیههای درمانی اختصاصی</h3>
|
||||||
@ -817,17 +817,17 @@ export default function PetProfile({ initialView, advisorNeed }: {
|
|||||||
className="bg-white rounded-[2.5rem] p-6 border border-medical-gray-200 hover:shadow-2xl transition-all cursor-pointer group flex flex-col justify-between relative overflow-hidden"
|
className="bg-white rounded-[2.5rem] p-6 border border-medical-gray-200 hover:shadow-2xl transition-all cursor-pointer group flex flex-col justify-between relative overflow-hidden"
|
||||||
>
|
>
|
||||||
{reason && (
|
{reason && (
|
||||||
<div className="absolute top-0 left-0 right-0 bg-canino-blue/10 py-2 px-4 text-[9px] font-black text-canino-blue text-center border-b border-canino-blue/10">
|
<div className="absolute top-0 left-0 right-0 bg-canina-blue/10 py-2 px-4 text-[9px] font-black text-canina-blue text-center border-b border-canina-blue/10">
|
||||||
{reason}
|
{reason}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div className={cn("aspect-square bg-medical-gray-50 rounded-[1.5rem] p-6 mb-6 flex items-center justify-center overflow-hidden", reason ? "mt-8" : "")}>
|
<div className={cn("aspect-square bg-medical-gray-50 rounded-[1.5rem] p-6 mb-6 flex items-center justify-center overflow-hidden", reason ? "mt-8" : "")}>
|
||||||
<SafeImage src={p.image} alt={p.name} className="w-full h-full object-contain group-hover:scale-110 transition-transform duration-500" />
|
<SafeImage src={p.image} alt={p.name} className="w-full h-full group-hover:scale-110 transition-transform duration-500" imgClassName="object-contain" />
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<h4 className="text-lg font-black text-medical-gray-900 group-hover:text-canino-blue transition-colors mb-2 italic">{p.name}</h4>
|
<h4 className="text-lg font-black text-medical-gray-900 group-hover:text-canina-blue transition-colors mb-2 italic">{p.name}</h4>
|
||||||
<p className="text-xs text-medical-gray-400 line-clamp-2 leading-relaxed mb-6 font-medium">{p.benefits}</p>
|
<p className="text-xs text-medical-gray-400 line-clamp-2 leading-relaxed mb-6 font-medium">{p.benefits}</p>
|
||||||
<button className="w-full py-3.5 bg-medical-gray-900 text-white rounded-xl text-[10px] font-black uppercase tracking-widest group-hover:bg-canino-blue transition-colors flex items-center justify-center gap-2">
|
<button className="w-full py-3.5 bg-medical-gray-900 text-white rounded-xl text-[10px] font-black uppercase tracking-widest group-hover:bg-canina-blue transition-colors flex items-center justify-center gap-2">
|
||||||
بررسی تخصصی
|
بررسی تخصصی
|
||||||
<ChevronLeft className="w-3.5 h-3.5" />
|
<ChevronLeft className="w-3.5 h-3.5" />
|
||||||
</button>
|
</button>
|
||||||
@ -842,7 +842,7 @@ export default function PetProfile({ initialView, advisorNeed }: {
|
|||||||
<div className="bg-white rounded-[3rem] border border-medical-gray-200 p-10 shadow-sm">
|
<div className="bg-white rounded-[3rem] border border-medical-gray-200 p-10 shadow-sm">
|
||||||
<div className="flex items-center justify-between mb-10">
|
<div className="flex items-center justify-between mb-10">
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
<Clock className="w-8 h-8 text-canino-blue" />
|
<Clock className="w-8 h-8 text-canina-blue" />
|
||||||
<h3 className="text-2xl font-black text-medical-gray-900 italic">یادآورهای فعال</h3>
|
<h3 className="text-2xl font-black text-medical-gray-900 italic">یادآورهای فعال</h3>
|
||||||
</div>
|
</div>
|
||||||
<TrendingUp className="w-6 h-6 text-green-500" />
|
<TrendingUp className="w-6 h-6 text-green-500" />
|
||||||
@ -863,7 +863,7 @@ export default function PetProfile({ initialView, advisorNeed }: {
|
|||||||
key={reminder.id}
|
key={reminder.id}
|
||||||
className={cn(
|
className={cn(
|
||||||
"flex items-center justify-between p-5 rounded-2xl border transition-all group",
|
"flex items-center justify-between p-5 rounded-2xl border transition-all group",
|
||||||
isCompleted ? "bg-green-50 border-green-200" : "bg-medical-gray-50 border-medical-gray-100 hover:border-canino-blue/30"
|
isCompleted ? "bg-green-50 border-green-200" : "bg-medical-gray-50 border-medical-gray-100 hover:border-canina-blue/30"
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<div className="flex items-center gap-4">
|
<div className="flex items-center gap-4">
|
||||||
@ -871,7 +871,7 @@ export default function PetProfile({ initialView, advisorNeed }: {
|
|||||||
onClick={() => handleToggleReminder(reminder)}
|
onClick={() => handleToggleReminder(reminder)}
|
||||||
className={cn(
|
className={cn(
|
||||||
"w-10 h-10 rounded-xl flex items-center justify-center shadow-inner transition-colors",
|
"w-10 h-10 rounded-xl flex items-center justify-center shadow-inner transition-colors",
|
||||||
isCompleted ? "bg-green-500 text-white" : "bg-white text-medical-gray-300 hover:text-canino-blue"
|
isCompleted ? "bg-green-500 text-white" : "bg-white text-medical-gray-300 hover:text-canina-blue"
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{isCompleted ? <Check className="w-5 h-5" /> : <Clock className="w-5 h-5" />}
|
{isCompleted ? <Check className="w-5 h-5" /> : <Clock className="w-5 h-5" />}
|
||||||
@ -892,7 +892,7 @@ export default function PetProfile({ initialView, advisorNeed }: {
|
|||||||
|
|
||||||
<button
|
<button
|
||||||
onClick={() => setIsAddingReminder(true)}
|
onClick={() => setIsAddingReminder(true)}
|
||||||
className="w-full mt-8 py-5 border-2 border-dashed border-medical-gray-200 rounded-2xl text-medical-gray-400 font-black hover:border-canino-blue hover:text-canino-blue transition-all flex items-center justify-center gap-2"
|
className="w-full mt-8 py-5 border-2 border-dashed border-medical-gray-200 rounded-2xl text-medical-gray-400 font-black hover:border-canina-blue hover:text-canina-blue transition-all flex items-center justify-center gap-2"
|
||||||
>
|
>
|
||||||
<Plus className="w-4 h-4" />
|
<Plus className="w-4 h-4" />
|
||||||
افزودن یادآور جدید
|
افزودن یادآور جدید
|
||||||
@ -902,7 +902,7 @@ export default function PetProfile({ initialView, advisorNeed }: {
|
|||||||
{/* Health Logs */}
|
{/* Health Logs */}
|
||||||
<div className="bg-white rounded-[3rem] border border-medical-gray-200 p-10 shadow-sm">
|
<div className="bg-white rounded-[3rem] border border-medical-gray-200 p-10 shadow-sm">
|
||||||
<div className="flex items-center gap-3 mb-10">
|
<div className="flex items-center gap-3 mb-10">
|
||||||
<ClipboardList className="w-8 h-8 text-canino-blue" />
|
<ClipboardList className="w-8 h-8 text-canina-blue" />
|
||||||
<h3 className="text-2xl font-black text-medical-gray-900 italic">تایملاین سلامت</h3>
|
<h3 className="text-2xl font-black text-medical-gray-900 italic">تایملاین سلامت</h3>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -919,7 +919,7 @@ export default function PetProfile({ initialView, advisorNeed }: {
|
|||||||
{toPersian(new Date(log.date).toLocaleDateString("fa-IR"))}
|
{toPersian(new Date(log.date).toLocaleDateString("fa-IR"))}
|
||||||
</div>
|
</div>
|
||||||
<div className="flex gap-2">
|
<div className="flex gap-2">
|
||||||
<div className="px-2 py-0.5 bg-canino-blue/10 text-canino-blue rounded-full text-[8px] font-black">{log.appetite}</div>
|
<div className="px-2 py-0.5 bg-canina-blue/10 text-canina-blue rounded-full text-[8px] font-black">{log.appetite}</div>
|
||||||
<div className="px-2 py-0.5 bg-green-500/10 text-green-500 rounded-full text-[8px] font-black">{log.energy}</div>
|
<div className="px-2 py-0.5 bg-green-500/10 text-green-500 rounded-full text-[8px] font-black">{log.energy}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -933,7 +933,7 @@ export default function PetProfile({ initialView, advisorNeed }: {
|
|||||||
|
|
||||||
<button
|
<button
|
||||||
onClick={() => setIsAddingHealthLog(true)}
|
onClick={() => setIsAddingHealthLog(true)}
|
||||||
className="w-full mt-8 py-5 bg-canino-blue text-white rounded-2xl font-black hover:bg-medical-gray-900 transition-all shadow-xl shadow-canino-blue/20"
|
className="w-full mt-8 py-5 bg-canina-blue text-white rounded-2xl font-black hover:bg-medical-gray-900 transition-all shadow-xl shadow-canina-blue/20"
|
||||||
>
|
>
|
||||||
ثبت گزارش روزانه جدید
|
ثبت گزارش روزانه جدید
|
||||||
</button>
|
</button>
|
||||||
@ -958,7 +958,7 @@ export default function PetProfile({ initialView, advisorNeed }: {
|
|||||||
</div>
|
</div>
|
||||||
<div className="text-left">
|
<div className="text-left">
|
||||||
<div className="text-[10px] font-black text-medical-gray-400 uppercase tracking-widest">مجموع هزینه درمانی</div>
|
<div className="text-[10px] font-black text-medical-gray-400 uppercase tracking-widest">مجموع هزینه درمانی</div>
|
||||||
<div className="text-2xl font-black text-canino-blue">{toPersian(petOrders.reduce((a, b) => a + b.total, 0).toLocaleString())} <span className="text-xs italic">تومان</span></div>
|
<div className="text-2xl font-black text-canina-blue">{toPersian(petOrders.reduce((a, b) => a + b.total, 0).toLocaleString())} <span className="text-xs italic">تومان</span></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -968,7 +968,7 @@ export default function PetProfile({ initialView, advisorNeed }: {
|
|||||||
<Package className="w-12 h-12" />
|
<Package className="w-12 h-12" />
|
||||||
</div>
|
</div>
|
||||||
<p className="text-medical-gray-400 font-black text-xl italic">هنوز سفارشی برای {activePet.name} ثبت نکردهاید.</p>
|
<p className="text-medical-gray-400 font-black text-xl italic">هنوز سفارشی برای {activePet.name} ثبت نکردهاید.</p>
|
||||||
<button onClick={() => router.push('/shop')} className="bg-canino-blue text-white px-10 py-4 rounded-2xl font-black hover:scale-105 transition-all">شروع اولین خرید</button>
|
<button onClick={() => router.push('/shop')} className="bg-canina-blue text-white px-10 py-4 rounded-2xl font-black hover:scale-105 transition-all">شروع اولین خرید</button>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="space-y-5">
|
<div className="space-y-5">
|
||||||
@ -984,10 +984,10 @@ export default function PetProfile({ initialView, advisorNeed }: {
|
|||||||
>
|
>
|
||||||
{/* Info on Left (Text side) */}
|
{/* Info on Left (Text side) */}
|
||||||
<div className="flex-1 text-right">
|
<div className="flex-1 text-right">
|
||||||
<h4 className="text-xl font-black text-medical-gray-900 group-hover:text-canino-blue transition-colors mb-2 italic">{item.product.name}</h4>
|
<h4 className="text-xl font-black text-medical-gray-900 group-hover:text-canina-blue transition-colors mb-2 italic">{item.product.name}</h4>
|
||||||
<div className="flex flex-wrap gap-x-6 gap-y-2 items-center">
|
<div className="flex flex-wrap gap-x-6 gap-y-2 items-center">
|
||||||
<div className="flex items-center gap-1.5 text-xs font-bold text-medical-gray-500">
|
<div className="flex items-center gap-1.5 text-xs font-bold text-medical-gray-500">
|
||||||
<Calendar className="w-4 h-4 text-canino-blue/40" />
|
<Calendar className="w-4 h-4 text-canina-blue/40" />
|
||||||
{toPersian(new Date(order.date).toLocaleDateString("fa-IR", { year: 'numeric', month: 'long', day: 'numeric' }))}
|
{toPersian(new Date(order.date).toLocaleDateString("fa-IR", { year: 'numeric', month: 'long', day: 'numeric' }))}
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center gap-1.5 px-3 py-1 bg-green-50 text-green-600 rounded-full text-[10px] font-black italic">
|
<div className="flex items-center gap-1.5 px-3 py-1 bg-green-50 text-green-600 rounded-full text-[10px] font-black italic">
|
||||||
@ -1020,11 +1020,11 @@ export default function PetProfile({ initialView, advisorNeed }: {
|
|||||||
{/* Seal of Authenticity */}
|
{/* Seal of Authenticity */}
|
||||||
<div className="p-16 border-4 border-double border-medical-gray-200 rounded-[5rem] text-center max-w-4xl mx-auto opacity-40 grayscale hover:opacity-100 hover:grayscale-0 transition-all duration-1000">
|
<div className="p-16 border-4 border-double border-medical-gray-200 rounded-[5rem] text-center max-w-4xl mx-auto opacity-40 grayscale hover:opacity-100 hover:grayscale-0 transition-all duration-1000">
|
||||||
<div className="flex justify-center mb-8">
|
<div className="flex justify-center mb-8">
|
||||||
<div className="w-20 h-20 border-4 border-canino-blue rounded-full flex items-center justify-center text-canino-blue font-black text-2xl rotate-12 shadow-2xl">آلمان</div>
|
<div className="w-20 h-20 border-4 border-canina-blue rounded-full flex items-center justify-center text-canina-blue font-black text-2xl rotate-12 shadow-2xl">آلمان</div>
|
||||||
</div>
|
</div>
|
||||||
<h4 className="text-2xl font-black text-medical-gray-900 mb-4 italic">ضمانت اصالت و سلامت کانینو آلمان</h4>
|
<h4 className="text-2xl font-black text-medical-gray-900 mb-4 italic">ضمانت اصالت و سلامت کانینا آلمان</h4>
|
||||||
<p className="text-sm text-medical-gray-500 font-medium leading-relaxed max-w-2xl mx-auto italic">
|
<p className="text-sm text-medical-gray-500 font-medium leading-relaxed max-w-2xl mx-auto italic">
|
||||||
این گزارش توسط سیستم هوش مصنوعی کانینو و با انطباق کامل بر پروتکلهای درمانی Canina Pharma GmbH آلمان تولید شده است. تمامی مکملهای پیشنهادی دارای استاندارد دارویی (Pharmaceutical Grade) میباشند.
|
این گزارش توسط سیستم هوش مصنوعی کانینا و با انطباق کامل بر پروتکلهای درمانی Canina Pharma GmbH آلمان تولید شده است. تمامی مکملهای پیشنهادی دارای استاندارد دارویی (Pharmaceutical Grade) میباشند.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -1059,7 +1059,7 @@ export default function PetProfile({ initialView, advisorNeed }: {
|
|||||||
value={reminderForm.title}
|
value={reminderForm.title}
|
||||||
onChange={e => setReminderForm({ ...reminderForm, title: e.target.value })}
|
onChange={e => setReminderForm({ ...reminderForm, title: e.target.value })}
|
||||||
placeholder="مثلاً: قرص مفاصل، کانهیدروکس"
|
placeholder="مثلاً: قرص مفاصل، کانهیدروکس"
|
||||||
className="w-full bg-medical-gray-50 border border-medical-gray-200 rounded-2xl py-4 px-6 focus:ring-2 focus:ring-canino-blue/20 outline-none font-bold"
|
className="w-full bg-medical-gray-50 border border-medical-gray-200 rounded-2xl py-4 px-6 focus:ring-2 focus:ring-canina-blue/20 outline-none font-bold"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="grid grid-cols-2 gap-4">
|
<div className="grid grid-cols-2 gap-4">
|
||||||
@ -1069,7 +1069,7 @@ export default function PetProfile({ initialView, advisorNeed }: {
|
|||||||
type="time"
|
type="time"
|
||||||
value={reminderForm.time}
|
value={reminderForm.time}
|
||||||
onChange={e => setReminderForm({ ...reminderForm, time: e.target.value })}
|
onChange={e => setReminderForm({ ...reminderForm, time: e.target.value })}
|
||||||
className="w-full bg-medical-gray-50 border border-medical-gray-200 rounded-2xl py-4 px-6 focus:ring-2 focus:ring-canino-blue/20 outline-none font-black"
|
className="w-full bg-medical-gray-50 border border-medical-gray-200 rounded-2xl py-4 px-6 focus:ring-2 focus:ring-canina-blue/20 outline-none font-black"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
@ -1077,7 +1077,7 @@ export default function PetProfile({ initialView, advisorNeed }: {
|
|||||||
<select
|
<select
|
||||||
value={reminderForm.frequency}
|
value={reminderForm.frequency}
|
||||||
onChange={e => setReminderForm({ ...reminderForm, frequency: e.target.value as any })}
|
onChange={e => setReminderForm({ ...reminderForm, frequency: e.target.value as any })}
|
||||||
className="w-full bg-medical-gray-50 border border-medical-gray-200 rounded-2xl py-4 px-6 focus:ring-2 focus:ring-canino-blue/20 outline-none font-black text-sm"
|
className="w-full bg-medical-gray-50 border border-medical-gray-200 rounded-2xl py-4 px-6 focus:ring-2 focus:ring-canina-blue/20 outline-none font-black text-sm"
|
||||||
>
|
>
|
||||||
<option value="روزانه">روزانه</option>
|
<option value="روزانه">روزانه</option>
|
||||||
<option value="هفتگی">هفتگی</option>
|
<option value="هفتگی">هفتگی</option>
|
||||||
@ -1089,7 +1089,7 @@ export default function PetProfile({ initialView, advisorNeed }: {
|
|||||||
<select
|
<select
|
||||||
value={reminderForm.productId}
|
value={reminderForm.productId}
|
||||||
onChange={e => setReminderForm({ ...reminderForm, productId: e.target.value })}
|
onChange={e => setReminderForm({ ...reminderForm, productId: e.target.value })}
|
||||||
className="w-full bg-medical-gray-50 border border-medical-gray-200 rounded-2xl py-4 px-6 focus:ring-2 focus:ring-canino-blue/20 outline-none font-black text-sm"
|
className="w-full bg-medical-gray-50 border border-medical-gray-200 rounded-2xl py-4 px-6 focus:ring-2 focus:ring-canina-blue/20 outline-none font-black text-sm"
|
||||||
>
|
>
|
||||||
<option value="">هیچکدام</option>
|
<option value="">هیچکدام</option>
|
||||||
{recommendedProducts.map(p => (
|
{recommendedProducts.map(p => (
|
||||||
@ -1100,7 +1100,7 @@ export default function PetProfile({ initialView, advisorNeed }: {
|
|||||||
|
|
||||||
<button
|
<button
|
||||||
onClick={handleReminderSubmit}
|
onClick={handleReminderSubmit}
|
||||||
className="w-full py-5 bg-canino-blue text-white rounded-2xl font-black hover:bg-medical-gray-900 transition-all shadow-xl shadow-canino-blue/20 mt-4"
|
className="w-full py-5 bg-canina-blue text-white rounded-2xl font-black hover:bg-medical-gray-900 transition-all shadow-xl shadow-canina-blue/20 mt-4"
|
||||||
>
|
>
|
||||||
ثبت نهایی یادآور
|
ثبت نهایی یادآور
|
||||||
</button>
|
</button>
|
||||||
@ -1142,7 +1142,7 @@ export default function PetProfile({ initialView, advisorNeed }: {
|
|||||||
onClick={() => setLogForm({ ...logForm, appetite: opt as any })}
|
onClick={() => setLogForm({ ...logForm, appetite: opt as any })}
|
||||||
className={cn(
|
className={cn(
|
||||||
"py-3 border-2 rounded-xl text-xs font-black transition-all",
|
"py-3 border-2 rounded-xl text-xs font-black transition-all",
|
||||||
logForm.appetite === opt ? "border-canino-blue bg-canino-blue/10 text-canino-blue" : "border-medical-gray-100 text-medical-gray-400"
|
logForm.appetite === opt ? "border-canina-blue bg-canina-blue/10 text-canina-blue" : "border-medical-gray-100 text-medical-gray-400"
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{opt}
|
{opt}
|
||||||
@ -1176,13 +1176,13 @@ export default function PetProfile({ initialView, advisorNeed }: {
|
|||||||
value={logForm.note}
|
value={logForm.note}
|
||||||
onChange={e => setLogForm({ ...logForm, note: e.target.value })}
|
onChange={e => setLogForm({ ...logForm, note: e.target.value })}
|
||||||
placeholder="مشاهدات خود را برای بررسی دکتر سیستم اینجا بنویسید..."
|
placeholder="مشاهدات خود را برای بررسی دکتر سیستم اینجا بنویسید..."
|
||||||
className="w-full bg-medical-gray-50 border border-medical-gray-200 rounded-2xl py-4 px-6 focus:ring-2 focus:ring-canino-blue/20 outline-none font-bold text-sm resize-none"
|
className="w-full bg-medical-gray-50 border border-medical-gray-200 rounded-2xl py-4 px-6 focus:ring-2 focus:ring-canina-blue/20 outline-none font-bold text-sm resize-none"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
onClick={handleHealthLogSubmit}
|
onClick={handleHealthLogSubmit}
|
||||||
className="w-full py-5 bg-medical-gray-900 text-white rounded-2xl font-black hover:bg-canino-blue transition-all shadow-xl mt-2"
|
className="w-full py-5 bg-medical-gray-900 text-white rounded-2xl font-black hover:bg-canina-blue transition-all shadow-xl mt-2"
|
||||||
>
|
>
|
||||||
ثبت نهایی گزارش
|
ثبت نهایی گزارش
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@ -169,8 +169,8 @@ export default function ProductPage({ productSlug }: { productSlug: string }) {
|
|||||||
<ChevronRight className="w-5 h-5" />
|
<ChevronRight className="w-5 h-5" />
|
||||||
بازگشت
|
بازگشت
|
||||||
</button>
|
</button>
|
||||||
<div className="text-[10px] font-black text-canino-blue bg-canino-blue/5 px-4 py-2 rounded-xl font-vazir whitespace-nowrap">
|
<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>
|
</div>
|
||||||
|
|
||||||
@ -178,19 +178,19 @@ export default function ProductPage({ productSlug }: { productSlug: string }) {
|
|||||||
<nav className="hidden md:flex items-center gap-2 text-xs font-bold text-medical-gray-400 mb-8 overflow-x-auto whitespace-nowrap py-2">
|
<nav className="hidden md:flex items-center gap-2 text-xs font-bold text-medical-gray-400 mb-8 overflow-x-auto whitespace-nowrap py-2">
|
||||||
<button
|
<button
|
||||||
onClick={() => router.push('/')}
|
onClick={() => router.push('/')}
|
||||||
className="hover:text-canino-blue transition-colors font-vazir cursor-pointer"
|
className="hover:text-canina-blue transition-colors font-vazir cursor-pointer"
|
||||||
>
|
>
|
||||||
خانه
|
خانه
|
||||||
</button>
|
</button>
|
||||||
<ChevronLeft className="w-3 h-3 flex-shrink-0" />
|
<ChevronLeft className="w-3 h-3 flex-shrink-0" />
|
||||||
<button
|
<button
|
||||||
onClick={() => router.push(`/shop?category=${product.category}`)}
|
onClick={() => router.push(`/shop?category=${product.categorySlug}`)}
|
||||||
className="hover:text-canino-blue cursor-pointer font-vazir"
|
className="hover:text-canina-blue cursor-pointer font-vazir"
|
||||||
>
|
>
|
||||||
{product.category}
|
{product.category}
|
||||||
</button>
|
</button>
|
||||||
<ChevronLeft className="w-3 h-3 flex-shrink-0" />
|
<ChevronLeft className="w-3 h-3 flex-shrink-0" />
|
||||||
<span className="text-canino-blue font-vazir whitespace-nowrap">{product.name}</span>
|
<span className="text-canina-blue font-vazir whitespace-nowrap">{product.name}</span>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<div className="grid lg:grid-cols-12 gap-12 items-start">
|
<div className="grid lg:grid-cols-12 gap-12 items-start">
|
||||||
@ -198,7 +198,7 @@ export default function ProductPage({ productSlug }: { productSlug: string }) {
|
|||||||
<div className="lg:col-span-8 space-y-12">
|
<div className="lg:col-span-8 space-y-12">
|
||||||
<div>
|
<div>
|
||||||
<div className="flex flex-wrap items-center gap-3 mb-4">
|
<div className="flex flex-wrap items-center gap-3 mb-4">
|
||||||
<div className="px-3 py-1 bg-canino-blue text-white rounded-full text-[10px] font-black uppercase tracking-widest font-vazir whitespace-nowrap">
|
<div className="px-3 py-1 bg-canina-blue text-white rounded-full text-[10px] font-black uppercase tracking-widest font-vazir whitespace-nowrap">
|
||||||
استاندارد صنعتی آلمان
|
استاندارد صنعتی آلمان
|
||||||
</div>
|
</div>
|
||||||
{product.specialBadge && (
|
{product.specialBadge && (
|
||||||
@ -210,7 +210,7 @@ export default function ProductPage({ productSlug }: { productSlug: string }) {
|
|||||||
<h1 className="text-4xl lg:text-6xl font-black text-medical-gray-900 leading-tight mb-4 italic font-vazir">
|
<h1 className="text-4xl lg:text-6xl font-black text-medical-gray-900 leading-tight mb-4 italic font-vazir">
|
||||||
{product.name}
|
{product.name}
|
||||||
</h1>
|
</h1>
|
||||||
<p className="text-xl text-canino-blue font-bold italic opacity-70 leading-relaxed max-w-2xl font-vazir mb-6">
|
<p className="text-xl text-canina-blue font-bold italic opacity-70 leading-relaxed max-w-2xl font-vazir mb-6">
|
||||||
{pets.length > 0 ? (
|
{pets.length > 0 ? (
|
||||||
product.optimisticTemplate?.replace("[PetName]", activePet?.name || "").replace("[OnSet]", product.onSetOfAction || "به زودی")
|
product.optimisticTemplate?.replace("[PetName]", activePet?.name || "").replace("[OnSet]", product.onSetOfAction || "به زودی")
|
||||||
) : (
|
) : (
|
||||||
@ -218,17 +218,17 @@ export default function ProductPage({ productSlug }: { productSlug: string }) {
|
|||||||
)}
|
)}
|
||||||
</p>
|
</p>
|
||||||
{fullProduct.shortDescription && (
|
{fullProduct.shortDescription && (
|
||||||
<p className="text-lg text-medical-gray-600 font-medium leading-relaxed max-w-3xl font-vazir border-r-4 border-canino-blue pr-6 py-2 bg-canino-blue/5 rounded-l-2xl">
|
<p className="text-lg text-medical-gray-600 font-medium leading-relaxed max-w-3xl font-vazir border-r-4 border-canina-blue pr-6 py-2 bg-canina-blue/5 rounded-l-2xl">
|
||||||
{fullProduct.shortDescription}
|
{fullProduct.shortDescription}
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Key Benefits Section */}
|
{/* Key Benefits Section */}
|
||||||
{fullProduct.keyBenefits && (
|
{fullProduct.keyBenefits?.length > 0 && (
|
||||||
<section className="space-y-8">
|
<section className="space-y-8">
|
||||||
<div className="flex items-center gap-4">
|
<div className="flex items-center gap-4">
|
||||||
<div className="w-12 h-12 bg-canino-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">
|
||||||
<Star className="w-6 h-6" />
|
<Star className="w-6 h-6" />
|
||||||
</div>
|
</div>
|
||||||
<h3 className="text-3xl font-black text-medical-gray-900 italic font-vazir">چرا {fullProduct.name}؟</h3>
|
<h3 className="text-3xl font-black text-medical-gray-900 italic font-vazir">چرا {fullProduct.name}؟</h3>
|
||||||
@ -238,8 +238,8 @@ export default function ProductPage({ productSlug }: { productSlug: string }) {
|
|||||||
const Icon = ICON_MAP[benefit.icon] || CheckCircle2;
|
const Icon = ICON_MAP[benefit.icon] || CheckCircle2;
|
||||||
return (
|
return (
|
||||||
<div key={i} className="bg-white border border-medical-gray-100 rounded-[2rem] p-8 shadow-sm hover:shadow-xl hover:-translate-y-1 transition-all group overflow-hidden relative">
|
<div key={i} className="bg-white border border-medical-gray-100 rounded-[2rem] p-8 shadow-sm hover:shadow-xl hover:-translate-y-1 transition-all group overflow-hidden relative">
|
||||||
<div className="absolute -top-10 -left-10 w-24 h-24 bg-canino-blue/5 rounded-full group-hover:scale-150 transition-transform duration-700" />
|
<div className="absolute -top-10 -left-10 w-24 h-24 bg-canina-blue/5 rounded-full group-hover:scale-150 transition-transform duration-700" />
|
||||||
<div className="w-12 h-12 bg-medical-gray-50 rounded-2xl flex items-center justify-center text-canino-blue mb-6 group-hover:bg-canino-blue group-hover:text-white transition-all">
|
<div className="w-12 h-12 bg-medical-gray-50 rounded-2xl flex items-center justify-center text-canina-blue mb-6 group-hover:bg-canina-blue group-hover:text-white transition-all">
|
||||||
<Icon className="w-6 h-6" />
|
<Icon className="w-6 h-6" />
|
||||||
</div>
|
</div>
|
||||||
<h4 className="text-xl font-black text-medical-gray-900 mb-2 font-vazir">{benefit.title}</h4>
|
<h4 className="text-xl font-black text-medical-gray-900 mb-2 font-vazir">{benefit.title}</h4>
|
||||||
@ -261,7 +261,7 @@ export default function ProductPage({ productSlug }: { productSlug: string }) {
|
|||||||
<CheckCircle2 className="w-3 h-3" />
|
<CheckCircle2 className="w-3 h-3" />
|
||||||
موجود در انبار
|
موجود در انبار
|
||||||
</div>
|
</div>
|
||||||
<div className="px-3 py-1 bg-canino-blue/5 text-canino-blue rounded-full text-[10px] font-black uppercase tracking-widest border border-canino-blue/10 font-vazir whitespace-nowrap">
|
<div className="px-3 py-1 bg-canina-blue/5 text-canina-blue rounded-full text-[10px] font-black uppercase tracking-widest border border-canina-blue/10 font-vazir whitespace-nowrap">
|
||||||
گرید دارویی اختصاصی
|
گرید دارویی اختصاصی
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -289,7 +289,7 @@ export default function ProductPage({ productSlug }: { productSlug: string }) {
|
|||||||
{product.main_ingredients.map((ing, idx) => {
|
{product.main_ingredients.map((ing, idx) => {
|
||||||
const termKey = termKeys.find(key => ing.includes(key));
|
const termKey = termKeys.find(key => ing.includes(key));
|
||||||
return (
|
return (
|
||||||
<div key={idx} className="bg-medical-gray-50 border border-medical-gray-100 px-5 py-3 rounded-2xl flex items-center gap-3 group hover:border-canino-blue/30 transition-all">
|
<div key={idx} className="bg-medical-gray-50 border border-medical-gray-100 px-5 py-3 rounded-2xl flex items-center gap-3 group hover:border-canina-blue/30 transition-all">
|
||||||
<span className="text-sm font-bold text-medical-gray-700 font-vazir">
|
<span className="text-sm font-bold text-medical-gray-700 font-vazir">
|
||||||
{termKey ? (
|
{termKey ? (
|
||||||
<Tooltip termKey={termKey} onWikiNavigate={(id) => router.push(`/wiki?term=${id}`)}>
|
<Tooltip termKey={termKey} onWikiNavigate={(id) => router.push(`/wiki?term=${id}`)}>
|
||||||
@ -297,7 +297,7 @@ export default function ProductPage({ productSlug }: { productSlug: string }) {
|
|||||||
</Tooltip>
|
</Tooltip>
|
||||||
) : ing}
|
) : ing}
|
||||||
</span>
|
</span>
|
||||||
<Sparkles className="w-3 h-3 text-canino-blue opacity-40 group-hover:opacity-100 transition-opacity" />
|
<Sparkles className="w-3 h-3 text-canina-blue opacity-40 group-hover:opacity-100 transition-opacity" />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
@ -305,24 +305,26 @@ export default function ProductPage({ productSlug }: { productSlug: string }) {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Analysis Cards Grid */}
|
{/* Analysis Cards Grid */}
|
||||||
<div className="space-y-6">
|
{Object.keys(product.analysis).length > 0 && (
|
||||||
<div className="text-[10px] font-black text-medical-gray-400 uppercase tracking-widest mb-4 font-vazir">تخمین اتمام بسته (هوش مصنوعی)</div>
|
<div className="space-y-6">
|
||||||
<div className="grid grid-cols-2 gap-4">
|
<div className="text-[10px] font-black text-medical-gray-400 uppercase tracking-widest mb-4 font-vazir">تخمین اتمام بسته (هوش مصنوعی)</div>
|
||||||
{Object.entries(product.analysis).map(([key, value]) => (
|
<div className="grid grid-cols-2 gap-4">
|
||||||
<div key={key} className="bg-canino-blue text-white p-8 rounded-[2rem] border-b-2 border-white/20 shadow-xl group hover:scale-[1.02] transition-all duration-300">
|
{Object.entries(product.analysis).map(([key, value]) => (
|
||||||
<div className="text-[10px] font-black text-white/80 uppercase tracking-widest mb-3 font-vazir whitespace-nowrap">{key}</div>
|
<div key={key} className="bg-canina-blue text-white p-8 rounded-[2rem] border-b-2 border-white/20 shadow-xl group hover:scale-[1.02] transition-all duration-300">
|
||||||
<div className="text-3xl font-black font-vazir tracking-tighter text-white">{toPersian(value)}</div>
|
<div className="text-[10px] font-black text-white/80 uppercase tracking-widest mb-3 font-vazir whitespace-nowrap">{key}</div>
|
||||||
</div>
|
<div className="text-3xl font-black font-vazir tracking-tighter text-white">{toPersian(value)}</div>
|
||||||
))}
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
)}
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{/* Feeding Section */}
|
{/* Feeding Section */}
|
||||||
<section className="bg-canino-blue/5 border border-canino-blue/10 rounded-[3rem] p-10">
|
<section className="bg-canina-blue/5 border border-canina-blue/10 rounded-[3rem] p-10">
|
||||||
<div className="flex items-center gap-4 mb-8">
|
<div className="flex items-center gap-4 mb-8">
|
||||||
<div className="w-10 h-10 bg-canino-blue text-white rounded-xl flex items-center justify-center">
|
<div className="w-10 h-10 bg-canina-blue text-white rounded-xl flex items-center justify-center">
|
||||||
<CalendarDays className="w-6 h-6" />
|
<CalendarDays className="w-6 h-6" />
|
||||||
</div>
|
</div>
|
||||||
<h3 className="text-2xl font-black text-medical-gray-900 italic font-vazir">توصیه غذایی و نحوه مصرف</h3>
|
<h3 className="text-2xl font-black text-medical-gray-900 italic font-vazir">توصیه غذایی و نحوه مصرف</h3>
|
||||||
@ -333,8 +335,8 @@ export default function ProductPage({ productSlug }: { productSlug: string }) {
|
|||||||
</section>
|
</section>
|
||||||
|
|
||||||
{/* Specialist Note */}
|
{/* Specialist Note */}
|
||||||
<section className="bg-white rounded-[3rem] p-10 border border-medical-gray-200">
|
{product.specialist && (
|
||||||
{product.specialist && (
|
<section className="bg-white rounded-[3rem] p-10 border border-medical-gray-200">
|
||||||
<div className="flex flex-col md:flex-row gap-10 items-start">
|
<div className="flex flex-col md:flex-row gap-10 items-start">
|
||||||
<img
|
<img
|
||||||
src={product.specialist.image}
|
src={product.specialist.image}
|
||||||
@ -347,19 +349,19 @@ export default function ProductPage({ productSlug }: { productSlug: string }) {
|
|||||||
مورد تأیید دامپزشکان
|
مورد تأیید دامپزشکان
|
||||||
</div>
|
</div>
|
||||||
<h4 className="text-2xl font-black text-medical-gray-900 mb-1 font-vazir">{product.specialist.name}</h4>
|
<h4 className="text-2xl font-black text-medical-gray-900 mb-1 font-vazir">{product.specialist.name}</h4>
|
||||||
<p className="text-sm font-bold text-canino-blue mb-6 font-vazir">{product.specialist.title}</p>
|
<p className="text-sm font-bold text-canina-blue mb-6 font-vazir">{product.specialist.title}</p>
|
||||||
<p className="text-base text-medical-gray-600 leading-relaxed italic font-vazir">
|
<p className="text-base text-medical-gray-600 leading-relaxed italic font-vazir">
|
||||||
"{product.specialist.message}"
|
"{product.specialist.message}"
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
</section>
|
||||||
</section>
|
)}
|
||||||
|
|
||||||
{/* Specialized Landing Banner */}
|
{/* Specialized Landing Banner */}
|
||||||
<section>
|
<section>
|
||||||
<div
|
<div
|
||||||
className="relative bg-canino-blue rounded-[3rem] p-12 overflow-hidden group cursor-pointer"
|
className="relative bg-canina-blue rounded-[3rem] p-12 overflow-hidden group cursor-pointer"
|
||||||
onClick={() => toast.info("بزودی: صفحه فرود تخصصی این محصول در حال آمادهسازی است")}
|
onClick={() => toast.info("بزودی: صفحه فرود تخصصی این محصول در حال آمادهسازی است")}
|
||||||
>
|
>
|
||||||
<div className="absolute top-0 right-0 w-full h-full bg-[url('https://www.transparenttextures.com/patterns/cubes.png')] opacity-10" />
|
<div className="absolute top-0 right-0 w-full h-full bg-[url('https://www.transparenttextures.com/patterns/cubes.png')] opacity-10" />
|
||||||
@ -372,7 +374,7 @@ export default function ProductPage({ productSlug }: { productSlug: string }) {
|
|||||||
گزارشهای علمی، ویدیوهای آموزشی و تجربیات واقعی دیگر صاحبان پت در لندینگپیج اختصاصی این محصول.
|
گزارشهای علمی، ویدیوهای آموزشی و تجربیات واقعی دیگر صاحبان پت در لندینگپیج اختصاصی این محصول.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="bg-white text-canino-blue px-8 py-4 rounded-2xl font-black shadow-2xl hover:scale-105 transition-transform flex items-center gap-3">
|
<div className="bg-white text-canina-blue px-8 py-4 rounded-2xl font-black shadow-2xl hover:scale-105 transition-transform flex items-center gap-3">
|
||||||
ورود به آزمایشگاه علمی
|
ورود به آزمایشگاه علمی
|
||||||
<ArrowRight className="w-5 h-5 rotate-180" />
|
<ArrowRight className="w-5 h-5 rotate-180" />
|
||||||
</div>
|
</div>
|
||||||
@ -381,20 +383,20 @@ export default function ProductPage({ productSlug }: { productSlug: string }) {
|
|||||||
</section>
|
</section>
|
||||||
|
|
||||||
{/* FAQ Section */}
|
{/* FAQ Section */}
|
||||||
{product.faqs && (
|
{product.faqs?.length > 0 && (
|
||||||
<section className="pt-10">
|
<section className="pt-10">
|
||||||
<div className="flex items-center gap-4 mb-10">
|
<div className="flex items-center gap-4 mb-10">
|
||||||
<div className="w-12 h-12 bg-blue-100 text-canino-blue rounded-2xl flex items-center justify-center">
|
<div className="w-12 h-12 bg-blue-100 text-canina-blue rounded-2xl flex items-center justify-center">
|
||||||
<Info className="w-6 h-6" />
|
<Info className="w-6 h-6" />
|
||||||
</div>
|
</div>
|
||||||
<h3 className="text-3xl font-black text-medical-gray-900 italic font-vazir">پاسخ به ابهامات شما</h3>
|
<h3 className="text-3xl font-black text-medical-gray-900 italic font-vazir">پاسخ به ابهامات شما</h3>
|
||||||
</div>
|
</div>
|
||||||
<div className="grid md:grid-cols-1 gap-4">
|
<div className="grid md:grid-cols-1 gap-4">
|
||||||
{product.faqs.map((faq, i) => (
|
{product.faqs.map((faq, i) => (
|
||||||
<details key={i} className="group bg-white border border-medical-gray-200 rounded-3xl overflow-hidden hover:border-canino-blue/30 transition-all">
|
<details key={i} className="group bg-white border border-medical-gray-200 rounded-3xl overflow-hidden hover:border-canina-blue/30 transition-all">
|
||||||
<summary className="flex items-center justify-between p-6 cursor-pointer list-none">
|
<summary className="flex items-center justify-between p-6 cursor-pointer list-none">
|
||||||
<span className="font-bold text-medical-gray-900 font-vazir">{faq.question}</span>
|
<span className="font-bold text-medical-gray-900 font-vazir">{faq.question}</span>
|
||||||
<ChevronDown className="w-5 h-5 text-canino-blue group-open:rotate-180 transition-transform" />
|
<ChevronDown className="w-5 h-5 text-canina-blue group-open:rotate-180 transition-transform" />
|
||||||
</summary>
|
</summary>
|
||||||
<div className="px-6 pb-6 text-sm text-medical-gray-500 font-medium leading-relaxed font-vazir border-t border-medical-gray-50 pt-4">
|
<div className="px-6 pb-6 text-sm text-medical-gray-500 font-medium leading-relaxed font-vazir border-t border-medical-gray-50 pt-4">
|
||||||
{faq.answer}
|
{faq.answer}
|
||||||
@ -409,14 +411,14 @@ export default function ProductPage({ productSlug }: { productSlug: string }) {
|
|||||||
{/* Sticky Sidebar */}
|
{/* Sticky Sidebar */}
|
||||||
<div className="lg:col-span-4 lg:sticky lg:top-24 space-y-8">
|
<div className="lg:col-span-4 lg:sticky lg:top-24 space-y-8">
|
||||||
<div className="bg-white rounded-[3rem] border-2 border-medical-gray-100 p-8 shadow-2xl relative overflow-hidden">
|
<div className="bg-white rounded-[3rem] 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-canino-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" />
|
||||||
|
|
||||||
<div className="text-4xl font-black font-vazir text-medical-gray-900 tracking-tighter mb-4">
|
<div className="text-4xl font-black font-vazir text-medical-gray-900 tracking-tighter mb-4">
|
||||||
{toPersian(product.price)}
|
{toPersian(product.price)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Refill Auto-Calculator */}
|
{/* Refill Auto-Calculator */}
|
||||||
<div className="bg-canino-blue rounded-[2rem] p-6 text-white mb-8 border-b-8 border-white/20 shadow-2xl">
|
<div className="bg-canina-blue rounded-[2rem] p-6 text-white mb-8 border-b-8 border-white/20 shadow-2xl">
|
||||||
<div className="flex items-center gap-2 mb-4 opacity-90">
|
<div className="flex items-center gap-2 mb-4 opacity-90">
|
||||||
<Clock className="w-4 h-4 text-white" />
|
<Clock className="w-4 h-4 text-white" />
|
||||||
<span className="text-[10px] font-bold uppercase tracking-widest font-vazir text-white">هوش مصنوعی تکرار خرید</span>
|
<span className="text-[10px] font-bold uppercase tracking-widest font-vazir text-white">هوش مصنوعی تکرار خرید</span>
|
||||||
@ -437,18 +439,18 @@ export default function ProductPage({ productSlug }: { productSlug: string }) {
|
|||||||
<div className="bg-medical-gray-50 rounded-2xl p-6 border border-medical-gray-100 mb-8 space-y-6">
|
<div className="bg-medical-gray-50 rounded-2xl p-6 border border-medical-gray-100 mb-8 space-y-6">
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<span className="text-[10px] font-black text-medical-gray-400 font-vazir">وزن پت (کیلوگرم)</span>
|
<span className="text-[10px] font-black text-medical-gray-400 font-vazir">وزن پت (کیلوگرم)</span>
|
||||||
<span className="text-sm font-black text-canino-blue font-vazir">{toPersian(weight)}</span>
|
<span className="text-sm font-black text-canina-blue font-vazir">{toPersian(weight)}</span>
|
||||||
</div>
|
</div>
|
||||||
<input
|
<input
|
||||||
type="range"
|
type="range"
|
||||||
min="1" max="100"
|
min="1" max="100"
|
||||||
value={weight}
|
value={weight}
|
||||||
onChange={(e) => setWeight(parseInt(e.target.value))}
|
onChange={(e) => setWeight(parseInt(e.target.value))}
|
||||||
className="w-full h-1.5 bg-medical-gray-200 rounded-lg appearance-none cursor-pointer accent-canino-blue"
|
className="w-full h-1.5 bg-medical-gray-200 rounded-lg appearance-none cursor-pointer accent-canina-blue"
|
||||||
/>
|
/>
|
||||||
<div className="flex gap-2">
|
<div className="flex gap-2">
|
||||||
<button onClick={() => setPetType("young")} className={`flex-1 py-2 rounded-xl text-[10px] font-black transition-all ${petType === "young" ? 'bg-canino-blue text-white shadow-lg' : 'bg-white text-medical-gray-400'}`}>جوان</button>
|
<button onClick={() => setPetType("young")} className={`flex-1 py-2 rounded-xl text-[10px] font-black transition-all ${petType === "young" ? 'bg-canina-blue text-white shadow-lg' : 'bg-white text-medical-gray-400'}`}>جوان</button>
|
||||||
<button onClick={() => setPetType("adult")} className={`flex-1 py-2 rounded-xl text-[10px] font-black transition-all ${petType === "adult" ? 'bg-canino-blue text-white shadow-lg' : 'bg-white text-medical-gray-400'}`}>بالغ</button>
|
<button onClick={() => setPetType("adult")} className={`flex-1 py-2 rounded-xl text-[10px] font-black transition-all ${petType === "adult" ? 'bg-canina-blue text-white shadow-lg' : 'bg-white text-medical-gray-400'}`}>بالغ</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -457,7 +459,7 @@ export default function ProductPage({ productSlug }: { productSlug: string }) {
|
|||||||
<div className="flex items-center gap-4 bg-medical-gray-50 border border-medical-gray-100 rounded-2xl p-2 h-16 w-[40%]">
|
<div className="flex items-center gap-4 bg-medical-gray-50 border border-medical-gray-100 rounded-2xl p-2 h-16 w-[40%]">
|
||||||
<button
|
<button
|
||||||
onClick={() => setItemQuantity(Math.max(1, itemQuantity - 1))}
|
onClick={() => setItemQuantity(Math.max(1, itemQuantity - 1))}
|
||||||
className="w-10 h-10 flex items-center justify-center rounded-xl bg-white text-medical-gray-900 border border-medical-gray-200 hover:bg-canino-blue hover:text-white hover:border-canino-blue transition-all shadow-sm"
|
className="w-10 h-10 flex items-center justify-center rounded-xl bg-white text-medical-gray-900 border border-medical-gray-200 hover:bg-canina-blue hover:text-white hover:border-canina-blue transition-all shadow-sm"
|
||||||
>
|
>
|
||||||
<Minus className="w-4 h-4" />
|
<Minus className="w-4 h-4" />
|
||||||
</button>
|
</button>
|
||||||
@ -466,7 +468,7 @@ export default function ProductPage({ productSlug }: { productSlug: string }) {
|
|||||||
</span>
|
</span>
|
||||||
<button
|
<button
|
||||||
onClick={() => setItemQuantity(itemQuantity + 1)}
|
onClick={() => setItemQuantity(itemQuantity + 1)}
|
||||||
className="w-10 h-10 flex items-center justify-center rounded-xl bg-white text-medical-gray-900 border border-medical-gray-200 hover:bg-canino-blue hover:text-white hover:border-canino-blue transition-all shadow-sm"
|
className="w-10 h-10 flex items-center justify-center rounded-xl bg-white text-medical-gray-900 border border-medical-gray-200 hover:bg-canina-blue hover:text-white hover:border-canina-blue transition-all shadow-sm"
|
||||||
>
|
>
|
||||||
<Plus className="w-4 h-4" />
|
<Plus className="w-4 h-4" />
|
||||||
</button>
|
</button>
|
||||||
@ -478,7 +480,7 @@ export default function ProductPage({ productSlug }: { productSlug: string }) {
|
|||||||
addItem(product, itemQuantity, { quantity: calculation.dailyDose, unit: calculation.unit });
|
addItem(product, itemQuantity, { quantity: calculation.dailyDose, unit: calculation.unit });
|
||||||
toast.success(`${toPersian(itemQuantity)} عدد ${product.name} به سبد خرید اضافه شد`);
|
toast.success(`${toPersian(itemQuantity)} عدد ${product.name} به سبد خرید اضافه شد`);
|
||||||
}}
|
}}
|
||||||
className="w-[60%] flex items-center justify-center gap-1.5 px-4 bg-medical-gray-900 text-white rounded-2xl h-16 font-black text-sm hover:bg-canino-blue transition-all shadow-xl shadow-black/10 font-vazir whitespace-nowrap"
|
className="w-[60%] flex items-center justify-center gap-1.5 px-4 bg-medical-gray-900 text-white rounded-2xl h-16 font-black text-sm hover:bg-canina-blue transition-all shadow-xl shadow-black/10 font-vazir whitespace-nowrap"
|
||||||
>
|
>
|
||||||
<ShoppingBag className="w-5 h-5 mb-1" />
|
<ShoppingBag className="w-5 h-5 mb-1" />
|
||||||
افزودن به سبد خرید
|
افزودن به سبد خرید
|
||||||
@ -491,14 +493,14 @@ export default function ProductPage({ productSlug }: { productSlug: string }) {
|
|||||||
ضمانت اصالت محصول (Made in Germany)
|
ضمانت اصالت محصول (Made in Germany)
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center gap-2 text-[10px] font-bold text-medical-gray-400 font-vazir">
|
<div className="flex items-center gap-2 text-[10px] font-bold text-medical-gray-400 font-vazir">
|
||||||
<Clock className="w-4 h-4 text-canino-blue" />
|
<Clock className="w-4 h-4 text-canina-blue" />
|
||||||
آماده ارسال (تحویل حداکثر ۴۸ ساعت)
|
آماده ارسال (تحویل حداکثر ۴۸ ساعت)
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* expected results box */}
|
{/* expected results box */}
|
||||||
{product.expectedResults && (
|
{product.expectedResults?.length > 0 && (
|
||||||
<div className="bg-white rounded-[2.5rem] border border-medical-gray-200 p-8">
|
<div className="bg-white rounded-[2.5rem] border border-medical-gray-200 p-8">
|
||||||
<h4 className="text-[10px] font-black text-medical-gray-400 uppercase tracking-widest mb-6 font-vazir">تغییرات قابل انتظار</h4>
|
<h4 className="text-[10px] font-black text-medical-gray-400 uppercase tracking-widest mb-6 font-vazir">تغییرات قابل انتظار</h4>
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
@ -506,7 +508,7 @@ export default function ProductPage({ productSlug }: { productSlug: string }) {
|
|||||||
const Icon = ICON_MAP[res.icon] || Sparkles;
|
const Icon = ICON_MAP[res.icon] || Sparkles;
|
||||||
return (
|
return (
|
||||||
<div key={i} className="flex items-center gap-4 group">
|
<div key={i} className="flex items-center gap-4 group">
|
||||||
<div className="w-10 h-10 bg-medical-gray-50 rounded-xl flex items-center justify-center text-canino-blue group-hover:bg-canino-blue group-hover:text-white transition-all">
|
<div className="w-10 h-10 bg-medical-gray-50 rounded-xl flex items-center justify-center text-canina-blue group-hover:bg-canina-blue group-hover:text-white transition-all">
|
||||||
<Icon className="w-5 h-5" />
|
<Icon className="w-5 h-5" />
|
||||||
</div>
|
</div>
|
||||||
<span className="text-xs font-bold text-medical-gray-700 font-vazir">{res.text}</span>
|
<span className="text-xs font-bold text-medical-gray-700 font-vazir">{res.text}</span>
|
||||||
@ -523,12 +525,12 @@ export default function ProductPage({ productSlug }: { productSlug: string }) {
|
|||||||
{product.relatedProducts && product.relatedProducts.length > 0 && (
|
{product.relatedProducts && product.relatedProducts.length > 0 && (
|
||||||
<section className="mt-32 pt-20 border-t border-medical-gray-200">
|
<section className="mt-32 pt-20 border-t border-medical-gray-200">
|
||||||
<div className="flex flex-col items-center text-center mb-16 px-4">
|
<div className="flex flex-col items-center text-center mb-16 px-4">
|
||||||
<div className="inline-flex items-center gap-2 px-4 py-2 bg-canino-blue/5 border border-canino-blue/10 rounded-full text-canino-blue text-xs font-black uppercase tracking-widest mb-6 font-vazir whitespace-nowrap">
|
<div className="inline-flex items-center gap-2 px-4 py-2 bg-canina-blue/5 border border-canina-blue/10 rounded-full text-canina-blue text-xs font-black uppercase tracking-widest mb-6 font-vazir whitespace-nowrap">
|
||||||
<Sparkles className="w-4 h-4" />
|
<Sparkles className="w-4 h-4" />
|
||||||
فرمولاسیون ترکیبی همافزا (Synergy Blend)
|
فرمولاسیون ترکیبی همافزا (Synergy Blend)
|
||||||
</div>
|
</div>
|
||||||
<h2 className="text-3xl lg:text-5xl font-black text-medical-gray-900 leading-tight">
|
<h2 className="text-3xl lg:text-5xl font-black text-medical-gray-900 leading-tight">
|
||||||
اثربخشی <span className="text-canino-blue italic">دوبرابر</span> با ترکیب هوشمند
|
اثربخشی <span className="text-canina-blue italic">دوبرابر</span> با ترکیب هوشمند
|
||||||
</h2>
|
</h2>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -546,20 +548,20 @@ export default function ProductPage({ productSlug }: { productSlug: string }) {
|
|||||||
onClick={() => router.push(`/shop/${relProduct.id}`)}
|
onClick={() => router.push(`/shop/${relProduct.id}`)}
|
||||||
>
|
>
|
||||||
<div className="w-40 h-40 bg-medical-gray-50 rounded-[2rem] p-4 flex items-center justify-center">
|
<div className="w-40 h-40 bg-medical-gray-50 rounded-[2rem] p-4 flex items-center justify-center">
|
||||||
<SafeImage src={relProduct.image} alt={relProduct.name} className="w-full h-full object-contain drop-shadow-xl" />
|
<SafeImage src={relProduct.image} alt={relProduct.name} className="w-full h-full drop-shadow-xl" imgClassName="object-contain" />
|
||||||
</div>
|
</div>
|
||||||
<div className="flex-1 text-center md:text-right">
|
<div className="flex-1 text-center md:text-right">
|
||||||
<h4 className="text-xl font-black text-medical-gray-900 mb-2">{relProduct.name}</h4>
|
<h4 className="text-xl font-black text-medical-gray-900 mb-2">{relProduct.name}</h4>
|
||||||
<p className="text-sm text-medical-gray-500 mb-6">{relProduct.description}</p>
|
<p className="text-sm text-medical-gray-500 mb-6">{relProduct.description}</p>
|
||||||
<div className="flex items-center justify-center md:justify-start gap-4">
|
<div className="flex items-center justify-center md:justify-start gap-4">
|
||||||
<span className="text-lg font-black text-canino-blue">{relProduct.price}</span>
|
<span className="text-lg font-black text-canina-blue">{relProduct.price}</span>
|
||||||
<ArrowRight className="w-4 h-4 text-medical-gray-300" />
|
<ArrowRight className="w-4 h-4 text-medical-gray-300" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="w-px h-24 bg-medical-gray-100 hidden md:block" />
|
<div className="w-px h-24 bg-medical-gray-100 hidden md:block" />
|
||||||
<div className="flex items-center justify-center gap-1 group">
|
<div className="flex items-center justify-center gap-1 group">
|
||||||
<span className="text-xs font-black text-medical-gray-400 group-hover:text-canino-blue transition-colors">مشاهده محصول مکمل</span>
|
<span className="text-xs font-black text-medical-gray-400 group-hover:text-canina-blue transition-colors">مشاهده محصول مکمل</span>
|
||||||
<ChevronLeft className="w-4 h-4 text-medical-gray-300 group-hover:text-canino-blue group-hover:-translate-x-1 transition-all rtl:group-hover:translate-x-1" />
|
<ChevronLeft className="w-4 h-4 text-medical-gray-300 group-hover:text-canina-blue group-hover:-translate-x-1 transition-all rtl:group-hover:translate-x-1" />
|
||||||
</div>
|
</div>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
);
|
);
|
||||||
@ -586,7 +588,7 @@ export default function ProductPage({ productSlug }: { productSlug: string }) {
|
|||||||
exit={{ opacity: 0, scale: 0.9, y: 20 }}
|
exit={{ opacity: 0, scale: 0.9, y: 20 }}
|
||||||
className="bg-white w-full max-w-lg rounded-[3rem] p-10 relative z-10 shadow-2xl overflow-hidden"
|
className="bg-white w-full max-w-lg rounded-[3rem] p-10 relative z-10 shadow-2xl overflow-hidden"
|
||||||
>
|
>
|
||||||
<div className="absolute top-0 left-0 w-full h-2 bg-gradient-to-r from-canino-blue via-blue-400 to-canino-blue" />
|
<div className="absolute top-0 left-0 w-full h-2 bg-gradient-to-r from-canina-blue via-blue-400 to-canina-blue" />
|
||||||
<button
|
<button
|
||||||
onClick={() => setShowRefillModal(false)}
|
onClick={() => setShowRefillModal(false)}
|
||||||
className="absolute top-6 left-6 text-medical-gray-400 hover:text-medical-gray-600 transition-colors"
|
className="absolute top-6 left-6 text-medical-gray-400 hover:text-medical-gray-600 transition-colors"
|
||||||
@ -595,13 +597,13 @@ export default function ProductPage({ productSlug }: { productSlug: string }) {
|
|||||||
</button>
|
</button>
|
||||||
|
|
||||||
<div className="text-center">
|
<div className="text-center">
|
||||||
<div className="w-20 h-20 bg-canino-blue/10 rounded-[2rem] flex items-center justify-center mx-auto mb-8">
|
<div className="w-20 h-20 bg-canina-blue/10 rounded-[2rem] flex items-center justify-center mx-auto mb-8">
|
||||||
<Bell className="w-10 h-10 text-canino-blue animate-bounce" />
|
<Bell className="w-10 h-10 text-canina-blue animate-bounce" />
|
||||||
</div>
|
</div>
|
||||||
<h3 className="text-3xl font-black text-medical-gray-900 mb-4 leading-tight italic">سیستم یادآوری هوشمند</h3>
|
<h3 className="text-3xl font-black text-medical-gray-900 mb-4 leading-tight italic">سیستم یادآوری هوشمند</h3>
|
||||||
<div className="bg-medical-gray-50 border border-medical-gray-100 rounded-3xl p-6 mb-8 text-right">
|
<div className="bg-medical-gray-50 border border-medical-gray-100 rounded-3xl p-6 mb-8 text-right">
|
||||||
<p className="text-medical-gray-700 leading-relaxed font-medium font-vazir">
|
<p className="text-medical-gray-700 leading-relaxed font-medium font-vazir">
|
||||||
بر اساس وزن <span className="text-canino-blue font-bold">{toPersian(weight)} کیلوگرمی</span> {activePet ? `برای ${activePet.name}` : 'سگ شما'}، این بسته {toPersian(product.packageSize)} تایی دقیقاً <span className="text-canino-blue font-bold">{toPersian(calculation.duration)} روز</span> دیگر تمام میشود.
|
بر اساس وزن <span className="text-canina-blue font-bold">{toPersian(weight)} کیلوگرمی</span> {activePet ? `برای ${activePet.name}` : 'سگ شما'}، این بسته {toPersian(product.packageSize)} تایی دقیقاً <span className="text-canina-blue font-bold">{toPersian(calculation.duration)} روز</span> دیگر تمام میشود.
|
||||||
</p>
|
</p>
|
||||||
<div className="mt-4 flex items-center gap-2 text-xs font-bold text-medical-gray-500 font-vazir">
|
<div className="mt-4 flex items-center gap-2 text-xs font-bold text-medical-gray-500 font-vazir">
|
||||||
<ShieldCheck className="w-4 h-4 text-green-500" />
|
<ShieldCheck className="w-4 h-4 text-green-500" />
|
||||||
@ -612,7 +614,7 @@ export default function ProductPage({ productSlug }: { productSlug: string }) {
|
|||||||
<div className="flex flex-col gap-3">
|
<div className="flex flex-col gap-3">
|
||||||
<button
|
<button
|
||||||
onClick={() => setShowRefillModal(false)}
|
onClick={() => setShowRefillModal(false)}
|
||||||
className="w-full bg-canino-blue text-white py-5 rounded-2xl font-black text-lg hover:shadow-xl hover:shadow-canino-blue/20 transition-all flex items-center justify-center gap-2"
|
className="w-full bg-canina-blue text-white py-5 rounded-2xl font-black text-lg hover:shadow-xl hover:shadow-canina-blue/20 transition-all flex items-center justify-center gap-2"
|
||||||
>
|
>
|
||||||
<CheckCircle2 className="w-5 h-5" />
|
<CheckCircle2 className="w-5 h-5" />
|
||||||
بله، پیامک یادآوری فعال شود
|
بله، پیامک یادآوری فعال شود
|
||||||
|
|||||||
@ -32,17 +32,17 @@ export default function SafeImage({
|
|||||||
<div className="absolute inset-0 opacity-[0.03] pointer-events-none">
|
<div className="absolute inset-0 opacity-[0.03] pointer-events-none">
|
||||||
<div className="grid grid-cols-6 h-full w-full">
|
<div className="grid grid-cols-6 h-full w-full">
|
||||||
{Array.from({length: 24}).map((_, i) => (
|
{Array.from({length: 24}).map((_, i) => (
|
||||||
<div key={i} className="border border-canino-blue" />
|
<div key={i} className="border border-canina-blue" />
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="w-16 h-16 bg-canino-blue rounded-2xl flex items-center justify-center text-white font-black text-3xl mb-4 shadow-xl shadow-canino-blue/20 italic transform -rotate-6">C</div>
|
<div className="w-16 h-16 bg-canina-blue rounded-2xl flex items-center justify-center text-white font-black text-3xl mb-4 shadow-xl shadow-canina-blue/20 italic transform -rotate-6">C</div>
|
||||||
<div className="relative">
|
<div className="relative">
|
||||||
<ImageOff className="w-5 h-5 text-medical-gray-200 mb-2" />
|
<ImageOff className="w-5 h-5 text-medical-gray-200 mb-2" />
|
||||||
<Sparkles className="w-3 h-3 text-canino-blue absolute -top-1 -right-1 animate-pulse" />
|
<Sparkles className="w-3 h-3 text-canina-blue absolute -top-1 -right-1 animate-pulse" />
|
||||||
</div>
|
</div>
|
||||||
<span className="text-[9px] font-black text-canino-blue/60 uppercase tracking-[0.2em] font-vazir leading-relaxed">
|
<span className="text-[9px] font-black text-canina-blue/60 uppercase tracking-[0.2em] font-vazir leading-relaxed">
|
||||||
{fallbackText}
|
{fallbackText}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
@ -53,7 +53,7 @@ export default function SafeImage({
|
|||||||
<div className={cn("relative overflow-hidden group flex items-center justify-center", className)}>
|
<div className={cn("relative overflow-hidden group flex items-center justify-center", className)}>
|
||||||
{loading && (
|
{loading && (
|
||||||
<div className="absolute inset-0 bg-medical-gray-50 animate-pulse flex items-center justify-center z-10">
|
<div className="absolute inset-0 bg-medical-gray-50 animate-pulse flex items-center justify-center z-10">
|
||||||
<Sparkles className="w-6 h-6 text-canino-blue/20" />
|
<Sparkles className="w-6 h-6 text-canina-blue/20" />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<img
|
<img
|
||||||
|
|||||||
@ -32,7 +32,7 @@ export default function SearchResultsPage({ query }: { query: string }) {
|
|||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-medical-gray-50 py-20 px-6 font-vazir" dir="rtl">
|
<div className="min-h-screen bg-medical-gray-50 py-20 px-6 font-vazir" dir="rtl">
|
||||||
<div className="max-w-7xl mx-auto">
|
<div className="max-w-7xl mx-auto">
|
||||||
<button onClick={() => router.back()} className="flex items-center gap-2 text-medical-gray-400 font-black mb-10 hover:text-canino-blue transition-colors">
|
<button onClick={() => router.back()} className="flex items-center gap-2 text-medical-gray-400 font-black mb-10 hover:text-canina-blue transition-colors">
|
||||||
<ArrowRight className="w-5 h-5 rotate-180" />
|
<ArrowRight className="w-5 h-5 rotate-180" />
|
||||||
بازگشت
|
بازگشت
|
||||||
</button>
|
</button>
|
||||||
@ -40,7 +40,7 @@ export default function SearchResultsPage({ query }: { query: string }) {
|
|||||||
<div className="flex flex-col md:flex-row md:items-end justify-between mb-16 gap-6">
|
<div className="flex flex-col md:flex-row md:items-end justify-between mb-16 gap-6">
|
||||||
<div>
|
<div>
|
||||||
<h1 className="text-4xl font-black text-medical-gray-900 italic mb-4">
|
<h1 className="text-4xl font-black text-medical-gray-900 italic mb-4">
|
||||||
نتایج جستجو برای: <span className="text-canino-blue">"{query}"</span>
|
نتایج جستجو برای: <span className="text-canina-blue">"{query}"</span>
|
||||||
</h1>
|
</h1>
|
||||||
<p className="text-medical-gray-500 font-medium">
|
<p className="text-medical-gray-500 font-medium">
|
||||||
{results.length} محصول با معیارهای شما مطابقت دارد.
|
{results.length} محصول با معیارهای شما مطابقت دارد.
|
||||||
@ -65,7 +65,7 @@ export default function SearchResultsPage({ query }: { query: string }) {
|
|||||||
key={product.id}
|
key={product.id}
|
||||||
layoutId={product.id}
|
layoutId={product.id}
|
||||||
onClick={() => router.push(`/shop/${product.slug || product.id}`)}
|
onClick={() => router.push(`/shop/${product.slug || product.id}`)}
|
||||||
className="bg-white rounded-[2.5rem] p-8 border border-medical-gray-200 group cursor-pointer hover:shadow-2xl hover:shadow-canino-blue/10 transition-all flex flex-col relative"
|
className="bg-white rounded-[2.5rem] p-8 border border-medical-gray-200 group cursor-pointer hover:shadow-2xl hover:shadow-canina-blue/10 transition-all flex flex-col relative"
|
||||||
>
|
>
|
||||||
<div className="relative aspect-square mb-8 bg-medical-gray-50 rounded-[2rem] overflow-hidden p-6 flex items-center justify-center">
|
<div className="relative aspect-square mb-8 bg-medical-gray-50 rounded-[2rem] overflow-hidden p-6 flex items-center justify-center">
|
||||||
<img
|
<img
|
||||||
@ -91,8 +91,8 @@ export default function SearchResultsPage({ query }: { query: string }) {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex-1">
|
<div className="flex-1">
|
||||||
<span className="text-[10px] font-black text-canino-blue uppercase tracking-widest mb-2 block">{product.category}</span>
|
<span className="text-[10px] font-black text-canina-blue uppercase tracking-widest mb-2 block">{product.category}</span>
|
||||||
<h3 className="text-xl font-black text-medical-gray-900 mb-2 leading-tight group-hover:text-canino-blue transition-colors">{product.name}</h3>
|
<h3 className="text-xl font-black text-medical-gray-900 mb-2 leading-tight group-hover:text-canina-blue transition-colors">{product.name}</h3>
|
||||||
<p className="text-xs text-medical-gray-400 line-clamp-2 leading-relaxed mb-6">{product.benefits}</p>
|
<p className="text-xs text-medical-gray-400 line-clamp-2 leading-relaxed mb-6">{product.benefits}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -100,7 +100,7 @@ export default function SearchResultsPage({ query }: { query: string }) {
|
|||||||
<div>
|
<div>
|
||||||
<span className="text-lg font-black text-medical-gray-900">{product.price}</span>
|
<span className="text-lg font-black text-medical-gray-900">{product.price}</span>
|
||||||
</div>
|
</div>
|
||||||
<button className="bg-medical-gray-900 text-white w-10 h-10 rounded-xl flex items-center justify-center group-hover:bg-canino-blue transition-colors">
|
<button className="bg-medical-gray-900 text-white w-10 h-10 rounded-xl flex items-center justify-center group-hover:bg-canina-blue transition-colors">
|
||||||
<ChevronLeft className="w-5 h-5" />
|
<ChevronLeft className="w-5 h-5" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -95,12 +95,12 @@ export default function SmartAdvisor({ onComplete, rules = [] }: SmartAdvisorPro
|
|||||||
<motion.div
|
<motion.div
|
||||||
initial={{ opacity: 0, y: 20 }}
|
initial={{ opacity: 0, y: 20 }}
|
||||||
whileInView={{ opacity: 1, y: 0 }}
|
whileInView={{ opacity: 1, y: 0 }}
|
||||||
className="inline-flex items-center gap-2 px-4 py-2 bg-canino-blue/5 rounded-full mb-6"
|
className="inline-flex items-center gap-2 px-4 py-2 bg-canina-blue/5 rounded-full mb-6"
|
||||||
>
|
>
|
||||||
<Sparkle className="w-4 h-4 text-canino-blue" />
|
<Sparkle className="w-4 h-4 text-canina-blue" />
|
||||||
<span className="text-canino-blue text-xs font-black uppercase tracking-widest font-vazir">تکنولوژی پایش هوشمند</span>
|
<span className="text-canina-blue text-xs font-black uppercase tracking-widest font-vazir">تکنولوژی پایش هوشمند</span>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
<h2 className="text-4xl lg:text-5xl font-black text-medical-gray-900 mb-4 font-vazir italic">دستیار سلامت کانینو</h2>
|
<h2 className="text-4xl lg:text-5xl font-black text-medical-gray-900 mb-4 font-vazir italic">دستیار سلامت کانینا</h2>
|
||||||
<p className="text-medical-gray-600 font-bold text-lg font-vazir">فقط چند قدم تا صدور شناسنامه هوشمند و دریافت پیشنهادات تخصصی</p>
|
<p className="text-medical-gray-600 font-bold text-lg font-vazir">فقط چند قدم تا صدور شناسنامه هوشمند و دریافت پیشنهادات تخصصی</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -108,7 +108,7 @@ export default function SmartAdvisor({ onComplete, rules = [] }: SmartAdvisorPro
|
|||||||
{/* Progress Indicator */}
|
{/* Progress Indicator */}
|
||||||
<div className="absolute top-0 left-0 w-full h-2 bg-medical-gray-200">
|
<div className="absolute top-0 left-0 w-full h-2 bg-medical-gray-200">
|
||||||
<motion.div
|
<motion.div
|
||||||
className="h-full bg-canino-blue"
|
className="h-full bg-canina-blue"
|
||||||
initial={{ width: "0%" }}
|
initial={{ width: "0%" }}
|
||||||
animate={{ width: `${(step / 3) * 100}%` }}
|
animate={{ width: `${(step / 3) * 100}%` }}
|
||||||
transition={{ duration: 0.5 }}
|
transition={{ duration: 0.5 }}
|
||||||
@ -132,16 +132,16 @@ export default function SmartAdvisor({ onComplete, rules = [] }: SmartAdvisorPro
|
|||||||
<div className="grid grid-cols-2 gap-4">
|
<div className="grid grid-cols-2 gap-4">
|
||||||
<button
|
<button
|
||||||
onClick={() => setType("سگ")}
|
onClick={() => setType("سگ")}
|
||||||
className={`flex flex-col items-center gap-4 p-8 rounded-[2.5rem] border-4 transition-all focus-visible:ring-4 focus-visible:ring-canino-blue/30 focus-visible:outline-none ${type === "سگ" ? 'border-canino-blue bg-white shadow-xl shadow-canino-blue/10 scale-105' : 'border-transparent bg-white/50 text-medical-gray-400 hover:bg-white'}`}
|
className={`flex flex-col items-center gap-4 p-8 rounded-[2.5rem] border-4 transition-all focus-visible:ring-4 focus-visible:ring-canina-blue/30 focus-visible:outline-none ${type === "سگ" ? 'border-canina-blue bg-white shadow-xl shadow-canina-blue/10 scale-105' : 'border-transparent bg-white/50 text-medical-gray-400 hover:bg-white'}`}
|
||||||
>
|
>
|
||||||
<Dog className={`w-12 h-12 ${type === "سگ" ? 'text-canino-blue' : 'text-current'}`} />
|
<Dog className={`w-12 h-12 ${type === "سگ" ? 'text-canina-blue' : 'text-current'}`} />
|
||||||
<span className="text-lg font-black font-vazir">سگ</span>
|
<span className="text-lg font-black font-vazir">سگ</span>
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => setType("گربه")}
|
onClick={() => setType("گربه")}
|
||||||
className={`flex flex-col items-center gap-4 p-8 rounded-[2.5rem] border-4 transition-all focus-visible:ring-4 focus-visible:ring-canino-blue/30 focus-visible:outline-none ${type === "گربه" ? 'border-canino-blue bg-white shadow-xl shadow-canino-blue/10 scale-105' : 'border-transparent bg-white/50 text-medical-gray-400 hover:bg-white'}`}
|
className={`flex flex-col items-center gap-4 p-8 rounded-[2.5rem] border-4 transition-all focus-visible:ring-4 focus-visible:ring-canina-blue/30 focus-visible:outline-none ${type === "گربه" ? 'border-canina-blue bg-white shadow-xl shadow-canina-blue/10 scale-105' : 'border-transparent bg-white/50 text-medical-gray-400 hover:bg-white'}`}
|
||||||
>
|
>
|
||||||
<Cat className={`w-12 h-12 ${type === "گربه" ? 'text-canino-blue' : 'text-current'}`} />
|
<Cat className={`w-12 h-12 ${type === "گربه" ? 'text-canina-blue' : 'text-current'}`} />
|
||||||
<span className="text-lg font-black font-vazir">گربه</span>
|
<span className="text-lg font-black font-vazir">گربه</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@ -154,7 +154,7 @@ export default function SmartAdvisor({ onComplete, rules = [] }: SmartAdvisorPro
|
|||||||
value={name}
|
value={name}
|
||||||
onChange={e => setName(e.target.value)}
|
onChange={e => setName(e.target.value)}
|
||||||
placeholder="لوسی، تدی..."
|
placeholder="لوسی، تدی..."
|
||||||
className="w-full bg-white border border-medical-gray-300 rounded-2xl py-4 px-6 focus:ring-2 focus:ring-canino-blue/30 focus-visible:ring-4 focus-visible:ring-canino-blue/40 outline-none font-black text-lg font-vazir placeholder-medical-gray-500 text-medical-gray-900"
|
className="w-full bg-white border border-medical-gray-300 rounded-2xl py-4 px-6 focus:ring-2 focus:ring-canina-blue/30 focus-visible:ring-4 focus-visible:ring-canina-blue/40 outline-none font-black text-lg font-vazir placeholder-medical-gray-500 text-medical-gray-900"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
@ -164,7 +164,7 @@ export default function SmartAdvisor({ onComplete, rules = [] }: SmartAdvisorPro
|
|||||||
value={breed}
|
value={breed}
|
||||||
onChange={e => setBreed(e.target.value)}
|
onChange={e => setBreed(e.target.value)}
|
||||||
placeholder="ژرمن، پرشین..."
|
placeholder="ژرمن، پرشین..."
|
||||||
className="w-full bg-white border border-medical-gray-300 rounded-2xl py-4 px-6 focus:ring-2 focus:ring-canino-blue/30 focus-visible:ring-4 focus-visible:ring-canino-blue/40 outline-none font-bold font-vazir placeholder-medical-gray-500 text-medical-gray-900"
|
className="w-full bg-white border border-medical-gray-300 rounded-2xl py-4 px-6 focus:ring-2 focus:ring-canina-blue/30 focus-visible:ring-4 focus-visible:ring-canina-blue/40 outline-none font-bold font-vazir placeholder-medical-gray-500 text-medical-gray-900"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -172,7 +172,7 @@ export default function SmartAdvisor({ onComplete, rules = [] }: SmartAdvisorPro
|
|||||||
<button
|
<button
|
||||||
onClick={handleNext}
|
onClick={handleNext}
|
||||||
disabled={!name || !breed}
|
disabled={!name || !breed}
|
||||||
className="w-full py-6 rounded-3xl font-black text-lg flex items-center justify-center gap-3 font-vazir min-h-[48px] transition-all focus-visible:ring-4 focus-visible:ring-canino-blue/30 focus-visible:outline-none disabled:bg-gray-200 disabled:text-gray-400 disabled:cursor-not-allowed disabled:shadow-none disabled:border-2 disabled:border-gray-300 bg-medical-gray-900 text-white hover:bg-canino-blue shadow-xl shadow-medical-gray-900/10"
|
className="w-full py-6 rounded-3xl font-black text-lg flex items-center justify-center gap-3 font-vazir min-h-[48px] transition-all focus-visible:ring-4 focus-visible:ring-canina-blue/30 focus-visible:outline-none disabled:bg-gray-300 disabled:text-gray-500 disabled:cursor-not-allowed disabled:shadow-none disabled:border-2 disabled:border-gray-400 bg-medical-gray-900 text-white hover:bg-canina-blue shadow-xl shadow-medical-gray-900/10"
|
||||||
>
|
>
|
||||||
ثبت هویت و ادامه
|
ثبت هویت و ادامه
|
||||||
<ChevronLeft className="w-5 h-5" />
|
<ChevronLeft className="w-5 h-5" />
|
||||||
@ -202,17 +202,17 @@ export default function SmartAdvisor({ onComplete, rules = [] }: SmartAdvisorPro
|
|||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<label className="block text-center text-sm font-black text-medical-gray-800 font-vazir">سن حیوان (سال)</label>
|
<label className="block text-center text-sm font-black text-medical-gray-800 font-vazir">سن حیوان (سال)</label>
|
||||||
<div className="flex items-center gap-4 bg-white rounded-3xl p-2 border-2 border-medical-gray-200">
|
<div className="flex items-center gap-4 bg-white rounded-3xl p-2 border-2 border-medical-gray-200">
|
||||||
<button onClick={() => setAge(Math.max(0, age - 1))} className="w-12 h-12 flex items-center justify-center bg-medical-gray-50 rounded-xl text-medical-gray-900 hover:bg-canino-blue hover:text-white focus-visible:ring-2 focus-visible:ring-canino-blue focus-visible:outline-none transition-all shadow-sm font-black text-lg">-</button>
|
<button onClick={() => setAge(Math.max(0, age - 1))} className="w-12 h-12 flex items-center justify-center bg-medical-gray-50 rounded-xl text-medical-gray-900 hover:bg-canina-blue hover:text-white focus-visible:ring-2 focus-visible:ring-canina-blue focus-visible:outline-none transition-all shadow-sm font-black text-lg">-</button>
|
||||||
<span className="flex-1 text-center text-2xl font-black text-canino-blue font-vazir">{toPersian(age.toString())} <span className="text-sm font-bold text-medical-gray-400">سال</span></span>
|
<span className="flex-1 text-center text-2xl font-black text-canina-blue font-vazir">{toPersian(age.toString())} <span className="text-sm font-bold text-medical-gray-400">سال</span></span>
|
||||||
<button onClick={() => setAge(age + 1)} className="w-12 h-12 flex items-center justify-center bg-medical-gray-50 rounded-xl text-medical-gray-900 hover:bg-canino-blue hover:text-white focus-visible:ring-2 focus-visible:ring-canino-blue focus-visible:outline-none transition-all shadow-sm font-black text-lg">+</button>
|
<button onClick={() => setAge(age + 1)} className="w-12 h-12 flex items-center justify-center bg-medical-gray-50 rounded-xl text-medical-gray-900 hover:bg-canina-blue hover:text-white focus-visible:ring-2 focus-visible:ring-canina-blue focus-visible:outline-none transition-all shadow-sm font-black text-lg">+</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<label className="block text-center text-sm font-black text-medical-gray-800 font-vazir">وزن حیوان (کیلوگرم)</label>
|
<label className="block text-center text-sm font-black text-medical-gray-800 font-vazir">وزن حیوان (کیلوگرم)</label>
|
||||||
<div className="flex items-center gap-4 bg-white rounded-3xl p-2 border-2 border-medical-gray-200">
|
<div className="flex items-center gap-4 bg-white rounded-3xl p-2 border-2 border-medical-gray-200">
|
||||||
<button onClick={() => setWeight(Math.max(1, weight - 1))} className="w-12 h-12 flex items-center justify-center bg-medical-gray-50 rounded-xl text-medical-gray-900 hover:bg-canino-blue hover:text-white focus-visible:ring-2 focus-visible:ring-canino-blue focus-visible:outline-none transition-all shadow-sm font-black text-lg">-</button>
|
<button onClick={() => setWeight(Math.max(1, weight - 1))} className="w-12 h-12 flex items-center justify-center bg-medical-gray-50 rounded-xl text-medical-gray-900 hover:bg-canina-blue hover:text-white focus-visible:ring-2 focus-visible:ring-canina-blue focus-visible:outline-none transition-all shadow-sm font-black text-lg">-</button>
|
||||||
<span className="flex-1 text-center text-2xl font-black text-canino-blue font-vazir">{toPersian(weight.toString())} <span className="text-sm font-bold text-medical-gray-400">kg</span></span>
|
<span className="flex-1 text-center text-2xl font-black text-canina-blue font-vazir">{toPersian(weight.toString())} <span className="text-sm font-bold text-medical-gray-400">kg</span></span>
|
||||||
<button onClick={() => setWeight(weight + 1)} className="w-12 h-12 flex items-center justify-center bg-medical-gray-50 rounded-xl text-medical-gray-900 hover:bg-canino-blue hover:text-white focus-visible:ring-2 focus-visible:ring-canino-blue focus-visible:outline-none transition-all shadow-sm font-black text-lg">+</button>
|
<button onClick={() => setWeight(weight + 1)} className="w-12 h-12 flex items-center justify-center bg-medical-gray-50 rounded-xl text-medical-gray-900 hover:bg-canina-blue hover:text-white focus-visible:ring-2 focus-visible:ring-canina-blue focus-visible:outline-none transition-all shadow-sm font-black text-lg">+</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -224,7 +224,7 @@ export default function SmartAdvisor({ onComplete, rules = [] }: SmartAdvisorPro
|
|||||||
<button
|
<button
|
||||||
key={level}
|
key={level}
|
||||||
onClick={() => setActivityLevel(level as any)}
|
onClick={() => setActivityLevel(level as any)}
|
||||||
className={`py-4 rounded-2xl border-2 transition-all font-black italic focus-visible:ring-4 focus-visible:ring-canino-blue/30 focus-visible:outline-none min-h-[48px] ${activityLevel === level ? 'border-canino-blue bg-white text-canino-blue shadow-lg' : 'border-transparent bg-white/50 text-medical-gray-500 hover:bg-white'}`}
|
className={`py-4 rounded-2xl border-2 transition-all font-black italic focus-visible:ring-4 focus-visible:ring-canina-blue/30 focus-visible:outline-none min-h-[48px] ${activityLevel === level ? 'border-canina-blue bg-white text-canina-blue shadow-lg' : 'border-transparent bg-white/50 text-medical-gray-500 hover:bg-white'}`}
|
||||||
>
|
>
|
||||||
{level}
|
{level}
|
||||||
</button>
|
</button>
|
||||||
@ -235,14 +235,14 @@ export default function SmartAdvisor({ onComplete, rules = [] }: SmartAdvisorPro
|
|||||||
<div className="flex gap-4 pt-4">
|
<div className="flex gap-4 pt-4">
|
||||||
<button
|
<button
|
||||||
onClick={handleBack}
|
onClick={handleBack}
|
||||||
className="flex-1 py-6 bg-medical-gray-100 text-medical-gray-600 rounded-3xl font-black text-lg hover:bg-medical-gray-200 focus-visible:ring-4 focus-visible:ring-canino-blue/30 focus-visible:outline-none transition-all flex items-center justify-center gap-3 font-vazir min-h-[48px]"
|
className="flex-1 py-6 bg-medical-gray-100 text-medical-gray-600 rounded-3xl font-black text-lg hover:bg-medical-gray-200 focus-visible:ring-4 focus-visible:ring-canina-blue/30 focus-visible:outline-none transition-all flex items-center justify-center gap-3 font-vazir min-h-[48px]"
|
||||||
>
|
>
|
||||||
<ChevronRight className="w-5 h-5" />
|
<ChevronRight className="w-5 h-5" />
|
||||||
قبلی
|
قبلی
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={handleNext}
|
onClick={handleNext}
|
||||||
className="flex-[2] py-6 bg-medical-gray-900 text-white rounded-3xl font-black text-lg hover:bg-canino-blue focus-visible:ring-4 focus-visible:ring-canino-blue/30 focus-visible:outline-none transition-all shadow-xl shadow-medical-gray-900/10 flex items-center justify-center gap-3 font-vazir min-h-[48px]"
|
className="flex-[2] py-6 bg-medical-gray-900 text-white rounded-3xl font-black text-lg hover:bg-canina-blue focus-visible:ring-4 focus-visible:ring-canina-blue/30 focus-visible:outline-none transition-all shadow-xl shadow-medical-gray-900/10 flex items-center justify-center gap-3 font-vazir min-h-[48px]"
|
||||||
>
|
>
|
||||||
گام نهایی سلامت
|
گام نهایی سلامت
|
||||||
<ChevronLeft className="w-5 h-5" />
|
<ChevronLeft className="w-5 h-5" />
|
||||||
@ -273,12 +273,12 @@ export default function SmartAdvisor({ onComplete, rules = [] }: SmartAdvisorPro
|
|||||||
prev.includes(opt.condition) ? prev.filter(c => c !== opt.condition) : [...prev, opt.condition]
|
prev.includes(opt.condition) ? prev.filter(c => c !== opt.condition) : [...prev, opt.condition]
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
className={`flex items-center gap-4 p-5 rounded-2xl border-2 transition-all text-right focus-visible:ring-4 focus-visible:ring-canino-blue/30 focus-visible:outline-none min-h-[48px] ${medicalConditions.includes(opt.condition) ? 'border-canino-blue bg-white shadow-md' : 'border-transparent bg-white/50 text-medical-gray-600 hover:bg-white'}`}
|
className={`flex items-center gap-4 p-5 rounded-2xl border-2 transition-all text-right focus-visible:ring-4 focus-visible:ring-canina-blue/30 focus-visible:outline-none min-h-[48px] ${medicalConditions.includes(opt.condition) ? 'border-canina-blue bg-white shadow-md' : 'border-transparent bg-white/50 text-medical-gray-600 hover:bg-white'}`}
|
||||||
>
|
>
|
||||||
<div className={`w-8 h-8 rounded-lg flex items-center justify-center border ${medicalConditions.includes(opt.condition) ? 'bg-canino-blue border-canino-blue text-white' : 'border-medical-gray-300 text-transparent'}`}>
|
<div className={`w-8 h-8 rounded-lg flex items-center justify-center border ${medicalConditions.includes(opt.condition) ? 'bg-canina-blue border-canina-blue text-white' : 'border-medical-gray-300 text-transparent'}`}>
|
||||||
<ShieldCheck className="w-5 h-5" />
|
<ShieldCheck className="w-5 h-5" />
|
||||||
</div>
|
</div>
|
||||||
<span className={`text-sm font-black font-vazir ${medicalConditions.includes(opt.condition) ? 'text-canino-blue' : 'text-medical-gray-900'}`}>{opt.label}</span>
|
<span className={`text-sm font-black font-vazir ${medicalConditions.includes(opt.condition) ? 'text-canina-blue' : 'text-medical-gray-900'}`}>{opt.label}</span>
|
||||||
</button>
|
</button>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
@ -286,14 +286,14 @@ export default function SmartAdvisor({ onComplete, rules = [] }: SmartAdvisorPro
|
|||||||
<div className="flex gap-4 pt-4">
|
<div className="flex gap-4 pt-4">
|
||||||
<button
|
<button
|
||||||
onClick={handleBack}
|
onClick={handleBack}
|
||||||
className="flex-1 py-6 bg-medical-gray-100 text-medical-gray-600 rounded-3xl font-black text-lg hover:bg-medical-gray-200 focus-visible:ring-4 focus-visible:ring-canino-blue/30 focus-visible:outline-none transition-all flex items-center justify-center gap-3 font-vazir min-h-[48px]"
|
className="flex-1 py-6 bg-medical-gray-100 text-medical-gray-600 rounded-3xl font-black text-lg hover:bg-medical-gray-200 focus-visible:ring-4 focus-visible:ring-canina-blue/30 focus-visible:outline-none transition-all flex items-center justify-center gap-3 font-vazir min-h-[48px]"
|
||||||
>
|
>
|
||||||
<ChevronRight className="w-5 h-5" />
|
<ChevronRight className="w-5 h-5" />
|
||||||
قبلی
|
قبلی
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={handleSubmit}
|
onClick={handleSubmit}
|
||||||
className="flex-[2] py-6 bg-canino-blue text-white rounded-3xl font-black text-lg hover:bg-indigo-700 focus-visible:ring-4 focus-visible:ring-canino-blue/30 focus-visible:outline-none transition-all shadow-xl shadow-canino-blue/20 flex items-center justify-center gap-3 font-vazir min-h-[48px]"
|
className="flex-[2] py-6 bg-canina-blue text-white rounded-3xl font-black text-lg hover:bg-indigo-700 focus-visible:ring-4 focus-visible:ring-canina-blue/30 focus-visible:outline-none transition-all shadow-xl shadow-canina-blue/20 flex items-center justify-center gap-3 font-vazir min-h-[48px]"
|
||||||
>
|
>
|
||||||
تکمیل و صدور شناسنامه
|
تکمیل و صدور شناسنامه
|
||||||
<ChevronLeft className="w-5 h-5" />
|
<ChevronLeft className="w-5 h-5" />
|
||||||
|
|||||||
@ -20,7 +20,7 @@ export default function Tooltip({ termKey, children, onWikiNavigate }: TooltipPr
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<span
|
<span
|
||||||
className="relative inline-block group cursor-help border-b border-dotted border-canino-blue/40"
|
className="relative inline-block group cursor-help border-b border-dotted border-canina-blue/40"
|
||||||
onMouseEnter={() => setIsVisible(true)}
|
onMouseEnter={() => setIsVisible(true)}
|
||||||
onMouseLeave={() => setIsVisible(false)}
|
onMouseLeave={() => setIsVisible(false)}
|
||||||
>
|
>
|
||||||
@ -35,9 +35,9 @@ export default function Tooltip({ termKey, children, onWikiNavigate }: TooltipPr
|
|||||||
className="absolute bottom-full left-1/2 -translate-x-1/2 mb-3 w-64 p-4 bg-medical-gray-900 text-white rounded-2xl shadow-2xl z-[100] text-sm"
|
className="absolute bottom-full left-1/2 -translate-x-1/2 mb-3 w-64 p-4 bg-medical-gray-900 text-white rounded-2xl shadow-2xl z-[100] text-sm"
|
||||||
dir="rtl"
|
dir="rtl"
|
||||||
>
|
>
|
||||||
<div className="flex items-center gap-2 mb-2 text-canino-blue">
|
<div className="flex items-center gap-2 mb-2 text-canina-blue">
|
||||||
<Info className="w-4 h-4" />
|
<Info className="w-4 h-4" />
|
||||||
<span className="font-black text-[10px] uppercase tracking-widest">دانشنامه علمی کانینو</span>
|
<span className="font-black text-[10px] uppercase tracking-widest">دانشنامه علمی کانینا</span>
|
||||||
</div>
|
</div>
|
||||||
<h5 className="font-black mb-1">{termData.term}</h5>
|
<h5 className="font-black mb-1">{termData.term}</h5>
|
||||||
<p className="text-white/70 text-xs leading-relaxed mb-3">
|
<p className="text-white/70 text-xs leading-relaxed mb-3">
|
||||||
@ -46,7 +46,7 @@ export default function Tooltip({ termKey, children, onWikiNavigate }: TooltipPr
|
|||||||
{termData.wikiId && (
|
{termData.wikiId && (
|
||||||
<button
|
<button
|
||||||
onClick={() => onWikiNavigate?.(termData.wikiId!)}
|
onClick={() => onWikiNavigate?.(termData.wikiId!)}
|
||||||
className="flex items-center gap-1.5 text-canino-blue hover:text-white transition-colors text-[10px] font-bold"
|
className="flex items-center gap-1.5 text-canina-blue hover:text-white transition-colors text-[10px] font-bold"
|
||||||
>
|
>
|
||||||
<span>مطالعه مقاله کامل</span>
|
<span>مطالعه مقاله کامل</span>
|
||||||
<ExternalLink className="w-3 h-3" />
|
<ExternalLink className="w-3 h-3" />
|
||||||
|
|||||||
@ -75,7 +75,7 @@ export default function TopUpModal({ isOpen, onClose, onConfirm }: TopUpModalPro
|
|||||||
>
|
>
|
||||||
<div className="bg-medical-gray-50 px-8 py-6 border-b border-medical-gray-100 flex items-center justify-between">
|
<div className="bg-medical-gray-50 px-8 py-6 border-b border-medical-gray-100 flex items-center justify-between">
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
<div className="w-10 h-10 bg-canino-blue rounded-xl flex items-center justify-center text-white">
|
<div className="w-10 h-10 bg-canina-blue rounded-xl flex items-center justify-center text-white">
|
||||||
<TrendingUp className="w-5 h-5" />
|
<TrendingUp className="w-5 h-5" />
|
||||||
</div>
|
</div>
|
||||||
<h3 className="text-xl font-black text-medical-gray-900 italic">شارژ سریع کیف پول</h3>
|
<h3 className="text-xl font-black text-medical-gray-900 italic">شارژ سریع کیف پول</h3>
|
||||||
@ -100,8 +100,8 @@ export default function TopUpModal({ isOpen, onClose, onConfirm }: TopUpModalPro
|
|||||||
className={cn(
|
className={cn(
|
||||||
"px-6 py-3 rounded-2xl text-sm font-black transition-all border",
|
"px-6 py-3 rounded-2xl text-sm font-black transition-all border",
|
||||||
selectedPreset === preset.value
|
selectedPreset === preset.value
|
||||||
? "bg-canino-blue text-white border-canino-blue shadow-lg shadow-canino-blue/20"
|
? "bg-canina-blue text-white border-canina-blue shadow-lg shadow-canina-blue/20"
|
||||||
: "bg-white text-medical-gray-700 border-medical-gray-100 hover:border-canino-blue"
|
: "bg-white text-medical-gray-700 border-medical-gray-100 hover:border-canina-blue"
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{preset.label}
|
{preset.label}
|
||||||
@ -118,7 +118,7 @@ export default function TopUpModal({ isOpen, onClose, onConfirm }: TopUpModalPro
|
|||||||
type="text"
|
type="text"
|
||||||
value={amount ? parseInt(amount).toLocaleString() : ""}
|
value={amount ? parseInt(amount).toLocaleString() : ""}
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
className="w-full bg-medical-gray-50 border border-medical-gray-100 rounded-3xl py-6 px-8 outline-none font-black text-2xl text-center text-medical-gray-900 transition-all focus:ring-4 focus:ring-canino-blue/10 focus:border-canino-blue italic"
|
className="w-full bg-medical-gray-50 border border-medical-gray-100 rounded-3xl py-6 px-8 outline-none font-black text-2xl text-center text-medical-gray-900 transition-all focus:ring-4 focus:ring-canina-blue/10 focus:border-canina-blue italic"
|
||||||
placeholder="۰"
|
placeholder="۰"
|
||||||
/>
|
/>
|
||||||
{amount && (
|
{amount && (
|
||||||
@ -128,14 +128,14 @@ export default function TopUpModal({ isOpen, onClose, onConfirm }: TopUpModalPro
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="bg-blue-50 border border-blue-100 rounded-2xl p-4 flex gap-3">
|
<div className="bg-blue-50 border border-blue-100 rounded-2xl p-4 flex gap-3">
|
||||||
<Sparkles className="w-5 h-5 text-canino-blue shrink-0" />
|
<Sparkles className="w-5 h-5 text-canina-blue shrink-0" />
|
||||||
<p className="text-[10px] font-bold text-canino-blue leading-relaxed">با شارژ کیف پول، از هدیههای هوشمند کانینو و اولویت در ارسال سفارشها بهرهمند شوید.</p>
|
<p className="text-[10px] font-bold text-canina-blue leading-relaxed">با شارژ کیف پول، از هدیههای هوشمند کانینا و اولویت در ارسال سفارشها بهرهمند شوید.</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
disabled={loading || !amount}
|
disabled={loading || !amount}
|
||||||
className="w-full py-5 bg-medical-gray-900 text-white rounded-[2rem] font-black text-lg flex items-center justify-center gap-3 hover:bg-canino-blue transition-all shadow-xl shadow-black/10 disabled:opacity-50 disabled:cursor-not-allowed group"
|
className="w-full py-5 bg-medical-gray-900 text-white rounded-[2rem] font-black text-lg flex items-center justify-center gap-3 hover:bg-canina-blue transition-all shadow-xl shadow-black/10 disabled:opacity-50 disabled:cursor-not-allowed group"
|
||||||
>
|
>
|
||||||
{loading ? (
|
{loading ? (
|
||||||
<div className="w-6 h-6 border-4 border-white/20 border-t-white rounded-full animate-spin" />
|
<div className="w-6 h-6 border-4 border-white/20 border-t-white rounded-full animate-spin" />
|
||||||
|
|||||||
@ -143,9 +143,9 @@ export default function UserDashboard() {
|
|||||||
<div className="max-w-6xl mx-auto">
|
<div className="max-w-6xl mx-auto">
|
||||||
{/* Breadcrumb */}
|
{/* Breadcrumb */}
|
||||||
<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 gap-2 text-[10px] font-black text-medical-gray-400 uppercase tracking-widest mb-10">
|
||||||
<span className="cursor-pointer hover:text-canino-blue" onClick={() => router.push('/')}>خانه</span>
|
<span className="cursor-pointer hover:text-canina-blue" onClick={() => router.push('/')}>خانه</span>
|
||||||
<ChevronRight className="w-2.5 h-2.5" />
|
<ChevronRight className="w-2.5 h-2.5" />
|
||||||
<span className="text-canino-blue">پنل کاربری</span>
|
<span className="text-canina-blue">پنل کاربری</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="grid lg:grid-cols-12 gap-8">
|
<div className="grid lg:grid-cols-12 gap-8">
|
||||||
@ -153,7 +153,7 @@ export default function UserDashboard() {
|
|||||||
<div className="lg:col-span-4 space-y-6">
|
<div className="lg:col-span-4 space-y-6">
|
||||||
<div className="bg-white rounded-[3rem] border border-medical-gray-200 p-8 shadow-xl">
|
<div className="bg-white rounded-[3rem] border border-medical-gray-200 p-8 shadow-xl">
|
||||||
<div className="flex items-center gap-4 mb-10">
|
<div className="flex items-center gap-4 mb-10">
|
||||||
<div className="w-16 h-16 bg-canino-blue rounded-3xl flex items-center justify-center text-white shadow-lg">
|
<div className="w-16 h-16 bg-canina-blue rounded-3xl flex items-center justify-center text-white shadow-lg">
|
||||||
<User className="w-8 h-8" />
|
<User className="w-8 h-8" />
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
@ -167,7 +167,7 @@ export default function UserDashboard() {
|
|||||||
<button
|
<button
|
||||||
key={tab.id}
|
key={tab.id}
|
||||||
onClick={() => setActiveTab(tab.id as any)}
|
onClick={() => setActiveTab(tab.id as any)}
|
||||||
className={`w-full flex items-center gap-3 p-4 rounded-2xl transition-all font-bold ${activeTab === tab.id ? "bg-canino-blue text-white shadow-lg shadow-canino-blue/20" : "text-medical-gray-600 hover:bg-medical-gray-50"}`}
|
className={`w-full flex items-center gap-3 p-4 rounded-2xl transition-all font-bold ${activeTab === tab.id ? "bg-canina-blue text-white shadow-lg shadow-canina-blue/20" : "text-medical-gray-600 hover:bg-medical-gray-50"}`}
|
||||||
>
|
>
|
||||||
{tab.icon}
|
{tab.icon}
|
||||||
{tab.label}
|
{tab.label}
|
||||||
@ -185,7 +185,7 @@ export default function UserDashboard() {
|
|||||||
|
|
||||||
<div className="bg-medical-gray-900 rounded-[3rem] p-8 text-white relative overflow-hidden shadow-2xl">
|
<div className="bg-medical-gray-900 rounded-[3rem] p-8 text-white relative overflow-hidden shadow-2xl">
|
||||||
<div className="absolute top-0 left-0 p-6 opacity-20">
|
<div className="absolute top-0 left-0 p-6 opacity-20">
|
||||||
<Wallet className="w-12 h-12 text-canino-blue" />
|
<Wallet className="w-12 h-12 text-canina-blue" />
|
||||||
</div>
|
</div>
|
||||||
<div className="relative z-10">
|
<div className="relative z-10">
|
||||||
<div className="text-[10px] font-black uppercase tracking-widest text-white mb-2">موجودی کیف پول</div>
|
<div className="text-[10px] font-black uppercase tracking-widest text-white mb-2">موجودی کیف پول</div>
|
||||||
@ -196,7 +196,7 @@ export default function UserDashboard() {
|
|||||||
<button
|
<button
|
||||||
onClick={() => { setActiveTab("wallet"); setIsTopUpModalOpen(true); }}
|
onClick={() => { setActiveTab("wallet"); setIsTopUpModalOpen(true); }}
|
||||||
disabled={isTopUpModalOpen}
|
disabled={isTopUpModalOpen}
|
||||||
className="mt-8 bg-canino-blue w-full py-4 rounded-2xl font-black hover:bg-white hover:text-canino-blue transition-all shadow-lg shadow-black/20 flex items-center justify-center gap-2"
|
className="mt-8 bg-canina-blue w-full py-4 rounded-2xl font-black hover:bg-white hover:text-canina-blue transition-all shadow-lg shadow-black/20 flex items-center justify-center gap-2"
|
||||||
>
|
>
|
||||||
شارژ کیف پول
|
شارژ کیف پول
|
||||||
</button>
|
</button>
|
||||||
@ -263,7 +263,7 @@ export default function UserDashboard() {
|
|||||||
className={cn(
|
className={cn(
|
||||||
"w-full border p-4 rounded-2xl font-bold outline-none transition-all",
|
"w-full border p-4 rounded-2xl font-bold outline-none transition-all",
|
||||||
isEditing
|
isEditing
|
||||||
? "bg-white border-canino-blue/30 focus:ring-2 focus:ring-canino-blue/20"
|
? "bg-white border-canina-blue/30 focus:ring-2 focus:ring-canina-blue/20"
|
||||||
: "bg-medical-gray-50 border-medical-gray-100"
|
: "bg-medical-gray-50 border-medical-gray-100"
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
@ -282,7 +282,7 @@ export default function UserDashboard() {
|
|||||||
className={cn(
|
className={cn(
|
||||||
"w-full border p-4 rounded-2xl font-bold outline-none transition-all",
|
"w-full border p-4 rounded-2xl font-bold outline-none transition-all",
|
||||||
isEditing
|
isEditing
|
||||||
? "bg-white border-canino-blue/30 focus:ring-2 focus:ring-canino-blue/20"
|
? "bg-white border-canina-blue/30 focus:ring-2 focus:ring-canina-blue/20"
|
||||||
: "bg-medical-gray-50 border-medical-gray-100"
|
: "bg-medical-gray-50 border-medical-gray-100"
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
@ -301,7 +301,7 @@ export default function UserDashboard() {
|
|||||||
className={cn(
|
className={cn(
|
||||||
"w-full border p-4 rounded-2xl font-bold outline-none transition-all text-left",
|
"w-full border p-4 rounded-2xl font-bold outline-none transition-all text-left",
|
||||||
isEditing
|
isEditing
|
||||||
? "bg-white border-canino-blue/30 focus:ring-2 focus:ring-canino-blue/20"
|
? "bg-white border-canina-blue/30 focus:ring-2 focus:ring-canina-blue/20"
|
||||||
: "bg-medical-gray-50 border-medical-gray-100"
|
: "bg-medical-gray-50 border-medical-gray-100"
|
||||||
)}
|
)}
|
||||||
dir="ltr"
|
dir="ltr"
|
||||||
@ -322,7 +322,7 @@ export default function UserDashboard() {
|
|||||||
className={cn(
|
className={cn(
|
||||||
"w-full border p-4 rounded-2xl font-bold outline-none transition-all text-left",
|
"w-full border p-4 rounded-2xl font-bold outline-none transition-all text-left",
|
||||||
isEditing
|
isEditing
|
||||||
? "bg-white border-canino-blue/30 focus:ring-2 focus:ring-canino-blue/20"
|
? "bg-white border-canina-blue/30 focus:ring-2 focus:ring-canina-blue/20"
|
||||||
: "bg-medical-gray-50 border-medical-gray-100 opacity-75 cursor-not-allowed"
|
: "bg-medical-gray-50 border-medical-gray-100 opacity-75 cursor-not-allowed"
|
||||||
)}
|
)}
|
||||||
dir="ltr"
|
dir="ltr"
|
||||||
@ -336,7 +336,7 @@ export default function UserDashboard() {
|
|||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
disabled={isSavingProfile}
|
disabled={isSavingProfile}
|
||||||
className="bg-canino-blue text-white px-10 py-4 rounded-2xl font-black hover:bg-indigo-700 transition-all flex items-center gap-2 disabled:opacity-50"
|
className="bg-canina-blue text-white px-10 py-4 rounded-2xl font-black hover:bg-indigo-700 transition-all flex items-center gap-2 disabled:opacity-50"
|
||||||
>
|
>
|
||||||
{isSavingProfile && <span className="w-4 h-4 border-2 border-white/30 border-t-white rounded-full animate-spin" />}
|
{isSavingProfile && <span className="w-4 h-4 border-2 border-white/30 border-t-white rounded-full animate-spin" />}
|
||||||
ذخیره تغییرات
|
ذخیره تغییرات
|
||||||
@ -361,7 +361,7 @@ export default function UserDashboard() {
|
|||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => setIsEditing(true)}
|
onClick={() => setIsEditing(true)}
|
||||||
className="bg-medical-gray-900 text-white px-10 py-4 rounded-2xl font-black hover:bg-canino-blue transition-all"
|
className="bg-medical-gray-900 text-white px-10 py-4 rounded-2xl font-black hover:bg-canina-blue transition-all"
|
||||||
>
|
>
|
||||||
ویرایش اطلاعات
|
ویرایش اطلاعات
|
||||||
</button>
|
</button>
|
||||||
@ -383,7 +383,7 @@ export default function UserDashboard() {
|
|||||||
<div className="text-center py-20">
|
<div className="text-center py-20">
|
||||||
<ShoppingBag className="w-16 h-16 text-medical-gray-200 mx-auto mb-4" />
|
<ShoppingBag className="w-16 h-16 text-medical-gray-200 mx-auto mb-4" />
|
||||||
<p className="text-medical-gray-400 font-bold">هنوز سفارشی ثبت نکردهاید.</p>
|
<p className="text-medical-gray-400 font-bold">هنوز سفارشی ثبت نکردهاید.</p>
|
||||||
<button onClick={() => router.push('/shop')} className="mt-6 text-canino-blue font-black underline underline-offset-8">برو به فروشگاه</button>
|
<button onClick={() => router.push('/shop')} className="mt-6 text-canina-blue font-black underline underline-offset-8">برو به فروشگاه</button>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
@ -395,15 +395,15 @@ export default function UserDashboard() {
|
|||||||
key={order.id}
|
key={order.id}
|
||||||
whileHover={{ scale: 1.01, x: -5 }}
|
whileHover={{ scale: 1.01, x: -5 }}
|
||||||
onClick={() => setSelectedOrder(order)}
|
onClick={() => setSelectedOrder(order)}
|
||||||
className="p-6 border border-medical-gray-100 rounded-[2.5rem] hover:border-canino-blue transition-all group cursor-pointer bg-white overflow-hidden relative"
|
className="p-6 border border-medical-gray-100 rounded-[2.5rem] hover:border-canina-blue transition-all group cursor-pointer bg-white overflow-hidden relative"
|
||||||
>
|
>
|
||||||
<div className="flex flex-wrap items-center justify-between gap-4">
|
<div className="flex flex-wrap items-center justify-between gap-4">
|
||||||
<div className="flex items-center gap-4">
|
<div className="flex items-center gap-4">
|
||||||
<div className="w-12 h-12 bg-medical-gray-50 rounded-2xl flex items-center justify-center text-canino-blue group-hover:bg-canino-blue group-hover:text-white transition-all shadow-sm">
|
<div className="w-12 h-12 bg-medical-gray-50 rounded-2xl flex items-center justify-center text-canina-blue group-hover:bg-canina-blue group-hover:text-white transition-all shadow-sm">
|
||||||
<Package className="w-6 h-6" />
|
<Package className="w-6 h-6" />
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<div className="text-sm font-black text-medical-gray-900 group-hover:text-canino-blue transition-colors italic">سفارش {toPersian(order.id.toUpperCase())}</div>
|
<div className="text-sm font-black text-medical-gray-900 group-hover:text-canina-blue transition-colors italic">سفارش {toPersian(order.id.toUpperCase())}</div>
|
||||||
<div className="text-[10px] font-bold text-medical-gray-400 flex items-center gap-1">
|
<div className="text-[10px] font-bold text-medical-gray-400 flex items-center gap-1">
|
||||||
<Calendar className="w-3 h-3 opacity-30" />
|
<Calendar className="w-3 h-3 opacity-30" />
|
||||||
{toPersian(new Date(order.date).toLocaleDateString("fa-IR"))}
|
{toPersian(new Date(order.date).toLocaleDateString("fa-IR"))}
|
||||||
@ -413,7 +413,7 @@ export default function UserDashboard() {
|
|||||||
<div className="text-left">
|
<div className="text-left">
|
||||||
<div className="text-lg font-black text-medical-gray-900 italic">{toPersian(order.total.toLocaleString())} <span className="text-xs">تومان</span></div>
|
<div className="text-lg font-black text-medical-gray-900 italic">{toPersian(order.total.toLocaleString())} <span className="text-xs">تومان</span></div>
|
||||||
<div className="flex items-center gap-2 justify-end mt-1">
|
<div className="flex items-center gap-2 justify-end mt-1">
|
||||||
<span className={`text-[9px] font-black px-2 py-0.5 rounded-full uppercase tracking-tighter ${order.status === 'delivered' ? 'bg-green-50 text-green-600' : 'bg-canino-blue/5 text-canino-blue'}`}>
|
<span className={`text-[9px] font-black px-2 py-0.5 rounded-full uppercase tracking-tighter ${order.status === 'delivered' ? 'bg-green-50 text-green-600' : 'bg-canina-blue/5 text-canina-blue'}`}>
|
||||||
{order.status === 'delivered' ? 'تحویل شده' : 'ارسال شده'}
|
{order.status === 'delivered' ? 'تحویل شده' : 'ارسال شده'}
|
||||||
</span>
|
</span>
|
||||||
<ChevronRight className="w-4 h-4 text-medical-gray-300 -rotate-180" />
|
<ChevronRight className="w-4 h-4 text-medical-gray-300 -rotate-180" />
|
||||||
@ -434,7 +434,7 @@ export default function UserDashboard() {
|
|||||||
<h3 className="text-2xl font-black text-medical-gray-900 italic">آدرسهای من</h3>
|
<h3 className="text-2xl font-black text-medical-gray-900 italic">آدرسهای من</h3>
|
||||||
<button
|
<button
|
||||||
onClick={handleAddClick}
|
onClick={handleAddClick}
|
||||||
className="px-6 py-3 bg-canino-blue text-white rounded-2xl font-black text-xs flex items-center gap-2 hover:bg-medical-gray-900 transition-all shadow-lg shadow-canino-blue/10"
|
className="px-6 py-3 bg-canina-blue text-white rounded-2xl font-black text-xs flex items-center gap-2 hover:bg-medical-gray-900 transition-all shadow-lg shadow-canina-blue/10"
|
||||||
>
|
>
|
||||||
<MapPin className="w-4 h-4" />
|
<MapPin className="w-4 h-4" />
|
||||||
افزودن آدرس جدید
|
افزودن آدرس جدید
|
||||||
@ -455,12 +455,12 @@ export default function UserDashboard() {
|
|||||||
animate={{ opacity: 1, y: 0 }}
|
animate={{ opacity: 1, y: 0 }}
|
||||||
className={cn(
|
className={cn(
|
||||||
"p-8 bg-white border rounded-[2.5rem] relative group transition-all",
|
"p-8 bg-white border rounded-[2.5rem] relative group transition-all",
|
||||||
addr.isDefault ? "border-canino-blue shadow-xl shadow-canino-blue/5" : "border-medical-gray-100 hover:border-medical-gray-200"
|
addr.isDefault ? "border-canina-blue shadow-xl shadow-canina-blue/5" : "border-medical-gray-100 hover:border-medical-gray-200"
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<div className="flex justify-between items-start mb-6">
|
<div className="flex justify-between items-start mb-6">
|
||||||
<div className="flex items-center gap-4">
|
<div className="flex items-center gap-4">
|
||||||
<div className={cn("w-12 h-12 rounded-2xl flex items-center justify-center transition-all", addr.isDefault ? "bg-canino-blue text-white shadow-lg" : "bg-medical-gray-50 text-canino-blue")}>
|
<div className={cn("w-12 h-12 rounded-2xl flex items-center justify-center transition-all", addr.isDefault ? "bg-canina-blue text-white shadow-lg" : "bg-medical-gray-50 text-canina-blue")}>
|
||||||
<MapPin className="w-6 h-6" />
|
<MapPin className="w-6 h-6" />
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
@ -476,7 +476,7 @@ export default function UserDashboard() {
|
|||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<button
|
<button
|
||||||
onClick={() => handleEditClick(addr)}
|
onClick={() => handleEditClick(addr)}
|
||||||
className="w-10 h-10 flex items-center justify-center rounded-xl bg-medical-gray-50 text-medical-gray-400 hover:bg-canino-blue hover:text-white transition-all shadow-sm"
|
className="w-10 h-10 flex items-center justify-center rounded-xl bg-medical-gray-50 text-medical-gray-400 hover:bg-canina-blue hover:text-white transition-all shadow-sm"
|
||||||
>
|
>
|
||||||
<Edit2 className="w-5 h-5" />
|
<Edit2 className="w-5 h-5" />
|
||||||
</button>
|
</button>
|
||||||
@ -495,11 +495,11 @@ export default function UserDashboard() {
|
|||||||
|
|
||||||
<div className="flex flex-wrap items-center gap-6">
|
<div className="flex flex-wrap items-center gap-6">
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<Phone className="w-4 h-4 text-canino-blue/40" />
|
<Phone className="w-4 h-4 text-canina-blue/40" />
|
||||||
<span className="text-xs font-bold text-medical-gray-500" dir="ltr">{toPersian(addr.phone)}</span>
|
<span className="text-xs font-bold text-medical-gray-500" dir="ltr">{toPersian(addr.phone)}</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<Hash className="w-4 h-4 text-canino-blue/40" />
|
<Hash className="w-4 h-4 text-canina-blue/40" />
|
||||||
<span className="text-xs font-bold text-medical-gray-500" dir="ltr">{toPersian(addr.zipCode)}</span>
|
<span className="text-xs font-bold text-medical-gray-500" dir="ltr">{toPersian(addr.zipCode)}</span>
|
||||||
</div>
|
</div>
|
||||||
{!addr.isDefault && (
|
{!addr.isDefault && (
|
||||||
@ -512,7 +512,7 @@ export default function UserDashboard() {
|
|||||||
toast.error("خطا در تغییر آدرس پیشفرض");
|
toast.error("خطا در تغییر آدرس پیشفرض");
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
className="mr-auto text-[10px] font-black text-canino-blue hover:text-medical-gray-900 uppercase tracking-widest whitespace-nowrap"
|
className="mr-auto text-[10px] font-black text-canina-blue hover:text-medical-gray-900 uppercase tracking-widest whitespace-nowrap"
|
||||||
>
|
>
|
||||||
انتخاب به عنوان پیشفرض
|
انتخاب به عنوان پیشفرض
|
||||||
</button>
|
</button>
|
||||||
@ -542,7 +542,7 @@ export default function UserDashboard() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Main Balance Card */}
|
{/* Main Balance Card */}
|
||||||
<div className="bg-gradient-to-br from-canino-blue to-blue-600 rounded-[3rem] p-12 text-white shadow-2xl shadow-canino-blue/20 relative overflow-hidden group">
|
<div className="bg-gradient-to-br from-canina-blue to-blue-600 rounded-[3rem] p-12 text-white shadow-2xl shadow-canina-blue/20 relative overflow-hidden group">
|
||||||
<div className="absolute top-0 right-0 p-12 opacity-10 group-hover:scale-110 transition-transform duration-700">
|
<div className="absolute top-0 right-0 p-12 opacity-10 group-hover:scale-110 transition-transform duration-700">
|
||||||
<Wallet className="w-48 h-48" />
|
<Wallet className="w-48 h-48" />
|
||||||
</div>
|
</div>
|
||||||
@ -572,7 +572,7 @@ export default function UserDashboard() {
|
|||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
onClick={() => setIsTopUpModalOpen(true)}
|
onClick={() => setIsTopUpModalOpen(true)}
|
||||||
className="flex-1 md:w-40 h-16 bg-white text-canino-blue rounded-2xl font-black text-sm flex items-center justify-center gap-2 hover:bg-medical-gray-900 hover:text-white transition-all shadow-xl shadow-black/10 group/topup"
|
className="flex-1 md:w-40 h-16 bg-white text-canina-blue rounded-2xl font-black text-sm flex items-center justify-center gap-2 hover:bg-medical-gray-900 hover:text-white transition-all shadow-xl shadow-black/10 group/topup"
|
||||||
>
|
>
|
||||||
<ArrowUpCircle className="w-5 h-5 group-hover:-translate-y-1 transition-transform" />
|
<ArrowUpCircle className="w-5 h-5 group-hover:-translate-y-1 transition-transform" />
|
||||||
شارژ آنی
|
شارژ آنی
|
||||||
@ -598,7 +598,7 @@ export default function UserDashboard() {
|
|||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
(profile?.transactions || []).map((trx) => (
|
(profile?.transactions || []).map((trx) => (
|
||||||
<div key={trx.id} className="p-6 bg-white border border-medical-gray-100 rounded-[2rem] flex flex-wrap items-center justify-between gap-6 hover:shadow-lg hover:border-canino-blue/10 transition-all group">
|
<div key={trx.id} className="p-6 bg-white border border-medical-gray-100 rounded-[2rem] flex flex-wrap items-center justify-between gap-6 hover:shadow-lg hover:border-canina-blue/10 transition-all group">
|
||||||
<div className="flex items-center gap-4">
|
<div className="flex items-center gap-4">
|
||||||
<div className={cn(
|
<div className={cn(
|
||||||
"w-12 h-12 rounded-2xl flex items-center justify-center transition-colors",
|
"w-12 h-12 rounded-2xl flex items-center justify-center transition-colors",
|
||||||
|
|||||||
@ -44,20 +44,20 @@ export default function VetGallery({ testimonials = [] }: { testimonials?: any[]
|
|||||||
<div className="max-w-7xl mx-auto px-4">
|
<div className="max-w-7xl mx-auto px-4">
|
||||||
<div className="flex flex-col md:flex-row md:items-end justify-between mb-16 gap-6">
|
<div className="flex flex-col md:flex-row md:items-end justify-between mb-16 gap-6">
|
||||||
<div className="max-w-2xl">
|
<div className="max-w-2xl">
|
||||||
<div className="inline-flex items-center gap-2 px-3 py-1 bg-canino-blue/10 text-canino-blue rounded-full text-[10px] font-black uppercase tracking-widest mb-4">
|
<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">
|
||||||
<Star className="w-3 h-3" />
|
<Star className="w-3 h-3" />
|
||||||
Vet Insights
|
Vet Insights
|
||||||
</div>
|
</div>
|
||||||
<h2 className="text-4xl md:text-5xl font-black text-medical-gray-900 italic leading-tight">
|
<h2 className="text-4xl md:text-5xl font-black text-medical-gray-900 italic leading-tight">
|
||||||
مشاوره ویدئویی <span className="text-canino-blue underline decoration-4 decoration-canino-blue/20 underline-offset-8">دوست دامپزشک پت شما</span>
|
مشاوره ویدئویی <span className="text-canina-blue underline decoration-4 decoration-canina-blue/20 underline-offset-8">دوست دامپزشک پت شما</span>
|
||||||
</h2>
|
</h2>
|
||||||
<p className="text-lg text-medical-gray-500 font-medium mt-6">
|
<p className="text-lg text-medical-gray-500 font-medium mt-6">
|
||||||
متخصصین آلمانی کانینو مستقیماً با شما صحبت میکنند. نحوه مصرف، مزایای رقابتی و دانش تخصصی پشت هر محصول.
|
متخصصین آلمانی کانینا مستقیماً با شما صحبت میکنند. نحوه مصرف، مزایای رقابتی و دانش تخصصی پشت هر محصول.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
onClick={() => router.push('/videos')}
|
onClick={() => router.push('/videos')}
|
||||||
className="inline-flex items-center gap-2 text-canino-blue font-bold text-sm hover:translate-x-1 transition-transform rtl:hover:-translate-x-1"
|
className="inline-flex items-center gap-2 text-canina-blue font-bold text-sm hover:translate-x-1 transition-transform rtl:hover:-translate-x-1"
|
||||||
>
|
>
|
||||||
مشاهده همه ویدئوها
|
مشاهده همه ویدئوها
|
||||||
<Play className="w-4 h-4" />
|
<Play className="w-4 h-4" />
|
||||||
@ -70,7 +70,7 @@ export default function VetGallery({ testimonials = [] }: { testimonials?: any[]
|
|||||||
key={video.id}
|
key={video.id}
|
||||||
whileHover={{ y: -8 }}
|
whileHover={{ y: -8 }}
|
||||||
onClick={() => setSelectedVideo(video)}
|
onClick={() => setSelectedVideo(video)}
|
||||||
className="w-full text-right block group cursor-pointer focus-visible:ring-4 focus-visible:ring-canino-blue/30 focus-visible:outline-none rounded-[2rem] p-2"
|
className="w-full text-right block group cursor-pointer focus-visible:ring-4 focus-visible:ring-canina-blue/30 focus-visible:outline-none rounded-[2rem] p-2"
|
||||||
>
|
>
|
||||||
<div className="relative aspect-video rounded-[2rem] overflow-hidden mb-4 shadow-xl">
|
<div className="relative aspect-video rounded-[2rem] overflow-hidden mb-4 shadow-xl">
|
||||||
<div className="absolute inset-0 bg-medical-gray-900/20 group-hover:bg-transparent transition-colors z-10" />
|
<div className="absolute inset-0 bg-medical-gray-900/20 group-hover:bg-transparent transition-colors z-10" />
|
||||||
@ -80,7 +80,7 @@ export default function VetGallery({ testimonials = [] }: { testimonials?: any[]
|
|||||||
className="w-full h-full object-cover grayscale-[30%] group-hover:grayscale-0 transition-all duration-700"
|
className="w-full h-full object-cover grayscale-[30%] group-hover:grayscale-0 transition-all duration-700"
|
||||||
/>
|
/>
|
||||||
<div className="absolute inset-0 flex items-center justify-center z-20">
|
<div className="absolute inset-0 flex items-center justify-center z-20">
|
||||||
<div className="w-16 h-16 bg-white/90 backdrop-blur-sm rounded-full flex items-center justify-center text-canino-blue scale-90 group-hover:scale-100 group-hover:bg-white transition-all shadow-xl">
|
<div className="w-16 h-16 bg-white/90 backdrop-blur-sm rounded-full flex items-center justify-center text-canina-blue scale-90 group-hover:scale-100 group-hover:bg-white transition-all shadow-xl">
|
||||||
<Play className="w-6 h-6 ml-1" />
|
<Play className="w-6 h-6 ml-1" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -89,11 +89,11 @@ export default function VetGallery({ testimonials = [] }: { testimonials?: any[]
|
|||||||
<span>{video.duration || (index === 0 ? '۱:۴۵' : index === 1 ? '۲:۲۰' : '۳:۱۰')}</span>
|
<span>{video.duration || (index === 0 ? '۱:۴۵' : index === 1 ? '۲:۲۰' : '۳:۱۰')}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<h4 className="text-lg font-black text-medical-gray-900 mb-2 group-hover:text-canino-blue transition-colors leading-tight font-vazir">
|
<h4 className="text-lg font-black text-medical-gray-900 mb-2 group-hover:text-canina-blue transition-colors leading-tight font-vazir">
|
||||||
{video.title || video.quote?.substring(0, 40) + '...'}
|
{video.title || video.quote?.substring(0, 40) + '...'}
|
||||||
</h4>
|
</h4>
|
||||||
<div className="flex items-center gap-2 text-medical-gray-500 font-bold text-sm font-vazir">
|
<div className="flex items-center gap-2 text-medical-gray-500 font-bold text-sm font-vazir">
|
||||||
<ShieldCheck className="w-4 h-4 text-canino-blue" />
|
<ShieldCheck className="w-4 h-4 text-canina-blue" />
|
||||||
{video.doctor || video.vetName}
|
{video.doctor || video.vetName}
|
||||||
</div>
|
</div>
|
||||||
</motion.button>
|
</motion.button>
|
||||||
|
|||||||
@ -69,12 +69,12 @@ export default function VideosPage() {
|
|||||||
{/* Header */}
|
{/* Header */}
|
||||||
<div className="flex flex-col md:flex-row items-center justify-between mb-16 gap-6">
|
<div className="flex flex-col md:flex-row items-center justify-between mb-16 gap-6">
|
||||||
<div className="text-right">
|
<div className="text-right">
|
||||||
<div className="inline-flex items-center gap-2 px-3 py-1 bg-canino-blue/10 text-canino-blue rounded-full text-[10px] font-black uppercase tracking-widest mb-4">
|
<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">
|
||||||
<PlayCircle className="w-3 h-3" />
|
<PlayCircle className="w-3 h-3" />
|
||||||
Video Academy
|
Video Academy
|
||||||
</div>
|
</div>
|
||||||
<h1 className="text-4xl lg:text-6xl font-black text-white italic leading-tight">
|
<h1 className="text-4xl lg:text-6xl font-black text-white italic leading-tight">
|
||||||
آکادمی ویدئویی <span className="text-canino-blue">کانینو</span>
|
آکادمی ویدئویی <span className="text-canina-blue">کانینا</span>
|
||||||
</h1>
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
@ -117,7 +117,7 @@ export default function VideosPage() {
|
|||||||
referrerPolicy="no-referrer"
|
referrerPolicy="no-referrer"
|
||||||
/>
|
/>
|
||||||
<div className="absolute inset-0 flex items-center justify-center">
|
<div className="absolute inset-0 flex items-center justify-center">
|
||||||
<div className="w-16 h-16 bg-canino-blue rounded-full flex items-center justify-center text-white shadow-2xl group-hover:scale-110 transition-transform">
|
<div className="w-16 h-16 bg-canina-blue rounded-full flex items-center justify-center text-white shadow-2xl group-hover:scale-110 transition-transform">
|
||||||
<PlayCircle className="w-10 h-10" />
|
<PlayCircle className="w-10 h-10" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -126,7 +126,7 @@ export default function VideosPage() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="px-4">
|
<div className="px-4">
|
||||||
<h3 className="text-xl font-black text-white group-hover:text-canino-blue transition-colors mb-2">{video.title}</h3>
|
<h3 className="text-xl font-black text-white group-hover:text-canina-blue transition-colors mb-2">{video.title}</h3>
|
||||||
<div className="flex items-center gap-4 text-xs font-bold text-white/40">
|
<div className="flex items-center gap-4 text-xs font-bold text-white/40">
|
||||||
<div className="flex items-center gap-1">
|
<div className="flex items-center gap-1">
|
||||||
<User className="w-3 h-3" />
|
<User className="w-3 h-3" />
|
||||||
@ -173,7 +173,7 @@ export default function VideosPage() {
|
|||||||
className="w-full h-full object-contain"
|
className="w-full h-full object-contain"
|
||||||
/>
|
/>
|
||||||
<div className="absolute bottom-0 left-0 right-0 p-10 bg-gradient-to-t from-black/90 to-transparent">
|
<div className="absolute bottom-0 left-0 right-0 p-10 bg-gradient-to-t from-black/90 to-transparent">
|
||||||
<div className="flex items-center gap-2 text-canino-blue text-xs font-black mb-2 uppercase tracking-widest">
|
<div className="flex items-center gap-2 text-canina-blue text-xs font-black mb-2 uppercase tracking-widest">
|
||||||
<ShieldCheck className="w-4 h-4" />
|
<ShieldCheck className="w-4 h-4" />
|
||||||
Verified Insight
|
Verified Insight
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
"use client";
|
"use client";
|
||||||
import { describe, it, expect, vi } from 'vitest';
|
import { describe, it, expect, vi } from 'vitest';
|
||||||
import { render, screen, fireEvent } from '@testing-library/react';
|
import { render, screen, fireEvent } from '@testing-library/react';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
@ -8,9 +8,9 @@ describe('Footer', () => {
|
|||||||
it('renders footer brand text and standard layout elements', () => {
|
it('renders footer brand text and standard layout elements', () => {
|
||||||
render(<Footer onNavigate={vi.fn()} onShopNavigate={vi.fn()} onB2BOpen={vi.fn()} />);
|
render(<Footer onNavigate={vi.fn()} onShopNavigate={vi.fn()} onB2BOpen={vi.fn()} />);
|
||||||
|
|
||||||
expect(screen.getByText('کانینو ایران')).toBeInTheDocument();
|
expect(screen.getByText('کانینا ایران')).toBeInTheDocument();
|
||||||
expect(screen.getByText('نماینده رسمی در ایران')).toBeInTheDocument();
|
expect(screen.getByText('نماینده رسمی در ایران')).toBeInTheDocument();
|
||||||
expect(screen.getByText('تهران، جردن، خیابان سعیدی، ساختمان کانینو، طبقه ۵، واحد ۱۹')).toBeInTheDocument();
|
expect(screen.getByText('تهران، جردن، خیابان سعیدی، ساختمان کانینا، طبقه ۵، واحد ۱۹')).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('triggers onNavigate and onShopNavigate when quick links are clicked', () => {
|
it('triggers onNavigate and onShopNavigate when quick links are clicked', () => {
|
||||||
|
|||||||
@ -54,7 +54,7 @@ describe('Header', () => {
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(screen.getByText('Canino')).toBeInTheDocument();
|
expect(screen.getByText('Canina')).toBeInTheDocument();
|
||||||
expect(screen.getByText('ایران')).toBeInTheDocument();
|
expect(screen.getByText('ایران')).toBeInTheDocument();
|
||||||
expect(screen.getByText('ورود / ثبتنام')).toBeInTheDocument();
|
expect(screen.getByText('ورود / ثبتنام')).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|||||||
@ -108,7 +108,7 @@ export const PRODUCTS: Product[] = [
|
|||||||
{
|
{
|
||||||
id: "canhydrox-gag",
|
id: "canhydrox-gag",
|
||||||
artNo: "123490",
|
artNo: "123490",
|
||||||
name: "Canino CANHYDROX GAG",
|
name: "Canina CANHYDROX GAG",
|
||||||
scientificTagline: "استاندارد طلایی ارتوپدی سگهای آلمان",
|
scientificTagline: "استاندارد طلایی ارتوپدی سگهای آلمان",
|
||||||
description: "ویژه سگهای بزرگ و سنگینوزن برای درمان بافت همبند، مفاصل، استخوانها، تاندونها و غضروف. هیدروکسیآپاتیت (کلسیم فسفات بیولوژیک) ساختار بلوری استخوانها را بازسازی کرده و به تشکیل سریعتر کالوس استخوانی پس از جراحیها کمک میکند. گلیکوزآمینوگلیکانهای صدف لبسبز با جذب ملکولهای آب به درون ماتریکس غضروفی، خاصیت الاستیسیته و بافری مفاصل را بازیابی میکنند.",
|
description: "ویژه سگهای بزرگ و سنگینوزن برای درمان بافت همبند، مفاصل، استخوانها، تاندونها و غضروف. هیدروکسیآپاتیت (کلسیم فسفات بیولوژیک) ساختار بلوری استخوانها را بازسازی کرده و به تشکیل سریعتر کالوس استخوانی پس از جراحیها کمک میکند. گلیکوزآمینوگلیکانهای صدف لبسبز با جذب ملکولهای آب به درون ماتریکس غضروفی، خاصیت الاستیسیته و بافری مفاصل را بازیابی میکنند.",
|
||||||
shortDescription: "قویترین فرمول ارتوپدی آلمان برای تقویت اسکلتبندی و رشد سالم استخوانها در نژادهای بزرگ. هیدروکسی آپاتیت به همراه صدف لبسبز و سیلیکا، قوام ناخنها، تاندونها و مینای دندانها را بهبود میبخشد.",
|
shortDescription: "قویترین فرمول ارتوپدی آلمان برای تقویت اسکلتبندی و رشد سالم استخوانها در نژادهای بزرگ. هیدروکسی آپاتیت به همراه صدف لبسبز و سیلیکا، قوام ناخنها، تاندونها و مینای دندانها را بهبود میبخشد.",
|
||||||
@ -173,7 +173,7 @@ export const PRODUCTS: Product[] = [
|
|||||||
{
|
{
|
||||||
id: "immun-booster",
|
id: "immun-booster",
|
||||||
artNo: "140504",
|
artNo: "140504",
|
||||||
name: "Canino Immun-Booster",
|
name: "Canina Immun-Booster",
|
||||||
scientificTagline: "سیستم دفاعی هوشمند بیولوژیک",
|
scientificTagline: "سیستم دفاعی هوشمند بیولوژیک",
|
||||||
description: "خمیر آغوز متمرکز با دوز بالای ایمونوگلوبولینها برای فعالسازی فوری سیستم ایمنی غیرفعال یا سرکوبشده. آغوز (اولین شیر پستانداران) حاوی IgG، IgA، IgM و لاکتوفرین است که سد دفاعی روده را تقویت کرده و از نفوذ پاتوژنها جلوگیری میکند. ویتامین D3 تولید کاتلیسیدین (پپتید ضد میکروبی ذاتی) را تحریک کرده و ویتامین E به عنوان آنتیاکسیدان قوی از غشاهای سلولی محافظت میکند.",
|
description: "خمیر آغوز متمرکز با دوز بالای ایمونوگلوبولینها برای فعالسازی فوری سیستم ایمنی غیرفعال یا سرکوبشده. آغوز (اولین شیر پستانداران) حاوی IgG، IgA، IgM و لاکتوفرین است که سد دفاعی روده را تقویت کرده و از نفوذ پاتوژنها جلوگیری میکند. ویتامین D3 تولید کاتلیسیدین (پپتید ضد میکروبی ذاتی) را تحریک کرده و ویتامین E به عنوان آنتیاکسیدان قوی از غشاهای سلولی محافظت میکند.",
|
||||||
shortDescription: "سپر دفاعی هوشمند؛ خمیر آغوز متمرکز برای فعالسازی فوری گلبولهای سفید و تقویت تولهها و مادران باردار.",
|
shortDescription: "سپر دفاعی هوشمند؛ خمیر آغوز متمرکز برای فعالسازی فوری گلبولهای سفید و تقویت تولهها و مادران باردار.",
|
||||||
@ -222,7 +222,7 @@ export const PRODUCTS: Product[] = [
|
|||||||
{
|
{
|
||||||
id: "mikrosilber-zahngel",
|
id: "mikrosilber-zahngel",
|
||||||
artNo: "131454",
|
artNo: "131454",
|
||||||
name: "Canino Mikrosilber Zahngel",
|
name: "Canina Mikrosilber Zahngel",
|
||||||
scientificTagline: "مراقبت آنتیسپتیک دهان با تکنولوژی نقره میکروسیمی",
|
scientificTagline: "مراقبت آنتیسپتیک دهان با تکنولوژی نقره میکروسیمی",
|
||||||
description: "ژل دندانی حاوی ذرات نقره میکروسیلور با ساختار اسفنجی که به دلیل اندازه درشت جذب جریان خون نشده اما اثر آنتیباکتریال پایداری روی سطح لثه و مینا ایجاد میکند. بر خلاف نقره کلوئیدی معمولی، میکروسیلور رسوب سطحی طولانیمدت داشته و فلور طبیعی دهان را تخریب نمیکند. عصاره دانه گریپفروت به عنوان مهارکننده تشکیل بیوفیلم باکتریایی عمل کرده و ویتامین C سنتز کلاژن لثه را تسریع میکند.",
|
description: "ژل دندانی حاوی ذرات نقره میکروسیلور با ساختار اسفنجی که به دلیل اندازه درشت جذب جریان خون نشده اما اثر آنتیباکتریال پایداری روی سطح لثه و مینا ایجاد میکند. بر خلاف نقره کلوئیدی معمولی، میکروسیلور رسوب سطحی طولانیمدت داشته و فلور طبیعی دهان را تخریب نمیکند. عصاره دانه گریپفروت به عنوان مهارکننده تشکیل بیوفیلم باکتریایی عمل کرده و ویتامین C سنتز کلاژن لثه را تسریع میکند.",
|
||||||
shortDescription: "انقلاب در بهداشت دهان؛ ژل نقره میکروسیمی برای حذف باکتریهای مولد جرم و بوی بد دهان بدون نیاز به بیهوشی.",
|
shortDescription: "انقلاب در بهداشت دهان؛ ژل نقره میکروسیمی برای حذف باکتریهای مولد جرم و بوی بد دهان بدون نیاز به بیهوشی.",
|
||||||
@ -270,7 +270,7 @@ export const PRODUCTS: Product[] = [
|
|||||||
{
|
{
|
||||||
id: "ballaststoff-mix",
|
id: "ballaststoff-mix",
|
||||||
artNo: "140108",
|
artNo: "140108",
|
||||||
name: "Canino Ballaststoff Mix",
|
name: "Canina Ballaststoff Mix",
|
||||||
scientificTagline: "بهینهسازی بیوم روده با فیبرهای گیاهی ارگانیک",
|
scientificTagline: "بهینهسازی بیوم روده با فیبرهای گیاهی ارگانیک",
|
||||||
description: "ترکیب متعادل فیبرهای گیاهی از منابع فیبر سیب (پکتین)، یونجه، نخود فرنگی و هویج برای تنظیم سیستم گوارش و بهبود کیفیت دفع. پکتین سیب به عنوان یک پریبیوتیک طبیعی، بستر增殖 باکتریهای مفید روده (لاکتوباسیلوس و بیفیدوباکتر) را فراهم کرده و فیبر یونجه حرکات پریستالتیک روده را تنظیم میکند.",
|
description: "ترکیب متعادل فیبرهای گیاهی از منابع فیبر سیب (پکتین)، یونجه، نخود فرنگی و هویج برای تنظیم سیستم گوارش و بهبود کیفیت دفع. پکتین سیب به عنوان یک پریبیوتیک طبیعی، بستر增殖 باکتریهای مفید روده (لاکتوباسیلوس و بیفیدوباکتر) را فراهم کرده و فیبر یونجه حرکات پریستالتیک روده را تنظیم میکند.",
|
||||||
shortDescription: "راهکار نهایی مشکلات گوارشی؛ تنظیمکننده حرکات روده و کمک به تخلیه طبیعی غدد مقعدی با فیبر سیب.",
|
shortDescription: "راهکار نهایی مشکلات گوارشی؛ تنظیمکننده حرکات روده و کمک به تخلیه طبیعی غدد مقعدی با فیبر سیب.",
|
||||||
@ -310,7 +310,7 @@ export const PRODUCTS: Product[] = [
|
|||||||
{
|
{
|
||||||
id: "lachs-ol",
|
id: "lachs-ol",
|
||||||
artNo: "111803",
|
artNo: "111803",
|
||||||
name: "Canino Lachs-Öl",
|
name: "Canina Lachs-Öl",
|
||||||
scientificTagline: "اسیدهای چرب ضروری با خلوص دارویی",
|
scientificTagline: "اسیدهای چرب ضروری با خلوص دارویی",
|
||||||
description: "روغن سالمون ۱۰۰٪ خالص نروژی حاوی اسیدهای چرب امگا ۳ (EPA و DHA) با روش پرس سرد (Cold Press) استخراج شده تا تمامی ویتامینهای حساس به حرارت (A، D، E) حفظ شوند. EPA (ایکوزاپنتائنوئیک اسید) پیشماده رزولوینها و پروستاگلاندینهای ضدالتهابی سری E3 بوده و DHA (دوکوزاهگزانوئیک اسید) ۳۰٪ وزن خشک مغز را تشکیل میدهد و برای بینایی و شناخت حیاتی است. نسبت EPA:DHA ۳:۲ بهینه جهت جذب سلولی در پتها رعایت شده است.",
|
description: "روغن سالمون ۱۰۰٪ خالص نروژی حاوی اسیدهای چرب امگا ۳ (EPA و DHA) با روش پرس سرد (Cold Press) استخراج شده تا تمامی ویتامینهای حساس به حرارت (A، D، E) حفظ شوند. EPA (ایکوزاپنتائنوئیک اسید) پیشماده رزولوینها و پروستاگلاندینهای ضدالتهابی سری E3 بوده و DHA (دوکوزاهگزانوئیک اسید) ۳۰٪ وزن خشک مغز را تشکیل میدهد و برای بینایی و شناخت حیاتی است. نسبت EPA:DHA ۳:۲ بهینه جهت جذب سلولی در پتها رعایت شده است.",
|
||||||
shortDescription: "اکسیر درخشش و سلامت؛ روغن سالمون نروژی با امگا ۳ غلیظ برای رفع خشکی پوست و ریزش مو.",
|
shortDescription: "اکسیر درخشش و سلامت؛ روغن سالمون نروژی با امگا ۳ غلیظ برای رفع خشکی پوست و ریزش مو.",
|
||||||
@ -348,14 +348,14 @@ export const PRODUCTS: Product[] = [
|
|||||||
name: "دکتر ماری کونیگ",
|
name: "دکتر ماری کونیگ",
|
||||||
title: "متخصص تغذیه دامپزشکی",
|
title: "متخصص تغذیه دامپزشکی",
|
||||||
image: "https://images.unsplash.com/photo-1559839734-2b71f1536783?auto=format&fit=crop&q=80&w=200",
|
image: "https://images.unsplash.com/photo-1559839734-2b71f1536783?auto=format&fit=crop&q=80&w=200",
|
||||||
message: "روغن سالمون کانینو به روش پرس سرد تهیه شده تا تمامی ویتامینهای حساس به حرارت حفظ شوند."
|
message: "روغن سالمون کانینا به روش پرس سرد تهیه شده تا تمامی ویتامینهای حساس به حرارت حفظ شوند."
|
||||||
},
|
},
|
||||||
image: "https://www.canina.de/media/6b/48/81/731000_Canino_Lachsoel_Lachs_Oel_1280x1280.png"
|
image: "https://www.canina.de/media/6b/48/81/731000_Canino_Lachsoel_Lachs_Oel_1280x1280.png"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "herz-vital",
|
id: "herz-vital",
|
||||||
artNo: "111858",
|
artNo: "111858",
|
||||||
name: "Canino Herz Vital",
|
name: "Canina Herz Vital",
|
||||||
scientificTagline: "محافظت تخصصی از میوکارد و سیستم گردش خون",
|
scientificTagline: "محافظت تخصصی از میوکارد و سیستم گردش خون",
|
||||||
description: "مکمل تخصصی قلب حاوی ال-کارنیتین (۳۰,۰۰۰mg/kg) و عصاره زالزالک (Crataegus oxyacantha) برای تقویت عضله قلب در سگها و گربههای مسن و کاری. ال-کارنیتین اسیدهای چرب زنجیره بلند را به داخل میتوکندری کاردیومیوسیتها منتقل کرده و ATP تولید میکند. زالزالک به عنوان مهارکننده ACE طبیعی، انقباض عروق کرونر را کاهش داده و ایسکمی میوکارد را بهبود میبخشد.",
|
description: "مکمل تخصصی قلب حاوی ال-کارنیتین (۳۰,۰۰۰mg/kg) و عصاره زالزالک (Crataegus oxyacantha) برای تقویت عضله قلب در سگها و گربههای مسن و کاری. ال-کارنیتین اسیدهای چرب زنجیره بلند را به داخل میتوکندری کاردیومیوسیتها منتقل کرده و ATP تولید میکند. زالزالک به عنوان مهارکننده ACE طبیعی، انقباض عروق کرونر را کاهش داده و ایسکمی میوکارد را بهبود میبخشد.",
|
||||||
shortDescription: "موتور تپنده زندگی؛ مکمل تخصصی حاوی ال-کارنیتین و زالزالک برای تقویت عضله قلب در پتهای مسن و کاری.",
|
shortDescription: "موتور تپنده زندگی؛ مکمل تخصصی حاوی ال-کارنیتین و زالزالک برای تقویت عضله قلب در پتهای مسن و کاری.",
|
||||||
@ -393,7 +393,7 @@ export const PRODUCTS: Product[] = [
|
|||||||
{
|
{
|
||||||
id: "energy-gel",
|
id: "energy-gel",
|
||||||
artNo: "111452",
|
artNo: "111452",
|
||||||
name: "Canino Petvital Energy-Gel",
|
name: "Canina Petvital Energy-Gel",
|
||||||
scientificTagline: "تامین فوری گلوکز و ویتامینهای متابولیک برای بازیابی توان",
|
scientificTagline: "تامین فوری گلوکز و ویتامینهای متابولیک برای بازیابی توان",
|
||||||
description: "کمکدرمانی تخصصی فرموله شده با دوز بالای ویتامینهای گروه B (B1، B2، B6، B12) به عنوان کوآنزیمهای چرخه کربس، گلوکز جهت تامین فوری ATP سلولی، ویتامین E به عنوان آنتیاکسیدان غشایی و منیزیم به عنوان کوفاکتور بیش از ۳۰۰ واکنش آنزیمی. مناسب برای بیاشتهایی، نقاهت جراحی، بارداری و شیردهی و مسابقات ورزشی.",
|
description: "کمکدرمانی تخصصی فرموله شده با دوز بالای ویتامینهای گروه B (B1، B2، B6، B12) به عنوان کوآنزیمهای چرخه کربس، گلوکز جهت تامین فوری ATP سلولی، ویتامین E به عنوان آنتیاکسیدان غشایی و منیزیم به عنوان کوفاکتور بیش از ۳۰۰ واکنش آنزیمی. مناسب برای بیاشتهایی، نقاهت جراحی، بارداری و شیردهی و مسابقات ورزشی.",
|
||||||
shortDescription: "منبع انرژی متمرکز و خوشخوراک؛ حاوی ویتامینهای ب-کمپلکس و گلوکز برای بازگشت سریع انرژی در دوران نقاهت.",
|
shortDescription: "منبع انرژی متمرکز و خوشخوراک؛ حاوی ویتامینهای ب-کمپلکس و گلوکز برای بازگشت سریع انرژی در دوران نقاهت.",
|
||||||
@ -433,7 +433,7 @@ export const PRODUCTS: Product[] = [
|
|||||||
{
|
{
|
||||||
id: "moor-tranke",
|
id: "moor-tranke",
|
||||||
artNo: "112404",
|
artNo: "112404",
|
||||||
name: "Canino Moor-Tränke",
|
name: "Canina Moor-Tränke",
|
||||||
scientificTagline: "اکسیر طبیعی بر پایه اسیدهای هومیک گیاهی",
|
scientificTagline: "اکسیر طبیعی بر پایه اسیدهای هومیک گیاهی",
|
||||||
description: "اکسیر طبیعی حاصل از تجزیه گیاهان در طول هزاران سال (پیت) با غلظت بالای اسیدهای هومیک. اسیدهای هومیک ساختار پلیمری با بار منفی دارند که سموم، قارچها و باکتریهای مضر را در روده به دام انداخته و دفع میکنند. همچنین با ایجاد لایه کلوئیدی محافظ روی مخاط روده، التهاب را کاهش داده و اشتها را تحریک میکند.",
|
description: "اکسیر طبیعی حاصل از تجزیه گیاهان در طول هزاران سال (پیت) با غلظت بالای اسیدهای هومیک. اسیدهای هومیک ساختار پلیمری با بار منفی دارند که سموم، قارچها و باکتریهای مضر را در روده به دام انداخته و دفع میکنند. همچنین با ایجاد لایه کلوئیدی محافظ روی مخاط روده، التهاب را کاهش داده و اشتها را تحریک میکند.",
|
||||||
shortDescription: "سمزدای قدرتمند طبیعت؛ عصاره پیت حاوی اسیدهای هومیک برای پاکسازی روده از توکسینها و تنظیم اشتها.",
|
shortDescription: "سمزدای قدرتمند طبیعت؛ عصاره پیت حاوی اسیدهای هومیک برای پاکسازی روده از توکسینها و تنظیم اشتها.",
|
||||||
@ -478,7 +478,7 @@ export const PRODUCTS: Product[] = [
|
|||||||
{
|
{
|
||||||
id: "schwarz-kummel",
|
id: "schwarz-kummel",
|
||||||
artNo: "112503",
|
artNo: "112503",
|
||||||
name: "Canino Schwarz-Kümmel",
|
name: "Canina Schwarz-Kümmel",
|
||||||
scientificTagline: "درمان سنتی ارتقا یافته با تکنولوژی آلمانی",
|
scientificTagline: "درمان سنتی ارتقا یافته با تکنولوژی آلمانی",
|
||||||
description: "روغن سیاه دانه مصری ۱۰۰٪ خالص حاوی تیموکینون (Thymoquinone) با غلظت بالا که به روش پرس سرد استخراج شده است. تیموکینون با مهار مسیر NF-κB و کاهش تولید سایتوکاینهای پیشالتهابی (TNF-α، IL-6) اثر آنتیهیستامین و آنتیآلرژیک دارد. ترکیبات ساپونینی سیاه دانه باعث دفع طبیعی انگلهای خارجی (کک و کنه) از طریق تغییر بوی پوست میشود.",
|
description: "روغن سیاه دانه مصری ۱۰۰٪ خالص حاوی تیموکینون (Thymoquinone) با غلظت بالا که به روش پرس سرد استخراج شده است. تیموکینون با مهار مسیر NF-κB و کاهش تولید سایتوکاینهای پیشالتهابی (TNF-α، IL-6) اثر آنتیهیستامین و آنتیآلرژیک دارد. ترکیبات ساپونینی سیاه دانه باعث دفع طبیعی انگلهای خارجی (کک و کنه) از طریق تغییر بوی پوست میشود.",
|
||||||
shortDescription: "درمان سنتی کهن؛ روغن سیاه دانه مصری با پرس سرد برای مقابله با آلرژی و دفع طبیعی پارازیتها.",
|
shortDescription: "درمان سنتی کهن؛ روغن سیاه دانه مصری با پرس سرد برای مقابله با آلرژی و دفع طبیعی پارازیتها.",
|
||||||
@ -509,14 +509,14 @@ export const PRODUCTS: Product[] = [
|
|||||||
name: "دکتر مونیخ",
|
name: "دکتر مونیخ",
|
||||||
title: "متخصص طب طبیعی دامپزشکی",
|
title: "متخصص طب طبیعی دامپزشکی",
|
||||||
image: "https://images.unsplash.com/photo-1559839734-2b71f1536783?auto=format&fit=crop&q=80&w=200",
|
image: "https://images.unsplash.com/photo-1559839734-2b71f1536783?auto=format&fit=crop&q=80&w=200",
|
||||||
message: "روغن سیاه دانه مصری کانینو حاوی مقادیر بالایی اسیدهای چرب چند غیراشباع است."
|
message: "روغن سیاه دانه مصری کانینا حاوی مقادیر بالایی اسیدهای چرب چند غیراشباع است."
|
||||||
},
|
},
|
||||||
image: "https://www.canina.de/media/1b/83/7d/1715077272/Schwarz-Kuemmel-112503-V1-Canino-250ml_600x600.webp"
|
image: "https://www.canina.de/media/1b/83/7d/1715077272/Schwarz-Kuemmel-112503-V1-Canino-250ml_600x600.webp"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "eierschalenpulver",
|
id: "eierschalenpulver",
|
||||||
artNo: "120208",
|
artNo: "120208",
|
||||||
name: "Canino Eierschalenpulver",
|
name: "Canina Eierschalenpulver",
|
||||||
scientificTagline: "جایگزین طبیعی پودر استخوان برای رژیم BARF",
|
scientificTagline: "جایگزین طبیعی پودر استخوان برای رژیم BARF",
|
||||||
description: "پودر ۱۰۰٪ پوسته تخم مرغ آسیاب شده با ۳۶٪ کلسیم خالص. جایگزین پودر استخوان در رژیمهای خام (BARF) برای سگهای دارای آلرژی به پروتئین گوشت. نسبت کلسیم به فسفر ۳۶۰:۱ نیاز کلسیم را بدون ایجاد عدم تعامل فسفر تأمین میکند.",
|
description: "پودر ۱۰۰٪ پوسته تخم مرغ آسیاب شده با ۳۶٪ کلسیم خالص. جایگزین پودر استخوان در رژیمهای خام (BARF) برای سگهای دارای آلرژی به پروتئین گوشت. نسبت کلسیم به فسفر ۳۶۰:۱ نیاز کلسیم را بدون ایجاد عدم تعامل فسفر تأمین میکند.",
|
||||||
shortDescription: "منبع خالص کلسیم از پوسته تخم مرغ آسیاب شده برای تکمیل رژیم BARF و سلامت دندانها و عضلات.",
|
shortDescription: "منبع خالص کلسیم از پوسته تخم مرغ آسیاب شده برای تکمیل رژیم BARF و سلامت دندانها و عضلات.",
|
||||||
@ -549,7 +549,7 @@ export const PRODUCTS: Product[] = [
|
|||||||
{
|
{
|
||||||
id: "flexan",
|
id: "flexan",
|
||||||
artNo: "710003",
|
artNo: "710003",
|
||||||
name: "Canino FLEXAN",
|
name: "Canina FLEXAN",
|
||||||
scientificTagline: "کلاژن خالص برای ترمیم غضروف و بافت همبند",
|
scientificTagline: "کلاژن خالص برای ترمیم غضروف و بافت همبند",
|
||||||
description: "پپتیدهای کلاژن هیدرولیز شده با ۹۴٪ پروتئین خالص که مستقیماً در ماتریکس غضروف مفصلی جذب شده و سنتز کلاژن نوع II را تحریک میکند. پودر صدف لب سبز گلیکوزآمینوگلیکانهای ضروری را تأمین کرده و خاصیت ارتجاعی بافت همبند را بهبود میبخشد.",
|
description: "پپتیدهای کلاژن هیدرولیز شده با ۹۴٪ پروتئین خالص که مستقیماً در ماتریکس غضروف مفصلی جذب شده و سنتز کلاژن نوع II را تحریک میکند. پودر صدف لب سبز گلیکوزآمینوگلیکانهای ضروری را تأمین کرده و خاصیت ارتجاعی بافت همبند را بهبود میبخشد.",
|
||||||
shortDescription: "کلاژن هیدرولیز شده با صدف لب سبز برای بازسازی مفاصل و غضروف در تولهها و سگهای مسن.",
|
shortDescription: "کلاژن هیدرولیز شده با صدف لب سبز برای بازسازی مفاصل و غضروف در تولهها و سگهای مسن.",
|
||||||
@ -588,7 +588,7 @@ export const PRODUCTS: Product[] = [
|
|||||||
{
|
{
|
||||||
id: "petvital-gag",
|
id: "petvital-gag",
|
||||||
artNo: "723201",
|
artNo: "723201",
|
||||||
name: "Canino PETVITAL GAG",
|
name: "Canina PETVITAL GAG",
|
||||||
scientificTagline: "گلیکوزآمینوگلیکانهای خالص برای سیستم حرکتی",
|
scientificTagline: "گلیکوزآمینوگلیکانهای خالص برای سیستم حرکتی",
|
||||||
description: "تأمین گلیکوزآمینوگلیکانها (GAG) جهت تثبیت تاندونها، رباطها و غضروف مفاصل. پودر صدف لب سبز با اسیدهای آمینه ضروری عملکرد بهینه سیستم حرکتی را تضمین کرده و متیونین به سنتز پروتئینهای غضروفی کمک میکند.",
|
description: "تأمین گلیکوزآمینوگلیکانها (GAG) جهت تثبیت تاندونها، رباطها و غضروف مفاصل. پودر صدف لب سبز با اسیدهای آمینه ضروری عملکرد بهینه سیستم حرکتی را تضمین کرده و متیونین به سنتز پروتئینهای غضروفی کمک میکند.",
|
||||||
shortDescription: "پودر و قرص GAG با صدف لب سبز برای تثبیت تاندونها، رباطها و غضروف مفاصل.",
|
shortDescription: "پودر و قرص GAG با صدف لب سبز برای تثبیت تاندونها، رباطها و غضروف مفاصل.",
|
||||||
@ -627,7 +627,7 @@ export const PRODUCTS: Product[] = [
|
|||||||
{
|
{
|
||||||
id: "velox-gelenkenergie",
|
id: "velox-gelenkenergie",
|
||||||
artNo: "701902",
|
artNo: "701902",
|
||||||
name: "Canino Velox Gelenkenergie",
|
name: "Canina Velox Gelenkenergie",
|
||||||
scientificTagline: "کنسانتره خالص صدف لب سبز نیوزیلند",
|
scientificTagline: "کنسانتره خالص صدف لب سبز نیوزیلند",
|
||||||
description: "۱۰۰٪ پودر گوشت صدف لب سبز نیوزیلندی (Perna canaliculus) با غلظت بالای گلیکوزآمینوگلیکانها و اسیدهای چرب امگا ۳ اختصاصی (ETA). بازسازی مفاصل، رباطها و غضروف را تسریع کرده و استقامت مفصلی تولههای در حال رشد و سگهای پیر را افزایش میدهد.",
|
description: "۱۰۰٪ پودر گوشت صدف لب سبز نیوزیلندی (Perna canaliculus) با غلظت بالای گلیکوزآمینوگلیکانها و اسیدهای چرب امگا ۳ اختصاصی (ETA). بازسازی مفاصل، رباطها و غضروف را تسریع کرده و استقامت مفصلی تولههای در حال رشد و سگهای پیر را افزایش میدهد.",
|
||||||
shortDescription: "کنسانتره خالص صدف لب سبز برای بازسازی سریع مفاصل و افزایش استقامت مفصلی.",
|
shortDescription: "کنسانتره خالص صدف لب سبز برای بازسازی سریع مفاصل و افزایش استقامت مفصلی.",
|
||||||
@ -661,7 +661,7 @@ export const PRODUCTS: Product[] = [
|
|||||||
{
|
{
|
||||||
id: "arthro-tabletten",
|
id: "arthro-tabletten",
|
||||||
artNo: "723003",
|
artNo: "723003",
|
||||||
name: "Canino PETVITAL Arthro-Tabletten",
|
name: "Canina PETVITAL Arthro-Tabletten",
|
||||||
scientificTagline: "آنتیاکسیدان گیاهی برای متابولیسم استخوان",
|
scientificTagline: "آنتیاکسیدان گیاهی برای متابولیسم استخوان",
|
||||||
description: "فرمول گیاهی با عصاره بید (Salix alba) و زنجبیل (Zingiber officinale) که به عنوان آنتیاکسیدان و ضدالتهاب طبیعی عمل کرده و خاصیت ارتجاعی استخوان را افزایش میدهد. متابولیسم استخوان را بهبود بخشیده و مفاصل ضعیف را تقویت میکند.",
|
description: "فرمول گیاهی با عصاره بید (Salix alba) و زنجبیل (Zingiber officinale) که به عنوان آنتیاکسیدان و ضدالتهاب طبیعی عمل کرده و خاصیت ارتجاعی استخوان را افزایش میدهد. متابولیسم استخوان را بهبود بخشیده و مفاصل ضعیف را تقویت میکند.",
|
||||||
shortDescription: "فرمول گیاهی بید و زنجبیل برای تقویت مفاصل ضعیف و بهبود متابولیسم استخوان.",
|
shortDescription: "فرمول گیاهی بید و زنجبیل برای تقویت مفاصل ضعیف و بهبود متابولیسم استخوان.",
|
||||||
@ -696,7 +696,7 @@ export const PRODUCTS: Product[] = [
|
|||||||
{
|
{
|
||||||
id: "biotin-tabs",
|
id: "biotin-tabs",
|
||||||
artNo: "702008",
|
artNo: "702008",
|
||||||
name: "Canino PETVITAL Biotin-Tabs",
|
name: "Canina PETVITAL Biotin-Tabs",
|
||||||
scientificTagline: "دوز بالای بیوتین برای مو و پنجههای محکم",
|
scientificTagline: "دوز بالای بیوتین برای مو و پنجههای محکم",
|
||||||
description: "دوز بالای بیوتین (ویتامین H / B7) با ۱,۰۰۰,۰۰۰ میکروگرم در کیلوگرم برای جلوگیری از ریزش مو، تقویت رنگدانههای پوشش و محکمسازی پنجهها. بیوتین کوآنزیم کربوکسیلازهای مسئول سنتز اسیدهای چرب و گلوکونئوژنز است.",
|
description: "دوز بالای بیوتین (ویتامین H / B7) با ۱,۰۰۰,۰۰۰ میکروگرم در کیلوگرم برای جلوگیری از ریزش مو، تقویت رنگدانههای پوشش و محکمسازی پنجهها. بیوتین کوآنزیم کربوکسیلازهای مسئول سنتز اسیدهای چرب و گلوکونئوژنز است.",
|
||||||
shortDescription: "قرص بیوتین فوقغلظت برای جلوگیری از ریزش مو، پوشش براق و پنجههای محکم.",
|
shortDescription: "قرص بیوتین فوقغلظت برای جلوگیری از ریزش مو، پوشش براق و پنجههای محکم.",
|
||||||
@ -735,7 +735,7 @@ export const PRODUCTS: Product[] = [
|
|||||||
{
|
{
|
||||||
id: "mineral-tabs",
|
id: "mineral-tabs",
|
||||||
artNo: "723102",
|
artNo: "723102",
|
||||||
name: "Canino PETVITAL MINERAL-Tabs",
|
name: "Canina PETVITAL MINERAL-Tabs",
|
||||||
scientificTagline: "انواع کلسیم برای تشکیل بافت استخوانی",
|
scientificTagline: "انواع کلسیم برای تشکیل بافت استخوانی",
|
||||||
description: "ترکیب انواع مختلف کلسیم (کربنات کلسیم) به همراه مخمر آبجو و ویتامین D3 برای ذخیرهسازی کلسیم در استخوان. حیاتی در دوره رشد، بارداری و شیردهی. هشدار: مصرف همزمان ویتامین D2 مجاز نیست.",
|
description: "ترکیب انواع مختلف کلسیم (کربنات کلسیم) به همراه مخمر آبجو و ویتامین D3 برای ذخیرهسازی کلسیم در استخوان. حیاتی در دوره رشد، بارداری و شیردهی. هشدار: مصرف همزمان ویتامین D2 مجاز نیست.",
|
||||||
shortDescription: "کلسیم چندمنبعی با ویتامین D3 برای بارداری، شیردهی و تولههای در حال رشد.",
|
shortDescription: "کلسیم چندمنبعی با ویتامین D3 برای بارداری، شیردهی و تولههای در حال رشد.",
|
||||||
@ -769,7 +769,7 @@ export const PRODUCTS: Product[] = [
|
|||||||
{
|
{
|
||||||
id: "vitamin-tabs",
|
id: "vitamin-tabs",
|
||||||
artNo: "712205",
|
artNo: "712205",
|
||||||
name: "Canino PETVITAL VITAMIN-Tabs",
|
name: "Canina PETVITAL VITAMIN-Tabs",
|
||||||
scientificTagline: "کمپلکس کامل ویتامینهای A تا K3",
|
scientificTagline: "کمپلکس کامل ویتامینهای A تا K3",
|
||||||
description: "کمپلکس کامل ویتامینهای A، B1 تا B12، D3، E و K3 از مخمر آبجو. اصلاح کمبود ویتامین، جلوگیری از خستگی، عدم تناسب و اختلالات رشد. ایدهآل برای مادران باردار و شرایط استرسزا.",
|
description: "کمپلکس کامل ویتامینهای A، B1 تا B12، D3، E و K3 از مخمر آبجو. اصلاح کمبود ویتامین، جلوگیری از خستگی، عدم تناسب و اختلالات رشد. ایدهآل برای مادران باردار و شرایط استرسزا.",
|
||||||
shortDescription: "مولتیویتامین کامل از A تا K برای رفع کمبودهای تغذیهای و استرس.",
|
shortDescription: "مولتیویتامین کامل از A تا K برای رفع کمبودهای تغذیهای و استرس.",
|
||||||
@ -801,7 +801,7 @@ export const PRODUCTS: Product[] = [
|
|||||||
{
|
{
|
||||||
id: "bio-aktivator",
|
id: "bio-aktivator",
|
||||||
artNo: "712007",
|
artNo: "712007",
|
||||||
name: "Canino PETVITAL Bio-Aktivator",
|
name: "Canina PETVITAL Bio-Aktivator",
|
||||||
scientificTagline: "سرم خون گاو برای تحریک اشتها و نقاهت",
|
scientificTagline: "سرم خون گاو برای تحریک اشتها و نقاهت",
|
||||||
description: "قطرههای خوراکی حاوی سرم خون گاو که اشتها را تحریک کرده و روند بهبودی را در دوره نقاهت تسریع میکند. رفاه و هماهنگی متابولیسم را بهبود بخشیده و برای پتهای بیاشتها یا پس از جراحی ایدهآل است.",
|
description: "قطرههای خوراکی حاوی سرم خون گاو که اشتها را تحریک کرده و روند بهبودی را در دوره نقاهت تسریع میکند. رفاه و هماهنگی متابولیسم را بهبود بخشیده و برای پتهای بیاشتها یا پس از جراحی ایدهآل است.",
|
||||||
shortDescription: "قطره سرم خون گاو برای تحریک اشتها و تسریع بهبودی در دوره نقاهت.",
|
shortDescription: "قطره سرم خون گاو برای تحریک اشتها و تسریع بهبودی در دوره نقاهت.",
|
||||||
@ -834,7 +834,7 @@ export const PRODUCTS: Product[] = [
|
|||||||
{
|
{
|
||||||
id: "seealgen",
|
id: "seealgen",
|
||||||
artNo: "130504",
|
artNo: "130504",
|
||||||
name: "Canino Seealgen / Bio-Seealgenmehl",
|
name: "Canina Seealgen / Bio-Seealgenmehl",
|
||||||
scientificTagline: "جلبک دریایی ارگانیک غنی از ید و مواد معدنی",
|
scientificTagline: "جلبک دریایی ارگانیک غنی از ید و مواد معدنی",
|
||||||
description: "جلبک دریایی ارگانیک سرشار از ید، روی، لیزین و سلولز که رنگدانههای پوست، بینی و پوشش مو را پشتیبانی میکند. ید جزء حیاتی هورمونهای تیروئیدی (T3 و T4) بوده و متابولیسم پایه را تنظیم میکند.",
|
description: "جلبک دریایی ارگانیک سرشار از ید، روی، لیزین و سلولز که رنگدانههای پوست، بینی و پوشش مو را پشتیبانی میکند. ید جزء حیاتی هورمونهای تیروئیدی (T3 و T4) بوده و متابولیسم پایه را تنظیم میکند.",
|
||||||
shortDescription: "جلبک دریایی ارگانیک برای رنگدانه قوی، سلامت پوست و تامین ید طبیعی.",
|
shortDescription: "جلبک دریایی ارگانیک برای رنگدانه قوی، سلامت پوست و تامین ید طبیعی.",
|
||||||
@ -866,7 +866,7 @@ export const PRODUCTS: Product[] = [
|
|||||||
{
|
{
|
||||||
id: "rinderblut-pulver",
|
id: "rinderblut-pulver",
|
||||||
artNo: "792016",
|
artNo: "792016",
|
||||||
name: "Canino Rinderblut Pulver",
|
name: "Canina Rinderblut Pulver",
|
||||||
scientificTagline: "آهن و هموگلوبین خالص برای بازسازی خون",
|
scientificTagline: "آهن و هموگلوبین خالص برای بازسازی خون",
|
||||||
description: "پودر خون کامل گاو خشک شده با ۹۲٪ پروتئین خام و آهن بالا. منبع ارزشمند هموگلوبین برای انتقال اکسیژن و رشد عضلات. مکمل عالی برای رژیم BARF جهت جبران خون از دست رفته و حمایت از سگهای ورزشی.",
|
description: "پودر خون کامل گاو خشک شده با ۹۲٪ پروتئین خام و آهن بالا. منبع ارزشمند هموگلوبین برای انتقال اکسیژن و رشد عضلات. مکمل عالی برای رژیم BARF جهت جبران خون از دست رفته و حمایت از سگهای ورزشی.",
|
||||||
shortDescription: "پودر خون گاو غنی از آهن برای رژیم BARF، نقاهت و سگهای ورزشی.",
|
shortDescription: "پودر خون گاو غنی از آهن برای رژیم BARF، نقاهت و سگهای ورزشی.",
|
||||||
@ -899,7 +899,7 @@ export const PRODUCTS: Product[] = [
|
|||||||
{
|
{
|
||||||
id: "rinderfett-pulver",
|
id: "rinderfett-pulver",
|
||||||
artNo: "131235",
|
artNo: "131235",
|
||||||
name: "Canino Rinderfett Pulver",
|
name: "Canina Rinderfett Pulver",
|
||||||
scientificTagline: "انرژی طبیعی از چربی گوشت گاو",
|
scientificTagline: "انرژی طبیعی از چربی گوشت گاو",
|
||||||
description: "پودر چربی گوشت گاو آب پز با ۷۲٪ چربی خالص و ۷۴۰ کیلوکالری انرژی. منبع عالی انرژی برای حیوانات لاغر، سگهای بسیار فعال و جبران کمبود چربی در وعدههای خام.",
|
description: "پودر چربی گوشت گاو آب پز با ۷۲٪ چربی خالص و ۷۴۰ کیلوکالری انرژی. منبع عالی انرژی برای حیوانات لاغر، سگهای بسیار فعال و جبران کمبود چربی در وعدههای خام.",
|
||||||
shortDescription: "پودر چربی گوشت گاو آب پز برای افزایش وزن و انرژی سگهای فعال.",
|
shortDescription: "پودر چربی گوشت گاو آب پز برای افزایش وزن و انرژی سگهای فعال.",
|
||||||
@ -932,7 +932,7 @@ export const PRODUCTS: Product[] = [
|
|||||||
{
|
{
|
||||||
id: "schwarz-kummel-samen",
|
id: "schwarz-kummel-samen",
|
||||||
artNo: "131105",
|
artNo: "131105",
|
||||||
name: "Canino Schwarz Kümmel Samen",
|
name: "Canina Schwarz Kümmel Samen",
|
||||||
scientificTagline: "دانه کامل سیاه دانه برای هضم و متابولیسم",
|
scientificTagline: "دانه کامل سیاه دانه برای هضم و متابولیسم",
|
||||||
description: "دانههای کامل زیره سیاه مصری سرشار از اسیدهای چرب غیراشباع که هضم و متابولیسم را تنظیم کرده و سیستم دفاعی را تقویت میکند. برای تقویت عمومی و بهبود عملکرد بدن سگ.",
|
description: "دانههای کامل زیره سیاه مصری سرشار از اسیدهای چرب غیراشباع که هضم و متابولیسم را تنظیم کرده و سیستم دفاعی را تقویت میکند. برای تقویت عمومی و بهبود عملکرد بدن سگ.",
|
||||||
shortDescription: "دانه کامل سیاه دانه مصری برای تقویت هضم، متابولیسم و سیستم ایمنی.",
|
shortDescription: "دانه کامل سیاه دانه مصری برای تقویت هضم، متابولیسم و سیستم ایمنی.",
|
||||||
@ -966,7 +966,7 @@ export const PRODUCTS: Product[] = [
|
|||||||
{
|
{
|
||||||
id: "marine-ol-mischung",
|
id: "marine-ol-mischung",
|
||||||
artNo: "153008",
|
artNo: "153008",
|
||||||
name: "Canino Marine-Ölmischung PREMIUM",
|
name: "Canina Marine-Ölmischung PREMIUM",
|
||||||
scientificTagline: "ترکیب روغنهای دریایی و گیاهی ممتاز",
|
scientificTagline: "ترکیب روغنهای دریایی و گیاهی ممتاز",
|
||||||
description: "ترکیب هماهنگ روغن ماهی، روغن گردو، روغن آرگان و روغن دانه گل رز. روغن آرگان و گل رز به عنوان آنتیاکسیدان و ترمیمکننده سلولی عمل کرده و اسیدهای چرب امگا ۳ و ۶ را در تعادل بهینه تأمین میکنند.",
|
description: "ترکیب هماهنگ روغن ماهی، روغن گردو، روغن آرگان و روغن دانه گل رز. روغن آرگان و گل رز به عنوان آنتیاکسیدان و ترمیمکننده سلولی عمل کرده و اسیدهای چرب امگا ۳ و ۶ را در تعادل بهینه تأمین میکنند.",
|
||||||
shortDescription: "ترکیب روغنهای ممتاز دریایی و گیاهی برای تامین متعادل اسیدهای چرب.",
|
shortDescription: "ترکیب روغنهای ممتاز دریایی و گیاهی برای تامین متعادل اسیدهای چرب.",
|
||||||
@ -999,7 +999,7 @@ export const PRODUCTS: Product[] = [
|
|||||||
{
|
{
|
||||||
id: "taurin-fur-katzen",
|
id: "taurin-fur-katzen",
|
||||||
artNo: "229505",
|
artNo: "229505",
|
||||||
name: "Canino TAURIN Für Katzen",
|
name: "Canina TAURIN Für Katzen",
|
||||||
scientificTagline: "اسید آمینه ضروری برای قلب و بینایی گربه",
|
scientificTagline: "اسید آمینه ضروری برای قلب و بینایی گربه",
|
||||||
description: "تورین با غلظت ۷۰۰ گرم در کیلوگرم از مخمر آبجو. اسید آمینه ضروری شرطی برای گربهها که بدن آنها قادر به سنتز تورین نیست. کمبود تورین باعث دژنراسیون مرکزی شبکیه (نابینایی) و کاردیومیوپاتی متسع میشود.",
|
description: "تورین با غلظت ۷۰۰ گرم در کیلوگرم از مخمر آبجو. اسید آمینه ضروری شرطی برای گربهها که بدن آنها قادر به سنتز تورین نیست. کمبود تورین باعث دژنراسیون مرکزی شبکیه (نابینایی) و کاردیومیوپاتی متسع میشود.",
|
||||||
shortDescription: "مکمل تورین فوقغلظت برای پیشگیری از نابینایی و نارسایی قلبی در گربهها.",
|
shortDescription: "مکمل تورین فوقغلظت برای پیشگیری از نابینایی و نارسایی قلبی در گربهها.",
|
||||||
@ -1037,7 +1037,7 @@ export const PRODUCTS: Product[] = [
|
|||||||
{
|
{
|
||||||
id: "welpenmilch",
|
id: "welpenmilch",
|
||||||
artNo: "130702",
|
artNo: "130702",
|
||||||
name: "Canino Welpenmilch",
|
name: "Canina Welpenmilch",
|
||||||
scientificTagline: "شیر کامل جایگزین مادر برای تولهسگها",
|
scientificTagline: "شیر کامل جایگزین مادر برای تولهسگها",
|
||||||
description: "شیر کامل جایگزین شیر مادر با ۳۰٪ پروتئین، لاکتوز و روغن ماهی. غنی از تورین و ویتامینها برای تولهسگهای بیمادر از روز اول زندگی. ترکیب شبیهسازی شده با شیر سگ ماده.",
|
description: "شیر کامل جایگزین شیر مادر با ۳۰٪ پروتئین، لاکتوز و روغن ماهی. غنی از تورین و ویتامینها برای تولهسگهای بیمادر از روز اول زندگی. ترکیب شبیهسازی شده با شیر سگ ماده.",
|
||||||
shortDescription: "شیر خشک مخصوص تولهسگهای بیمادر با پروتئین و ویتامین بالا.",
|
shortDescription: "شیر خشک مخصوص تولهسگهای بیمادر با پروتئین و ویتامین بالا.",
|
||||||
@ -1061,14 +1061,14 @@ export const PRODUCTS: Product[] = [
|
|||||||
name: "دکتر بکر",
|
name: "دکتر بکر",
|
||||||
title: "متخصص تولیدمثل دامپزشکی",
|
title: "متخصص تولیدمثل دامپزشکی",
|
||||||
image: "https://images.unsplash.com/photo-1559839734-2b71f1536783?auto=format&fit=crop&q=80&w=200",
|
image: "https://images.unsplash.com/photo-1559839734-2b71f1536783?auto=format&fit=crop&q=80&w=200",
|
||||||
message: "شیر تولهسگ کانینو نزدیکترین ترکیب به شیر طبیعی سگ ماده را دارد."
|
message: "شیر تولهسگ کانینا نزدیکترین ترکیب به شیر طبیعی سگ ماده را دارد."
|
||||||
},
|
},
|
||||||
image: "https://www.canina.de/media/6b/48/81/731000_Canino_Lachsoel_Lachs_Oel_1280x1280.png"
|
image: "https://www.canina.de/media/6b/48/81/731000_Canino_Lachsoel_Lachs_Oel_1280x1280.png"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "welpenbrei",
|
id: "welpenbrei",
|
||||||
artNo: "130603",
|
artNo: "130603",
|
||||||
name: "Canino Welpenbrei",
|
name: "Canina Welpenbrei",
|
||||||
scientificTagline: "فرنی پروتئین بالا برای تولهسگهای ۳ هفته به بالا",
|
scientificTagline: "فرنی پروتئین بالا برای تولهسگهای ۳ هفته به بالا",
|
||||||
description: "فرنی با ۲۷٪ پروتئین، غلات، گوشت و لبنیات برای پرورش سالم تولهسگ از هفته سوم. هشدار: مصرف همزمان ویتامین D2 مجاز نیست.",
|
description: "فرنی با ۲۷٪ پروتئین، غلات، گوشت و لبنیات برای پرورش سالم تولهسگ از هفته سوم. هشدار: مصرف همزمان ویتامین D2 مجاز نیست.",
|
||||||
shortDescription: "فرنی پروتئین و ویتامین بالا برای شروع تغذیه کمکی تولهسگ از هفته سوم.",
|
shortDescription: "فرنی پروتئین و ویتامین بالا برای شروع تغذیه کمکی تولهسگ از هفته سوم.",
|
||||||
@ -1093,14 +1093,14 @@ export const PRODUCTS: Product[] = [
|
|||||||
name: "دکتر کوهن",
|
name: "دکتر کوهن",
|
||||||
title: "متخصص طب سنتی دامپزشکی",
|
title: "متخصص طب سنتی دامپزشکی",
|
||||||
image: "https://images.unsplash.com/photo-1559839734-2b71f1536783?auto=format&fit=crop&q=80&w=200",
|
image: "https://images.unsplash.com/photo-1559839734-2b71f1536783?auto=format&fit=crop&q=80&w=200",
|
||||||
message: "فرنی تولهسگ کانینو انتقال نرم از شیر به غذای جامد را تضمین میکند."
|
message: "فرنی تولهسگ کانینا انتقال نرم از شیر به غذای جامد را تضمین میکند."
|
||||||
},
|
},
|
||||||
image: "https://www.canina.de/media/6b/48/81/731000_Canino_Lachsoel_Lachs_Oel_1280x1280.png"
|
image: "https://www.canina.de/media/6b/48/81/731000_Canino_Lachsoel_Lachs_Oel_1280x1280.png"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "bio-insect-shocker",
|
id: "bio-insect-shocker",
|
||||||
artNo: "741304",
|
artNo: "741304",
|
||||||
name: "Canino PETVITAL Bio-Insect Shocker",
|
name: "Canina PETVITAL Bio-Insect Shocker",
|
||||||
scientificTagline: "اسپری دفعکننده طبیعی کک و کنه",
|
scientificTagline: "اسپری دفعکننده طبیعی کک و کنه",
|
||||||
description: "اسپری محیطی با دودکانوئیک اسید (۱۵ گرم در لیتر) و عصاره مارگوسا (چریش) که تخمها و انگلهای خارجی را به طور مؤثر از بین میبرد. ۱۰۰٪ طبیعی و بدون مواد شیمیایی سمی.",
|
description: "اسپری محیطی با دودکانوئیک اسید (۱۵ گرم در لیتر) و عصاره مارگوسا (چریش) که تخمها و انگلهای خارجی را به طور مؤثر از بین میبرد. ۱۰۰٪ طبیعی و بدون مواد شیمیایی سمی.",
|
||||||
shortDescription: "اسپری دفعکننده محیطی کک، شپش و کنه با عصاره چریش.",
|
shortDescription: "اسپری دفعکننده محیطی کک، شپش و کنه با عصاره چریش.",
|
||||||
@ -1131,7 +1131,7 @@ export const PRODUCTS: Product[] = [
|
|||||||
{
|
{
|
||||||
id: "novagard-augenpflege",
|
id: "novagard-augenpflege",
|
||||||
artNo: "NG0013",
|
artNo: "NG0013",
|
||||||
name: "Canino NovaGard Green Augenpflege",
|
name: "Canina NovaGard Green Augenpflege",
|
||||||
scientificTagline: "قطره چشم ضدالتهاب با نقره کلوئیدی و هیالورونات",
|
scientificTagline: "قطره چشم ضدالتهاب با نقره کلوئیدی و هیالورونات",
|
||||||
description: "قطره چشمی استریل با هیالورونات سدیم (مرطوبکننده و محافظ قرنیه) و نقره کلوئیدی (ضدالتهاب و ضدعفونیکننده). ایدهآل برای تمیز کردن چشمهای گرفته و گریان.",
|
description: "قطره چشمی استریل با هیالورونات سدیم (مرطوبکننده و محافظ قرنیه) و نقره کلوئیدی (ضدالتهاب و ضدعفونیکننده). ایدهآل برای تمیز کردن چشمهای گرفته و گریان.",
|
||||||
shortDescription: "قطره چشم ضدالتهاب برای تمیز کردن چشمهای گریان و گرفته.",
|
shortDescription: "قطره چشم ضدالتهاب برای تمیز کردن چشمهای گریان و گرفته.",
|
||||||
@ -1162,7 +1162,7 @@ export const PRODUCTS: Product[] = [
|
|||||||
{
|
{
|
||||||
id: "novagard-pfotenpflege",
|
id: "novagard-pfotenpflege",
|
||||||
artNo: "NG0016",
|
artNo: "NG0016",
|
||||||
name: "Canino NovaGard Green Pfotenpflege",
|
name: "Canina NovaGard Green Pfotenpflege",
|
||||||
scientificTagline: "کرم ۱۰۰٪ طبیعی برای ترمیم پنجههای ترک خورده",
|
scientificTagline: "کرم ۱۰۰٪ طبیعی برای ترمیم پنجههای ترک خورده",
|
||||||
description: "کرم ۱۰۰٪ طبیعی با روغن پالپ سنجد دریایی (Sea Buckthorn)، روغن کالاندولا و پانتنول (پروویتامین B5) برای تسکین پوست خارشدار، التیام زخمها و خراشیدگی پنجه در تابستان و زمستان.",
|
description: "کرم ۱۰۰٪ طبیعی با روغن پالپ سنجد دریایی (Sea Buckthorn)، روغن کالاندولا و پانتنول (پروویتامین B5) برای تسکین پوست خارشدار، التیام زخمها و خراشیدگی پنجه در تابستان و زمستان.",
|
||||||
shortDescription: "کرم طبیعی پنجه با سنجد دریایی و کالاندولا برای زمستان و تابستان.",
|
shortDescription: "کرم طبیعی پنجه با سنجد دریایی و کالاندولا برای زمستان و تابستان.",
|
||||||
@ -1193,7 +1193,7 @@ export const PRODUCTS: Product[] = [
|
|||||||
{
|
{
|
||||||
id: "katzenmilch",
|
id: "katzenmilch",
|
||||||
artNo: "230808",
|
artNo: "230808",
|
||||||
name: "Canino Katzenmilch",
|
name: "Canina Katzenmilch",
|
||||||
scientificTagline: "شیر جایگزین کامل برای بچهگربههای بیمادر",
|
scientificTagline: "شیر جایگزین کامل برای بچهگربههای بیمادر",
|
||||||
description: "غذای کامل جایگزین شیر مادر با ۳۰٪ پروتئین، لاکتوز، چربی نارگیل، روغن ماهی و ۱۰۰ میلیگرم تورین. مناسب بچهگربههای بیمادر از ۱ روزگی، گربههای مسن، بیمار و شیرده.",
|
description: "غذای کامل جایگزین شیر مادر با ۳۰٪ پروتئین، لاکتوز، چربی نارگیل، روغن ماهی و ۱۰۰ میلیگرم تورین. مناسب بچهگربههای بیمادر از ۱ روزگی، گربههای مسن، بیمار و شیرده.",
|
||||||
shortDescription: "شیر خشک مخصوص بچهگربههای بیمادر با تورین بالا از بدو تولد.",
|
shortDescription: "شیر خشک مخصوص بچهگربههای بیمادر با تورین بالا از بدو تولد.",
|
||||||
@ -1217,7 +1217,7 @@ export const PRODUCTS: Product[] = [
|
|||||||
name: "دکتر بکر",
|
name: "دکتر بکر",
|
||||||
title: "متخصص تولیدمثل دامپزشکی",
|
title: "متخصص تولیدمثل دامپزشکی",
|
||||||
image: "https://images.unsplash.com/photo-1559839734-2b71f1536783?auto=format&fit=crop&q=80&w=200",
|
image: "https://images.unsplash.com/photo-1559839734-2b71f1536783?auto=format&fit=crop&q=80&w=200",
|
||||||
message: "شیر گربه کانینو با تورین بالا برای سلامت قلب و بینایی بچهگربهها حیاتی است."
|
message: "شیر گربه کانینا با تورین بالا برای سلامت قلب و بینایی بچهگربهها حیاتی است."
|
||||||
},
|
},
|
||||||
image: "https://www.canina.de/media/6b/48/81/731000_Canino_Lachsoel_Lachs_Oel_1280x1280.png"
|
image: "https://www.canina.de/media/6b/48/81/731000_Canino_Lachsoel_Lachs_Oel_1280x1280.png"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
export interface ScientificTerm {
|
export interface ScientificTerm {
|
||||||
term: string;
|
term: string;
|
||||||
definition: string;
|
definition: string;
|
||||||
wikiId?: string;
|
wikiId?: string;
|
||||||
@ -42,7 +42,7 @@ export const SCIENTIFIC_TERMS: Record<string, ScientificTerm> = {
|
|||||||
},
|
},
|
||||||
"نسبت Ca:P": {
|
"نسبت Ca:P": {
|
||||||
term: "نسبت کلسیم به فسفر (Ca:P Ratio)",
|
term: "نسبت کلسیم به فسفر (Ca:P Ratio)",
|
||||||
definition: "نسبت ایدهآل کلسیم به فسفر در رژیم حیوانات ۱.۲:۱ تا ۱.۵:۱ است. عدم تعادل این نسبت منجر به مشکلات کلیوی و استخوانی میشود. پودر پوسته تخم مرغ کانینو با ۳۶٪ کلسیم و ۰.۱٪ فسفر بهترین تنظیمکننده این نسبت است.",
|
definition: "نسبت ایدهآل کلسیم به فسفر در رژیم حیوانات ۱.۲:۱ تا ۱.۵:۱ است. عدم تعادل این نسبت منجر به مشکلات کلیوی و استخوانی میشود. پودر پوسته تخم مرغ کانینا با ۳۶٪ کلسیم و ۰.۱٪ فسفر بهترین تنظیمکننده این نسبت است.",
|
||||||
wikiId: "nutrition"
|
wikiId: "nutrition"
|
||||||
},
|
},
|
||||||
"ویتامین D3": {
|
"ویتامین D3": {
|
||||||
@ -52,17 +52,17 @@ export const SCIENTIFIC_TERMS: Record<string, ScientificTerm> = {
|
|||||||
},
|
},
|
||||||
"BARF": {
|
"BARF": {
|
||||||
term: "رژیم BARF (Biologically Appropriate Raw Food)",
|
term: "رژیم BARF (Biologically Appropriate Raw Food)",
|
||||||
definition: "رژیم غذایی خام متناسب با زیستشناسی حیوان که شامل گوشت خام، استخوان، اندامها و سبزیجات است. مکملهای کانینو مانند Eierschalenpulver، Rinderblut Pulver و Rinderfett Pulver برای تکمیل این رژیم طراحی شدهاند.",
|
definition: "رژیم غذایی خام متناسب با زیستشناسی حیوان که شامل گوشت خام، استخوان، اندامها و سبزیجات است. مکملهای کانینا مانند Eierschalenpulver، Rinderblut Pulver و Rinderfett Pulver برای تکمیل این رژیم طراحی شدهاند.",
|
||||||
wikiId: "nutrition"
|
wikiId: "nutrition"
|
||||||
},
|
},
|
||||||
"آغوز": {
|
"آغوز": {
|
||||||
term: "آغوز (Colostrum)",
|
term: "آغوز (Colostrum)",
|
||||||
definition: "اولین شیر پستانداران حاوی IgG, IgA, IgM و لاکتوفرین که سد دفاعی روده را تقویت کرده و ایمنی غیرفعال منتقل میکند. محصول Immun-Booster کانینو حاوی ۲۰٪ پودر آغوز است.",
|
definition: "اولین شیر پستانداران حاوی IgG, IgA, IgM و لاکتوفرین که سد دفاعی روده را تقویت کرده و ایمنی غیرفعال منتقل میکند. محصول Immun-Booster کانینا حاوی ۲۰٪ پودر آغوز است.",
|
||||||
wikiId: "immune"
|
wikiId: "immune"
|
||||||
},
|
},
|
||||||
"ال-کارنیتین": {
|
"ال-کارنیتین": {
|
||||||
term: "ال-کارنیتین",
|
term: "ال-کارنیتین",
|
||||||
definition: "مادهای شبهآمینواسید که اسیدهای چرب زنجیره بلند را به داخل میتوکندری کاردیومیوسیتها منتقل کرده و ATP تولید میکند. محصول Herz Vital کانینو حاوی ۳۰,۰۰۰mg/kg ال-کارنیتین است.",
|
definition: "مادهای شبهآمینواسید که اسیدهای چرب زنجیره بلند را به داخل میتوکندری کاردیومیوسیتها منتقل کرده و ATP تولید میکند. محصول Herz Vital کانینا حاوی ۳۰,۰۰۰mg/kg ال-کارنیتین است.",
|
||||||
wikiId: "heart"
|
wikiId: "heart"
|
||||||
},
|
},
|
||||||
"زالزالک": {
|
"زالزالک": {
|
||||||
@ -72,7 +72,7 @@ export const SCIENTIFIC_TERMS: Record<string, ScientificTerm> = {
|
|||||||
},
|
},
|
||||||
"بیوتین": {
|
"بیوتین": {
|
||||||
term: "بیوتین (ویتامین H / B7)",
|
term: "بیوتین (ویتامین H / B7)",
|
||||||
definition: "کوآنزیم کربوکسیلازهای مسئول سنتز اسیدهای چرب و گلوکونئوژنز. کمبود آن منجر به ریزش مو و شکنندگی پنجه میشود. قرص Biotin-Tabs کانینو با ۱,۰۰۰,۰۰۰ میکروگرم در کیلوگرم قویترین دوز موجود است.",
|
definition: "کوآنزیم کربوکسیلازهای مسئول سنتز اسیدهای چرب و گلوکونئوژنز. کمبود آن منجر به ریزش مو و شکنندگی پنجه میشود. قرص Biotin-Tabs کانینا با ۱,۰۰۰,۰۰۰ میکروگرم در کیلوگرم قویترین دوز موجود است.",
|
||||||
wikiId: "skin"
|
wikiId: "skin"
|
||||||
},
|
},
|
||||||
"هیدروکسی آپاتیت": {
|
"هیدروکسی آپاتیت": {
|
||||||
@ -82,7 +82,7 @@ export const SCIENTIFIC_TERMS: Record<string, ScientificTerm> = {
|
|||||||
},
|
},
|
||||||
"EPA/DHA": {
|
"EPA/DHA": {
|
||||||
term: "EPA و DHA",
|
term: "EPA و DHA",
|
||||||
definition: "ایکوزاپنتائنوئیک اسید (EPA) پیشماده رزولوینهای ضدالتهابی و دوکوزاهگزانوئیک اسید (DHA) ۳۰٪ وزن خشک مغز را تشکیل میدهد. نسبت ۳:۲ EPA:DHA در روغن سالمون کانینو بهینهسازی شده است.",
|
definition: "ایکوزاپنتائنوئیک اسید (EPA) پیشماده رزولوینهای ضدالتهابی و دوکوزاهگزانوئیک اسید (DHA) ۳۰٪ وزن خشک مغز را تشکیل میدهد. نسبت ۳:۲ EPA:DHA در روغن سالمون کانینا بهینهسازی شده است.",
|
||||||
wikiId: "omega3"
|
wikiId: "omega3"
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,6 +1,16 @@
|
|||||||
import api from './api';
|
import api from './api';
|
||||||
import { PRODUCTS, Product, PetType } from "../data/products";
|
import { PRODUCTS, Product, PetType } from "../data/products";
|
||||||
|
|
||||||
|
const CATEGORY_SLUG_TO_NAME: Record<string, string> = {
|
||||||
|
'joints': 'مفاصل و استخوان',
|
||||||
|
'immune': 'تقویت سیستم ایمنی و گوارش',
|
||||||
|
'energy': 'ویتامینها و انرژیبخشها',
|
||||||
|
'special-care': 'مراقبتهای ویژه (پوست، دندان و چشم)',
|
||||||
|
'general': 'تقویت عمومی',
|
||||||
|
'nutrition': 'تغذیه تخصصی',
|
||||||
|
'supplements': 'مکملهای غذایی و درمانی',
|
||||||
|
};
|
||||||
|
|
||||||
export class ProductService {
|
export class ProductService {
|
||||||
private static instance: ProductService;
|
private static instance: ProductService;
|
||||||
|
|
||||||
@ -34,7 +44,7 @@ export class ProductService {
|
|||||||
shortDescription: data.shortDescription,
|
shortDescription: data.shortDescription,
|
||||||
price: data.priceDisplay || `${data.priceValue.toLocaleString('fa-IR')} تومان`,
|
price: data.priceDisplay || `${data.priceValue.toLocaleString('fa-IR')} تومان`,
|
||||||
priceValue: Number(data.priceValue),
|
priceValue: Number(data.priceValue),
|
||||||
category: data.category?.name || data.category || data.categorySlug || '',
|
category: data.category?.name || data.category || CATEGORY_SLUG_TO_NAME[data.categorySlug] || data.categorySlug || '',
|
||||||
categorySlug: data.categorySlug,
|
categorySlug: data.categorySlug,
|
||||||
unit: data.unit,
|
unit: data.unit,
|
||||||
packageSize: data.packageSize,
|
packageSize: data.packageSize,
|
||||||
@ -71,7 +81,7 @@ export class ProductService {
|
|||||||
const params = new URLSearchParams();
|
const params = new URLSearchParams();
|
||||||
if (filters?.category && filters.category !== "all") params.append('category', filters.category);
|
if (filters?.category && filters.category !== "all") params.append('category', filters.category);
|
||||||
if (filters?.petType && filters.petType !== "all") params.append('petType', filters.petType);
|
if (filters?.petType && filters.petType !== "all") params.append('petType', filters.petType);
|
||||||
if (filters?.query) params.append('query', filters.query);
|
if (filters?.query) params.append('search', filters.query);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await api.get(`/products?${params.toString()}`);
|
const response = await api.get(`/products?${params.toString()}`);
|
||||||
|
|||||||
@ -33,7 +33,7 @@ describe('settingsStore', () => {
|
|||||||
|
|
||||||
it('should fetch settings successfully and map array to object', async () => {
|
it('should fetch settings successfully and map array to object', async () => {
|
||||||
const mockUiTexts = [
|
const mockUiTexts = [
|
||||||
{ key: 'hero_title', value: 'Welcome to Canino' },
|
{ key: 'hero_title', value: 'Welcome to Canina' },
|
||||||
{ key: 'hero_desc', value: 'Best supplements' },
|
{ key: 'hero_desc', value: 'Best supplements' },
|
||||||
];
|
];
|
||||||
const mockTerms = [
|
const mockTerms = [
|
||||||
@ -54,7 +54,7 @@ describe('settingsStore', () => {
|
|||||||
await store.fetchSettings();
|
await store.fetchSettings();
|
||||||
|
|
||||||
const state = useSettingsStore.getState();
|
const state = useSettingsStore.getState();
|
||||||
expect(state.texts['hero_title']).toBe('Welcome to Canino');
|
expect(state.texts['hero_title']).toBe('Welcome to Canina');
|
||||||
expect(state.texts['hero_desc']).toBe('Best supplements');
|
expect(state.texts['hero_desc']).toBe('Best supplements');
|
||||||
expect(state.scientificTerms['mussel']).toEqual(mockTerms[0]);
|
expect(state.scientificTerms['mussel']).toEqual(mockTerms[0]);
|
||||||
expect(state.isLoading).toBe(false);
|
expect(state.isLoading).toBe(false);
|
||||||
|
|||||||
@ -165,6 +165,6 @@ export const useCartStore = create<CartStore>()(
|
|||||||
},
|
},
|
||||||
getTotal: () => get().getSubtotal() - get().getDiscount() + get().charityDonation,
|
getTotal: () => get().getSubtotal() - get().getDiscount() + get().charityDonation,
|
||||||
}),
|
}),
|
||||||
{ name: "canino-cart" }
|
{ name: "canina-cart" }
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|||||||
@ -212,6 +212,6 @@ export const usePetStore = create<PetStore>()(
|
|||||||
set({ pets: mappedPets, activePetId: get().activePetId && mappedPets.some(p => p.id === get().activePetId) ? get().activePetId : (mappedPets[0]?.id || null) });
|
set({ pets: mappedPets, activePetId: get().activePetId && mappedPets.some(p => p.id === get().activePetId) ? get().activePetId : (mappedPets[0]?.id || null) });
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
{ name: "canino-pets" }
|
{ name: "canina-pets" }
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|||||||
@ -191,6 +191,6 @@ export const useUserStore = create<UserStore>()(
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
{ name: "canino-user" }
|
{ name: "canina-user" }
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
# Application Backend Integration & Refactoring Plan
|
# Application Backend Integration & Refactoring Plan
|
||||||
|
|
||||||
This plan details the migration of the CaninoIran frontend application from using mock data to communicating entirely with the backend APIs, adding email/password authentication, and resolving issues with the pet profile forms.
|
This plan details the migration of the CaninaIran frontend application from using mock data to communicating entirely with the backend APIs, adding email/password authentication, and resolving issues with the pet profile forms.
|
||||||
|
|
||||||
## User Review Required
|
## User Review Required
|
||||||
> [!IMPORTANT]
|
> [!IMPORTANT]
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"name": "Canino Iran - Official Representative",
|
"name": "Canina Iran - Official Representative",
|
||||||
"description": "The official representative of Canina pharma GmbH in Iran. Specialist in veterinary supplements and pharmaceutical-grade pet care products since 1984.",
|
"description": "The official representative of Canina pharma GmbH in Iran. Specialist in veterinary supplements and pharmaceutical-grade pet care products since 1984.",
|
||||||
"requestFramePermissions": [],
|
"requestFramePermissions": [],
|
||||||
"majorCapabilities": [
|
"majorCapabilities": [
|
||||||
|
|||||||
@ -7,7 +7,7 @@
|
|||||||
"dev:backend": "cd backend && npm run start:dev",
|
"dev:backend": "cd backend && npm run start:dev",
|
||||||
"dev:frontend": "cd frontend/application && npm run dev",
|
"dev:frontend": "cd frontend/application && npm run dev",
|
||||||
"dev:admin": "cd frontend/admin-panel && npm run dev",
|
"dev:admin": "cd frontend/admin-panel && npm run dev",
|
||||||
"dev": "node scripts/start-dev.js"
|
"dev": "node scripts/start-dev.js",
|
||||||
"build:backend": "cd backend && npm run build",
|
"build:backend": "cd backend && npm run build",
|
||||||
"build:frontend": "cd frontend/application && npm run build",
|
"build:frontend": "cd frontend/application && npm run build",
|
||||||
"build:admin": "cd frontend/admin-panel && npm run build",
|
"build:admin": "cd frontend/admin-panel && npm run build",
|
||||||
|
|||||||