feat: rename brand from canina to canino across codebase

This commit is contained in:
پارسا آقایی 2026-07-10 16:32:31 +03:30
parent 2851ef8a25
commit f69537a688
73 changed files with 577 additions and 577 deletions

View File

@ -1,6 +1,6 @@
# نقشه جامع اتصال به بک‌بند (Comprehensive Backend Integration Map) 🏗️
این سند حاوی معماری دقیق، فهرست کامل نقاط اتصال (API Endpoints)، کامنت‌های مکان‌نما در کد (TODO Markers)، و تعاریف رسمی تمامی تایپ‌های ورودی (Inputs) و خروجی (Outputs) پلتفرم درمانی و فروشگاهی کانی‌نا ایران است.
این سند حاوی معماری دقیق، فهرست کامل نقاط اتصال (API Endpoints)، کامنت‌های مکان‌نما در کد (TODO Markers)، و تعاریف رسمی تمامی تایپ‌های ورودی (Inputs) و خروجی (Outputs) پلتفرم درمانی و فروشگاهی کانی‌نو ایران است.
---

View File

@ -1,6 +1,6 @@
# طرح‌واره پایگاه داده کانی‌نا ایران (Canina Iran Database Schema) 🗄️
# طرح‌واره پایگاه داده کانی‌نو ایران (Canino 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
);
-- ۴. جدول کاتالوگ محصولات کانی‌نا (products)
-- ۴. جدول کاتالوگ محصولات کانی‌نو (products)
CREATE TABLE products (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
art_no VARCHAR(20) UNIQUE NOT NULL,
@ -250,7 +250,7 @@ CREATE INDEX idx_reminder_completions_ref ON reminder_completions(reminder_id, c
"reminders": [
{
"id": "REM-001",
"productId": "6472f8d38bfcb8234eccb611", // مکمل آرتروفیت کانینا فیزیکی جهت کسر انبار پت
"productId": "6472f8d38bfcb8234eccb611", // مکمل آرتروفیت کانینو فیزیکی جهت کسر انبار پت
"title": "مصرف قرص مفصل‌ساز Canhydrox",
"time": "08:30",
"frequency": "روزانه",
@ -297,7 +297,7 @@ CREATE INDEX idx_reminder_completions_ref ON reminder_completions(reminder_id, c
"dosageLogic": "به ازای هر ۵ کیلوگرم وزن، ۲ قرص روزانه تجویز بالا گردد.",
"symptoms": ["درد مفاصل", "سختی در بلند شدن", "لنگیدن"],
"suitableFor": "هر دو",
"image": "https://www.canina.de/media/89/34/9a/1715077271/Petvital-Canhydrox-111421-V1-Canina-100g_600x600.webp"
"image": "https://www.canina.de/media/89/34/9a/1715077271/Petvital-Canhydrox-111421-V1-Canino-100g_600x600.webp"
}
```

View File

@ -1,7 +1,7 @@
# پلتفرم کانی‌نا ایران (Canina Iran Platform) 🐾
# پلتفرم کانی‌نو ایران (Canino Iran Platform) 🐾
### لندینگ، فروشگاه تخصصی و پرونده سلامت الکترونیک پت (نمایندگی رسمی دارویی Canina Pharma)
پلتفرم **کانی‌نا ایران** یک برنامه جامع تحت وب (SPA/PWA) مجهز به بردهای تعاملی و ابزارهای بهداشتی-دامپزشکی است که با هدف ارتقای سلامت حیوانات خانگی و دسترسی آسان‌تر به مکمل‌های دارویی گرید فوق‌ارگانیک و دارویی کمپانی والای **Canina pharma GmbH آلمان** توسعه یافته است.
پلتفرم **کانی‌نو ایران** یک برنامه جامع تحت وب (SPA/PWA) مجهز به بردهای تعاملی و ابزارهای بهداشتی-دامپزشکی است که با هدف ارتقای سلامت حیوانات خانگی و دسترسی آسان‌تر به مکمل‌های دارویی گرید فوق‌ارگانیک و دارویی کمپانی والای **Canina pharma GmbH آلمان** توسعه یافته است.
---

View File

@ -39,7 +39,7 @@ async function main() {
vetName: 'دکتر علیرضا رضایی',
clinicName: 'کلینیک دامپزشکی پایتخت',
imageUrl: '/images/vets/vet1.webp',
quote: 'مکمل‌های مفصلی کانینا از نظر سرعت جذب و اثربخشی در سگ‌های نژاد بزرگ بی‌نظیر هستند. ما نتایج فوق‌العاده‌ای روی دیسپلازی هیپ مشاهده کردیم.',
quote: 'مکمل‌های مفصلی کانینو از نظر سرعت جذب و اثربخشی در سگ‌های نژاد بزرگ بی‌نظیر هستند. ما نتایج فوق‌العاده‌ای روی دیسپلازی هیپ مشاهده کردیم.',
rating: 5,
order: 1,
isActive: true,
@ -48,7 +48,7 @@ async function main() {
vetName: 'دکتر سارا شمس',
clinicName: 'بیمارستان دامپزشکی تهران',
imageUrl: '/images/vets/vet2.webp',
quote: 'من همیشه برای ریزش مو و مشکلات پوستی گربه‌ها، قرص‌های مخمر و بیوتین کانینا را تجویز می‌کنم. نتایج معمولاً در کمتر از ۳ هفته قابل مشاهده است.',
quote: 'من همیشه برای ریزش مو و مشکلات پوستی گربه‌ها، قرص‌های مخمر و بیوتین کانینو را تجویز می‌کنم. نتایج معمولاً در کمتر از ۳ هفته قابل مشاهده است.',
rating: 5,
order: 2,
isActive: true,

View File

@ -14,9 +14,9 @@ async function main() {
create: {
name: 'مکمل‌های غذایی و درمانی',
slug: 'supplements',
description: 'انواع مکمل‌های اورجینال کانینا آلمان',
metaTitle: 'خرید مکمل کانینا',
metaDescription: 'بهترین مکمل‌های کانینا'
description: 'انواع مکمل‌های اورجینال کانینو آلمان',
metaTitle: 'خرید مکمل کانینو',
metaDescription: 'بهترین مکمل‌های کانینو'
}
});
@ -77,7 +77,7 @@ async function main() {
create: {
id: adminId,
mobile: '09120000000',
email: 'admin@canina-iran.com',
email: 'admin@canino-iran.com',
firstName: 'Admin',
lastName: 'User',
role: 'admin'
@ -94,9 +94,9 @@ async function main() {
isPublished: true,
},
{
title: 'چرا مکمل‌های کانینا؟',
slug: 'why-canina-supplements',
content: 'محتوای کامل مقاله در مورد محصولات کانینا...',
title: 'چرا مکمل‌های کانینو؟',
slug: 'why-canino-supplements',
content: 'محتوای کامل مقاله در مورد محصولات کانینو...',
authorId: '12345678-1234-1234-1234-123456789012',
isPublished: true,
}

View File

@ -36,7 +36,7 @@ async function main() {
id: '12345678-1234-1234-1234-123456789012',
firstName: 'Admin',
lastName: 'System',
email: 'admin@canina.ir',
email: 'admin@canino.ir',
role: 'ADMIN',
mobile: '09000000000'
}
@ -57,11 +57,11 @@ async function main() {
hero_image_title: "مکمل‌های تایید شده دامپزشکی",
hero_quality_standard: "استاندارد کیفی آلمان",
cta_title: "می‌خواهید بدانید کدام محصول برای پت شما مناسب‌تر است؟",
cta_subtitle: "تیم متخصص دامپزشکی کانینا ایران آماده پاسخگویی به سوالات شماست.",
cta_subtitle: "تیم متخصص دامپزشکی کانینو ایران آماده پاسخگویی به سوالات شماست.",
cta_btn_free: "دریافت رژیم مکمل رایگان",
cta_btn_products: "ورود به محصولات تخصصی",
about_teaser_badge: "میراث ما از آلمان",
about_teaser_title: "چرا برند آلمانی Canina مرجع دامپزشکان است؟",
about_teaser_title: "چرا برند آلمانی Canino مرجع دامپزشکان است؟",
about_teaser_feat1_title: "مواد اولیه نایاب",
about_teaser_feat1_desc: "استفاده از پودر صدف لب‌سبز اصل نیوزیلند و مواد ارگانیک با گرید دارویی.",
about_teaser_feat2_title: "فاقد مواد نگهدارنده",

View File

@ -134,7 +134,7 @@ export class AuthService {
}
async adminLogin(body: any) {
if (body.email === 'admin@canina-iran.com' && body.password === 'admin123') {
if (body.email === 'admin@canino-iran.com' && body.password === 'admin123') {
const payload = { sub: '12345678-1234-1234-1234-123456789012', email: body.email, role: 'Admin' };
return {
success: true,

View File

@ -52,13 +52,13 @@ node_cpu_system_time_microseconds ${cpu.system}
# TYPE node_app_uptime_seconds gauge
node_app_uptime_seconds ${uptime}
# HELP canina_db_connected Database connection status (1 = connected, 0 = disconnected).
# TYPE canina_db_connected gauge
canina_db_connected ${dbStatus}
# HELP canino_db_connected Database connection status (1 = connected, 0 = disconnected).
# TYPE canino_db_connected gauge
canino_db_connected ${dbStatus}
# HELP canina_http_requests_total Total HTTP requests processed.
# TYPE canina_http_requests_total counter
canina_http_requests_total ${MetricsController.requestCount}
# HELP canino_http_requests_total Total HTTP requests processed.
# TYPE canino_http_requests_total counter
canino_http_requests_total ${MetricsController.requestCount}
`;
res.set('Content-Type', 'text/plain; version=0.0.4; charset=utf-8');

View File

@ -34,8 +34,8 @@ async function bootstrap() {
app.useGlobalFilters(new HttpExceptionFilter());
const config = new DocumentBuilder()
.setTitle('Canina Iran API')
.setDescription('API Documentation for Canina Iran Pet Health & Supplement Platform')
.setTitle('Canino Iran API')
.setDescription('API Documentation for Canino Iran Pet Health & Supplement Platform')
.setVersion('1.0.0')
.addBearerAuth()
.build();

View File

@ -3,12 +3,12 @@ version: '3.8'
services:
db:
image: docker.arvancloud.ir/library/postgres:16-alpine
container_name: canina_db
container_name: canino_db
restart: always
environment:
POSTGRES_USER: canina
POSTGRES_PASSWORD: caninapassword
POSTGRES_DB: caninadb
POSTGRES_USER: canino
POSTGRES_PASSWORD: caninopassword
POSTGRES_DB: caninodb
ports:
- "5432:5432"
volumes:
@ -16,7 +16,7 @@ services:
redis:
image: docker.arvancloud.ir/library/redis:7-alpine
container_name: canina_redis
container_name: canino_redis
restart: always
ports:
- "16379:6379"
@ -25,10 +25,10 @@ services:
build:
context: ./backend
dockerfile: Dockerfile
container_name: canina_backend
container_name: canino_backend
restart: always
environment:
- DATABASE_URL=postgresql://canina:caninapassword@db:5432/caninadb?schema=public
- DATABASE_URL=postgresql://canino:caninopassword@db:5432/caninodb?schema=public
- REDIS_HOST=redis
- REDIS_PORT=6379
- PORT=3000
@ -42,7 +42,7 @@ services:
build:
context: .
dockerfile: Dockerfile
container_name: canina_frontend
container_name: canino_frontend
restart: always
ports:
- "3001:8080"
@ -51,7 +51,7 @@ services:
prometheus:
image: docker.arvancloud.ir/prom/prometheus:v2.51.0
container_name: canina_prometheus
container_name: canino_prometheus
restart: always
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
@ -62,7 +62,7 @@ services:
grafana:
image: docker.arvancloud.ir/grafana/grafana:10.4.1
container_name: canina_grafana
container_name: canino_grafana
restart: always
ports:
- "3002:3000"

View File

@ -1,7 +1,7 @@
# معرفی پروژه کانینا ایران (Canina Iran)
# معرفی پروژه کانینو ایران (Canino Iran)
## این پروژه چیست؟
سامانه «کانینا ایران» پلتفرم تخصصی معرفی، فروش و مدیریت مکمل‌های درمانی حیوانات خانگی با گرید دارویی است. این سامانه به عنوان درگاه آنلاین نماینده انحصاری کانینا آلمان در ایران فعالیت می‌کند. هدف اصلی پروژه، ارائه یک تجربه کاربری (UX) بسیار غنی، سریع و در کلاس جهانی برای خریداران، کلینیک‌های دامپزشکی (مشتریان B2B) و همچنین فراهم‌کردن ابزارهای هوشمند (مانند مشاوره هوشمند و دانشنامه ترکیبات دارویی) است.
سامانه «کانینو ایران» پلتفرم تخصصی معرفی، فروش و مدیریت مکمل‌های درمانی حیوانات خانگی با گرید دارویی است. این سامانه به عنوان درگاه آنلاین نماینده انحصاری کانینو آلمان در ایران فعالیت می‌کند. هدف اصلی پروژه، ارائه یک تجربه کاربری (UX) بسیار غنی، سریع و در کلاس جهانی برای خریداران، کلینیک‌های دامپزشکی (مشتریان B2B) و همچنین فراهم‌کردن ابزارهای هوشمند (مانند مشاوره هوشمند و دانشنامه ترکیبات دارویی) است.
## قابلیت‌های کلیدی سامانه
سامانه به گونه‌ای طراحی شده تا تمام نیازهای یک کسب‌وکار مدرن e-commerce را در کنار قابلیت‌های تخصصی حوزه سلامت حیوانات برآورده کند:

View File

@ -1,6 +1,6 @@
# راهنمای کاربری سیستم (User Guide)
سیستم کانینا از نظر نوع مخاطب به دو دسته کلی B2C (مشتریان عادی) و B2B (کلینیک‌ها و فروشگاه‌ها) تقسیم می‌شود. علاوه بر این، نقش «ادمین» برای مدیریت سیستم وجود دارد.
سیستم کانینو از نظر نوع مخاطب به دو دسته کلی B2C (مشتریان عادی) و B2B (کلینیک‌ها و فروشگاه‌ها) تقسیم می‌شود. علاوه بر این، نقش «ادمین» برای مدیریت سیستم وجود دارد.
## ۱. مشتریان عادی (B2C Users)
مشتری عادی کسی است که وارد سایت می‌شود تا برای حیوان خانگی خود مکمل خریداری کند یا اطلاعات کسب کند.

View File

@ -51,7 +51,7 @@ backend/
### سبک استایل‌دهی (TailwindCSS)
- استایل‌دهی باید فقط و فقط از طریق کلاس‌های Tailwind انجام شود.
- از کلاس کمکی `cn` (موجود در `lib/utils`) برای ترکیب کلاس‌های شرطی (Conditional Classes) استفاده کنید.
- رنگ‌های اختصاصی پروژه (مثل `canina-blue`, `medical-gray`) در فایل `tailwind.config.ts` تعریف شده‌اند و باید استفاده شوند، نه مقادیر هگزادسیمال خام.
- رنگ‌های اختصاصی پروژه (مثل `canino-blue`, `medical-gray`) در فایل `tailwind.config.ts` تعریف شده‌اند و باید استفاده شوند، نه مقادیر هگزادسیمال خام.
## ۳. استانداردهای توسعه در Backend (NestJS)

View File

@ -14,7 +14,7 @@
1. وارد پوشه بک‌اند شوید: `cd backend`
2. پکیج‌ها را نصب کنید: `npm install`
3. فایل `.env` را ایجاد کنید و متغیر دیتابیس را به شکل زیر تنظیم کنید:
`DATABASE_URL="postgresql://user:password@localhost:5432/caninadb?schema=public"`
`DATABASE_URL="postgresql://user:password@localhost:5432/caninodb?schema=public"`
4. جداول را ایجاد کنید: `npx prisma db push` و سپس `npx prisma generate`
5. پروژه را در حالت توسعه اجرا کنید: `npm run start:dev`
6. بک‌اند شما اکنون روی پورت پیش‌فرض (معمولاً `3001` یا `3005`) در حال اجراست.
@ -52,13 +52,13 @@ npm run build
#### برای راه‌اندازی بک‌اند:
```bash
cd backend
pm2 start dist/main.js --name "canina-api"
pm2 start dist/main.js --name "canino-api"
```
#### برای راه‌اندازی فرانت‌اند Next.js:
```bash
cd frontend/application
pm2 start npm --name "canina-web" -- start
pm2 start npm --name "canino-web" -- start
```
### ذخیره پروسه‌ها تا پس از ری‌استارت سرور قطع نشوند:
@ -72,14 +72,14 @@ pm2 startup
## ۳. تنظیمات Nginx (Reverse Proxy)
سرور Nginx مسئول دریافت ترافیک عمومی و هدایت آن‌ها به پورت‌های صحیح لوکال است.
- ترافیک‌های دامنه `canina-iran.com` به پورت فرانت‌اند (`3000`) هدایت می‌شوند.
- ترافیک‌های دامنه `canino-iran.com` به پورت فرانت‌اند (`3000`) هدایت می‌شوند.
- ترافیک‌هایی که دارای آدرس `/api/` در مسیر خود هستند مستقیماً به پورت بک‌اند (`3001`) هدایت می‌شوند.
### نمونه فایل کانفیگ Nginx
```nginx
server {
listen 80;
server_name canina-iran.com www.canina-iran.com;
server_name canino-iran.com www.canino-iran.com;
# ارسال ترافیک /api به Backend
location /api/ {

View File

@ -33,7 +33,7 @@
```
- برای فیلتر کردن لاگ‌های مشخص، مثلاً فقط بک‌اند:
```bash
pm2 logs canina-api --lines 100
pm2 logs canino-api --lines 100
```
## ۴. مانیتورینگ دیتابیس (PostgreSQL)

View File

@ -1,6 +1,6 @@
# مستندات توسعه‌دهندگان (Developer Documentation)
به مستندات رسمی سامانه «کانینا ایران» خوش آمدید. این مستندات به منظور راهنمایی توسعه‌دهندگان، مهندسین دواپس و تیم فنی شرکت نوشته شده است و نباید در دسترس کاربران عمومی قرار گیرد.
به مستندات رسمی سامانه «کانینو ایران» خوش آمدید. این مستندات به منظور راهنمایی توسعه‌دهندگان، مهندسین دواپس و تیم فنی شرکت نوشته شده است و نباید در دسترس کاربران عمومی قرار گیرد.
در این دایرکتوری تمامی ساختارها، معماری‌ها، قوانین کدنویسی و مراحل انتشار (Deployment) به دقت تدوین شده‌اند تا سرعت 온‌بوردینگ (Onboarding) توسعه‌دهندگان جدید افزایش یافته و نگهداری کدهای قدیمی با کمترین ریسک انجام شود.

View File

@ -68,7 +68,7 @@ export default function Sidebar({ isOpen, setIsOpen }: SidebarProps) {
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">
<h1 className="text-xl font-black text-purple-600">کانینا | ادمینپنل</h1>
<h1 className="text-xl font-black text-purple-600">کانینو | ادمینپنل</h1>
</div>
<nav className="flex-1 overflow-y-auto py-4 px-3 space-y-6">

View File

@ -53,7 +53,7 @@ export default function Dashboard() {
<div className="space-y-6">
<div>
<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 className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">

View File

@ -36,7 +36,7 @@ export default function Login() {
ورود به پنل مدیریت
</h2>
<p className="mt-2 text-center text-sm text-gray-600 font-bold">
کانینا | لابراتوار تخصصی مکملهای درمانی حیوانات
کانینو | لابراتوار تخصصی مکملهای درمانی حیوانات
</p>
</div>
@ -55,7 +55,7 @@ export default function Login() {
value={email}
onChange={(e) => setEmail(e.target.value)}
className="block w-full pl-3 pr-10 py-3 border border-gray-200 rounded-xl focus:ring-purple-500 focus:border-purple-500 sm:text-sm bg-gray-50 font-bold transition-all"
placeholder="admin@canina-iran.com"
placeholder="admin@canino-iran.com"
dir="ltr"
/>
</div>

View File

@ -57,7 +57,7 @@ export default function Settings() {
<SettingsIcon className="w-6 h-6 text-purple-600" />
تنظیمات فروشگاه
</h2>
<p className="text-gray-500 font-medium mt-1">مدیریت پارامترهای اصلی و سیستمی کانینا</p>
<p className="text-gray-500 font-medium mt-1">مدیریت پارامترهای اصلی و سیستمی کانینو</p>
</div>
</div>

View File

@ -100,7 +100,7 @@ export default function Wiki() {
<div>
<h2 className="text-2xl font-black text-gray-900 flex items-center gap-2">
<BookOpen className="w-6 h-6 text-purple-600" />
دانشنامه کانینا (Wiki)
دانشنامه کانینو (Wiki)
</h2>
<p className="text-gray-500 font-medium mt-1">مدیریت اصطلاحات علمی، مواد تشکیلدهنده و خواص درمانی</p>
</div>

View File

@ -15,7 +15,7 @@ async function getBlog(slug: string) {
excerpt: b.metaDescription || b.content.substring(0, 150).replace(/<[^>]+>/g, '') + '...',
image: b.imageUrl,
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
};
} catch (error) {
@ -41,7 +41,7 @@ export default async function BlogPostPage({ params }: { params: { slug: string
return (
<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>
<Link href="/blog" className="text-canina-blue font-bold flex items-center gap-2">
<Link href="/blog" className="text-canino-blue font-bold flex items-center gap-2">
<ChevronRight className="w-4 h-4" />
بازگشت به مجله سلامت
</Link>
@ -54,11 +54,11 @@ export default async function BlogPostPage({ params }: { params: { slug: string
<div className="max-w-7xl mx-auto">
{/* Breadcrumbs */}
<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-canina-blue transition-colors">خانه</Link>
<Link href="/" className="hover:text-canino-blue transition-colors">خانه</Link>
<ChevronRight className="w-2.5 h-2.5" />
<Link href="/blog" className="hover:text-canina-blue transition-colors">مجله سلامت</Link>
<Link href="/blog" className="hover:text-canino-blue transition-colors">مجله سلامت</Link>
<ChevronRight className="w-2.5 h-2.5" />
<span className="text-canina-blue">{selectedPost.title}</span>
<span className="text-canino-blue">{selectedPost.title}</span>
</div>
<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" />
</div>
<div className="p-12">
<div className="flex items-center gap-4 text-xs font-bold text-canina-blue mb-8">
<div className="bg-canina-blue/10 px-4 py-1.5 rounded-full uppercase tracking-widest">تحقیق بالینی</div>
<div className="flex items-center gap-4 text-xs font-bold text-canino-blue mb-8">
<div className="bg-canino-blue/10 px-4 py-1.5 rounded-full uppercase tracking-widest">تحقیق بالینی</div>
<div className="flex items-center gap-1">
<Calendar className="w-4 h-4" />
{selectedPost.date}
@ -79,7 +79,7 @@ export default async function BlogPostPage({ params }: { params: { slug: string
{selectedPost.title}
</h1>
<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-canina-blue pr-6 py-2">
<p className="font-bold text-medical-gray-900 italic text-xl border-r-4 border-canino-blue pr-6 py-2">
{selectedPost.excerpt}
</p>
<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 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 className="flex gap-4">
<button className="p-4 bg-medical-gray-100 rounded-2xl hover:bg-canina-blue hover:text-white transition-all text-medical-gray-400">
<button className="p-4 bg-medical-gray-100 rounded-2xl hover:bg-canino-blue hover:text-white transition-all text-medical-gray-400">
<Sparkles className="w-6 h-6" />
</button>
</div>
@ -106,7 +106,7 @@ export default async function BlogPostPage({ params }: { params: { slug: string
</div>
<div className="lg:col-span-4 space-y-10">
<div className="bg-canina-blue rounded-[3rem] p-10 text-white shadow-2xl relative overflow-hidden">
<div className="bg-canino-blue rounded-[3rem] p-10 text-white shadow-2xl relative overflow-hidden">
<div className="absolute top-0 left-0 p-8 opacity-10">
<Sparkles className="w-20 h-20" />
</div>

View File

@ -18,7 +18,7 @@ async function getBlogs() {
excerpt: b.metaDescription || b.content.substring(0, 150).replace(/<[^>]+>/g, '') + '...',
image: b.imageUrl,
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
}));
} catch (error) {

View File

@ -6,7 +6,7 @@
--font-vazir: "Vazirmatn", sans-serif;
--font-inter: "Inter", sans-serif;
--color-canina-blue: #004182;
--color-canino-blue: #004182;
--color-medical-gray-50: #f8fafc;
--color-medical-gray-100: #f1f5f9;
--color-medical-gray-200: #e2e8f0;
@ -74,5 +74,5 @@
}
::-webkit-scrollbar-thumb:hover {
background: var(--color-canina-blue);
background: var(--color-canino-blue);
}

View File

@ -3,33 +3,33 @@ import './globals.css';
import ClientLayout from './ClientLayout';
export const metadata: Metadata = {
metadataBase: new URL(process.env.NEXT_PUBLIC_SITE_URL || 'https://canina-iran.com'),
metadataBase: new URL(process.env.NEXT_PUBLIC_SITE_URL || 'https://canino-iran.com'),
title: {
template: '%s | کانینا ایران',
default: 'کانینا ایران - مکمل‌های درمانی حیوانات خانگی',
template: '%s | کانینو ایران',
default: 'کانینو ایران - مکمل‌های درمانی حیوانات خانگی',
},
description: 'تدارک هوشمندانه سلامت برای همراهان وفادار شما. کانینا ایران واردکننده انحصاری مکمل‌های درمانی با گرید دارویی اختصاصی از آلمان.',
keywords: ['مکمل حیوانات خانگی', 'مکمل سگ', 'مکمل گربه', 'کانینا', 'داروی حیوانات', 'Canina Iran'],
authors: [{ name: 'Canina Iran' }],
creator: 'Canina Iran',
publisher: 'Canina Iran',
description: 'تدارک هوشمندانه سلامت برای همراهان وفادار شما. کانینو ایران واردکننده انحصاری مکمل‌های درمانی با گرید دارویی اختصاصی از آلمان.',
keywords: ['مکمل حیوانات خانگی', 'مکمل سگ', 'مکمل گربه', 'کانینو', 'داروی حیوانات', 'Canino Iran'],
authors: [{ name: 'Canino Iran' }],
creator: 'Canino Iran',
publisher: 'Canino Iran',
formatDetection: {
email: false,
address: false,
telephone: false,
},
openGraph: {
title: 'کانینا ایران - مکمل‌های درمانی حیوانات خانگی',
title: 'کانینو ایران - مکمل‌های درمانی حیوانات خانگی',
description: 'واردکننده انحصاری مکمل‌های درمانی با گرید دارویی اختصاصی از آلمان',
url: 'https://canina-iran.com',
siteName: 'کانینا ایران',
url: 'https://canino-iran.com',
siteName: 'کانینو ایران',
locale: 'fa_IR',
type: 'website',
},
twitter: {
card: 'summary_large_image',
title: 'کانینا ایران',
description: 'مکمل‌های درمانی حیوانات خانگی کانینا',
title: 'کانینو ایران',
description: 'مکمل‌های درمانی حیوانات خانگی کانینو',
},
robots: {
index: true,
@ -52,14 +52,14 @@ export default function RootLayout({
const jsonLd = {
'@context': 'https://schema.org',
'@type': 'Organization',
name: 'کانینا ایران',
url: 'https://canina-iran.com',
name: 'کانینو ایران',
url: 'https://canino-iran.com',
logo: 'https://canina.de/media/fb/d5/47/1683116813/Logo.png',
contactPoint: {
'@type': 'ContactPoint',
telephone: '+98-21-88884444',
contactType: 'customer service',
email: 'info@canina-iran.com',
email: 'info@canino-iran.com',
areaServed: 'IR',
availableLanguage: 'Persian'
}

View File

@ -35,9 +35,9 @@ export default async function Home() {
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"
>
<h3 className="text-3xl font-black text-medical-gray-900 mb-4 group-hover:text-canina-blue transition-colors italic">فروشگاه تخصصی</h3>
<h3 className="text-3xl font-black text-medical-gray-900 mb-4 group-hover:text-canino-blue transition-colors italic">فروشگاه تخصصی</h3>
<p className="text-medical-gray-500 mb-8 leading-relaxed">دسترسی به تمامی محصولات بر اساس علائم بالینی و نیازهای پت شما.</p>
<div className="flex items-center gap-2 text-canina-blue font-black tracking-widest uppercase text-xs">
<div className="flex items-center gap-2 text-canino-blue font-black tracking-widest uppercase text-xs">
کاتالوگ کامل محصولات
<span className="text-lg"></span>
</div>
@ -46,9 +46,9 @@ export default async function Home() {
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"
>
<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>
<div className="flex items-center gap-2 text-canina-blue font-black tracking-widest uppercase text-xs">
<h3 className="text-3xl font-black mb-4 group-hover:text-canino-blue transition-colors italic">دانشنامه علمی</h3>
<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">
مطالعه مقالات تخصصی
<span className="text-lg"></span>
</div>
@ -60,21 +60,21 @@ export default async function Home() {
<section className="py-24 bg-white overflow-hidden">
<div className="max-w-7xl mx-auto px-4 grid lg:grid-cols-2 gap-16 items-center">
<div className="relative">
<div className="absolute -top-10 -right-10 w-40 h-40 bg-canina-blue/5 rounded-full blur-3xl" />
<div className="absolute -top-10 -right-10 w-40 h-40 bg-canino-blue/5 rounded-full blur-3xl" />
<img
src="/assets/images/regenerated_image_1779109861747.png"
alt="Laboratory"
className="rounded-[3rem] shadow-2xl relative z-10 grayscale-[10%]"
/>
<div className="absolute -bottom-6 -left-6 bg-canina-blue text-white p-8 rounded-3xl shadow-xl z-20">
<div className="absolute -bottom-6 -left-6 bg-canino-blue text-white p-8 rounded-3xl shadow-xl z-20">
<div className="text-4xl font-black mb-1 italic">کیفیت</div>
<div className="text-xs uppercase tracking-widest font-bold opacity-80">استانداردهای فوقدارویی</div>
</div>
</div>
<div>
<div className="text-canina-blue text-xs font-bold uppercase tracking-[0.2em] mb-4">میراث ما از آلمان</div>
<div className="text-canino-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-8">
چرا برند آلمانی Canina مرجع دامپزشکان است؟
چرا برند آلمانی Canino مرجع دامپزشکان است؟
</h2>
<div className="space-y-6">
{[
@ -83,7 +83,7 @@ export default async function Home() {
{ title: 'تاییدیه اروپا', desc: 'مطابق با سخت‌گیرانه‌ترین استانداردهای ایمنی مواد غذایی و دارویی در اتحادیه اروپا.' }
].map((item, idx) => (
<div key={idx} className="flex gap-4">
<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">
<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">
{idx + 1}
</div>
<div>
@ -98,7 +98,7 @@ export default async function Home() {
</section>
{/* Call to Action */}
<section className="bg-canina-blue py-20 relative overflow-hidden">
<section className="bg-canino-blue py-20 relative overflow-hidden">
<div className="absolute inset-0 opacity-10">
<div className="grid grid-cols-10 h-full w-full">
{Array.from({length: 100}).map((_, i) => (
@ -111,15 +111,15 @@ export default async function Home() {
میخواهید بدانید کدام محصول برای پت شما مناسبتر است؟
</h2>
<p className="text-white/80 text-lg mb-10 leading-relaxed">
تیم متخصص دامپزشکی کانینا ایران آماده پاسخگویی به سوالات شماست.
تیم متخصص دامپزشکی کانینو ایران آماده پاسخگویی به سوالات شماست.
</p>
<div className="flex flex-wrap justify-center gap-4">
<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 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>
<Link
href="/shop"
className="bg-canina-blue/20 backdrop-blur-md 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"
className="bg-canino-blue/20 backdrop-blur-md 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"
>
ورود به محصولات تخصصی
</Link>

View File

@ -1,7 +1,7 @@
import { MetadataRoute } from 'next';
export default function robots(): MetadataRoute.Robots {
const baseUrl = process.env.NEXT_PUBLIC_SITE_URL || 'https://canina-iran.com';
const baseUrl = process.env.NEXT_PUBLIC_SITE_URL || 'https://canino-iran.com';
return {
rules: {

View File

@ -3,7 +3,7 @@ import type { Metadata } from 'next';
export const metadata: Metadata = {
title: 'جستجوی محصولات',
description: 'جستجوی مکمل‌های درمانی حیوانات خانگی، داروها و مقالات سلامت در کانینا ایران.',
description: 'جستجوی مکمل‌های درمانی حیوانات خانگی، داروها و مقالات سلامت در کانینو ایران.',
};
export default async function SearchPage({ searchParams }: { searchParams: Promise<{ q?: string }> }) {

View File

@ -54,11 +54,11 @@ export default async function ShopProductPage({ params }: { params: Promise<{ sl
sku: product.artNo,
brand: {
'@type': 'Brand',
name: 'Canina'
name: 'Canino'
},
offers: {
'@type': 'Offer',
url: `https://canina-iran.com/shop/${product.id}`,
url: `https://canino-iran.com/shop/${product.id}`,
priceCurrency: 'IRR',
price: product.priceValue * 10, // Assuming priceValue is in Toman, converting to Rial
availability: 'https://schema.org/InStock',

View File

@ -2,7 +2,7 @@ import { MetadataRoute } from 'next';
import { productService } from '../lib/services/productService';
export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
const baseUrl = process.env.NEXT_PUBLIC_SITE_URL || 'https://canina-iran.com';
const baseUrl = process.env.NEXT_PUBLIC_SITE_URL || 'https://canino-iran.com';
// Static routes
const staticRoutes: MetadataRoute.Sitemap = [

View File

@ -30,7 +30,7 @@ export default async function BlogPage({ params }: { params: { slug: string } })
return (
<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>
<Link href="/wiki" className="text-canina-blue font-bold flex items-center gap-2">
<Link href="/wiki" className="text-canino-blue font-bold flex items-center gap-2">
<ChevronRight className="w-4 h-4" />
بازگشت به دانشنامه
</Link>
@ -41,7 +41,7 @@ export default async function BlogPage({ params }: { params: { slug: string } })
return (
<div className="bg-white py-20 px-4 font-vazir" dir="rtl">
<div className="max-w-4xl mx-auto">
<Link href="/wiki" className="inline-flex items-center gap-2 text-medical-gray-400 hover:text-canina-blue transition-colors font-bold mb-8">
<Link href="/wiki" className="inline-flex items-center gap-2 text-medical-gray-400 hover:text-canino-blue transition-colors font-bold mb-8">
<ChevronRight className="w-5 h-5" />
بازگشت به مقالات
</Link>
@ -67,7 +67,7 @@ export default async function BlogPage({ params }: { params: { slug: string } })
</div>
<div
className="prose prose-lg prose-medical-gray max-w-none prose-headings:font-black prose-p:leading-relaxed prose-a:text-canina-blue"
className="prose prose-lg prose-medical-gray max-w-none prose-headings:font-black prose-p:leading-relaxed prose-a:text-canino-blue"
dangerouslySetInnerHTML={{ __html: blog.content }}
/>
</div>

View File

@ -3,7 +3,7 @@ import type { Metadata } from 'next';
export const metadata: Metadata = {
title: 'دانشنامه ترکیبات دارویی',
description: 'اطلاعات کامل در مورد مواد موثره، ویتامین‌ها و ترکیبات گیاهی به کار رفته در محصولات تخصصی کانینا ایران.',
description: 'اطلاعات کامل در مورد مواد موثره، ویتامین‌ها و ترکیبات گیاهی به کار رفته در محصولات تخصصی کانینو ایران.',
};
export default function WikiPage() {

View File

@ -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="flex items-center gap-3">
<div className="w-10 h-10 bg-canina-blue rounded-xl flex items-center justify-center text-white">
<div className="w-10 h-10 bg-canino-blue rounded-xl flex items-center justify-center text-white">
<MapPin className="w-5 h-5" />
</div>
<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"
value={formData.title}
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-canina-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-canino-blue/20", errors.title ? "border-red-300" : "border-medical-gray-100")}
placeholder="مثال: منزل اصلی"
/>
{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"
value={formData.receptorName}
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-canina-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-canino-blue/20", errors.receptorName ? "border-red-300" : "border-medical-gray-100")}
placeholder="نام و نام‌خانوادگی..."
/>
{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"
value={formData.phone}
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-canina-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-canino-blue/20 text-left", errors.phone ? "border-red-300" : "border-medical-gray-100")}
placeholder="09120000000"
dir="ltr"
/>
@ -200,7 +200,7 @@ export default function AddressModal({ isOpen, onClose, onSave, editingAddress }
type="text"
value={formData.province}
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-canina-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-canino-blue/20", errors.province ? "border-red-300" : "border-medical-gray-100")}
placeholder="نام استان..."
/>
{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"
value={formData.city}
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-canina-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-canino-blue/20", errors.city ? "border-red-300" : "border-medical-gray-100")}
placeholder="نام شهر..."
/>
{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}
value={formData.detail}
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-canina-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-canino-blue/20 resize-none", errors.detail ? "border-red-300" : "border-medical-gray-100")}
placeholder="خیابان، کوچه، پلاک، واحد..."
/>
{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"
value={formData.zipCode}
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-canina-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-canino-blue/20 text-left", errors.zipCode ? "border-red-300" : "border-medical-gray-100")}
placeholder="1234567890"
dir="ltr"
/>
@ -252,7 +252,7 @@ export default function AddressModal({ isOpen, onClose, onSave, editingAddress }
onClick={() => setFormData({...formData, isDefault: !formData.isDefault})}
className={cn(
"w-6 h-6 rounded-lg border-2 flex items-center justify-center transition-all",
formData.isDefault ? "bg-canina-blue border-canina-blue text-white" : "border-medical-gray-200 text-transparent"
formData.isDefault ? "bg-canino-blue border-canino-blue text-white" : "border-medical-gray-200 text-transparent"
)}
>
<Check className="w-4 h-4" />
@ -272,7 +272,7 @@ export default function AddressModal({ isOpen, onClose, onSave, editingAddress }
<button
type="submit"
disabled={isSubmitting}
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"
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"
>
{isSubmitting ? (
<div className="w-5 h-5 border-2 border-white/30 border-t-white rounded-full animate-spin" />

View File

@ -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"
>
{product.specialBadge && (
<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">
<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">
{product.specialBadge}
</div>
)}
@ -136,8 +136,8 @@ const ArchiveProductCard: React.FC<{ product: Product, onClick: (p: Product) =>
</div>
<div className="p-6 flex flex-col flex-1">
<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-canina-blue transition-colors mb-3 leading-tight">{product.name}</h3>
<div className="text-[10px] font-bold text-canino-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>
<div className="flex flex-wrap gap-1 mb-6">
{product.symptoms.slice(0, 2).map((s, i) => (
@ -152,7 +152,7 @@ const ArchiveProductCard: React.FC<{ product: Product, onClick: (p: Product) =>
<button
onClick={handleAddToCart}
disabled={isAdding}
className="w-10 h-10 rounded-xl bg-medical-gray-50 text-canina-blue flex items-center justify-center group-hover:bg-canina-blue group-hover:text-white transition-all disabled:opacity-50"
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"
>
{isAdding ? <Loader2 className="w-4 h-4 animate-spin" /> : <Plus className="w-4 h-4" />}
</button>
@ -263,24 +263,24 @@ export default function ArchivePage({
<div className="lg:hidden mb-10 space-y-4">
<button
onClick={() => router.back()}
className="flex items-center gap-2 text-medical-gray-500 font-bold hover:text-canina-blue transition-colors"
className="flex items-center gap-2 text-medical-gray-500 font-bold hover:text-canino-blue transition-colors"
>
<ChevronRight className="w-5 h-5 font-vazir" />
<span>بازگشت</span>
</button>
<div className="flex items-center gap-2 text-[10px] font-black text-medical-gray-400 uppercase tracking-widest overflow-x-auto whitespace-nowrap pb-2">
<span className="cursor-pointer hover:text-canina-blue" onClick={() => router.push('/')}>کانینا</span>
<span className="cursor-pointer hover:text-canino-blue" onClick={() => router.push('/')}>کانینو</span>
<ChevronLeft className="w-2.5 h-2.5" />
<span className="text-canina-blue">فروشگاه تخصصی</span>
<span className="text-canino-blue">فروشگاه تخصصی</span>
</div>
</div>
{/* Desktop Breadcrumbs */}
<div className="hidden lg:flex items-center gap-2 text-[10px] font-black text-medical-gray-400 uppercase tracking-widest mb-10">
<span className="cursor-pointer hover:text-canina-blue" onClick={() => router.push('/')}>خانه</span>
<span className="cursor-pointer hover:text-canino-blue" onClick={() => router.push('/')}>خانه</span>
<ChevronLeft className="w-2.5 h-2.5" />
<span className="text-canina-blue">کاتالوگ کامل محصولات</span>
<span className="text-canino-blue">کاتالوگ کامل محصولات</span>
</div>
<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">
<div className="bg-white rounded-[2rem] p-6 border border-medical-gray-200 shadow-sm">
<div className="flex items-center gap-2 mb-6">
<Filter className="w-5 h-5 text-canina-blue" />
<Filter className="w-5 h-5 text-canino-blue" />
<h3 className="font-black text-medical-gray-900">فیلترهای تخصصی</h3>
</div>
@ -306,7 +306,7 @@ export default function ArchivePage({
<button
key={pet.id}
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-canina-blue border-canina-blue text-white shadow-lg shadow-canina-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-canino-blue border-canino-blue text-white shadow-lg shadow-canino-blue/20' : 'bg-white border-medical-gray-200 text-medical-gray-400'}`}
>
{pet.icon}
{pet.label}
@ -323,7 +323,7 @@ export default function ArchivePage({
<button
key={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-canina-blue border-canina-blue text-white' : 'bg-white border-medical-gray-100 text-medical-gray-600 hover:border-canina-blue/30'}`}
className={`flex items-center gap-3 px-4 py-3 rounded-2xl text-xs font-bold transition-all border ${selectedCategory === cat.id ? 'bg-canino-blue border-canino-blue text-white' : 'bg-white border-medical-gray-100 text-medical-gray-600 hover:border-canino-blue/30'}`}
>
{cat.icon}
{cat.label}
@ -352,8 +352,8 @@ export default function ArchivePage({
{/* Promo Card */}
<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-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-canina-blue underline-offset-8">مشاوره رایگان</h4>
<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" />
<h4 className="text-lg font-black italic mb-4 relative z-10 underline decoration-canino-blue underline-offset-8">مشاوره رایگان</h4>
<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>
</div>
@ -362,7 +362,7 @@ export default function ArchivePage({
{/* Main Content */}
<main className="flex-1 relative">
<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-canina-blue">Canina</span></h2>
<h2 className="text-3xl font-black text-medical-gray-900">کاتولوگ دارویی <span className="text-canino-blue">Canino</span></h2>
<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" />
<input
@ -370,7 +370,7 @@ export default function ArchivePage({
placeholder="جستجوی محصول..."
value={searchQuery}
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-canina-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-canino-blue/20"
/>
</div>
</div>
@ -405,7 +405,7 @@ export default function ArchivePage({
setActiveSymptoms([]);
setSearchQuery("");
}}
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"
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"
>
پاک کردن همه فیلترها و نمایش همه
</button>

View File

@ -181,7 +181,7 @@ export default function AuthModal({ isOpen, onClose }: AuthModalProps) {
dir="rtl"
>
{/* Top highlight bar */}
<div className="absolute top-0 left-0 w-full h-2 bg-gradient-to-r from-canina-blue to-indigo-500" />
<div className="absolute top-0 left-0 w-full h-2 bg-gradient-to-r from-canino-blue to-indigo-500" />
<div className="p-8 relative">
{/* Close Button */}
@ -194,11 +194,11 @@ export default function AuthModal({ isOpen, onClose }: AuthModalProps) {
{/* Title Header */}
<div className="flex flex-col items-center text-center mb-8 pt-4">
<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-canina-blue" />
<div className="w-20 h-20 bg-canino-blue/10 rounded-3xl flex items-center justify-center mb-4 shadow-inner">
<ShieldCheck className="w-10 h-10 text-canino-blue" />
</div>
<h2 className="text-3xl font-black text-medical-gray-900 mb-2 italic">
ورود به دنیای کانینا
ورود به دنیای کانینو
</h2>
<p className="text-medical-gray-500 text-sm font-bold max-w-[280px]">
{view === "otp"
@ -227,7 +227,7 @@ export default function AuthModal({ isOpen, onClose }: AuthModalProps) {
value={phoneNumber}
onChange={(e) => setPhoneNumber(e.target.value.replace(/[^0-9]/g, ''))}
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-canina-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-canino-blue/20 outline-none font-bold text-left tracking-widest"
/>
</div>
<div className="space-y-2">
@ -238,7 +238,7 @@ export default function AuthModal({ isOpen, onClose }: AuthModalProps) {
value={password}
onChange={(e) => setPassword(e.target.value)}
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-canina-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-canino-blue/20 outline-none text-left"
/>
</div>
@ -246,14 +246,14 @@ export default function AuthModal({ isOpen, onClose }: AuthModalProps) {
<button
type="button"
onClick={() => setView("otp-phone")}
className="text-xs font-bold text-canina-blue hover:underline"
className="text-xs font-bold text-canino-blue hover:underline"
>
ورود با کد یکبار مصرف (OTP)
</button>
<button
type="button"
onClick={() => setView("register")}
className="text-xs font-bold text-canina-blue hover:underline"
className="text-xs font-bold text-canino-blue hover:underline"
>
حساب ندارید؟ ثبتنام
</button>
@ -262,7 +262,7 @@ export default function AuthModal({ isOpen, onClose }: AuthModalProps) {
<button
type="submit"
disabled={isLoading || !phoneNumber || !password}
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"
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"
>
{isLoading ? <RefreshCw className="w-5 h-5 animate-spin" /> : <>ورود به حساب</>}
</button>
@ -286,7 +286,7 @@ export default function AuthModal({ isOpen, onClose }: AuthModalProps) {
value={firstName}
onChange={(e) => setFirstName(e.target.value)}
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-canina-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-canino-blue/20 outline-none text-sm"
/>
</div>
<div className="space-y-1">
@ -296,7 +296,7 @@ export default function AuthModal({ isOpen, onClose }: AuthModalProps) {
value={lastName}
onChange={(e) => setLastName(e.target.value)}
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-canina-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-canino-blue/20 outline-none text-sm"
/>
</div>
</div>
@ -309,7 +309,7 @@ export default function AuthModal({ isOpen, onClose }: AuthModalProps) {
value={phoneNumber}
onChange={(e) => setPhoneNumber(e.target.value.replace(/[^0-9]/g, ''))}
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-canina-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-canino-blue/20 outline-none text-left tracking-widest text-sm"
/>
</div>
@ -320,7 +320,7 @@ export default function AuthModal({ isOpen, onClose }: AuthModalProps) {
value={email}
onChange={(e) => setEmail(e.target.value)}
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-canina-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-canino-blue/20 outline-none text-left text-sm"
/>
</div>
@ -331,7 +331,7 @@ export default function AuthModal({ isOpen, onClose }: AuthModalProps) {
value={password}
onChange={(e) => setPassword(e.target.value)}
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-canina-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-canino-blue/20 outline-none text-left text-sm"
/>
</div>
@ -339,7 +339,7 @@ export default function AuthModal({ isOpen, onClose }: AuthModalProps) {
<button
type="button"
onClick={() => setView("login")}
className="text-xs font-bold text-canina-blue hover:underline"
className="text-xs font-bold text-canino-blue hover:underline"
>
بازگشت به ورود
</button>
@ -348,7 +348,7 @@ export default function AuthModal({ isOpen, onClose }: AuthModalProps) {
<button
type="submit"
disabled={isLoading || !phoneNumber || !password || !firstName || !lastName}
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"
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"
>
{isLoading ? <RefreshCw className="w-4 h-4 animate-spin" /> : <>ثبتنام</>}
</button>
@ -370,7 +370,7 @@ export default function AuthModal({ isOpen, onClose }: AuthModalProps) {
<button
type="button"
onClick={() => setView("login")}
className="text-[10px] font-black text-canina-blue hover:underline"
className="text-[10px] font-black text-canino-blue hover:underline"
>
برگشت به صفحه ورود
</button>
@ -385,7 +385,7 @@ export default function AuthModal({ isOpen, onClose }: AuthModalProps) {
value={phoneNumber}
onChange={(e) => setPhoneNumber(e.target.value.replace(/[^0-9]/g, ''))}
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-canina-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-canino-blue/20 outline-none font-bold text-lg text-left tracking-widest"
/>
</div>
</div>
@ -393,7 +393,7 @@ export default function AuthModal({ isOpen, onClose }: AuthModalProps) {
<button
type="submit"
disabled={isLoading || phoneNumber.length < 11}
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"
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"
>
{isLoading ? (
<RefreshCw className="w-6 h-6 animate-spin" />
@ -422,7 +422,7 @@ export default function AuthModal({ isOpen, onClose }: AuthModalProps) {
<button
type="button"
onClick={() => setView("otp-phone")}
className="text-[10px] font-black text-canina-blue flex items-center gap-1 hover:underline"
className="text-[10px] font-black text-canino-blue flex items-center gap-1 hover:underline"
>
<ArrowRight className="w-3 h-3" />
تغییر شماره
@ -438,7 +438,7 @@ export default function AuthModal({ isOpen, onClose }: AuthModalProps) {
value={otpCode}
onChange={(e) => setOtpCode(e.target.value.replace(/[^0-9]/g, ''))}
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-canina-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-canino-blue/20 outline-none font-black text-2xl text-center tracking-[0.5em]"
/>
</div>
</div>
@ -453,7 +453,7 @@ export default function AuthModal({ isOpen, onClose }: AuthModalProps) {
type="button"
onClick={handleResendOtp}
disabled={isLoading}
className="text-xs font-black text-canina-blue hover:underline flex items-center gap-1.5 justify-center mx-auto"
className="text-xs font-black text-canino-blue hover:underline flex items-center gap-1.5 justify-center mx-auto"
>
<RefreshCw className="w-3.5 h-3.5" />
ارسال مجدد کد تایید
@ -464,7 +464,7 @@ export default function AuthModal({ isOpen, onClose }: AuthModalProps) {
<button
type="submit"
disabled={isLoading || otpCode.length < 5}
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"
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"
>
{isLoading ? (
<RefreshCw className="w-6 h-6 animate-spin" />

View File

@ -79,7 +79,7 @@ export default function B2BPortal({ onClose }: { onClose: () => void }) {
</button>
{/* Sidebar Info */}
<div className="w-full md:w-80 bg-canina-blue p-10 text-white flex flex-col">
<div className="w-full md:w-80 bg-canino-blue p-10 text-white flex flex-col">
<div className="mb-10">
<div className="w-16 h-16 bg-white/20 rounded-2xl flex items-center justify-center mb-6">
<Building2 className="w-8 h-8" />
@ -113,14 +113,14 @@ export default function B2BPortal({ onClose }: { onClose: () => void }) {
placeholder="جستجوی کد کالا یا نام محصول..."
value={searchQuery}
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-canina-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-canino-blue/20"
/>
</div>
<button
onClick={handleAddAll}
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-canina-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-canino-blue transition-colors disabled:opacity-30"
>
<ShoppingCart className="w-4 h-4" />
افزودن کلی ({totalItems} عدد)
@ -162,7 +162,7 @@ export default function B2BPortal({ onClose }: { onClose: () => void }) {
value={quantities[product.id] || ""}
onChange={(e) => handleQuantityChange(product.id, e.target.value)}
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-canina-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-canino-blue/20 outline-none"
/>
</td>
</tr>

View File

@ -33,11 +33,11 @@ export default function BlogPage({ blogs = [] }: { blogs: BlogPost[] }) {
<div className="max-w-7xl mx-auto">
{/* Breadcrumbs */}
<div className="flex items-center gap-2 text-[10px] font-black text-medical-gray-400 uppercase tracking-widest mb-10">
<span className="cursor-pointer hover:text-canina-blue" onClick={() => router.push('/')}>خانه</span>
<span className="cursor-pointer hover:text-canino-blue" onClick={() => router.push('/')}>خانه</span>
<ChevronRight className="w-2.5 h-2.5" />
<span className="cursor-pointer hover:text-canina-blue" onClick={() => setSelectedPost(null)}>مجله سلامت</span>
<span className="cursor-pointer hover:text-canino-blue" onClick={() => setSelectedPost(null)}>مجله سلامت</span>
<ChevronRight className="w-2.5 h-2.5" />
<span className="text-canina-blue">{selectedPost.title}</span>
<span className="text-canino-blue">{selectedPost.title}</span>
</div>
<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" />
</div>
<div className="p-12">
<div className="flex items-center gap-4 text-xs font-bold text-canina-blue mb-8">
<div className="bg-canina-blue/10 px-4 py-1.5 rounded-full uppercase tracking-widest">تحقیق بالینی</div>
<div className="flex items-center gap-4 text-xs font-bold text-canino-blue mb-8">
<div className="bg-canino-blue/10 px-4 py-1.5 rounded-full uppercase tracking-widest">تحقیق بالینی</div>
<div className="flex items-center gap-1">
<Calendar className="w-4 h-4" />
{selectedPost.date}
@ -62,7 +62,7 @@ export default function BlogPage({ blogs = [] }: { blogs: BlogPost[] }) {
{selectedPost.title}
</h1>
<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-canina-blue pr-6 py-2">
<p className="font-bold text-medical-gray-900 italic text-xl border-r-4 border-canino-blue pr-6 py-2">
{selectedPost.excerpt}
</p>
<div className="whitespace-pre-line">
@ -77,11 +77,11 @@ export default function BlogPage({ blogs = [] }: { blogs: BlogPost[] }) {
</div>
<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 className="flex gap-4">
<button className="p-4 bg-medical-gray-100 rounded-2xl hover:bg-canina-blue hover:text-white transition-all text-medical-gray-400">
<button className="p-4 bg-medical-gray-100 rounded-2xl hover:bg-canino-blue hover:text-white transition-all text-medical-gray-400">
<Sparkles className="w-6 h-6" />
</button>
</div>
@ -91,7 +91,7 @@ export default function BlogPage({ blogs = [] }: { blogs: BlogPost[] }) {
</div>
<div className="lg:col-span-4 space-y-10">
<div className="bg-canina-blue rounded-[3rem] p-10 text-white shadow-2xl relative overflow-hidden">
<div className="bg-canino-blue rounded-[3rem] p-10 text-white shadow-2xl relative overflow-hidden">
<div className="absolute top-0 left-0 p-8 opacity-10">
<Sparkles className="w-20 h-20" />
</div>
@ -127,7 +127,7 @@ export default function BlogPage({ blogs = [] }: { blogs: BlogPost[] }) {
<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" />
</div>
<div className="text-sm font-black text-medical-gray-900 group-hover:text-canina-blue transition-colors line-clamp-2">
<div className="text-sm font-black text-medical-gray-900 group-hover:text-canino-blue transition-colors line-clamp-2">
{p.title}
</div>
</div>
@ -147,15 +147,15 @@ export default function BlogPage({ blogs = [] }: { blogs: BlogPost[] }) {
{/* Header */}
<div className="flex flex-col md:flex-row items-center justify-between mb-16 gap-6">
<div className="text-right">
<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">
<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">
<BookOpen className="w-3 h-3" />
Canina Science Blog
Canino Science Blog
</div>
<h1 className="text-4xl lg:text-6xl font-black text-medical-gray-900 italic leading-tight">
مجله تخصصی <span className="text-canina-blue">سلامت پتها</span>
مجله تخصصی <span className="text-canino-blue">سلامت پتها</span>
</h1>
<p className="text-lg text-medical-gray-500 font-medium mt-4 max-w-xl">
آخرین یافتههای علمی محققین کانینا آلمان در مورد تغذیه و سلامت پتها.
آخرین یافتههای علمی محققین کانینو آلمان در مورد تغذیه و سلامت پتها.
</p>
</div>
<button
@ -184,14 +184,14 @@ export default function BlogPage({ blogs = [] }: { blogs: BlogPost[] }) {
/>
</div>
<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-canina-blue mb-6">
<div className="bg-canina-blue/10 px-3 py-1 rounded-full uppercase tracking-widest">تخصصی</div>
<div className="flex items-center gap-4 text-xs font-bold text-canino-blue mb-6">
<div className="bg-canino-blue/10 px-3 py-1 rounded-full uppercase tracking-widest">تخصصی</div>
<div className="flex items-center gap-1">
<Calendar className="w-3 h-3" />
{blogs[0].date}
</div>
</div>
<h2 className="text-3xl lg:text-4xl font-black text-medical-gray-900 mb-6 leading-tight group-hover:text-canina-blue transition-colors">
<h2 className="text-3xl lg:text-4xl font-black text-medical-gray-900 mb-6 leading-tight group-hover:text-canino-blue transition-colors">
{blogs[0].title}
</h2>
<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 className="text-sm">
<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 className="flex items-center gap-2 text-canina-blue font-black">
<div className="flex items-center gap-2 text-canino-blue font-black">
ادامه مطلب
<ArrowLeft className="w-5 h-5 group-hover:-translate-x-2 transition-transform" />
</div>
@ -237,13 +237,13 @@ export default function BlogPage({ blogs = [] }: { blogs: BlogPost[] }) {
/>
</div>
<div className="p-8">
<div className="flex items-center gap-4 text-[10px] font-bold text-canina-blue mb-4">
<div className="flex items-center gap-4 text-[10px] font-bold text-canino-blue mb-4">
<div className="flex items-center gap-1">
<Calendar className="w-3 h-3" />
{post.date}
</div>
</div>
<h3 className="text-xl font-black text-medical-gray-900 mb-4 group-hover:text-canina-blue transition-colors">
<h3 className="text-xl font-black text-medical-gray-900 mb-4 group-hover:text-canino-blue transition-colors">
{post.title}
</h3>
<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 */}
<div className="bg-canina-blue rounded-[3rem] p-10 text-white relative overflow-hidden flex flex-col justify-center">
<div className="bg-canino-blue rounded-[3rem] p-10 text-white relative overflow-hidden flex flex-col justify-center">
<div className="absolute top-0 right-0 p-8 opacity-20">
<Sparkles className="w-24 h-24" />
</div>
@ -272,7 +272,7 @@ export default function BlogPage({ blogs = [] }: { blogs: BlogPost[] }) {
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"
/>
<button className="bg-white text-canina-blue px-6 py-3 rounded-xl font-black">
<button className="bg-white text-canino-blue px-6 py-3 rounded-xl font-black">
عضویت
</button>
</div>
@ -280,7 +280,7 @@ export default function BlogPage({ blogs = [] }: { blogs: BlogPost[] }) {
</div>
{/* Synergy Products Cross-sell */}
<section className="mt-32 p-12 bg-canina-blue rounded-[4rem] text-white overflow-hidden relative shadow-2xl">
<section className="mt-32 p-12 bg-canino-blue rounded-[4rem] text-white overflow-hidden relative shadow-2xl">
<div className="absolute inset-0 opacity-20 pointer-events-none">
<div className="grid grid-cols-6 h-full w-full">
{Array.from({length: 36}).map((_, i) => (
@ -292,11 +292,11 @@ export default function BlogPage({ blogs = [] }: { blogs: BlogPost[] }) {
<div className="flex-1">
<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>
<button
onClick={() => router.push('/shop')}
className="bg-white text-canina-blue px-8 py-4 rounded-2xl font-black hover:scale-105 transition-transform"
className="bg-white text-canino-blue px-8 py-4 rounded-2xl font-black hover:scale-105 transition-transform"
>
مشاهده محصولات تخصصی
</button>

View File

@ -69,7 +69,7 @@ export default function CartDrawer({ isOpen, onClose, onCheckout, onShopNavigate
{/* Header */}
<div className="p-6 border-b border-medical-gray-100 flex items-center justify-between">
<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-canina-blue">
<div className="w-10 h-10 bg-medical-gray-50 rounded-xl flex items-center justify-center text-canino-blue">
<ShoppingBag className="w-6 h-6" />
</div>
<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();
onShopNavigate?.();
}}
className="text-canina-blue font-black text-sm border-b-2 border-canina-blue pb-1 font-vazir"
className="text-canino-blue font-black text-sm border-b-2 border-canino-blue pb-1 font-vazir"
>
مشاهده محصولات تخصصی
</button>
@ -107,12 +107,12 @@ export default function CartDrawer({ isOpen, onClose, onCheckout, onShopNavigate
</div>
<div className="flex-1 min-w-0">
<h4 className="text-sm font-black text-medical-gray-900 truncate mb-1">{item.product.name}</h4>
<p className="text-[10px] text-canina-blue font-bold mb-3">{item.product.category}</p>
<p className="text-[10px] text-canino-blue font-bold mb-3">{item.product.category}</p>
<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">
<button
onClick={() => updateQuantity(item.product.id, item.quantity - 1)}
className="p-1 hover:text-canina-blue transition-colors"
className="p-1 hover:text-canino-blue transition-colors"
data-testid="minus-btn"
>
<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>
<button
onClick={() => updateQuantity(item.product.id, item.quantity + 1)}
className="p-1 hover:text-canina-blue transition-colors"
className="p-1 hover:text-canino-blue transition-colors"
data-testid="plus-btn"
>
<Plus className="w-3 h-3" />
@ -184,14 +184,14 @@ export default function CartDrawer({ isOpen, onClose, onCheckout, onShopNavigate
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
className="p-5 bg-gradient-to-br from-canina-blue/5 to-transparent border border-canina-blue/10 rounded-3xl"
className="p-5 bg-gradient-to-br from-canino-blue/5 to-transparent border border-canino-blue/10 rounded-3xl"
>
<div className="flex items-center gap-2 mb-4">
<Sparkles className="w-4 h-4 text-canina-blue animate-pulse" />
<Sparkles className="w-4 h-4 text-canino-blue animate-pulse" />
<span className="text-xs font-black text-medical-gray-900">پیشنهاد هوشمند برای جذب بهتر</span>
</div>
<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-canina-blue/5">
<div className="w-16 h-16 bg-white rounded-2xl p-2 shrink-0 shadow-sm border border-canino-blue/5">
<SafeImage src={suggestedProduct.image} alt="" className="w-full h-full object-contain" />
</div>
<div className="flex-1">
@ -200,7 +200,7 @@ export default function CartDrawer({ isOpen, onClose, onCheckout, onShopNavigate
</div>
<button
onClick={() => addItem(suggestedProduct, 1)}
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"
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"
>
<Plus className="w-4 h-4" />
</button>
@ -223,14 +223,14 @@ export default function CartDrawer({ isOpen, onClose, onCheckout, onShopNavigate
<div className="relative">
<input
type="text"
placeholder="CANINA2024"
placeholder="CANINO2024"
value={couponCode}
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-canina-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-canino-blue/20 transition-all`}
/>
<button
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-canina-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-canino-blue'}`}
>
{couponStatus === 'success' ? <CheckCircle2 className="w-3 h-3" /> : 'اعمال'}
</button>
@ -257,17 +257,17 @@ export default function CartDrawer({ isOpen, onClose, onCheckout, onShopNavigate
{/* Subscription Toggle */}
<div
onClick={toggleSubscription}
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'}`}
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'}`}
>
<div className="flex items-center gap-3">
<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'}`}>
<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'}`}>
<ShieldCheck className="w-6 h-6" />
</div>
<div className="flex-1">
<h5 className="text-xs font-black text-medical-gray-900">فعالسازی سرویس تمدید خودکار (Refill)</h5>
<p className="text-[10px] text-medical-gray-500 font-medium">۵٪ تخفیف روی تمام فاکتور + ارسال اولویتدار</p>
</div>
<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'}`}>
<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'}`}>
{isSubscribed && <X className="w-3 h-3 text-white" />}
</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">
<span className="text-lg font-black text-medical-gray-900 italic">مجموع قابل پرداخت</span>
<div className="text-left">
<p className="text-2xl font-black text-canina-blue tracking-tighter leading-none font-vazir">{toPersian(getTotal().toLocaleString())}</p>
<p className="text-2xl font-black text-canino-blue tracking-tighter leading-none font-vazir">{toPersian(getTotal().toLocaleString())}</p>
<p className="text-[10px] text-medical-gray-400 font-bold">تومان</p>
</div>
</div>
@ -295,7 +295,7 @@ export default function CartDrawer({ isOpen, onClose, onCheckout, onShopNavigate
<button
onClick={onCheckout}
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"
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"
>
ثبت نهایی و تسویه حساب
<ArrowLeft className="w-5 h-5 group-hover:translate-x-[-4px] transition-transform" />

View File

@ -113,7 +113,7 @@ export default function CheckoutPage() {
<ShieldCheck className="w-12 h-12" />
</div>
<h2 className="text-2xl font-black text-medical-gray-900 italic">سبد خرید شما خالی است</h2>
<button onClick={() => router.push('/shop')} className="text-canina-blue font-black underline underline-offset-8">بازگشت به فروشگاه</button>
<button onClick={() => router.push('/shop')} className="text-canino-blue font-black underline underline-offset-8">بازگشت به فروشگاه</button>
</div>
</div>
);
@ -127,24 +127,24 @@ export default function CheckoutPage() {
<div className="lg:hidden mb-10 space-y-4">
<button
onClick={() => router.back()}
className="flex items-center gap-2 text-medical-gray-500 font-bold hover:text-canina-blue transition-colors"
className="flex items-center gap-2 text-medical-gray-500 font-bold hover:text-canino-blue transition-colors"
>
<ChevronRight className="w-5 h-5" />
<span>بازگشت به سبد خرید</span>
</button>
<div className="flex items-center gap-2 text-[10px] font-black text-medical-gray-400 uppercase tracking-widest overflow-x-auto whitespace-nowrap pb-2">
<span className="cursor-pointer hover:text-canina-blue" onClick={() => router.push('/shop')}>سبد خرید</span>
<span className="cursor-pointer hover:text-canino-blue" onClick={() => router.push('/shop')}>سبد خرید</span>
<ChevronLeft className="w-2.5 h-2.5" />
<span className="text-canina-blue">نهاییسازی سفارش</span>
<span className="text-canino-blue">نهاییسازی سفارش</span>
</div>
</div>
{/* 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">
<span className="cursor-pointer hover:text-canina-blue" onClick={() => router.push('/')}>خانه</span>
<span className="cursor-pointer hover:text-canino-blue" onClick={() => router.push('/')}>خانه</span>
<ChevronLeft className="w-2.5 h-2.5" />
<span className="text-canina-blue">درگاه پرداخت امن و نهاییسازی</span>
<span className="text-canino-blue">درگاه پرداخت امن و نهاییسازی</span>
</div>
<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">
{/* Step 1: Shipping */}
<section className="bg-white rounded-[3rem] border border-medical-gray-200 p-10 overflow-hidden relative">
<div className="absolute top-0 right-0 w-3 h-full bg-canina-blue opacity-20" />
<div className="absolute top-0 right-0 w-3 h-full bg-canino-blue opacity-20" />
<div className="flex items-center gap-4 mb-10">
<div className="w-12 h-12 bg-medical-gray-900 text-white rounded-2xl flex items-center justify-center font-black">۱</div>
<h2 className="text-2xl font-black text-medical-gray-900 italic">اطلاعات ارسال</h2>
@ -161,15 +161,15 @@ export default function CheckoutPage() {
<div className="grid md:grid-cols-2 gap-6">
<div className="space-y-2">
<label className="text-[10px] font-black text-medical-gray-400 uppercase tracking-widest block">نام و نام خانوادگی</label>
<input type="text" className="w-full bg-medical-gray-50 border border-medical-gray-200 rounded-2xl py-4 px-6 text-sm focus:outline-none focus:ring-2 focus:ring-canina-blue/20" placeholder="مثلاً: پارسا آقایی" />
<input type="text" className="w-full bg-medical-gray-50 border border-medical-gray-200 rounded-2xl py-4 px-6 text-sm focus:outline-none focus:ring-2 focus:ring-canino-blue/20" placeholder="مثلاً: پارسا آقایی" />
</div>
<div className="space-y-2">
<label className="text-[10px] font-black text-medical-gray-400 uppercase tracking-widest block">شماره تماس</label>
<input type="text" className="w-full bg-medical-gray-50 border border-medical-gray-200 rounded-2xl py-4 px-6 text-sm focus:outline-none focus:ring-2 focus:ring-canina-blue/20" placeholder="۰۹۱۲XXXXXXX" />
<input type="text" className="w-full bg-medical-gray-50 border border-medical-gray-200 rounded-2xl py-4 px-6 text-sm focus:outline-none focus:ring-2 focus:ring-canino-blue/20" placeholder="۰۹۱۲XXXXXXX" />
</div>
<div className="md:col-span-2 space-y-2">
<label className="text-[10px] font-black text-medical-gray-400 uppercase tracking-widest block">آدرس دقیق پستی</label>
<textarea className="w-full bg-medical-gray-50 border border-medical-gray-200 rounded-2xl py-4 px-6 text-sm focus:outline-none focus:ring-2 focus:ring-canina-blue/20 h-32" placeholder="استان، شهر، خیابان..." />
<textarea className="w-full bg-medical-gray-50 border border-medical-gray-200 rounded-2xl py-4 px-6 text-sm focus:outline-none focus:ring-2 focus:ring-canino-blue/20 h-32" placeholder="استان، شهر، خیابان..." />
</div>
</div>
</section>
@ -199,9 +199,9 @@ export default function CheckoutPage() {
console.error("Payment init failed");
}
}}
className={cn("p-6 rounded-3xl border-2 cursor-pointer transition-all group", paymentMethod === pay.id ? "border-canina-blue bg-canina-blue/5" : "border-medical-gray-100 hover:border-canina-blue")}
className={cn("p-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")}
>
<div className="w-12 h-12 bg-medical-gray-50 rounded-2xl flex items-center justify-center text-medical-gray-400 group-hover:text-canina-blue group-hover:bg-canina-blue/10 mb-4 transition-all">
<div className="w-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">
{pay.icon}
</div>
<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-1 min-w-[280px]">
<h4 className="text-lg font-black text-medical-gray-900 italic mb-2">رند کردن مبلغ و کمک به پناهگاه</h4>
<p className="text-sm text-medical-gray-600 leading-relaxed font-medium"> با انتخاب این گزینه، مابقی مبلغ تا ده هزار تومان بعدی یا ۱٪ از خرید شما (هر کدام بیشتر باشد) صرف تامین غذا و دارو برای حیوانات بی-سرپرست تحت حمایت کانینا میشود.</p>
<p className="text-sm text-medical-gray-600 leading-relaxed font-medium"> با انتخاب این گزینه، مابقی مبلغ تا ده هزار تومان بعدی یا ۱٪ از خرید شما (هر کدام بیشتر باشد) صرف تامین غذا و دارو برای حیوانات بی-سرپرست تحت حمایت کانینو میشود.</p>
<div className="mt-4 flex items-center gap-3 text-pink-600">
<ShieldCheck className="w-4 h-4" />
<span className="text-[10px] font-black uppercase tracking-widest">گزارش شفاف هزینهکرد در داشبورد شما</span>
@ -305,7 +305,7 @@ export default function CheckoutPage() {
<div className="flex justify-between items-end pt-4">
<span className="text-xl font-black italic">مبلغ نهایی</span>
<div className="text-left">
<p className="text-3xl font-black text-canina-blue leading-none font-vazir">{toPersian(getTotal().toLocaleString())}</p>
<p className="text-3xl font-black text-canino-blue leading-none font-vazir">{toPersian(getTotal().toLocaleString())}</p>
<p className="text-[10px] text-white/30 font-bold mt-1">تومان</p>
</div>
</div>
@ -329,8 +329,8 @@ export default function CheckoutPage() {
<input
name="coupon"
type="text"
placeholder="کد تخفیف (مثلاً: CANINA2024)"
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"
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"
/>
<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>
@ -339,7 +339,7 @@ export default function CheckoutPage() {
{/* Refill Estimates */}
<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">
<Clock className="w-5 h-5 text-canina-blue" />
<Clock className="w-5 h-5 text-canino-blue" />
<h4 className="text-xs font-black uppercase tracking-widest font-vazir">تخمین اتمام مصرف (هوش مصنوعی)</h4>
</div>
<div className="space-y-2">
@ -353,7 +353,7 @@ export default function CheckoutPage() {
return (
<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-canina-blue">~ {toPersian(days)} روز دیگر</span>
<span className="text-canino-blue">~ {toPersian(days)} روز دیگر</span>
</div>
);
})}
@ -363,7 +363,7 @@ export default function CheckoutPage() {
<button
onClick={handleFinalize}
disabled={loading}
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"
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"
>
{loading ? (
<>

View File

@ -52,14 +52,14 @@ export class ErrorBoundary extends React.Component<Props, State> {
<button
onClick={this.handleRetry}
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"
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"
>
<RefreshCcw className="w-5 h-5" />
تلاش مجدد
</button>
<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-canina-blue rounded-xl flex items-center justify-center text-white font-bold text-xs italic">C</div>
<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>
<span className="text-[10px] font-black text-medical-gray-300 uppercase tracking-widest">Canina Pharma Support</span>
</div>
</div>

View File

@ -13,7 +13,7 @@ export const NotFoundPage = () => {
<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="w-32 h-32 bg-white rounded-[3rem] shadow-2xl flex items-center justify-center">
<FileQuestion className="w-16 h-16 text-canina-blue" />
<FileQuestion className="w-16 h-16 text-canino-blue" />
</div>
</div>
</div>
@ -25,7 +25,7 @@ export const NotFoundPage = () => {
<button
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-canina-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-canino-blue transition-all shadow-2xl shadow-medical-gray-900/10"
>
<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>
<p className="text-medical-gray-500 mb-12 font-bold text-lg">
ارتباط با دیتابیس کانینا با مشکل مواجه شده است. در حال بررسی موضوع هستیم.
ارتباط با دیتابیس کانینو با مشکل مواجه شده است. در حال بررسی موضوع هستیم.
</p>
<div className="flex flex-col sm:flex-row gap-4 justify-center">
<button
onClick={onRetry}
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"
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"
>
<RefreshCw className="w-5 h-5" />
تلاش مجدد

View File

@ -29,7 +29,7 @@ function ProductCard({ product, onClick }: { product: Product; key?: string | nu
viewport={{ once: true }}
transition={{ duration: 0.5 }}
onClick={() => onClick(product)}
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"
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"
>
{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 ${
@ -53,11 +53,11 @@ function ProductCard({ product, onClick }: { product: Product; key?: string | nu
{/* Hover Actions */}
<Link href={`/shop/${product.slug || product.id}`} className="absolute inset-0 z-10" />
<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-canina-blue flex items-center justify-center hover:scale-110 transition-transform shadow-lg">
<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="w-12 h-12 rounded-full bg-white text-canino-blue flex items-center justify-center hover:scale-110 transition-transform shadow-lg">
<Eye className="w-5 h-5" />
</div>
<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">
<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">
<ShoppingCart className="w-5 h-5" />
</div>
</div>
@ -66,10 +66,10 @@ function ProductCard({ product, onClick }: { product: Product; key?: string | nu
{/* Content Area */}
<div className="p-8 flex flex-col flex-1">
<div className="flex items-start justify-between mb-4 gap-2">
<h3 className="text-xl font-black text-medical-gray-900 group-hover:text-canina-blue transition-colors leading-tight">
<h3 className="text-xl font-black text-medical-gray-900 group-hover:text-canino-blue transition-colors leading-tight">
{product.name}
</h3>
<ShieldCheck className="w-6 h-6 text-canina-blue flex-shrink-0" />
<ShieldCheck className="w-6 h-6 text-canino-blue flex-shrink-0" />
</div>
<p className="text-sm text-medical-gray-500 leading-relaxed mb-6 flex-1">
@ -78,13 +78,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="flex items-center gap-3">
<div className="w-1 h-1 rounded-full bg-canina-blue" />
<div className="w-1 h-1 rounded-full bg-canino-blue" />
<span className="text-xs font-semibold text-medical-gray-700 italic">{product.benefits}</span>
</div>
<div className="flex items-center justify-between">
<div className="text-xl font-black text-medical-gray-900 font-vazir">{product.price}</div>
<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 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>
</div>
@ -122,19 +122,19 @@ export default function FeaturedProducts() {
<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="lg:w-2/3">
<div className="text-canina-blue text-xs font-bold uppercase tracking-[0.2em] mb-4 font-vazir">بیشترین انتخاب توسط دامپزشکان</div>
<div className="text-canino-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]">
محصولات برگزیده و راهکارهای <br />
<span className="italic text-canina-blue">درمان تخصصی</span>
<span className="italic text-canino-blue">درمان تخصصی</span>
</h2>
</div>
<div className="lg:w-1/3 text-left lg:text-right">
<p className="text-medical-gray-500 text-sm leading-relaxed mb-4">
محصولات دارویی کانینا با استفاده از دانش پیشرفته بیوتکنولوژی و مواد اولیه ارگانیک نایاب فرآوری شدهاند.
محصولات دارویی کانینو با استفاده از دانش پیشرفته بیوتکنولوژی و مواد اولیه ارگانیک نایاب فرآوری شدهاند.
</p>
<button
onClick={() => router.push('/shop')}
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"
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"
>
مشاهده تمامی محصولات
<span className="text-lg"></span>

View File

@ -16,10 +16,10 @@ export default function Footer({ onNavigate, onShopNavigate, onB2BOpen }: {
<div className="space-y-8">
<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">
<img src="https://canina.de/media/fb/d5/47/1683116813/Logo.png" alt="Canina Logo" className="w-full h-auto" referrerPolicy="no-referrer" />
<img src="https://canina.de/media/fb/d5/47/1683116813/Logo.png" alt="Canino Logo" className="w-full h-auto" referrerPolicy="no-referrer" />
</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>
</div>
</div>
@ -28,7 +28,7 @@ export default function Footer({ onNavigate, onShopNavigate, onB2BOpen }: {
</p>
<div className="flex gap-4">
{[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-canina-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-canino-blue hover:text-white transition-all text-white/40">
<Icon className="w-5 h-5" />
</a>
))}
@ -37,26 +37,26 @@ export default function Footer({ onNavigate, onShopNavigate, onB2BOpen }: {
{/* Quick Links */}
<div className="space-y-8">
<h4 className="text-lg font-black text-canina-blue italic underline decoration-white/20 underline-offset-8">دسترسی سریع</h4>
<h4 className="text-lg font-black text-canino-blue italic underline decoration-white/20 underline-offset-8">دسترسی سریع</h4>
<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">
<div className="w-1.5 h-1.5 rounded-full bg-canina-blue group-hover:w-4 transition-all" />
<div className="w-1.5 h-1.5 rounded-full bg-canino-blue group-hover:w-4 transition-all" />
محصولات تخصصی ۲۰۲۴
</li>
<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-canina-blue group-hover:w-4 transition-all" />
<div className="w-1.5 h-1.5 rounded-full bg-canino-blue group-hover:w-4 transition-all" />
مجله سلامت پت (وبلاگ)
</li>
<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-canina-blue group-hover:w-4 transition-all" />
<div className="w-1.5 h-1.5 rounded-full bg-canino-blue group-hover:w-4 transition-all" />
شناسنامه پتها
</li>
<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-canina-blue group-hover:w-4 transition-all" />
<div className="w-1.5 h-1.5 rounded-full bg-canino-blue group-hover:w-4 transition-all" />
دانشنامه ترکیبات
</li>
<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-canina-blue group-hover:w-4 transition-all" />
<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">
<div className="w-1.5 h-1.5 rounded-full bg-canino-blue group-hover:w-4 transition-all" />
پنل سفارش عمده (B2B)
</li>
</ul>
@ -64,11 +64,11 @@ export default function Footer({ onNavigate, onShopNavigate, onB2BOpen }: {
{/* Location & Contact */}
<div className="space-y-8 lg:col-span-2">
<h4 className="text-lg font-black text-canina-blue italic underline decoration-white/20 underline-offset-8">اطلاعات تماس نمایندگی</h4>
<h4 className="text-lg font-black text-canino-blue italic underline decoration-white/20 underline-offset-8">اطلاعات تماس نمایندگی</h4>
<div className="grid md:grid-cols-2 gap-8">
<div className="space-y-6">
<div className="flex gap-4 group">
<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">
<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">
<Phone className="w-6 h-6" />
</div>
<div>
@ -77,23 +77,23 @@ export default function Footer({ onNavigate, onShopNavigate, onB2BOpen }: {
</div>
</div>
<div className="flex gap-4 group">
<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">
<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">
<Mail className="w-6 h-6" />
</div>
<div>
<p className="text-[10px] text-white/40 font-black uppercase mb-1">مکاتبات رسمی</p>
<p className="text-sm font-bold">info@canina-iran.com</p>
<p className="text-sm font-bold">info@canino-iran.com</p>
</div>
</div>
</div>
<div className="flex gap-4 group">
<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">
<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">
<MapPin className="w-6 h-6" />
</div>
<div>
<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>
@ -108,14 +108,14 @@ export default function Footer({ onNavigate, onShopNavigate, onB2BOpen }: {
<p className="text-[10px] text-white/40 font-bold">تمامی محصولات دارای لیبل اصالت وزارت بهداشت و QR Code اختصاصی هستند.</p>
</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 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">
<button onClick={() => onNavigate("home")} className="hover:text-white transition-colors">درباره ما</button>
<button onClick={() => onNavigate("home")} className="hover:text-white transition-colors">تماس با ما</button>

View File

@ -110,9 +110,9 @@ export default function Header({
setIsMobileMenuOpen(false);
}}
>
<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="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="flex flex-col">
<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-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-[10px] text-medical-gray-400 font-bold uppercase tracking-widest leading-none mt-1.5 font-vazir">نماینده رسمی Canina Pharma GmbH آلمان</span>
</div>
</div>
@ -125,7 +125,7 @@ export default function Header({
onMouseEnter={() => setIsMegaMenuOpen(true)}
onMouseLeave={() => setIsMegaMenuOpen(false)}
>
<button className={`flex items-center gap-1.5 px-3 py-2 rounded-xl text-sm font-black transition-all whitespace-nowrap ${isMegaMenuOpen ? 'bg-medical-gray-50 text-canina-blue' : 'text-medical-gray-600 hover:bg-medical-gray-50 hover:text-canina-blue'} font-vazir`}>
<button className={`flex items-center gap-1.5 px-3 py-2 rounded-xl text-sm font-black transition-all whitespace-nowrap ${isMegaMenuOpen ? 'bg-medical-gray-50 text-canino-blue' : 'text-medical-gray-600 hover:bg-medical-gray-50 hover:text-canino-blue'} font-vazir`}>
راهکارهای درمانی
<ChevronDown className={`w-4 h-4 transition-transform duration-300 ${isMegaMenuOpen ? 'rotate-180' : ''}`} />
</button>
@ -148,7 +148,7 @@ export default function Header({
}}
>
<div className="flex items-center gap-4 mb-4">
<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">
<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">
{item.icon}
</div>
<h4 className="font-black text-medical-gray-900 text-sm font-vazir whitespace-nowrap">{item.title}</h4>
@ -157,7 +157,7 @@ export default function Header({
{item.solutions.map((sol, sIdx) => (
<li
key={sIdx}
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"
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"
onClick={(e) => {
e.stopPropagation();
onShopNavigate(item.id, sol);
@ -184,7 +184,7 @@ export default function Header({
<button
key={item.id}
onClick={item.action}
className={`px-3 py-2 rounded-xl text-sm font-black transition-all font-vazir whitespace-nowrap ${currentView === item.id ? 'bg-canina-blue/5 text-canina-blue' : 'text-medical-gray-600 hover:bg-medical-gray-50 hover:text-canina-blue'}`}
className={`px-3 py-2 rounded-xl text-sm font-black transition-all font-vazir whitespace-nowrap ${currentView === item.id ? 'bg-canino-blue/5 text-canino-blue' : 'text-medical-gray-600 hover:bg-medical-gray-50 hover:text-canino-blue'}`}
>
{item.label}
</button>
@ -203,7 +203,7 @@ export default function Header({
animate={{ width: 350, opacity: 1 }}
exit={{ width: 0, opacity: 0 }}
transition={{ type: "spring", damping: 20, stiffness: 200 }}
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"
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"
>
<form onSubmit={handleSearch} className="w-full flex items-center">
<input
@ -215,7 +215,7 @@ export default function Header({
placeholder="جستجوی محصولات، مقالات سلامت و..."
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-canina-blue text-white text-[10px] font-black hover:bg-medical-gray-900 transition-colors">
<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>
</form>
@ -225,7 +225,7 @@ export default function Header({
<HeaderButton
variant={isSearchFocused ? "primary" : "secondary"}
className={cn("w-12 h-12 transition-all duration-300", isSearchFocused ? "z-30 bg-canina-blue text-white" : "")}
className={cn("w-12 h-12 transition-all duration-300", isSearchFocused ? "z-30 bg-canino-blue text-white" : "")}
onClick={() => setIsSearchFocused(!isSearchFocused)}
>
<Search className="w-5 h-5" />
@ -240,7 +240,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"
onClick={() => onNavigate("user-dashboard")}
>
<User className="w-5 h-5 text-canina-blue" />
<User className="w-5 h-5 text-canino-blue" />
<span className="text-[14px] font-black font-vazir text-medical-gray-900 leading-none">
{profile.firstName}
</span>
@ -254,16 +254,16 @@ export default function Header({
<div
className={cn(
"flex items-center gap-2.5 px-4 py-2 rounded-2xl transition-all cursor-pointer",
isPetSwitcherOpen ? "bg-canina-blue text-white shadow-lg shadow-canina-blue/20" : "text-canina-blue hover:bg-white"
isPetSwitcherOpen ? "bg-canino-blue text-white shadow-lg shadow-canino-blue/20" : "text-canino-blue hover:bg-white"
)}
onClick={() => setIsPetSwitcherOpen(!isPetSwitcherOpen)}
>
{activePet?.type === "گربه" ? (
<Cat className={cn("w-5 h-5", isPetSwitcherOpen ? "text-white" : "text-canina-blue/60")} />
<Cat 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")} />
<Dog className={cn("w-5 h-5", isPetSwitcherOpen ? "text-white" : "text-canino-blue/60")} />
)}
<span className={cn("text-[14px] font-black font-vazir leading-none", isPetSwitcherOpen ? "text-white" : "text-canina-blue")}>
<span className={cn("text-[14px] font-black font-vazir leading-none", isPetSwitcherOpen ? "text-white" : "text-canino-blue")}>
{activePet?.name || "بدون پت"}
</span>
<ChevronDown className={cn("w-4 h-4 transition-transform", isPetSwitcherOpen ? "rotate-180" : "")} />
@ -284,7 +284,7 @@ export default function Header({
key={pet.id}
className={cn(
"w-full flex items-center justify-between p-3 rounded-xl transition-all group/item",
activePetId === pet.id ? "bg-canina-blue/5 text-canina-blue" : "hover:bg-medical-gray-50 text-medical-gray-600"
activePetId === pet.id ? "bg-canino-blue/5 text-canino-blue" : "hover:bg-medical-gray-50 text-medical-gray-600"
)}
>
<div
@ -297,7 +297,7 @@ export default function Header({
>
<div className={cn(
"w-8 h-8 rounded-lg flex items-center justify-center text-[11px] font-black transition-colors",
activePetId === pet.id ? "bg-canina-blue text-white" : "bg-medical-gray-100 text-medical-gray-400 group-hover/item:bg-medical-gray-200"
activePetId === pet.id ? "bg-canino-blue text-white" : "bg-medical-gray-100 text-medical-gray-400 group-hover/item:bg-medical-gray-200"
)}>
{pet.name[0]}
</div>
@ -313,7 +313,7 @@ export default function Header({
onNavigate({ view: "profile", subview: "detail" });
setIsPetSwitcherOpen(false);
}}
className="p-1.5 rounded-lg hover:bg-canina-blue hover:text-white transition-all text-medical-gray-300 hover:shadow-lg"
className="p-1.5 rounded-lg hover:bg-canino-blue hover:text-white transition-all text-medical-gray-300 hover:shadow-lg"
title="مشاهده شناسنامه سلامت"
>
<FileHeart className="w-4 h-4" />
@ -326,7 +326,7 @@ export default function Header({
<div className="pt-4 border-t border-medical-gray-100 space-y-1">
<button
onClick={() => { onNavigate({ view: "profile", subview: "add" }); setIsPetSwitcherOpen(false); }}
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"
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"
>
<PlusCircle className="w-5 h-5" />
ثبت همدم (Pet) جدید
@ -343,7 +343,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"
>
<LogOut className="w-5 h-5" />
خروج از حساب کانینا
خروج از حساب کانینو
</button>
</div>
</motion.div>
@ -399,8 +399,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 gap-3">
<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-canina-blue font-black text-xl italic font-inter">Canina</span>
<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>
<span className="text-canino-blue font-black text-xl italic font-inter">Canino</span>
</div>
<button
onClick={() => setIsMobileMenuOpen(false)}
@ -432,20 +432,20 @@ export default function Header({
{MENU_ITEMS.map((item, idx) => (
<div key={idx} className="py-1">
<div
className="text-[13px] font-bold text-medical-gray-800 font-vazir hover:text-canina-blue cursor-pointer flex items-center gap-2"
className="text-[13px] font-bold text-medical-gray-800 font-vazir hover:text-canino-blue cursor-pointer flex items-center gap-2"
onClick={() => {
onShopNavigate(item.id);
setIsMobileMenuOpen(false);
}}
>
<span className="text-canina-blue/80">{item.icon}</span>
<span className="text-canino-blue/80">{item.icon}</span>
<span>{item.title}</span>
</div>
<ul className="mt-1 space-y-1 mr-6">
{item.solutions.map((sol, sIdx) => (
<li
key={sIdx}
className="text-[11px] text-medical-gray-500 hover:text-canina-blue cursor-pointer py-1 font-vazir"
className="text-[11px] text-medical-gray-500 hover:text-canino-blue cursor-pointer py-1 font-vazir"
onClick={(e) => {
e.stopPropagation();
onShopNavigate(item.id, sol);
@ -477,7 +477,7 @@ export default function Header({
}}
className={`w-full text-right px-4 py-3 rounded-xl text-sm font-black transition-all font-vazir ${
currentView === item.id
? 'bg-canina-blue/5 text-canina-blue'
? 'bg-canino-blue/5 text-canino-blue'
: 'text-medical-gray-600 hover:bg-medical-gray-50'
}`}
>

View File

@ -23,10 +23,10 @@ export default function HeaderButton({
const baseStyles = "relative flex flex-col items-center justify-center rounded-xl transition-all duration-300 font-vazir select-none cursor-pointer overflow-visible";
const variants = {
primary: "bg-canina-blue text-white hover:bg-medical-gray-900 shadow-lg shadow-canina-blue/20",
primary: "bg-canino-blue text-white hover:bg-medical-gray-900 shadow-lg shadow-canino-blue/20",
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-canina-blue hover:text-canina-blue",
ghost: "text-medical-gray-600 hover:bg-medical-gray-50 hover:text-canina-blue"
outline: "border-2 border-medical-gray-100 text-medical-gray-700 hover:border-canino-blue hover:text-canino-blue",
ghost: "text-medical-gray-600 hover:bg-medical-gray-50 hover:text-canino-blue"
};
return (

View File

@ -22,7 +22,7 @@ function StatCounter({ target }: { target: number }) {
initial={{ scale: 0.8, opacity: 0 }}
animate={{ scale: 1, opacity: 1 }}
transition={{ duration: 2.5, ease: "easeOut" }}
className="text-4xl lg:text-6xl font-black text-canina-blue font-vazir origin-right flex items-center"
className="text-4xl lg:text-6xl font-black text-canino-blue font-vazir origin-right flex items-center"
>
<motion.span
animate={{ scale: [1, 1.1, 1] }}
@ -47,13 +47,13 @@ function Typewriter({ text }: { text: string }) {
}, [text]);
return (
<div className="text-4xl lg:text-6xl font-black text-canina-blue font-vazir flex flex-row-reverse items-center">
<div className="text-4xl lg:text-6xl font-black text-canino-blue font-vazir flex flex-row-reverse items-center">
<span className="relative">
{toPersian(displayText)}
<motion.span
animate={{ opacity: [0, 1, 0] }}
transition={{ duration: 0.8, repeat: Infinity }}
className="absolute -left-1 top-0 h-full w-[3px] bg-canina-blue"
className="absolute -left-1 top-0 h-full w-[3px] bg-canino-blue"
/>
</span>
</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 subtitle = banners.length > 0 ? banners[0].subtitle : getText(
'hero_desc',
'بیش از <span className="font-bold text-canina-blue">۴۰ سال</span> تجربه نوآورانه در تولید مکمل‌های درمانی با بالاترین استاندارد کیفی «گرید دارویی اختصاصی». راهکار هوشمند برای هر نیاز بالینی.'
'بیش از <span className="font-bold text-canino-blue">۴۰ سال</span> تجربه نوآورانه در تولید مکمل‌های درمانی با بالاترین استاندارد کیفی «گرید دارویی اختصاصی». راهکار هوشمند برای هر نیاز بالینی.'
);
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">
{/* 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 right-0 w-[800px] h-[800px] bg-canina-blue rounded-full blur-[120px] -mr-96 -mt-96" />
<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 bottom-0 left-0 w-[600px] h-[600px] bg-medical-gray-500 rounded-full blur-[100px] -ml-40 -mb-40" />
</div>
@ -88,14 +88,14 @@ export default function Hero({ banners = [] }: { banners?: any[] }) {
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.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-canina-blue animate-pulse" />
<span className="text-canina-blue text-xs font-bold uppercase tracking-widest leading-none">{getText('hero_badge', "تخصص دارویی از آلمان")}</span>
<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">
<span className="w-2 h-2 rounded-full bg-canino-blue animate-pulse" />
<span className="text-canino-blue text-xs font-bold uppercase tracking-widest leading-none">{getText('hero_badge', "تخصص دارویی از آلمان")}</span>
</div>
<h1 className="text-4xl lg:text-7xl font-black text-medical-gray-900 leading-[1.1] mb-6">
{titleParts[0]} <br />
{titleParts[1] && <span className="text-canina-blue font-vazir">{titleParts[1]}</span>}
{titleParts[1] && <span className="text-canino-blue font-vazir">{titleParts[1]}</span>}
</h1>
<p
@ -108,19 +108,19 @@ export default function Hero({ banners = [] }: { banners?: any[] }) {
<div className="flex flex-wrap justify-center lg:justify-start gap-4">
<button
onClick={() => {
const element = document.getElementById('canina-advisor');
const element = document.getElementById('canino-advisor');
if (element) {
element.scrollIntoView({ behavior: 'smooth' });
}
}}
className="bg-medical-gray-900 text-white px-10 py-5 rounded-full font-bold text-lg hover:bg-canina-blue hover:shadow-2xl transition-all flex items-center gap-2 group font-vazir"
className="bg-medical-gray-900 text-white px-10 py-5 rounded-full font-bold text-lg hover:bg-canino-blue hover:shadow-2xl transition-all flex items-center gap-2 group font-vazir"
>
{getText('hero_btn_advisor', "دستیار سلامت پت")}
<ChevronLeft className="w-5 h-5 group-hover:-translate-x-1 transition-transform" />
</button>
<button
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-canina-blue hover:text-canina-blue transition-all font-vazir"
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 transition-all font-vazir"
>
{getText('hero_btn_products', "مشاهده محصولات")}
</button>
@ -144,7 +144,7 @@ export default function Hero({ banners = [] }: { banners?: any[] }) {
<div className="flex flex-col items-center lg:items-end">
<div className="relative overflow-hidden group">
<motion.div
className="text-4xl lg:text-6xl font-black text-canina-blue font-vazir relative z-10"
className="text-4xl lg:text-6xl font-black text-canino-blue font-vazir relative z-10"
>
۱۰۰٪
</motion.div>
@ -186,10 +186,10 @@ export default function Hero({ banners = [] }: { banners?: any[] }) {
<motion.div
animate={{ rotate: 360 }}
transition={{ duration: 20, repeat: Infinity, ease: "linear" }}
className="absolute -top-6 -right-6 lg:-top-10 lg:-right-10 z-20 w-32 h-32 lg:w-40 lg:h-40 bg-white shadow-xl rounded-full p-1 border-2 border-dashed border-canina-blue flex items-center justify-center text-center p-4"
className="absolute -top-6 -right-6 lg:-top-10 lg:-right-10 z-20 w-32 h-32 lg:w-40 lg:h-40 bg-white shadow-xl rounded-full p-1 border-2 border-dashed border-canino-blue flex items-center justify-center text-center p-4"
>
<div className="flex flex-col items-center">
<span className="text-2xl lg:text-3xl font-black text-canina-blue leading-none tracking-tighter">DE</span>
<span className="text-2xl lg:text-3xl font-black text-canino-blue leading-none tracking-tighter">DE</span>
<span className="text-[8px] lg:text-[10px] font-bold text-medical-gray-500 uppercase tracking-widest mt-1">{getText('hero_quality_standard', "استاندارد کیفی آلمان")}</span>
</div>
</motion.div>

View File

@ -39,33 +39,33 @@ export default function IngredientWiki() {
<div className="lg:hidden mb-12 space-y-4">
<button
onClick={() => router.back()}
className="flex items-center gap-2 text-medical-gray-500 font-bold hover:text-canina-blue transition-colors"
className="flex items-center gap-2 text-medical-gray-500 font-bold hover:text-canino-blue transition-colors"
>
<ChevronRight className="w-5 h-5" />
<span>بازگشت</span>
</button>
<div className="flex items-center gap-2 text-[10px] font-black text-medical-gray-400 uppercase tracking-widest overflow-x-auto whitespace-nowrap pb-2">
<span className="cursor-pointer hover:text-canina-blue" onClick={() => router.push('/')}>کانینا</span>
<span className="cursor-pointer hover:text-canino-blue" onClick={() => router.push('/')}>کانینو</span>
<ChevronLeft className="w-2.5 h-2.5" />
<span className="text-canina-blue">دانشنامه علمی</span>
<span className="text-canino-blue">دانشنامه علمی</span>
</div>
</div>
{/* Desktop Breadcrumbs */}
<div className="hidden lg:flex items-center gap-2 text-[10px] font-black text-medical-gray-400 uppercase tracking-widest mb-12">
<span className="cursor-pointer hover:text-canina-blue" onClick={() => router.push('/')}>خانه</span>
<span className="cursor-pointer hover:text-canino-blue" onClick={() => router.push('/')}>خانه</span>
<ChevronLeft className="w-2.5 h-2.5" />
<span className="text-canina-blue">دانشنامه مواد نایاب و ارگانیک</span>
<span className="text-canino-blue">دانشنامه مواد نایاب و ارگانیک</span>
</div>
<div className="flex flex-col items-center text-center mb-20">
<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">
<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">
<FlaskConical className="w-4 h-4" />
علم در خدمت کیفیت
</div>
<h2 className="text-4xl lg:text-6xl font-black text-medical-gray-900 leading-tight md:max-w-4xl">
دانشنامه مواد <span className="text-canina-blue italic">نایاب و ارگانیک</span> کانینا
دانشنامه مواد <span className="text-canino-blue italic">نایاب و ارگانیک</span> کانینو
</h2>
<p className="mt-6 text-lg text-medical-gray-500 max-w-2xl leading-relaxed">
ما از مواد اولیهای استفاده میکنیم که در سطح دارویی فرآوری شدهاند. در اینجا با قدرت بیولوژیک این ترکیبات آشنا شوید.
@ -103,7 +103,7 @@ export default function IngredientWiki() {
<div className="grid grid-cols-1 gap-4 mb-10">
{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">
<CheckCircle2 className="w-6 h-6 text-canina-blue flex-shrink-0" />
<CheckCircle2 className="w-6 h-6 text-canino-blue flex-shrink-0" />
<span className="text-sm font-bold text-medical-gray-700">{benefit}</span>
</div>
))}
@ -131,7 +131,7 @@ export default function IngredientWiki() {
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" />
<h4 className="text-sm font-black text-center text-medical-gray-900 group-hover:text-canina-blue transition-colors px-2">{p.name}</h4>
<h4 className="text-sm font-black text-center text-medical-gray-900 group-hover:text-canino-blue transition-colors px-2">{p.name}</h4>
</div>
)) : (
<div className="col-span-full py-12 text-center text-medical-gray-400 font-bold italic">
@ -141,7 +141,7 @@ export default function IngredientWiki() {
</div>
{/* Decorative backdrop */}
<div className="absolute -bottom-20 -left-20 w-80 h-80 bg-canina-blue rounded-full blur-[100px] opacity-10" />
<div className="absolute -bottom-20 -left-20 w-80 h-80 bg-canino-blue rounded-full blur-[100px] opacity-10" />
</motion.div>
</div>
</div>
@ -159,11 +159,11 @@ export default function IngredientWiki() {
</div>
</div>
<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-canina-blue">گرید دارویی اختصاصی</span> هستند.</h3>
<h3 className="text-3xl lg:text-5xl font-black mb-8 leading-tight italic">تمام مواد اولیه ما دارای گواهینامه <br /> <span className="text-canino-blue">گرید دارویی اختصاصی</span> هستند.</h3>
<p className="text-white/60 text-lg mb-10">این یعنی استانداردی فراتر از مکملهای معمولی، مشابه استانداردهای تولید دارو در اتحادیه اروپا.</p>
<div className="flex justify-center gap-12">
<div className="flex flex-col items-center">
<div className="text-2xl font-black font-vazir text-canina-blue">۱۰۰٪</div>
<div className="text-2xl font-black font-vazir text-canino-blue">۱۰۰٪</div>
<div className="text-[10px] font-bold uppercase tracking-widest text-white/40 mt-1">تست آزمایشگاهی</div>
</div>
<div className="flex flex-col items-center">

View File

@ -137,7 +137,7 @@ export default function LoginModal({ isOpen, onClose, onLogin, petName, isAdviso
dir="rtl"
>
{/* Top color indicator */}
<div className="absolute top-0 left-0 w-full h-2 bg-gradient-to-r from-canina-blue to-indigo-500" />
<div className="absolute top-0 left-0 w-full h-2 bg-gradient-to-r from-canino-blue to-indigo-500" />
{/* Close Button */}
<button
@ -149,15 +149,15 @@ export default function LoginModal({ isOpen, onClose, onLogin, petName, isAdviso
{/* Header info */}
<div className="text-center mb-8">
<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-canina-blue" />
<div className="w-20 h-20 bg-canino-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" />
</div>
<h3 className="text-3xl font-black text-medical-gray-900 mb-2 italic">
ورود به کانینا
ورود به کانینو
</h3>
{isAdvisorContext ? (
<p className="text-medical-gray-500 font-bold leading-relaxed px-2 text-sm">
تحلیل سلامت <span className="text-canina-blue">{petName || "همدم شما"}</span> آماده است! برای مشاهده رژیم مکمل پیشنهادی و ذخیره شناسنامه، وارد شوید.
تحلیل سلامت <span className="text-canino-blue">{petName || "همدم شما"}</span> آماده است! برای مشاهده رژیم مکمل پیشنهادی و ذخیره شناسنامه، وارد شوید.
</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}
onChange={(e) => setPhoneNumber(e.target.value.replace(/[^0-9]/g, ''))}
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-canina-blue/20 focus:border-canina-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-canino-blue/20 focus:border-canino-blue outline-none font-bold text-lg text-left tracking-widest"
/>
</div>
</div>
@ -195,7 +195,7 @@ export default function LoginModal({ isOpen, onClose, onLogin, petName, isAdviso
<button
type="submit"
disabled={isLoading || phoneNumber.length < 11}
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"
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"
>
{isLoading ? (
<RefreshCw className="w-6 h-6 animate-spin" />
@ -222,7 +222,7 @@ export default function LoginModal({ isOpen, onClose, onLogin, petName, isAdviso
<button
type="button"
onClick={() => setStep("phone")}
className="text-[10px] font-black text-canina-blue flex items-center gap-1 hover:underline"
className="text-[10px] font-black text-canino-blue flex items-center gap-1 hover:underline"
>
<ArrowRight className="w-3 h-3" />
ویرایش شماره
@ -238,7 +238,7 @@ export default function LoginModal({ isOpen, onClose, onLogin, petName, isAdviso
value={otpCode}
onChange={(e) => setOtpCode(e.target.value.replace(/[^0-9]/g, ''))}
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-canina-blue/20 focus:border-canina-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-canino-blue/20 focus:border-canino-blue outline-none font-black text-2xl text-center tracking-[0.5em]"
/>
</div>
<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"
onClick={handleResendOtp}
disabled={isLoading}
className="text-xs font-black text-canina-blue hover:underline flex items-center gap-1.5"
className="text-xs font-black text-canino-blue hover:underline flex items-center gap-1.5"
>
<RefreshCw className="w-3.5 h-3.5" />
ارسال مجدد کد تایید
@ -267,7 +267,7 @@ export default function LoginModal({ isOpen, onClose, onLogin, petName, isAdviso
<button
type="submit"
disabled={isLoading || otpCode.length < 5}
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"
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"
>
{isLoading ? (
<RefreshCw className="w-6 h-6 animate-spin" />

View File

@ -62,7 +62,7 @@ export default function OrderDetailsModal({ isOpen, onClose, order }: OrderDetai
</head>
<body>
<div class="header">
<div class="logo">CANINA | کانینا</div>
<div class="logo">CANINO | کانینو</div>
<div>تاریخ: ${toPersian(new Date(order.date).toLocaleDateString('fa-IR'))}</div>
</div>
<div class="info">
@ -139,7 +139,7 @@ export default function OrderDetailsModal({ isOpen, onClose, order }: OrderDetai
{/* Header */}
<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="w-14 h-14 bg-canina-blue rounded-2xl flex items-center justify-center text-white shadow-lg">
<div className="w-14 h-14 bg-canino-blue rounded-2xl flex items-center justify-center text-white shadow-lg">
<Package className="w-7 h-7" />
</div>
<div>
@ -168,7 +168,7 @@ export default function OrderDetailsModal({ isOpen, onClose, order }: OrderDetai
</div>
<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-sm font-mono font-bold text-canina-blue">{toPersian(order.trackingNumber)}</div>
<div className="text-sm font-mono font-bold text-canino-blue">{toPersian(order.trackingNumber)}</div>
</div>
<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>
@ -182,12 +182,12 @@ export default function OrderDetailsModal({ isOpen, onClose, order }: OrderDetai
{/* Items List */}
<div>
<h4 className="text-sm font-black text-medical-gray-900 mb-6 flex items-center gap-2">
<ShoppingBag className="w-4 h-4 text-canina-blue" />
<ShoppingBag className="w-4 h-4 text-canino-blue" />
سبد محصولات خریده شده
</h4>
<div className="space-y-4">
{(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-canina-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-canino-blue transition-all">
<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">
<SafeImage
@ -203,7 +203,7 @@ export default function OrderDetailsModal({ isOpen, onClose, order }: OrderDetai
</div>
</div>
<div className="text-left">
<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 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>
</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>
<h4 className="text-sm font-black text-medical-gray-900 mb-4 flex items-center gap-2">
<MapPin className="w-4 h-4 text-canina-blue" />
<MapPin className="w-4 h-4 text-canino-blue" />
اطلاعات ارسال
</h4>
<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>
<h4 className="text-sm font-black text-medical-gray-900 mb-4 flex items-center gap-2">
<CreditCard className="w-4 h-4 text-canina-blue" />
<CreditCard className="w-4 h-4 text-canino-blue" />
جزئیات پرداخت
</h4>
<div className="space-y-2">
@ -253,7 +253,7 @@ export default function OrderDetailsModal({ isOpen, onClose, order }: OrderDetai
<Download className="w-5 h-5" />
دانلود فاکتور رسمی
</button>
<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">
<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">
<Printer className="w-6 h-6" />
</button>
</div>

View File

@ -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"
>
{/* Confetti-like background elements */}
<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="absolute top-0 left-0 w-full h-2 bg-gradient-to-r from-canino-blue via-green-500 to-canino-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">
<CheckCircle2 className="w-12 h-12" />
</div>
<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-canina-blue font-mono">{order.id}</span></p>
<p className="text-medical-gray-500 font-bold mb-10">شماره سفارش: <span className="text-canino-blue font-mono">{order.id}</span></p>
{/* Empathetic Message */}
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: 0.3 }}
className="p-8 bg-canina-blue/5 border border-canina-blue/10 rounded-[3rem] mb-12 text-right relative"
className="p-8 bg-canino-blue/5 border border-canino-blue/10 rounded-[3rem] mb-12 text-right relative"
>
<Sparkles className="absolute top-6 left-6 w-8 h-8 text-canina-blue opacity-20" />
<Sparkles className="absolute top-6 left-6 w-8 h-8 text-canino-blue opacity-20" />
<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-canina-blue shadow-sm">
<div className="w-10 h-10 bg-white rounded-2xl flex items-center justify-center text-canino-blue shadow-sm">
<Heart className="w-6 h-6 fill-current" />
</div>
<h4 className="text-lg font-black text-canina-blue italic">خیالت راحت باشه!</h4>
<h4 className="text-lg font-black text-canino-blue italic">خیالت راحت باشه!</h4>
</div>
<p className="text-sm font-bold text-canina-blue/80 leading-relaxed">
<p className="text-sm font-bold text-canino-blue/80 leading-relaxed">
{activePet ? (
<>
انتخاب درستی برای <span className="text-canina-blue font-black">{activePet.name}</span> کردی.
انتخاب درستی برای <span className="text-canino-blue font-black">{activePet.name}</span> کردی.
{hasCanhydrox ? (
` مکمل Canhydrox با فرمول آلمانی‌اش دقیقاً همون چیزیه که استخوان‌های ${activePet.name} برای بازیگوشی دوباره بهش نیاز دارن.`
) : (
@ -94,13 +94,13 @@ export default function OrderSuccess({ orderId }: { orderId: string }) {
<div className="space-y-4">
<button
onClick={() => router.push('/track')}
className="w-full bg-medical-gray-900 text-white py-5 rounded-2xl font-black text-lg hover:bg-canina-blue transition-all"
className="w-full bg-medical-gray-900 text-white py-5 rounded-2xl font-black text-lg hover:bg-canino-blue transition-all"
>
مشاهده و پیگیری زنده سفارش
</button>
<button
onClick={() => router.push('/shop')}
className="flex items-center justify-center gap-2 w-full text-medical-gray-400 font-bold hover:text-canina-blue transition-colors"
className="flex items-center justify-center gap-2 w-full text-medical-gray-400 font-bold hover:text-canino-blue transition-colors"
>
<ChevronLeft className="w-4 h-4" />
بازگشت به فروشگاه

View File

@ -44,24 +44,24 @@ export default function OrderTracking() {
<div className="lg:hidden mb-12 space-y-4">
<button
onClick={() => router.back()}
className="flex items-center gap-2 text-medical-gray-500 font-bold hover:text-canina-blue transition-colors"
className="flex items-center gap-2 text-medical-gray-500 font-bold hover:text-canino-blue transition-colors"
>
<ChevronRight className="w-5 h-5 font-vazir" />
<span>بازگشت</span>
</button>
<div className="flex items-center gap-2 text-[10px] font-black text-medical-gray-400 uppercase tracking-widest overflow-x-auto whitespace-nowrap pb-2">
<span className="cursor-pointer hover:text-canina-blue" onClick={() => router.push('/')}>کانینا</span>
<span className="cursor-pointer hover:text-canino-blue" onClick={() => router.push('/')}>کانینو</span>
<ChevronLeft className="w-2.5 h-2.5" />
<span className="text-canina-blue">پیگیری سفارش</span>
<span className="text-canino-blue">پیگیری سفارش</span>
</div>
</div>
{/* Desktop Breadcrumbs */}
<div className="hidden lg:flex items-center gap-2 text-[10px] font-black text-medical-gray-400 uppercase tracking-widest mb-12">
<span className="cursor-pointer hover:text-canina-blue" onClick={() => router.push('/')}>خانه</span>
<span className="cursor-pointer hover:text-canino-blue" onClick={() => router.push('/')}>خانه</span>
<ChevronLeft className="w-2.5 h-2.5" />
<span className="text-canina-blue">رهگیری هوشمند محموله</span>
<span className="text-canino-blue">رهگیری هوشمند محموله</span>
</div>
<div className="flex items-center justify-between mb-12">
@ -78,12 +78,12 @@ export default function OrderTracking() {
placeholder="شماره سفارش (CN-XXXXX) یا کد رهگیری پستی را وارد کنید..."
value={searchId}
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-canina-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-canino-blue/20 outline-none font-mono"
/>
</div>
<button
onClick={handleSearch}
className="bg-medical-gray-900 text-white px-10 py-4 rounded-2xl font-black italic hover:bg-canina-blue transition-all"
className="bg-medical-gray-900 text-white px-10 py-4 rounded-2xl font-black italic hover:bg-canino-blue transition-all"
>
رهگیری آنی
</button>
@ -97,7 +97,7 @@ export default function OrderTracking() {
<div className="flex items-center justify-between mb-12">
<div>
<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-canina-blue">{activeOrder.trackingNumber}</p>
<p className="text-sm font-mono font-bold text-canino-blue">{activeOrder.trackingNumber}</p>
</div>
<div className="text-left">
<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) => (
<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-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'}`}>
<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'}`}>
{step.status === 'completed' ? <CheckCircle2 className="w-6 h-6" /> : step.icon}
</div>
<div>
@ -136,13 +136,13 @@ export default function OrderTracking() {
</div>
<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-lg text-canina-blue">{activeOrder.total.toLocaleString()} تومان</span>
<span className="text-lg text-canino-blue">{activeOrder.total.toLocaleString()} تومان</span>
</div>
</div>
<div className="bg-white rounded-[2rem] p-6 border border-medical-gray-200">
<div className="flex items-center gap-3 mb-4">
<div className="w-10 h-10 bg-canina-blue/10 text-canina-blue rounded-xl flex items-center justify-center">
<div className="w-10 h-10 bg-canino-blue/10 text-canino-blue rounded-xl flex items-center justify-center">
<MapPin className="w-5 h-5" />
</div>
<h4 className="text-xs font-black italic">آدرس تحویل</h4>

View File

@ -285,7 +285,7 @@ export default function PetProfile({ initialView, advisorNeed }: {
setView("add");
setStep(1);
}}
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"
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"
>
<Plus className="w-5 h-5" />
صدور شناسنامه جدید
@ -299,7 +299,7 @@ export default function PetProfile({ initialView, advisorNeed }: {
whileHover={{ y: -5 }}
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-canina-blue mb-6 group-hover:bg-canina-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-canino-blue mb-6 group-hover:bg-canino-blue group-hover:text-white transition-all shadow-inner">
{pet.type === "سگ" ? <Dog className="w-12 h-12" /> : <Cat className="w-12 h-12" />}
</div>
<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
onClick={() => { setActivePet(pet.id); setView("detail"); }}
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"
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"
>
مشاهده شناسنامه سلامت
<ChevronLeft className="w-4 h-4" />
@ -390,7 +390,7 @@ export default function PetProfile({ initialView, advisorNeed }: {
{/* Progress Bar */}
<div className="absolute top-0 left-0 w-full h-1.5 bg-medical-gray-100 font-vazir">
<motion.div
className="h-full bg-canina-blue"
className="h-full bg-canino-blue"
initial={{ width: "0%" }}
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>
<p className="text-medical-gray-500 mt-2 font-medium">مرحله {toPersian(step)} از {toPersian(3)}: بروزرسانی اطلاعات تخصصی</p>
</div>
<div className="w-16 h-16 bg-canina-blue/10 rounded-2xl flex items-center justify-center text-canina-blue">
<div className="w-16 h-16 bg-canino-blue/10 rounded-2xl flex items-center justify-center text-canino-blue">
<ClipboardList className="w-8 h-8" />
</div>
</div>
@ -422,7 +422,7 @@ export default function PetProfile({ initialView, advisorNeed }: {
type="text"
value={formData.name}
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-canina-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-canino-blue/20 outline-none font-black text-lg"
placeholder="مثلاً: لوسی"
/>
</div>
@ -431,14 +431,14 @@ export default function PetProfile({ initialView, advisorNeed }: {
<div className="grid grid-cols-2 gap-4">
<button
onClick={() => setFormData({...formData, type: "سگ"})}
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'}`}
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'}`}
>
<Dog className="w-6 h-6" />
سگ
</button>
<button
onClick={() => setFormData({...formData, type: "گربه"})}
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'}`}
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'}`}
>
<Cat className="w-6 h-6" />
گربه
@ -451,7 +451,7 @@ export default function PetProfile({ initialView, advisorNeed }: {
type="text"
value={formData.breed}
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-canina-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-canino-blue/20 outline-none font-bold"
placeholder="آلمانی، پرشین، میکس و..."
/>
</div>
@ -473,7 +473,7 @@ export default function PetProfile({ initialView, advisorNeed }: {
type="number"
value={formData.age || ""}
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-canina-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-canino-blue/20 outline-none font-black text-lg"
placeholder="۳"
/>
</div>
@ -484,7 +484,7 @@ export default function PetProfile({ initialView, advisorNeed }: {
type="number"
value={formData.weight || ""}
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-canina-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-canino-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" />
</div>
@ -497,7 +497,7 @@ export default function PetProfile({ initialView, advisorNeed }: {
<button
key={level}
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-canina-blue bg-canina-blue/5 text-canina-blue shadow-lg shadow-canina-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-canino-blue bg-canino-blue/5 text-canino-blue shadow-lg shadow-canino-blue/10' : 'border-medical-gray-100 text-medical-gray-400'}`}
>
{level}
</button>
@ -536,9 +536,9 @@ export default function PetProfile({ initialView, advisorNeed }: {
: [...current, condition]
})
}}
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'}`}
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'}`}
>
<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'}`}>
<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'}`}>
{formData.medicalConditions.includes(condition) && <ShieldCheck className="w-3.5 h-3.5" />}
</div>
<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 router.back();
}}
className="absolute top-8 left-8 text-medical-gray-400 hover:text-canina-blue transition-colors text-[10px] font-black uppercase tracking-widest"
className="absolute top-8 left-8 text-medical-gray-400 hover:text-canino-blue transition-colors text-[10px] font-black uppercase tracking-widest"
>
انصراف
</button>
@ -572,7 +572,7 @@ export default function PetProfile({ initialView, advisorNeed }: {
<button
onClick={step === 3 ? handleSubmit : handleNext}
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-canina-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-canino-blue transition-all"
>
{step === 3 ? (view === "edit" ? "ذخیره تغییرات" : "مشاهده پرونده سلامت") : "گام بعدی"}
<ChevronLeft className="w-5 h-5" />
@ -594,21 +594,21 @@ export default function PetProfile({ initialView, advisorNeed }: {
{/* Navigation Bar */}
<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">
<span className="cursor-pointer hover:text-canina-blue" onClick={() => setView("index")}>همدمهای من</span>
<span className="cursor-pointer hover:text-canino-blue" onClick={() => setView("index")}>همدمهای من</span>
<ChevronLeft className="w-3 h-3" />
<span className="text-canina-blue">پرونده سلامت {activePet?.name}</span>
<span className="text-canino-blue">پرونده سلامت {activePet?.name}</span>
</div>
<div className="flex gap-3">
<button
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-canina-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-canino-blue transition-all"
>
بازگشت به لیست
</button>
<button
onClick={startEdit}
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"
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"
>
<Edit3 className="w-3.5 h-3.5" />
ویرایش پرونده
@ -619,10 +619,10 @@ export default function PetProfile({ initialView, advisorNeed }: {
{/* Profile Card */}
<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="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="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="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-canina-blue">
<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-full h-full bg-white rounded-[2.2rem] flex items-center justify-center text-canino-blue">
{activePet.type === "سگ" ? <Dog className="w-24 h-24" /> : <Cat className="w-24 h-24" />}
</div>
</div>
@ -652,7 +652,7 @@ export default function PetProfile({ initialView, advisorNeed }: {
<div className="flex flex-wrap gap-2">
{activePet.medicalConditions.map(c => (
<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">
<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">
<Stethoscope className="w-3 h-3" />
{c}
</div>
@ -661,7 +661,7 @@ export default function PetProfile({ initialView, advisorNeed }: {
</div>
</div>
<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="bg-canino-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">
<Activity className="w-16 h-16 text-white" />
</div>
@ -712,10 +712,10 @@ export default function PetProfile({ initialView, advisorNeed }: {
{/* Refill & Stock Tracking */}
<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-canina-blue to-blue-300" />
<div className="absolute top-0 left-0 w-full h-1 bg-gradient-to-r from-canino-blue to-blue-300" />
<div className="flex items-center justify-between mb-8">
<div className="flex items-center gap-3">
<Package className="w-8 h-8 text-canina-blue" />
<Package className="w-8 h-8 text-canino-blue" />
<h3 className="text-2xl font-black text-medical-gray-900 italic">پایش موجودی مکملها</h3>
</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 className={cn(
"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-canina-blue shadow-inner"
isLow ? "bg-red-50 text-red-500 animate-pulse" : "bg-white text-canino-blue shadow-inner"
)}>
{toPersian(Math.round(percentage))}%
</div>
@ -754,7 +754,7 @@ export default function PetProfile({ initialView, advisorNeed }: {
<motion.div
initial={{ width: 0 }}
animate={{ width: `${Math.min(100, Math.max(0, percentage))}%` }}
className={cn("h-full", isLow ? "bg-red-500" : "bg-canina-blue")}
className={cn("h-full", isLow ? "bg-red-500" : "bg-canino-blue")}
/>
</div>
@ -783,11 +783,11 @@ export default function PetProfile({ initialView, advisorNeed }: {
<button
key={tab.id}
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-canina-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-canino-blue" : "text-medical-gray-400 hover:text-medical-gray-600"}`}
>
{tab.icon}
{tab.label}
{activePetTab === tab.id && <motion.div layoutId="petTab" className="absolute bottom-0 left-0 right-0 h-1 bg-canina-blue rounded-full" />}
{activePetTab === tab.id && <motion.div layoutId="petTab" className="absolute bottom-0 left-0 right-0 h-1 bg-canino-blue rounded-full" />}
</button>
))}
</div>
@ -798,7 +798,7 @@ export default function PetProfile({ initialView, advisorNeed }: {
<section>
<div className="flex items-center justify-between mb-8 px-4">
<div className="flex items-center gap-4">
<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">
<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">
<Star className="w-6 h-6" />
</div>
<h3 className="text-3xl font-black text-medical-gray-900 italic">توصیههای درمانی اختصاصی</h3>
@ -817,7 +817,7 @@ 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"
>
{reason && (
<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">
<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">
{reason}
</div>
)}
@ -825,9 +825,9 @@ export default function PetProfile({ initialView, advisorNeed }: {
<SafeImage src={p.image} alt={p.name} className="w-full h-full object-contain group-hover:scale-110 transition-transform duration-500" />
</div>
<div>
<h4 className="text-lg font-black text-medical-gray-900 group-hover:text-canina-blue transition-colors mb-2 italic">{p.name}</h4>
<h4 className="text-lg font-black text-medical-gray-900 group-hover:text-canino-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>
<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">
<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">
بررسی تخصصی
<ChevronLeft className="w-3.5 h-3.5" />
</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="flex items-center justify-between mb-10">
<div className="flex items-center gap-3">
<Clock className="w-8 h-8 text-canina-blue" />
<Clock className="w-8 h-8 text-canino-blue" />
<h3 className="text-2xl font-black text-medical-gray-900 italic">یادآورهای فعال</h3>
</div>
<TrendingUp className="w-6 h-6 text-green-500" />
@ -863,7 +863,7 @@ export default function PetProfile({ initialView, advisorNeed }: {
key={reminder.id}
className={cn(
"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-canina-blue/30"
isCompleted ? "bg-green-50 border-green-200" : "bg-medical-gray-50 border-medical-gray-100 hover:border-canino-blue/30"
)}
>
<div className="flex items-center gap-4">
@ -871,7 +871,7 @@ export default function PetProfile({ initialView, advisorNeed }: {
onClick={() => handleToggleReminder(reminder)}
className={cn(
"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-canina-blue"
isCompleted ? "bg-green-500 text-white" : "bg-white text-medical-gray-300 hover:text-canino-blue"
)}
>
{isCompleted ? <Check className="w-5 h-5" /> : <Clock className="w-5 h-5" />}
@ -892,7 +892,7 @@ export default function PetProfile({ initialView, advisorNeed }: {
<button
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-canina-blue hover:text-canina-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-canino-blue hover:text-canino-blue transition-all flex items-center justify-center gap-2"
>
<Plus className="w-4 h-4" />
افزودن یادآور جدید
@ -902,7 +902,7 @@ export default function PetProfile({ initialView, advisorNeed }: {
{/* Health Logs */}
<div className="bg-white rounded-[3rem] border border-medical-gray-200 p-10 shadow-sm">
<div className="flex items-center gap-3 mb-10">
<ClipboardList className="w-8 h-8 text-canina-blue" />
<ClipboardList className="w-8 h-8 text-canino-blue" />
<h3 className="text-2xl font-black text-medical-gray-900 italic">تایملاین سلامت</h3>
</div>
@ -919,7 +919,7 @@ export default function PetProfile({ initialView, advisorNeed }: {
{toPersian(new Date(log.date).toLocaleDateString("fa-IR"))}
</div>
<div className="flex gap-2">
<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-canino-blue/10 text-canino-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>
</div>
@ -933,7 +933,7 @@ export default function PetProfile({ initialView, advisorNeed }: {
<button
onClick={() => setIsAddingHealthLog(true)}
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"
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"
>
ثبت گزارش روزانه جدید
</button>
@ -958,7 +958,7 @@ export default function PetProfile({ initialView, advisorNeed }: {
</div>
<div className="text-left">
<div className="text-[10px] font-black text-medical-gray-400 uppercase tracking-widest">مجموع هزینه درمانی</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 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>
</div>
@ -968,7 +968,7 @@ export default function PetProfile({ initialView, advisorNeed }: {
<Package className="w-12 h-12" />
</div>
<p className="text-medical-gray-400 font-black text-xl italic">هنوز سفارشی برای {activePet.name} ثبت نکردهاید.</p>
<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>
<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>
</div>
) : (
<div className="space-y-5">
@ -984,10 +984,10 @@ export default function PetProfile({ initialView, advisorNeed }: {
>
{/* Info on Left (Text side) */}
<div className="flex-1 text-right">
<h4 className="text-xl font-black text-medical-gray-900 group-hover:text-canina-blue transition-colors mb-2 italic">{item.product.name}</h4>
<h4 className="text-xl font-black text-medical-gray-900 group-hover:text-canino-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 items-center gap-1.5 text-xs font-bold text-medical-gray-500">
<Calendar className="w-4 h-4 text-canina-blue/40" />
<Calendar className="w-4 h-4 text-canino-blue/40" />
{toPersian(new Date(order.date).toLocaleDateString("fa-IR", { year: 'numeric', month: 'long', day: 'numeric' }))}
</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">
@ -1020,11 +1020,11 @@ export default function PetProfile({ initialView, advisorNeed }: {
{/* 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="flex justify-center mb-8">
<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 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>
<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">
این گزارش توسط سیستم هوش مصنوعی کانینا و با انطباق کامل بر پروتکلهای درمانی Canina Pharma GmbH آلمان تولید شده است. تمامی مکملهای پیشنهادی دارای استاندارد دارویی (Pharmaceutical Grade) میباشند.
این گزارش توسط سیستم هوش مصنوعی کانینو و با انطباق کامل بر پروتکلهای درمانی Canina Pharma GmbH آلمان تولید شده است. تمامی مکملهای پیشنهادی دارای استاندارد دارویی (Pharmaceutical Grade) میباشند.
</p>
</div>
@ -1059,7 +1059,7 @@ export default function PetProfile({ initialView, advisorNeed }: {
value={reminderForm.title}
onChange={e => setReminderForm({...reminderForm, title: e.target.value})}
placeholder="مثلاً: قرص مفاصل، کانهیدروکس"
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"
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"
/>
</div>
<div className="grid grid-cols-2 gap-4">
@ -1069,7 +1069,7 @@ export default function PetProfile({ initialView, advisorNeed }: {
type="time"
value={reminderForm.time}
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-canina-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-canino-blue/20 outline-none font-black"
/>
</div>
<div>
@ -1077,7 +1077,7 @@ export default function PetProfile({ initialView, advisorNeed }: {
<select
value={reminderForm.frequency}
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-canina-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-canino-blue/20 outline-none font-black text-sm"
>
<option value="روزانه">روزانه</option>
<option value="هفتگی">هفتگی</option>
@ -1089,7 +1089,7 @@ export default function PetProfile({ initialView, advisorNeed }: {
<select
value={reminderForm.productId}
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-canina-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-canino-blue/20 outline-none font-black text-sm"
>
<option value="">هیچکدام</option>
{recommendedProducts.map(p => (
@ -1100,7 +1100,7 @@ export default function PetProfile({ initialView, advisorNeed }: {
<button
onClick={handleReminderSubmit}
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"
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"
>
ثبت نهایی یادآور
</button>
@ -1142,7 +1142,7 @@ export default function PetProfile({ initialView, advisorNeed }: {
onClick={() => setLogForm({...logForm, appetite: opt as any})}
className={cn(
"py-3 border-2 rounded-xl text-xs font-black transition-all",
logForm.appetite === opt ? "border-canina-blue bg-canina-blue/10 text-canina-blue" : "border-medical-gray-100 text-medical-gray-400"
logForm.appetite === opt ? "border-canino-blue bg-canino-blue/10 text-canino-blue" : "border-medical-gray-100 text-medical-gray-400"
)}
>
{opt}
@ -1176,13 +1176,13 @@ export default function PetProfile({ initialView, advisorNeed }: {
value={logForm.note}
onChange={e => setLogForm({...logForm, note: e.target.value})}
placeholder="مشاهدات خود را برای بررسی دکتر سیستم اینجا بنویسید..."
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"
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"
/>
</div>
<button
onClick={handleHealthLogSubmit}
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"
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"
>
ثبت نهایی گزارش
</button>

View File

@ -169,8 +169,8 @@ export default function ProductPage({ productSlug }: { productSlug: string }) {
<ChevronRight className="w-5 h-5" />
بازگشت
</button>
<div className="text-[10px] font-black text-canina-blue bg-canina-blue/5 px-4 py-2 rounded-xl font-vazir whitespace-nowrap">
کانینا ایران
<div className="text-[10px] font-black text-canino-blue bg-canino-blue/5 px-4 py-2 rounded-xl font-vazir whitespace-nowrap">
کانینو ایران
</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">
<button
onClick={() => router.push('/')}
className="hover:text-canina-blue transition-colors font-vazir cursor-pointer"
className="hover:text-canino-blue transition-colors font-vazir cursor-pointer"
>
خانه
</button>
<ChevronLeft className="w-3 h-3 flex-shrink-0" />
<button
onClick={() => router.push(`/shop?category=${product.category}`)}
className="hover:text-canina-blue cursor-pointer font-vazir"
className="hover:text-canino-blue cursor-pointer font-vazir"
>
{product.category}
</button>
<ChevronLeft className="w-3 h-3 flex-shrink-0" />
<span className="text-canina-blue font-vazir whitespace-nowrap">{product.name}</span>
<span className="text-canino-blue font-vazir whitespace-nowrap">{product.name}</span>
</nav>
<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>
<div className="flex flex-wrap items-center gap-3 mb-4">
<div className="px-3 py-1 bg-canina-blue text-white rounded-full text-[10px] font-black uppercase tracking-widest font-vazir whitespace-nowrap">
<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>
{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">
{product.name}
</h1>
<p className="text-xl text-canina-blue font-bold italic opacity-70 leading-relaxed max-w-2xl font-vazir mb-6">
<p className="text-xl text-canino-blue font-bold italic opacity-70 leading-relaxed max-w-2xl font-vazir mb-6">
{pets.length > 0 ? (
product.optimisticTemplate?.replace("[PetName]", activePet?.name || "").replace("[OnSet]", product.onSetOfAction || "به زودی")
) : (
@ -218,7 +218,7 @@ export default function ProductPage({ productSlug }: { productSlug: string }) {
)}
</p>
{fullProduct.shortDescription && (
<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">
<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">
{fullProduct.shortDescription}
</p>
)}
@ -228,7 +228,7 @@ export default function ProductPage({ productSlug }: { productSlug: string }) {
{fullProduct.keyBenefits && (
<section className="space-y-8">
<div className="flex items-center gap-4">
<div className="w-12 h-12 bg-canina-blue text-white rounded-2xl flex items-center justify-center shadow-lg">
<div className="w-12 h-12 bg-canino-blue text-white rounded-2xl flex items-center justify-center shadow-lg">
<Star className="w-6 h-6" />
</div>
<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;
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 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-canina-blue mb-6 group-hover:bg-canina-blue group-hover:text-white transition-all">
<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="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">
<Icon className="w-6 h-6" />
</div>
<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" />
موجود در انبار
</div>
<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 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>
</div>
@ -289,7 +289,7 @@ export default function ProductPage({ productSlug }: { productSlug: string }) {
{product.main_ingredients.map((ing, idx) => {
const termKey = termKeys.find(key => ing.includes(key));
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-canina-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-canino-blue/30 transition-all">
<span className="text-sm font-bold text-medical-gray-700 font-vazir">
{termKey ? (
<Tooltip termKey={termKey} onWikiNavigate={(id) => router.push(`/wiki?term=${id}`)}>
@ -297,7 +297,7 @@ export default function ProductPage({ productSlug }: { productSlug: string }) {
</Tooltip>
) : ing}
</span>
<Sparkles className="w-3 h-3 text-canina-blue opacity-40 group-hover:opacity-100 transition-opacity" />
<Sparkles className="w-3 h-3 text-canino-blue opacity-40 group-hover:opacity-100 transition-opacity" />
</div>
);
})}
@ -309,7 +309,7 @@ export default function ProductPage({ productSlug }: { productSlug: string }) {
<div className="text-[10px] font-black text-medical-gray-400 uppercase tracking-widest mb-4 font-vazir">تخمین اتمام بسته (هوش مصنوعی)</div>
<div className="grid grid-cols-2 gap-4">
{Object.entries(product.analysis).map(([key, value]) => (
<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 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">
<div className="text-[10px] font-black text-white/80 uppercase tracking-widest mb-3 font-vazir whitespace-nowrap">{key}</div>
<div className="text-3xl font-black font-vazir tracking-tighter text-white">{toPersian(value)}</div>
</div>
@ -320,9 +320,9 @@ export default function ProductPage({ productSlug }: { productSlug: string }) {
</section>
{/* Feeding Section */}
<section className="bg-canina-blue/5 border border-canina-blue/10 rounded-[3rem] p-10">
<section className="bg-canino-blue/5 border border-canino-blue/10 rounded-[3rem] p-10">
<div className="flex items-center gap-4 mb-8">
<div className="w-10 h-10 bg-canina-blue text-white rounded-xl flex items-center justify-center">
<div className="w-10 h-10 bg-canino-blue text-white rounded-xl flex items-center justify-center">
<CalendarDays className="w-6 h-6" />
</div>
<h3 className="text-2xl font-black text-medical-gray-900 italic font-vazir">توصیه غذایی و نحوه مصرف</h3>
@ -347,7 +347,7 @@ export default function ProductPage({ productSlug }: { productSlug: string }) {
مورد تأیید دامپزشکان
</div>
<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-canina-blue mb-6 font-vazir">{product.specialist.title}</p>
<p className="text-sm font-bold text-canino-blue mb-6 font-vazir">{product.specialist.title}</p>
<p className="text-base text-medical-gray-600 leading-relaxed italic font-vazir">
"{product.specialist.message}"
</p>
@ -359,7 +359,7 @@ export default function ProductPage({ productSlug }: { productSlug: string }) {
{/* Specialized Landing Banner */}
<section>
<div
className="relative bg-canina-blue rounded-[3rem] p-12 overflow-hidden group cursor-pointer"
className="relative bg-canino-blue rounded-[3rem] p-12 overflow-hidden group cursor-pointer"
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" />
@ -372,7 +372,7 @@ export default function ProductPage({ productSlug }: { productSlug: string }) {
گزارشهای علمی، ویدیوهای آموزشی و تجربیات واقعی دیگر صاحبان پت در لندینگپیج اختصاصی این محصول.
</p>
</div>
<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">
<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">
ورود به آزمایشگاه علمی
<ArrowRight className="w-5 h-5 rotate-180" />
</div>
@ -384,17 +384,17 @@ export default function ProductPage({ productSlug }: { productSlug: string }) {
{product.faqs && (
<section className="pt-10">
<div className="flex items-center gap-4 mb-10">
<div className="w-12 h-12 bg-blue-100 text-canina-blue rounded-2xl flex items-center justify-center">
<div className="w-12 h-12 bg-blue-100 text-canino-blue rounded-2xl flex items-center justify-center">
<Info className="w-6 h-6" />
</div>
<h3 className="text-3xl font-black text-medical-gray-900 italic font-vazir">پاسخ به ابهامات شما</h3>
</div>
<div className="grid md:grid-cols-1 gap-4">
{product.faqs.map((faq, i) => (
<details key={i} className="group bg-white border border-medical-gray-200 rounded-3xl overflow-hidden hover:border-canina-blue/30 transition-all">
<details key={i} className="group bg-white border border-medical-gray-200 rounded-3xl overflow-hidden hover:border-canino-blue/30 transition-all">
<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>
<ChevronDown className="w-5 h-5 text-canina-blue group-open:rotate-180 transition-transform" />
<ChevronDown className="w-5 h-5 text-canino-blue group-open:rotate-180 transition-transform" />
</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">
{faq.answer}
@ -409,14 +409,14 @@ export default function ProductPage({ productSlug }: { productSlug: string }) {
{/* Sticky Sidebar */}
<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="absolute top-0 right-0 w-24 h-24 bg-canina-blue/5 rounded-full -mr-12 -mt-12" />
<div className="absolute top-0 right-0 w-24 h-24 bg-canino-blue/5 rounded-full -mr-12 -mt-12" />
<div className="text-4xl font-black font-vazir text-medical-gray-900 tracking-tighter mb-4">
{toPersian(product.price)}
</div>
{/* Refill Auto-Calculator */}
<div className="bg-canina-blue rounded-[2rem] p-6 text-white mb-8 border-b-8 border-white/20 shadow-2xl">
<div className="bg-canino-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">
<Clock className="w-4 h-4 text-white" />
<span className="text-[10px] font-bold uppercase tracking-widest font-vazir text-white">هوش مصنوعی تکرار خرید</span>
@ -437,18 +437,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="flex items-center justify-between">
<span className="text-[10px] font-black text-medical-gray-400 font-vazir">وزن پت (کیلوگرم)</span>
<span className="text-sm font-black text-canina-blue font-vazir">{toPersian(weight)}</span>
<span className="text-sm font-black text-canino-blue font-vazir">{toPersian(weight)}</span>
</div>
<input
type="range"
min="1" max="100"
value={weight}
onChange={(e) => setWeight(parseInt(e.target.value))}
className="w-full h-1.5 bg-medical-gray-200 rounded-lg appearance-none cursor-pointer accent-canina-blue"
className="w-full h-1.5 bg-medical-gray-200 rounded-lg appearance-none cursor-pointer accent-canino-blue"
/>
<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-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-canina-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-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-canino-blue text-white shadow-lg' : 'bg-white text-medical-gray-400'}`}>بالغ</button>
</div>
</div>
@ -457,7 +457,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%]">
<button
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-canina-blue hover:text-white hover:border-canina-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-canino-blue hover:text-white hover:border-canino-blue transition-all shadow-sm"
>
<Minus className="w-4 h-4" />
</button>
@ -466,7 +466,7 @@ export default function ProductPage({ productSlug }: { productSlug: string }) {
</span>
<button
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-canina-blue hover:text-white hover:border-canina-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-canino-blue hover:text-white hover:border-canino-blue transition-all shadow-sm"
>
<Plus className="w-4 h-4" />
</button>
@ -478,7 +478,7 @@ export default function ProductPage({ productSlug }: { productSlug: string }) {
addItem(product, itemQuantity, { quantity: calculation.dailyDose, unit: calculation.unit });
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-canina-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-canino-blue transition-all shadow-xl shadow-black/10 font-vazir whitespace-nowrap"
>
<ShoppingBag className="w-5 h-5 mb-1" />
افزودن به سبد خرید
@ -491,7 +491,7 @@ export default function ProductPage({ productSlug }: { productSlug: string }) {
ضمانت اصالت محصول (Made in Germany)
</div>
<div className="flex items-center gap-2 text-[10px] font-bold text-medical-gray-400 font-vazir">
<Clock className="w-4 h-4 text-canina-blue" />
<Clock className="w-4 h-4 text-canino-blue" />
آماده ارسال (تحویل حداکثر ۴۸ ساعت)
</div>
</div>
@ -506,7 +506,7 @@ export default function ProductPage({ productSlug }: { productSlug: string }) {
const Icon = ICON_MAP[res.icon] || Sparkles;
return (
<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-canina-blue group-hover:bg-canina-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-canino-blue group-hover:bg-canino-blue group-hover:text-white transition-all">
<Icon className="w-5 h-5" />
</div>
<span className="text-xs font-bold text-medical-gray-700 font-vazir">{res.text}</span>
@ -523,12 +523,12 @@ export default function ProductPage({ productSlug }: { productSlug: string }) {
{product.relatedProducts && product.relatedProducts.length > 0 && (
<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="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">
<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">
<Sparkles className="w-4 h-4" />
فرمولاسیون ترکیبی همافزا (Synergy Blend)
</div>
<h2 className="text-3xl lg:text-5xl font-black text-medical-gray-900 leading-tight">
اثربخشی <span className="text-canina-blue italic">دوبرابر</span> با ترکیب هوشمند
اثربخشی <span className="text-canino-blue italic">دوبرابر</span> با ترکیب هوشمند
</h2>
</div>
@ -552,14 +552,14 @@ export default function ProductPage({ productSlug }: { productSlug: string }) {
<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>
<div className="flex items-center justify-center md:justify-start gap-4">
<span className="text-lg font-black text-canina-blue">{relProduct.price}</span>
<span className="text-lg font-black text-canino-blue">{relProduct.price}</span>
<ArrowRight className="w-4 h-4 text-medical-gray-300" />
</div>
</div>
<div className="w-px h-24 bg-medical-gray-100 hidden md:block" />
<div className="flex items-center justify-center gap-1 group">
<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-canina-blue group-hover:-translate-x-1 transition-all rtl:group-hover:translate-x-1" />
<span className="text-xs font-black text-medical-gray-400 group-hover:text-canino-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" />
</div>
</motion.div>
);
@ -586,7 +586,7 @@ export default function ProductPage({ productSlug }: { productSlug: string }) {
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"
>
<div className="absolute top-0 left-0 w-full h-2 bg-gradient-to-r from-canina-blue via-blue-400 to-canina-blue" />
<div className="absolute top-0 left-0 w-full h-2 bg-gradient-to-r from-canino-blue via-blue-400 to-canino-blue" />
<button
onClick={() => setShowRefillModal(false)}
className="absolute top-6 left-6 text-medical-gray-400 hover:text-medical-gray-600 transition-colors"
@ -595,13 +595,13 @@ export default function ProductPage({ productSlug }: { productSlug: string }) {
</button>
<div className="text-center">
<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-canina-blue animate-bounce" />
<div className="w-20 h-20 bg-canino-blue/10 rounded-[2rem] flex items-center justify-center mx-auto mb-8">
<Bell className="w-10 h-10 text-canino-blue animate-bounce" />
</div>
<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">
<p className="text-medical-gray-700 leading-relaxed font-medium font-vazir">
بر اساس وزن <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> دیگر تمام میشود.
بر اساس وزن <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> دیگر تمام میشود.
</p>
<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" />
@ -612,7 +612,7 @@ export default function ProductPage({ productSlug }: { productSlug: string }) {
<div className="flex flex-col gap-3">
<button
onClick={() => setShowRefillModal(false)}
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"
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"
>
<CheckCircle2 className="w-5 h-5" />
بله، پیامک یادآوری فعال شود

View File

@ -32,17 +32,17 @@ export default function SafeImage({
<div className="absolute inset-0 opacity-[0.03] pointer-events-none">
<div className="grid grid-cols-6 h-full w-full">
{Array.from({length: 24}).map((_, i) => (
<div key={i} className="border border-canina-blue" />
<div key={i} className="border border-canino-blue" />
))}
</div>
</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="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="relative">
<ImageOff className="w-5 h-5 text-medical-gray-200 mb-2" />
<Sparkles className="w-3 h-3 text-canina-blue absolute -top-1 -right-1 animate-pulse" />
<Sparkles className="w-3 h-3 text-canino-blue absolute -top-1 -right-1 animate-pulse" />
</div>
<span className="text-[9px] font-black text-canina-blue/60 uppercase tracking-[0.2em] font-vazir leading-relaxed">
<span className="text-[9px] font-black text-canino-blue/60 uppercase tracking-[0.2em] font-vazir leading-relaxed">
{fallbackText}
</span>
</div>
@ -53,7 +53,7 @@ export default function SafeImage({
<div className={cn("relative overflow-hidden group flex items-center justify-center", className)}>
{loading && (
<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-canina-blue/20" />
<Sparkles className="w-6 h-6 text-canino-blue/20" />
</div>
)}
<img

View File

@ -32,7 +32,7 @@ export default function SearchResultsPage({ query }: { query: string }) {
return (
<div className="min-h-screen bg-medical-gray-50 py-20 px-6 font-vazir" dir="rtl">
<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-canina-blue transition-colors">
<button onClick={() => router.back()} className="flex items-center gap-2 text-medical-gray-400 font-black mb-10 hover:text-canino-blue transition-colors">
<ArrowRight className="w-5 h-5 rotate-180" />
بازگشت
</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>
<h1 className="text-4xl font-black text-medical-gray-900 italic mb-4">
نتایج جستجو برای: <span className="text-canina-blue">"{query}"</span>
نتایج جستجو برای: <span className="text-canino-blue">"{query}"</span>
</h1>
<p className="text-medical-gray-500 font-medium">
{results.length} محصول با معیارهای شما مطابقت دارد.
@ -65,7 +65,7 @@ export default function SearchResultsPage({ query }: { query: string }) {
key={product.id}
layoutId={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-canina-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-canino-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">
<img
@ -91,8 +91,8 @@ export default function SearchResultsPage({ query }: { query: string }) {
</div>
<div className="flex-1">
<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-canina-blue transition-colors">{product.name}</h3>
<span className="text-[10px] font-black text-canino-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>
<p className="text-xs text-medical-gray-400 line-clamp-2 leading-relaxed mb-6">{product.benefits}</p>
</div>
@ -100,7 +100,7 @@ export default function SearchResultsPage({ query }: { query: string }) {
<div>
<span className="text-lg font-black text-medical-gray-900">{product.price}</span>
</div>
<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">
<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">
<ChevronLeft className="w-5 h-5" />
</button>
</div>

View File

@ -89,18 +89,18 @@ export default function SmartAdvisor({ onComplete, rules = [] }: SmartAdvisorPro
};
return (
<section id="canina-advisor" className="py-24 bg-white">
<section id="canino-advisor" className="py-24 bg-white">
<div className="max-w-4xl mx-auto px-4">
<div className="text-center mb-12">
<motion.div
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
className="inline-flex items-center gap-2 px-4 py-2 bg-canina-blue/5 rounded-full mb-6"
className="inline-flex items-center gap-2 px-4 py-2 bg-canino-blue/5 rounded-full mb-6"
>
<Sparkle className="w-4 h-4 text-canina-blue" />
<span className="text-canina-blue text-xs font-black uppercase tracking-widest font-vazir">تکنولوژی پایش هوشمند</span>
<Sparkle className="w-4 h-4 text-canino-blue" />
<span className="text-canino-blue text-xs font-black uppercase tracking-widest font-vazir">تکنولوژی پایش هوشمند</span>
</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-500 font-bold text-lg font-vazir">فقط چند قدم تا صدور شناسنامه هوشمند و دریافت پیشنهادات تخصصی</p>
</div>
@ -108,7 +108,7 @@ export default function SmartAdvisor({ onComplete, rules = [] }: SmartAdvisorPro
{/* Progress Indicator */}
<div className="absolute top-0 left-0 w-full h-2 bg-medical-gray-200">
<motion.div
className="h-full bg-canina-blue"
className="h-full bg-canino-blue"
initial={{ width: "0%" }}
animate={{ width: `${(step / 3) * 100}%` }}
transition={{ duration: 0.5 }}
@ -132,16 +132,16 @@ export default function SmartAdvisor({ onComplete, rules = [] }: SmartAdvisorPro
<div className="grid grid-cols-2 gap-4">
<button
onClick={() => setType("سگ")}
className={`flex flex-col items-center gap-4 p-8 rounded-[2.5rem] border-4 transition-all ${type === "سگ" ? 'border-canina-blue bg-white shadow-xl shadow-canina-blue/10 scale-105' : 'border-transparent bg-white/50 text-medical-gray-300 hover:bg-white'}`}
className={`flex flex-col items-center gap-4 p-8 rounded-[2.5rem] border-4 transition-all ${type === "سگ" ? 'border-canino-blue bg-white shadow-xl shadow-canino-blue/10 scale-105' : 'border-transparent bg-white/50 text-medical-gray-300 hover:bg-white'}`}
>
<Dog className={`w-12 h-12 ${type === "سگ" ? 'text-canina-blue' : 'text-current'}`} />
<Dog className={`w-12 h-12 ${type === "سگ" ? 'text-canino-blue' : 'text-current'}`} />
<span className="text-lg font-black font-vazir">سگ</span>
</button>
<button
onClick={() => setType("گربه")}
className={`flex flex-col items-center gap-4 p-8 rounded-[2.5rem] border-4 transition-all ${type === "گربه" ? 'border-canina-blue bg-white shadow-xl shadow-canina-blue/10 scale-105' : 'border-transparent bg-white/50 text-medical-gray-300 hover:bg-white'}`}
className={`flex flex-col items-center gap-4 p-8 rounded-[2.5rem] border-4 transition-all ${type === "گربه" ? 'border-canino-blue bg-white shadow-xl shadow-canino-blue/10 scale-105' : 'border-transparent bg-white/50 text-medical-gray-300 hover:bg-white'}`}
>
<Cat className={`w-12 h-12 ${type === "گربه" ? 'text-canina-blue' : 'text-current'}`} />
<Cat className={`w-12 h-12 ${type === "گربه" ? 'text-canino-blue' : 'text-current'}`} />
<span className="text-lg font-black font-vazir">گربه</span>
</button>
</div>
@ -154,7 +154,7 @@ export default function SmartAdvisor({ onComplete, rules = [] }: SmartAdvisorPro
value={name}
onChange={e => setName(e.target.value)}
placeholder="لوسی، تدی..."
className="w-full bg-white 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 font-vazir"
className="w-full bg-white 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 font-vazir"
/>
</div>
<div className="space-y-2">
@ -164,7 +164,7 @@ export default function SmartAdvisor({ onComplete, rules = [] }: SmartAdvisorPro
value={breed}
onChange={e => setBreed(e.target.value)}
placeholder="ژرمن، پرشین..."
className="w-full bg-white border border-medical-gray-200 rounded-2xl py-4 px-6 focus:ring-2 focus:ring-canina-blue/20 outline-none font-bold font-vazir"
className="w-full bg-white border border-medical-gray-200 rounded-2xl py-4 px-6 focus:ring-2 focus:ring-canino-blue/20 outline-none font-bold font-vazir"
/>
</div>
</div>
@ -172,7 +172,7 @@ export default function SmartAdvisor({ onComplete, rules = [] }: SmartAdvisorPro
<button
onClick={handleNext}
disabled={!name || !breed}
className="w-full py-6 bg-medical-gray-900 text-white rounded-3xl font-black text-lg hover:bg-canina-blue transition-all shadow-xl shadow-medical-gray-900/10 flex items-center justify-center gap-3 font-vazir disabled:opacity-50"
className="w-full py-6 bg-medical-gray-900 text-white rounded-3xl font-black text-lg hover:bg-canino-blue transition-all shadow-xl shadow-medical-gray-900/10 flex items-center justify-center gap-3 font-vazir disabled:opacity-50"
>
ثبت هویت و ادامه
<ChevronLeft className="w-5 h-5" />
@ -197,17 +197,17 @@ export default function SmartAdvisor({ onComplete, rules = [] }: SmartAdvisorPro
<div className="space-y-4">
<label className="block text-center text-xs font-black text-medical-gray-400 uppercase tracking-widest font-vazir">سن (سال)</label>
<div className="flex items-center gap-4 bg-white rounded-3xl p-2 border border-medical-gray-200">
<button onClick={() => setAge(Math.max(0, age - 1))} className="w-10 h-10 flex items-center justify-center bg-medical-gray-50 rounded-xl text-medical-gray-900 hover:bg-canina-blue hover:text-white transition-all shadow-sm">-</button>
<span className="flex-1 text-center text-2xl font-black text-canina-blue font-vazir">{toPersian(age.toString())}</span>
<button onClick={() => setAge(age + 1)} className="w-10 h-10 flex items-center justify-center bg-medical-gray-50 rounded-xl text-medical-gray-900 hover:bg-canina-blue hover:text-white transition-all shadow-sm">+</button>
<button onClick={() => setAge(Math.max(0, age - 1))} className="w-10 h-10 flex items-center justify-center bg-medical-gray-50 rounded-xl text-medical-gray-900 hover:bg-canino-blue hover:text-white transition-all shadow-sm">-</button>
<span className="flex-1 text-center text-2xl font-black text-canino-blue font-vazir">{toPersian(age.toString())}</span>
<button onClick={() => setAge(age + 1)} className="w-10 h-10 flex items-center justify-center bg-medical-gray-50 rounded-xl text-medical-gray-900 hover:bg-canino-blue hover:text-white transition-all shadow-sm">+</button>
</div>
</div>
<div className="space-y-4">
<label className="block text-center text-xs font-black text-medical-gray-400 uppercase tracking-widest font-vazir">وزن (کیلوگرم)</label>
<div className="flex items-center gap-4 bg-white rounded-3xl p-2 border border-medical-gray-200">
<button onClick={() => setWeight(Math.max(1, weight - 1))} className="w-10 h-10 flex items-center justify-center bg-medical-gray-50 rounded-xl text-medical-gray-900 hover:bg-canina-blue hover:text-white transition-all shadow-sm">-</button>
<span className="flex-1 text-center text-2xl font-black text-canina-blue font-vazir">{toPersian(weight.toString())}</span>
<button onClick={() => setWeight(weight + 1)} className="w-10 h-10 flex items-center justify-center bg-medical-gray-50 rounded-xl text-medical-gray-900 hover:bg-canina-blue hover:text-white transition-all shadow-sm">+</button>
<button onClick={() => setWeight(Math.max(1, weight - 1))} className="w-10 h-10 flex items-center justify-center bg-medical-gray-50 rounded-xl text-medical-gray-900 hover:bg-canino-blue hover:text-white transition-all shadow-sm">-</button>
<span className="flex-1 text-center text-2xl font-black text-canino-blue font-vazir">{toPersian(weight.toString())}</span>
<button onClick={() => setWeight(weight + 1)} className="w-10 h-10 flex items-center justify-center bg-medical-gray-50 rounded-xl text-medical-gray-900 hover:bg-canino-blue hover:text-white transition-all shadow-sm">+</button>
</div>
</div>
</div>
@ -219,7 +219,7 @@ export default function SmartAdvisor({ onComplete, rules = [] }: SmartAdvisorPro
<button
key={level}
onClick={() => setActivityLevel(level as any)}
className={`py-4 rounded-2xl border-2 transition-all font-black italic ${activityLevel === level ? 'border-canina-blue bg-white text-canina-blue shadow-lg' : 'border-transparent bg-white/50 text-medical-gray-400 hover:bg-white'}`}
className={`py-4 rounded-2xl border-2 transition-all font-black italic ${activityLevel === level ? 'border-canino-blue bg-white text-canino-blue shadow-lg' : 'border-transparent bg-white/50 text-medical-gray-400 hover:bg-white'}`}
>
{level}
</button>
@ -237,7 +237,7 @@ export default function SmartAdvisor({ onComplete, rules = [] }: SmartAdvisorPro
</button>
<button
onClick={handleNext}
className="flex-[2] py-6 bg-medical-gray-900 text-white rounded-3xl font-black text-lg hover:bg-canina-blue transition-all shadow-xl shadow-medical-gray-900/10 flex items-center justify-center gap-3 font-vazir"
className="flex-[2] py-6 bg-medical-gray-900 text-white rounded-3xl font-black text-lg hover:bg-canino-blue transition-all shadow-xl shadow-medical-gray-900/10 flex items-center justify-center gap-3 font-vazir"
>
گام نهایی سلامت
<ChevronLeft className="w-5 h-5" />
@ -268,12 +268,12 @@ export default function SmartAdvisor({ onComplete, rules = [] }: SmartAdvisorPro
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 ${medicalConditions.includes(opt.condition) ? 'border-canina-blue bg-white shadow-md' : 'border-transparent bg-white/50 text-medical-gray-500 hover:bg-white'}`}
className={`flex items-center gap-4 p-5 rounded-2xl border-2 transition-all text-right ${medicalConditions.includes(opt.condition) ? 'border-canino-blue bg-white shadow-md' : 'border-transparent bg-white/50 text-medical-gray-500 hover:bg-white'}`}
>
<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-200 text-transparent'}`}>
<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-200 text-transparent'}`}>
<ShieldCheck className="w-5 h-5" />
</div>
<span className={`text-sm font-black font-vazir ${medicalConditions.includes(opt.condition) ? 'text-canina-blue' : 'text-medical-gray-700'}`}>{opt.label}</span>
<span className={`text-sm font-black font-vazir ${medicalConditions.includes(opt.condition) ? 'text-canino-blue' : 'text-medical-gray-700'}`}>{opt.label}</span>
</button>
))}
</div>
@ -288,7 +288,7 @@ export default function SmartAdvisor({ onComplete, rules = [] }: SmartAdvisorPro
</button>
<button
onClick={handleSubmit}
className="flex-[2] py-6 bg-canina-blue text-white rounded-3xl font-black text-lg hover:bg-indigo-700 transition-all shadow-xl shadow-canina-blue/20 flex items-center justify-center gap-3 font-vazir"
className="flex-[2] py-6 bg-canino-blue text-white rounded-3xl font-black text-lg hover:bg-indigo-700 transition-all shadow-xl shadow-canino-blue/20 flex items-center justify-center gap-3 font-vazir"
>
تکمیل و صدور شناسنامه
<ChevronLeft className="w-5 h-5" />

View File

@ -20,7 +20,7 @@ export default function Tooltip({ termKey, children, onWikiNavigate }: TooltipPr
return (
<span
className="relative inline-block group cursor-help border-b border-dotted border-canina-blue/40"
className="relative inline-block group cursor-help border-b border-dotted border-canino-blue/40"
onMouseEnter={() => setIsVisible(true)}
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"
dir="rtl"
>
<div className="flex items-center gap-2 mb-2 text-canina-blue">
<div className="flex items-center gap-2 mb-2 text-canino-blue">
<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>
<h5 className="font-black mb-1">{termData.term}</h5>
<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 && (
<button
onClick={() => onWikiNavigate?.(termData.wikiId!)}
className="flex items-center gap-1.5 text-canina-blue hover:text-white transition-colors text-[10px] font-bold"
className="flex items-center gap-1.5 text-canino-blue hover:text-white transition-colors text-[10px] font-bold"
>
<span>مطالعه مقاله کامل</span>
<ExternalLink className="w-3 h-3" />

View File

@ -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="flex items-center gap-3">
<div className="w-10 h-10 bg-canina-blue rounded-xl flex items-center justify-center text-white">
<div className="w-10 h-10 bg-canino-blue rounded-xl flex items-center justify-center text-white">
<TrendingUp className="w-5 h-5" />
</div>
<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(
"px-6 py-3 rounded-2xl text-sm font-black transition-all border",
selectedPreset === preset.value
? "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-canina-blue"
? "bg-canino-blue text-white border-canino-blue shadow-lg shadow-canino-blue/20"
: "bg-white text-medical-gray-700 border-medical-gray-100 hover:border-canino-blue"
)}
>
{preset.label}
@ -118,7 +118,7 @@ export default function TopUpModal({ isOpen, onClose, onConfirm }: TopUpModalPro
type="text"
value={amount ? parseInt(amount).toLocaleString() : ""}
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-canina-blue/10 focus:border-canina-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-canino-blue/10 focus:border-canino-blue italic"
placeholder="۰"
/>
{amount && (
@ -128,14 +128,14 @@ export default function TopUpModal({ isOpen, onClose, onConfirm }: TopUpModalPro
</div>
<div className="bg-blue-50 border border-blue-100 rounded-2xl p-4 flex gap-3">
<Sparkles className="w-5 h-5 text-canina-blue shrink-0" />
<p className="text-[10px] font-bold text-canina-blue leading-relaxed">با شارژ کیف پول، از هدیههای هوشمند کانینا و اولویت در ارسال سفارشها بهرهمند شوید.</p>
<Sparkles className="w-5 h-5 text-canino-blue shrink-0" />
<p className="text-[10px] font-bold text-canino-blue leading-relaxed">با شارژ کیف پول، از هدیههای هوشمند کانینو و اولویت در ارسال سفارشها بهرهمند شوید.</p>
</div>
<button
type="submit"
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-canina-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-canino-blue transition-all shadow-xl shadow-black/10 disabled:opacity-50 disabled:cursor-not-allowed group"
>
{loading ? (
<div className="w-6 h-6 border-4 border-white/20 border-t-white rounded-full animate-spin" />

View File

@ -143,9 +143,9 @@ export default function UserDashboard() {
<div className="max-w-6xl mx-auto">
{/* Breadcrumb */}
<div className="flex items-center gap-2 text-[10px] font-black text-medical-gray-400 uppercase tracking-widest mb-10">
<span className="cursor-pointer hover:text-canina-blue" onClick={() => router.push('/')}>خانه</span>
<span className="cursor-pointer hover:text-canino-blue" onClick={() => router.push('/')}>خانه</span>
<ChevronRight className="w-2.5 h-2.5" />
<span className="text-canina-blue">پنل کاربری</span>
<span className="text-canino-blue">پنل کاربری</span>
</div>
<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="bg-white rounded-[3rem] border border-medical-gray-200 p-8 shadow-xl">
<div className="flex items-center gap-4 mb-10">
<div className="w-16 h-16 bg-canina-blue rounded-3xl flex items-center justify-center text-white shadow-lg">
<div className="w-16 h-16 bg-canino-blue rounded-3xl flex items-center justify-center text-white shadow-lg">
<User className="w-8 h-8" />
</div>
<div>
@ -167,7 +167,7 @@ export default function UserDashboard() {
<button
key={tab.id}
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-canina-blue text-white shadow-lg shadow-canina-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-canino-blue text-white shadow-lg shadow-canino-blue/20" : "text-medical-gray-600 hover:bg-medical-gray-50"}`}
>
{tab.icon}
{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="absolute top-0 left-0 p-6 opacity-20">
<Wallet className="w-12 h-12 text-canina-blue" />
<Wallet className="w-12 h-12 text-canino-blue" />
</div>
<div className="relative z-10">
<div className="text-[10px] font-black uppercase tracking-widest text-white mb-2">موجودی کیف پول</div>
@ -196,7 +196,7 @@ export default function UserDashboard() {
<button
onClick={() => { setActiveTab("wallet"); setIsTopUpModalOpen(true); }}
disabled={isTopUpModalOpen}
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"
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"
>
شارژ کیف پول
</button>
@ -263,7 +263,7 @@ export default function UserDashboard() {
className={cn(
"w-full border p-4 rounded-2xl font-bold outline-none transition-all",
isEditing
? "bg-white border-canina-blue/30 focus:ring-2 focus:ring-canina-blue/20"
? "bg-white border-canino-blue/30 focus:ring-2 focus:ring-canino-blue/20"
: "bg-medical-gray-50 border-medical-gray-100"
)}
/>
@ -282,7 +282,7 @@ export default function UserDashboard() {
className={cn(
"w-full border p-4 rounded-2xl font-bold outline-none transition-all",
isEditing
? "bg-white border-canina-blue/30 focus:ring-2 focus:ring-canina-blue/20"
? "bg-white border-canino-blue/30 focus:ring-2 focus:ring-canino-blue/20"
: "bg-medical-gray-50 border-medical-gray-100"
)}
/>
@ -301,7 +301,7 @@ export default function UserDashboard() {
className={cn(
"w-full border p-4 rounded-2xl font-bold outline-none transition-all text-left",
isEditing
? "bg-white border-canina-blue/30 focus:ring-2 focus:ring-canina-blue/20"
? "bg-white border-canino-blue/30 focus:ring-2 focus:ring-canino-blue/20"
: "bg-medical-gray-50 border-medical-gray-100"
)}
dir="ltr"
@ -322,7 +322,7 @@ export default function UserDashboard() {
className={cn(
"w-full border p-4 rounded-2xl font-bold outline-none transition-all text-left",
isEditing
? "bg-white border-canina-blue/30 focus:ring-2 focus:ring-canina-blue/20"
? "bg-white border-canino-blue/30 focus:ring-2 focus:ring-canino-blue/20"
: "bg-medical-gray-50 border-medical-gray-100 opacity-75 cursor-not-allowed"
)}
dir="ltr"
@ -336,7 +336,7 @@ export default function UserDashboard() {
<button
type="submit"
disabled={isSavingProfile}
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"
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"
>
{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
type="button"
onClick={() => setIsEditing(true)}
className="bg-medical-gray-900 text-white px-10 py-4 rounded-2xl font-black hover:bg-canina-blue transition-all"
className="bg-medical-gray-900 text-white px-10 py-4 rounded-2xl font-black hover:bg-canino-blue transition-all"
>
ویرایش اطلاعات
</button>
@ -383,7 +383,7 @@ export default function UserDashboard() {
<div className="text-center py-20">
<ShoppingBag className="w-16 h-16 text-medical-gray-200 mx-auto mb-4" />
<p className="text-medical-gray-400 font-bold">هنوز سفارشی ثبت نکردهاید.</p>
<button onClick={() => router.push('/shop')} className="mt-6 text-canina-blue font-black underline underline-offset-8">برو به فروشگاه</button>
<button onClick={() => router.push('/shop')} className="mt-6 text-canino-blue font-black underline underline-offset-8">برو به فروشگاه</button>
</div>
) : (
<div className="space-y-4">
@ -395,15 +395,15 @@ export default function UserDashboard() {
key={order.id}
whileHover={{ scale: 1.01, x: -5 }}
onClick={() => setSelectedOrder(order)}
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"
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"
>
<div className="flex flex-wrap items-center justify-between 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-canina-blue group-hover:bg-canina-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-canino-blue group-hover:bg-canino-blue group-hover:text-white transition-all shadow-sm">
<Package className="w-6 h-6" />
</div>
<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-sm font-black text-medical-gray-900 group-hover:text-canino-blue transition-colors italic">سفارش {toPersian(order.id.toUpperCase())}</div>
<div className="text-[10px] font-bold text-medical-gray-400 flex items-center gap-1">
<Calendar className="w-3 h-3 opacity-30" />
{toPersian(new Date(order.date).toLocaleDateString("fa-IR"))}
@ -413,7 +413,7 @@ export default function UserDashboard() {
<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="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-canina-blue/5 text-canina-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-canino-blue/5 text-canino-blue'}`}>
{order.status === 'delivered' ? 'تحویل شده' : 'ارسال شده'}
</span>
<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>
<button
onClick={handleAddClick}
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"
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"
>
<MapPin className="w-4 h-4" />
افزودن آدرس جدید
@ -455,12 +455,12 @@ export default function UserDashboard() {
animate={{ opacity: 1, y: 0 }}
className={cn(
"p-8 bg-white border rounded-[2.5rem] relative group transition-all",
addr.isDefault ? "border-canina-blue shadow-xl shadow-canina-blue/5" : "border-medical-gray-100 hover:border-medical-gray-200"
addr.isDefault ? "border-canino-blue shadow-xl shadow-canino-blue/5" : "border-medical-gray-100 hover:border-medical-gray-200"
)}
>
<div className="flex justify-between items-start mb-6">
<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-canina-blue text-white shadow-lg" : "bg-medical-gray-50 text-canina-blue")}>
<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")}>
<MapPin className="w-6 h-6" />
</div>
<div>
@ -476,7 +476,7 @@ export default function UserDashboard() {
<div className="flex items-center gap-2">
<button
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-canina-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-canino-blue hover:text-white transition-all shadow-sm"
>
<Edit2 className="w-5 h-5" />
</button>
@ -495,11 +495,11 @@ export default function UserDashboard() {
<div className="flex flex-wrap items-center gap-6">
<div className="flex items-center gap-2">
<Phone className="w-4 h-4 text-canina-blue/40" />
<Phone className="w-4 h-4 text-canino-blue/40" />
<span className="text-xs font-bold text-medical-gray-500" dir="ltr">{toPersian(addr.phone)}</span>
</div>
<div className="flex items-center gap-2">
<Hash className="w-4 h-4 text-canina-blue/40" />
<Hash className="w-4 h-4 text-canino-blue/40" />
<span className="text-xs font-bold text-medical-gray-500" dir="ltr">{toPersian(addr.zipCode)}</span>
</div>
{!addr.isDefault && (
@ -512,7 +512,7 @@ export default function UserDashboard() {
toast.error("خطا در تغییر آدرس پیش‌فرض");
}
}}
className="mr-auto text-[10px] font-black text-canina-blue hover:text-medical-gray-900 uppercase tracking-widest whitespace-nowrap"
className="mr-auto text-[10px] font-black text-canino-blue hover:text-medical-gray-900 uppercase tracking-widest whitespace-nowrap"
>
انتخاب به عنوان پیشفرض
</button>
@ -542,7 +542,7 @@ export default function UserDashboard() {
</div>
{/* Main Balance Card */}
<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="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="absolute top-0 right-0 p-12 opacity-10 group-hover:scale-110 transition-transform duration-700">
<Wallet className="w-48 h-48" />
</div>
@ -572,7 +572,7 @@ export default function UserDashboard() {
</div>
<button
onClick={() => setIsTopUpModalOpen(true)}
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"
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"
>
<ArrowUpCircle className="w-5 h-5 group-hover:-translate-y-1 transition-transform" />
شارژ آنی
@ -598,7 +598,7 @@ export default function UserDashboard() {
</div>
) : (
(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-canina-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-canino-blue/10 transition-all group">
<div className="flex items-center gap-4">
<div className={cn(
"w-12 h-12 rounded-2xl flex items-center justify-center transition-colors",

View File

@ -44,20 +44,20 @@ export default function VetGallery({ testimonials = [] }: { testimonials?: any[]
<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="max-w-2xl">
<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">
<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">
<Star className="w-3 h-3" />
Vet Insights
</div>
<h2 className="text-4xl md:text-5xl font-black text-medical-gray-900 italic leading-tight">
مشاوره ویدئویی <span className="text-canina-blue underline decoration-4 decoration-canina-blue/20 underline-offset-8">دوست دامپزشک پت شما</span>
مشاوره ویدئویی <span className="text-canino-blue underline decoration-4 decoration-canino-blue/20 underline-offset-8">دوست دامپزشک پت شما</span>
</h2>
<p className="text-lg text-medical-gray-500 font-medium mt-6">
متخصصین آلمانی کانینا مستقیماً با شما صحبت میکنند. نحوه مصرف، مزایای رقابتی و دانش تخصصی پشت هر محصول.
متخصصین آلمانی کانینو مستقیماً با شما صحبت میکنند. نحوه مصرف، مزایای رقابتی و دانش تخصصی پشت هر محصول.
</p>
</div>
<button
onClick={() => router.push('/videos')}
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"
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"
>
مشاهده همه ویدئوها
<Play className="w-4 h-4" />
@ -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"
/>
<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-canina-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-canino-blue scale-90 group-hover:scale-100 group-hover:bg-white transition-all shadow-xl">
<Play className="w-6 h-6 ml-1" />
</div>
</div>
@ -88,11 +88,11 @@ export default function VetGallery({ testimonials = [] }: { testimonials?: any[]
{video.duration || '۱:۰۰'}
</div>
</div>
<h4 className="text-lg font-black text-medical-gray-900 mb-2 group-hover:text-canina-blue transition-colors leading-tight font-vazir">
<h4 className="text-lg font-black text-medical-gray-900 mb-2 group-hover:text-canino-blue transition-colors leading-tight font-vazir">
{video.title || video.quote?.substring(0, 40) + '...'}
</h4>
<div className="flex items-center gap-2 text-medical-gray-500 font-bold text-sm font-vazir">
<ShieldCheck className="w-4 h-4 text-canina-blue" />
<ShieldCheck className="w-4 h-4 text-canino-blue" />
{video.doctor || video.vetName}
</div>
</motion.div>

View File

@ -69,12 +69,12 @@ export default function VideosPage() {
{/* Header */}
<div className="flex flex-col md:flex-row items-center justify-between mb-16 gap-6">
<div className="text-right">
<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">
<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">
<PlayCircle className="w-3 h-3" />
Video Academy
</div>
<h1 className="text-4xl lg:text-6xl font-black text-white italic leading-tight">
آکادمی ویدئویی <span className="text-canina-blue">کانینا</span>
آکادمی ویدئویی <span className="text-canino-blue">کانینو</span>
</h1>
</div>
<button
@ -117,7 +117,7 @@ export default function VideosPage() {
referrerPolicy="no-referrer"
/>
<div className="absolute inset-0 flex items-center justify-center">
<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">
<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">
<PlayCircle className="w-10 h-10" />
</div>
</div>
@ -126,7 +126,7 @@ export default function VideosPage() {
</div>
</div>
<div className="px-4">
<h3 className="text-xl font-black text-white group-hover:text-canina-blue transition-colors mb-2">{video.title}</h3>
<h3 className="text-xl font-black text-white group-hover:text-canino-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-1">
<User className="w-3 h-3" />
@ -173,7 +173,7 @@ export default function VideosPage() {
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="flex items-center gap-2 text-canina-blue text-xs font-black mb-2 uppercase tracking-widest">
<div className="flex items-center gap-2 text-canino-blue text-xs font-black mb-2 uppercase tracking-widest">
<ShieldCheck className="w-4 h-4" />
Verified Insight
</div>

View File

@ -8,9 +8,9 @@ describe('Footer', () => {
it('renders footer brand text and standard layout elements', () => {
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();
});
it('triggers onNavigate and onShopNavigate when quick links are clicked', () => {

View File

@ -54,7 +54,7 @@ describe('Header', () => {
/>
);
expect(screen.getByText('Canina')).toBeInTheDocument();
expect(screen.getByText('Canino')).toBeInTheDocument();
expect(screen.getByText('ایران')).toBeInTheDocument();
expect(screen.getByText('ورود / ثبت‌نام')).toBeInTheDocument();
});

View File

@ -215,7 +215,7 @@ export const PRODUCTS: Product[] = [
image: "https://images.unsplash.com/photo-1594824812397-237f41c63230?auto=format&fit=crop&q=80&w=200",
message: "خمیر ایمون بوستر با استفاده از آغوز با کیفیت دارویی، بلافاصله سیستم ایمنی غیرفعال پت را فعال می‌کند."
},
image: "https://www.canina.de/media/8c/fb/8e/311000_Canina_Immun_Booster_Paste_Abwehrkraefte_1280x1280.png"
image: "https://www.canina.de/media/8c/fb/8e/311000_Canino_Immun_Booster_Paste_Abwehrkraefte_1280x1280.png"
},
{
id: "mikrosilber-zahngel",
@ -303,7 +303,7 @@ export const PRODUCTS: Product[] = [
image: "https://images.unsplash.com/photo-1559839734-2b71f1536783?auto=format&fit=crop&q=80&w=200",
message: "فیبر سیب منبع پکتین است که به رشد باکتری‌های مفید روده کمک شایانی می‌کند."
},
image: "https://www.canina.de/media/4c/32/38/1715077271/Ballaststoff-Mix-140108-V1-Canina-100g_600x600.webp"
image: "https://www.canina.de/media/4c/32/38/1715077271/Ballaststoff-Mix-140108-V1-Canino-100g_600x600.webp"
},
{
id: "lachs-ol",
@ -346,9 +346,9 @@ export const PRODUCTS: Product[] = [
name: "دکتر ماری کونیگ",
title: "متخصص تغذیه دامپزشکی",
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_Canina_Lachsoel_Lachs_Oel_1280x1280.png"
image: "https://www.canina.de/media/6b/48/81/731000_Canino_Lachsoel_Lachs_Oel_1280x1280.png"
},
{
id: "herz-vital",
@ -386,7 +386,7 @@ export const PRODUCTS: Product[] = [
image: "https://images.unsplash.com/photo-1559839734-2b71f1536783?auto=format&fit=crop&q=80&w=200",
message: "زالزالک جریان خون کرونر را بهبود بخشیده و فشار بر قلب را کاهش می‌دهد."
},
image: "https://www.canina.de/media/73/6e/8b/1715077271/Herz-Vital-111858-V1-Canina-100ml_600x600.webp"
image: "https://www.canina.de/media/73/6e/8b/1715077271/Herz-Vital-111858-V1-Canino-100ml_600x600.webp"
},
{
id: "energy-gel",
@ -426,7 +426,7 @@ export const PRODUCTS: Product[] = [
image: "https://images.unsplash.com/photo-1559839734-2b71f1536783?auto=format&fit=crop&q=80&w=200",
message: "این ژل برای پت‌هایی که در شرایط بحرانی نیاز به کالری فوزی دارند بی‌نظیر است."
},
image: "https://www.canina.de/media/cc/e0/75/1715077271/Petvital-Energy-Gel-111452-V1-Canina-100g_600x600.webp"
image: "https://www.canina.de/media/cc/e0/75/1715077271/Petvital-Energy-Gel-111452-V1-Canino-100g_600x600.webp"
},
{
id: "moor-tranke",
@ -507,8 +507,8 @@ export const PRODUCTS: Product[] = [
name: "دکتر مونیخ",
title: "متخصص طب طبیعی دامپزشکی",
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-Canina-250ml_600x600.webp"
image: "https://www.canina.de/media/1b/83/7d/1715077272/Schwarz-Kuemmel-112503-V1-Canino-250ml_600x600.webp"
}
];

View File

@ -92,17 +92,17 @@ describe('cartStore', () => {
it('should apply discount coupon', () => {
const store = useCartStore.getState();
const success = store.applyCoupon('CANINA2024');
const success = store.applyCoupon('CANINO2024');
expect(success).toBe(true);
const state = useCartStore.getState();
expect(state.coupon).toEqual({ code: 'CANINA2024', discount: 0.1 });
expect(state.coupon).toEqual({ code: 'CANINO2024', discount: 0.1 });
});
it('should calculate subtotal, discount and total', () => {
const store = useCartStore.getState();
store.addItem(mockProduct, 2); // 2 * 1000 = 2000
store.applyCoupon('CANINA2024'); // 10% discount
store.applyCoupon('CANINO2024'); // 10% discount
expect(useCartStore.getState().getSubtotal()).toBe(2000);
expect(useCartStore.getState().getDiscount()).toBe(200);

View File

@ -33,7 +33,7 @@ describe('settingsStore', () => {
it('should fetch settings successfully and map array to object', async () => {
const mockUiTexts = [
{ key: 'hero_title', value: 'Welcome to Canina' },
{ key: 'hero_title', value: 'Welcome to Canino' },
{ key: 'hero_desc', value: 'Best supplements' },
];
const mockTerms = [
@ -54,7 +54,7 @@ describe('settingsStore', () => {
await store.fetchSettings();
const state = useSettingsStore.getState();
expect(state.texts['hero_title']).toBe('Welcome to Canina');
expect(state.texts['hero_title']).toBe('Welcome to Canino');
expect(state.texts['hero_desc']).toBe('Best supplements');
expect(state.scientificTerms['mussel']).toEqual(mockTerms[0]);
expect(state.isLoading).toBe(false);

View File

@ -165,6 +165,6 @@ export const useCartStore = create<CartStore>()(
},
getTotal: () => get().getSubtotal() - get().getDiscount() + get().charityDonation,
}),
{ name: "canina-cart" }
{ name: "canino-cart" }
)
);

View File

@ -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) });
},
}),
{ name: "canina-pets" }
{ name: "canino-pets" }
)
);

View File

@ -191,6 +191,6 @@ export const useUserStore = create<UserStore>()(
}
},
}),
{ name: "canina-user" }
{ name: "canino-user" }
)
);

View File

@ -1,6 +1,6 @@
# Application Backend Integration & Refactoring Plan
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.
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.
## User Review Required
> [!IMPORTANT]
@ -18,15 +18,15 @@ This plan details the migration of the CaninaIran frontend application from usin
### 1. Database & Backend Auth [Backend]
Adds email/password authentication capabilities and standardizes the auth endpoints.
#### [MODIFY] [schema.prisma](file:///c:/Users/parsa/Desktop/work/caninairan/backend/prisma/schema.prisma)
#### [MODIFY] [schema.prisma](file:///c:/Users/parsa/Desktop/work/caninoiran/backend/prisma/schema.prisma)
- Add `password String? @db.VarChar(255)` to the `User` model.
- Run `npx prisma migrate dev --name add_user_password`.
#### [MODIFY] [auth.controller.ts](file:///c:/Users/parsa/Desktop/work/caninairan/backend/src/auth/auth.controller.ts)
#### [MODIFY] [auth.controller.ts](file:///c:/Users/parsa/Desktop/work/caninoiran/backend/src/auth/auth.controller.ts)
- Add `@Post('register-email')` endpoint to accept `email`, `password`, `firstName`, and `lastName`.
- Add `@Post('login-email')` endpoint to accept `email` and `password`.
#### [MODIFY] [auth.service.ts](file:///c:/Users/parsa/Desktop/work/caninairan/backend/src/auth/auth.service.ts)
#### [MODIFY] [auth.service.ts](file:///c:/Users/parsa/Desktop/work/caninoiran/backend/src/auth/auth.service.ts)
- Implement `bcrypt` hashing for `registerEmail` and password verification for `loginEmail`.
- Update `sendOtp` to return the generated code in the response body (as a fallback before SMS panel is implemented) and add a `// TODO: Connect to SMS provider` comment.
@ -34,7 +34,7 @@ Adds email/password authentication capabilities and standardizes the auth endpoi
### 2. Frontend Auth (Storefront) [Frontend]
Refactors the storefront authentication modal to remove mock tests and integrate real email/password + mobile/OTP login.
#### [MODIFY] [AuthModal.tsx](file:///c:/Users/parsa/Desktop/work/caninairan/frontend/application/components/AuthModal.tsx)
#### [MODIFY] [AuthModal.tsx](file:///c:/Users/parsa/Desktop/work/caninoiran/frontend/application/components/AuthModal.tsx)
- Remove the "ورود سریع تستی" (mock login) button entirely.
- Implement two tabs: "ایمیل و رمز عبور" (Email/Password) and "شماره موبایل" (Mobile OTP).
- Wire up the Email tab to `/auth/register-email` and `/auth/login-email`.
@ -45,11 +45,11 @@ Refactors the storefront authentication modal to remove mock tests and integrate
### 3. Pet Profile Update Form [Frontend]
Resolves the issue where updating the pet profile in the multi-step form sends an incomplete payload to the backend.
#### [MODIFY] [PetProfileWizard.tsx](file:///c:/Users/parsa/Desktop/work/caninairan/frontend/application/components/PetProfileWizard.tsx)
#### [MODIFY] [PetProfileWizard.tsx](file:///c:/Users/parsa/Desktop/work/caninoiran/frontend/application/components/PetProfileWizard.tsx)
- Update the `handleComplete` or `onSubmit` function to ensure it merges the state of all wizard steps (Name, Breed, Age, Weight, Activity Level, Medical Conditions).
- Ensure the payload strictly matches what the backend `PUT /api/pets/:id` expects.
#### [MODIFY] [usePetStore.ts](file:///c:/Users/parsa/Desktop/work/caninairan/frontend/application/lib/store/usePetStore.ts)
#### [MODIFY] [usePetStore.ts](file:///c:/Users/parsa/Desktop/work/caninoiran/frontend/application/lib/store/usePetStore.ts)
- Verify `updatePet` action properly merges changes and reflects the server response.
---
@ -64,7 +64,7 @@ Currently, several sections in the Home page (`page.tsx`) rely on mock data or h
> 4. **Categories/Links:** Links to `/shop` and `/wiki` are static HTML.
> 5. **Hero Section:** Banners and text are static.
#### [MODIFY] [page.tsx](file:///c:/Users/parsa/Desktop/work/caninairan/frontend/application/app/page.tsx)
#### [MODIFY] [page.tsx](file:///c:/Users/parsa/Desktop/work/caninoiran/frontend/application/app/page.tsx)
- No immediate file changes if we just wanted the list, but we will wrap components to fetch data dynamically where applicable.
- For `SmartAdvisor`, we will ensure it uses the real database.
@ -72,7 +72,7 @@ Currently, several sections in the Home page (`page.tsx`) rely on mock data or h
### 5. Blogs/Wiki Integration [Frontend & Backend]
Connects the Wiki page to the real backend database instead of hardcoded articles.
#### [MODIFY] [wiki/page.tsx](file:///c:/Users/parsa/Desktop/work/caninairan/frontend/application/app/wiki/page.tsx)
#### [MODIFY] [wiki/page.tsx](file:///c:/Users/parsa/Desktop/work/caninoiran/frontend/application/app/wiki/page.tsx)
- Replace static blog cards with `api.get('/blogs')` or Server-Side Rendering (SSR) fetching from the database.
- Create dynamic routing `/wiki/[slug]/page.tsx` for individual blog articles.

View File

@ -1,5 +1,5 @@
{
"name": "Canina Iran - Official Representative",
"name": "Canino 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.",
"requestFramePermissions": [],
"majorCapabilities": [

View File

@ -1,5 +1,5 @@
{
"name": "caninairan-workspace",
"name": "caninoiran-workspace",
"version": "1.0.0",
"private": true,
"scripts": {

View File

@ -1,10 +1,10 @@
openapi: 3.0.0
info:
title: Canina Iran API
description: API Documentation for Canina Iran Pet Health & Supplement Platform
title: Canino Iran API
description: API Documentation for Canino Iran Pet Health & Supplement Platform
version: 1.0.0
servers:
- url: https://api.canina.ir/v1
- url: https://api.canino.ir/v1
description: Production Server
paths: