Compare commits

..

No commits in common. "5e08c8d23e7637f2fb3d8a8b43f2f10b0d1d52f8" and "b96379b88b8506ac6e576d7eae0b7c1fb1429998" have entirely different histories.

13 changed files with 148 additions and 493 deletions

View File

@ -128,7 +128,6 @@ export default function Products() {
shortDescription: product.shortDescription || '',
categoryId: product.categoryId || '',
priceValue: Number(product.priceValue),
wholesalePrice: product.wholesalePrice ? Number(product.wholesalePrice) : '',
priceDisplay: product.priceDisplay || '',
unit: product.unit || '',
packageSize: Number(product.packageSize),
@ -146,7 +145,7 @@ export default function Products() {
setEditingProduct(null);
setFormData({
artNo: '', nameFa: '', nameEn: '', scientificTagline: '', description: '', shortDescription: '', categoryId: '',
priceValue: 0, wholesalePrice: '', priceDisplay: '', unit: '', packageSize: 0, dosageLogic: '', suitableFor: 'سگ و گربه',
priceValue: 0, priceDisplay: '', unit: '', packageSize: 0, dosageLogic: '', suitableFor: 'سگ و گربه',
imageUrl: '', metaTitle: '', metaDescription: '', keywords: '', canonicalUrl: '', slug: '',
symptoms: []
});
@ -536,13 +535,6 @@ export default function Products() {
<label className="text-sm font-bold text-gray-700">قیمت (تومان) *</label>
<input required type="number" min="0" value={formData.priceValue} onChange={(e) => setFormData({...formData, priceValue: Number(e.target.value)})} className="w-full px-4 py-3 rounded-xl border border-gray-200 focus:border-purple-500 outline-none" dir="ltr" />
</div>
<div className="space-y-2">
<label className="text-sm font-bold text-purple-700 flex items-center gap-1">
<span>قیمت اختصاصی B2B (تومان)</span>
<span className="text-[10px] font-normal text-gray-400">(اختیاری)</span>
</label>
<input type="number" min="0" placeholder="در صورت عدم ورود، درصد کلی اعمال می‌شود" value={formData.wholesalePrice} onChange={(e) => setFormData({...formData, wholesalePrice: e.target.value ? Number(e.target.value) : ''})} className="w-full px-4 py-3 rounded-xl border border-purple-200 focus:border-purple-600 outline-none font-bold bg-purple-50/20" dir="ltr" />
</div>
<div className="space-y-2">
<label className="text-sm font-bold text-gray-700">نمایش قیمت (متنی) *</label>
<input required type="text" placeholder="مثال: ۸۵۰,۰۰۰ تومان" value={formData.priceDisplay} onChange={(e) => setFormData({...formData, priceDisplay: e.target.value})} className="w-full px-4 py-3 rounded-xl border border-gray-200 focus:border-purple-500 outline-none" />

View File

@ -1,5 +1,5 @@
import { useState, useEffect } from 'react';
import { Settings as SettingsIcon, Save, Truck, ShieldAlert, Percent, AlertCircle, CreditCard, Share2 } from 'lucide-react';
import { Settings as SettingsIcon, Save, Truck, ShieldAlert, Percent, AlertCircle } from 'lucide-react';
import api from '../services/api';
import Spinner from '../components/ui/Spinner';
@ -10,16 +10,6 @@ export default function Settings() {
B2B_DISCOUNT_PERCENT: '',
MAINTENANCE_MODE: 'false',
CHARITY_ROUND_STEP: '10000',
PAY_GATEWAY_CARD_ENABLE: 'true',
PAY_GATEWAY_WALLET_ENABLE: 'true',
PAY_GATEWAY_ONLINE_ENABLE: 'false',
PAY_GATEWAY_COD_ENABLE: 'false',
CONTACT_PHONE: '۰۲۱-۸۸۸۸ ۴۴۴۴',
CONTACT_EMAIL: 'info@canina-iran.com',
SOCIAL_WHATSAPP: '09120000000',
SOCIAL_INSTAGRAM: 'https://instagram.com/canina_iran',
SOCIAL_TELEGRAM: 'https://t.me/canina_iran',
CONTACT_ADDRESS: 'تهران، جردن، خیابان سعیدی، ساختمان کانینا، طبقه ۵، واحد ۱۹',
});
const [isLoading, setIsLoading] = useState(true);
const [isSaving, setIsSaving] = useState(false);
@ -35,16 +25,6 @@ export default function Settings() {
B2B_DISCOUNT_PERCENT: response.data.data.B2B_DISCOUNT_PERCENT || '0',
MAINTENANCE_MODE: response.data.data.MAINTENANCE_MODE || 'false',
CHARITY_ROUND_STEP: response.data.data.CHARITY_ROUND_STEP || '10000',
PAY_GATEWAY_CARD_ENABLE: response.data.data.PAY_GATEWAY_CARD_ENABLE || 'true',
PAY_GATEWAY_WALLET_ENABLE: response.data.data.PAY_GATEWAY_WALLET_ENABLE || 'true',
PAY_GATEWAY_ONLINE_ENABLE: response.data.data.PAY_GATEWAY_ONLINE_ENABLE || 'false',
PAY_GATEWAY_COD_ENABLE: response.data.data.PAY_GATEWAY_COD_ENABLE || 'false',
CONTACT_PHONE: response.data.data.CONTACT_PHONE || '۰۲۱-۸۸۸۸ ۴۴۴۴',
CONTACT_EMAIL: response.data.data.CONTACT_EMAIL || 'info@canina-iran.com',
SOCIAL_WHATSAPP: response.data.data.SOCIAL_WHATSAPP || '09120000000',
SOCIAL_INSTAGRAM: response.data.data.SOCIAL_INSTAGRAM || 'https://instagram.com/canina_iran',
SOCIAL_TELEGRAM: response.data.data.SOCIAL_TELEGRAM || 'https://t.me/canina_iran',
CONTACT_ADDRESS: response.data.data.CONTACT_ADDRESS || 'تهران، جردن، خیابان سعیدی، ساختمان کانینا، طبقه ۵، واحد ۱۹',
});
}
} catch (err) {
@ -159,156 +139,6 @@ export default function Settings() {
</div>
</div>
{/* Payment Gateways Settings */}
<div className="bg-white p-6 rounded-2xl shadow-sm border border-gray-200 space-y-6 lg:col-span-2">
<h3 className="text-lg font-bold text-gray-900 border-b border-gray-100 pb-4 flex items-center gap-2">
<CreditCard className="w-5 h-5 text-indigo-500" />
مدیریت روش‌های پرداخت
</h3>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div className="flex items-center justify-between p-4 bg-gray-50 rounded-xl border border-gray-200">
<div>
<h4 className="font-bold text-gray-900 text-sm">کارت به کارت (واریز مستقیم)</h4>
<p className="text-xs text-gray-500 mt-0.5">واریز به شماره کارت/شبا رسمی کانینا</p>
</div>
<label className="relative inline-flex items-center cursor-pointer">
<input
type="checkbox"
className="sr-only peer"
checked={settings.PAY_GATEWAY_CARD_ENABLE === 'true'}
onChange={(e) => setSettings({ ...settings, PAY_GATEWAY_CARD_ENABLE: e.target.checked ? 'true' : 'false' })}
/>
<div className="w-11 h-6 bg-gray-200 peer-focus:outline-none rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-purple-600"></div>
</label>
</div>
<div className="flex items-center justify-between p-4 bg-gray-50 rounded-xl border border-gray-200">
<div>
<h4 className="font-bold text-gray-900 text-sm">اعتبار حساب (کیف پول)</h4>
<p className="text-xs text-gray-500 mt-0.5">پرداخت لحظه‌ای از موجودی کیف پول کاربر</p>
</div>
<label className="relative inline-flex items-center cursor-pointer">
<input
type="checkbox"
className="sr-only peer"
checked={settings.PAY_GATEWAY_WALLET_ENABLE === 'true'}
onChange={(e) => setSettings({ ...settings, PAY_GATEWAY_WALLET_ENABLE: e.target.checked ? 'true' : 'false' })}
/>
<div className="w-11 h-6 bg-gray-200 peer-focus:outline-none rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-purple-600"></div>
</label>
</div>
<div className="flex items-center justify-between p-4 bg-gray-50 rounded-xl border border-gray-200">
<div>
<h4 className="font-bold text-gray-900 text-sm">درگاه آنلاین شتاب</h4>
<p className="text-xs text-gray-500 mt-0.5">پرداخت الکترونیک (در صورت غیرفعال بودن: برچسب به زودی)</p>
</div>
<label className="relative inline-flex items-center cursor-pointer">
<input
type="checkbox"
className="sr-only peer"
checked={settings.PAY_GATEWAY_ONLINE_ENABLE === 'true'}
onChange={(e) => setSettings({ ...settings, PAY_GATEWAY_ONLINE_ENABLE: e.target.checked ? 'true' : 'false' })}
/>
<div className="w-11 h-6 bg-gray-200 peer-focus:outline-none rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-purple-600"></div>
</label>
</div>
<div className="flex items-center justify-between p-4 bg-gray-50 rounded-xl border border-gray-200">
<div>
<h4 className="font-bold text-gray-900 text-sm">پرداخت در محل (COD)</h4>
<p className="text-xs text-gray-500 mt-0.5">پرداخت با کارتخوان هنگام تحویل (در صورت غیرفعال بودن: به زودی)</p>
</div>
<label className="relative inline-flex items-center cursor-pointer">
<input
type="checkbox"
className="sr-only peer"
checked={settings.PAY_GATEWAY_COD_ENABLE === 'true'}
onChange={(e) => setSettings({ ...settings, PAY_GATEWAY_COD_ENABLE: e.target.checked ? 'true' : 'false' })}
/>
<div className="w-11 h-6 bg-gray-200 peer-focus:outline-none rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-purple-600"></div>
</label>
</div>
</div>
</div>
{/* Social Media & Contact Info Settings */}
<div className="bg-white p-6 rounded-2xl shadow-sm border border-gray-200 space-y-6 lg:col-span-2">
<h3 className="text-lg font-bold text-gray-900 border-b border-gray-100 pb-4 flex items-center gap-2">
<Share2 className="w-5 h-5 text-blue-600" />
راه‌های ارتباطی و شبکه‌های اجتماعی
</h3>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<label className="block text-xs font-bold text-gray-700 mb-1">تلفن پشتیبانی و فروش</label>
<input
type="text"
value={settings.CONTACT_PHONE}
onChange={(e) => setSettings({ ...settings, CONTACT_PHONE: e.target.value })}
className="w-full border border-gray-200 rounded-xl p-2.5 outline-none focus:ring-2 focus:ring-purple-500 text-xs font-bold"
dir="ltr"
/>
</div>
<div>
<label className="block text-xs font-bold text-gray-700 mb-1">ایمیل رسمی پشتیبانی</label>
<input
type="text"
value={settings.CONTACT_EMAIL}
onChange={(e) => setSettings({ ...settings, CONTACT_EMAIL: e.target.value })}
className="w-full border border-gray-200 rounded-xl p-2.5 outline-none focus:ring-2 focus:ring-purple-500 text-xs font-bold"
dir="ltr"
/>
</div>
<div>
<label className="block text-xs font-bold text-gray-700 mb-1">شماره واتس‌اپ پشتیبانی</label>
<input
type="text"
value={settings.SOCIAL_WHATSAPP}
onChange={(e) => setSettings({ ...settings, SOCIAL_WHATSAPP: e.target.value })}
className="w-full border border-gray-200 rounded-xl p-2.5 outline-none focus:ring-2 focus:ring-purple-500 text-xs font-bold"
dir="ltr"
/>
</div>
<div>
<label className="block text-xs font-bold text-gray-700 mb-1">لینک پیج اینستاگرام</label>
<input
type="text"
value={settings.SOCIAL_INSTAGRAM}
onChange={(e) => setSettings({ ...settings, SOCIAL_INSTAGRAM: e.target.value })}
className="w-full border border-gray-200 rounded-xl p-2.5 outline-none focus:ring-2 focus:ring-purple-500 text-xs font-bold"
dir="ltr"
/>
</div>
<div>
<label className="block text-xs font-bold text-gray-700 mb-1">کانال تلگرام</label>
<input
type="text"
value={settings.SOCIAL_TELEGRAM}
onChange={(e) => setSettings({ ...settings, SOCIAL_TELEGRAM: e.target.value })}
className="w-full border border-gray-200 rounded-xl p-2.5 outline-none focus:ring-2 focus:ring-purple-500 text-xs font-bold"
dir="ltr"
/>
</div>
<div>
<label className="block text-xs font-bold text-gray-700 mb-1">آدرس دفتر مرکزی</label>
<input
type="text"
value={settings.CONTACT_ADDRESS}
onChange={(e) => setSettings({ ...settings, CONTACT_ADDRESS: e.target.value })}
className="w-full border border-gray-200 rounded-xl p-2.5 outline-none focus:ring-2 focus:ring-purple-500 text-xs font-bold"
dir="rtl"
/>
</div>
</div>
</div>
{/* System Settings */}
<div className="bg-white p-6 rounded-2xl shadow-sm border border-gray-200 space-y-6 lg:col-span-2">
<h3 className="text-lg font-bold text-gray-900 border-b border-gray-100 pb-4 flex items-center gap-2">

View File

@ -137,11 +137,6 @@
}
}
/* Sonner Toasts Vazirmatn Font */
[data-sonner-toaster] {
font-family: "Vazirmatn", sans-serif !important;
}
/* Custom scrollbar for a professional look */
::-webkit-scrollbar {
width: 6px;

View File

@ -1,6 +1,8 @@
import React from 'react';
import { Metadata } from 'next';
import EnamadBadge from '@/components/EnamadBadge';
import Header from '@/components/Header';
import Footer from '@/components/Footer';
import { ShieldCheck, Award, FileCheck, CheckCircle2, Building2, ExternalLink } from 'lucide-react';
export const metadata: Metadata = {
@ -45,7 +47,9 @@ export default function TrustSealsPage() {
];
return (
<div className="bg-slate-50 flex flex-col font-vazir">
<div className="min-h-screen bg-slate-50 flex flex-col font-vazir">
<Header />
<main className="flex-1 max-w-7xl w-full mx-auto px-4 sm:px-6 lg:px-8 py-12">
{/* Banner Section */}
<div className="relative bg-gradient-to-r from-teal-700 via-teal-600 to-emerald-700 rounded-3xl p-8 md:p-12 text-white shadow-xl overflow-hidden mb-12">
@ -125,6 +129,8 @@ export default function TrustSealsPage() {
</div>
</section>
</main>
<Footer />
</div>
);
}

View File

@ -5,7 +5,6 @@ import { X, MapPin, User, Phone, Hash, Save, Check } from "lucide-react";
import { toPersian, cn } from "../lib/utils";
import { Address } from "../lib/store/userStore";
import { IRAN_PROVINCES, PROVINCE_CITIES } from "../lib/data/provinces";
import SearchableSelect from "./SearchableSelect";
import { toast } from "sonner";
interface AddressModalProps {
@ -207,13 +206,12 @@ export default function AddressModal({ isOpen, onClose, onSave, editingAddress }
{/* Row 3: Province & City */}
<div className="space-y-1">
<label htmlFor="addr-province" className="text-[10px] font-black text-medical-gray-400 uppercase tracking-widest block pr-2">استان</label>
<SearchableSelect
<select
id="addr-province"
options={IRAN_PROVINCES}
name="address-level1"
value={formData.province}
placeholder="انتخاب استان..."
searchPlaceholder="جستجوی استان..."
onChange={(newProv) => {
onChange={e => {
const newProv = e.target.value;
const cities = PROVINCE_CITIES[newProv] || [];
setFormData({
...formData,
@ -221,21 +219,31 @@ export default function AddressModal({ isOpen, onClose, onSave, editingAddress }
city: cities[0] || ""
});
}}
/>
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 bg-white", errors.province ? "border-red-300" : "border-medical-gray-100")}
>
<option value="">انتخاب استان...</option>
{IRAN_PROVINCES.map(prov => (
<option key={prov} value={prov}>{prov}</option>
))}
</select>
{errors.province && <p className="text-[10px] text-red-500 font-bold pr-2">{errors.province}</p>}
</div>
<div className="space-y-1">
<label htmlFor="addr-city" className="text-[10px] font-black text-medical-gray-400 uppercase tracking-widest block pr-2">شهر</label>
{formData.province && PROVINCE_CITIES[formData.province] ? (
<SearchableSelect
<select
id="addr-city"
options={PROVINCE_CITIES[formData.province]}
name="address-level2"
value={formData.city}
placeholder="انتخاب شهر..."
searchPlaceholder="جستجوی شهر..."
onChange={(c) => setFormData({...formData, city: c})}
/>
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 bg-white", errors.city ? "border-red-300" : "border-medical-gray-100")}
>
<option value="">انتخاب شهر...</option>
{PROVINCE_CITIES[formData.province].map(c => (
<option key={c} value={c}>{c}</option>
))}
</select>
) : (
<input
id="addr-city"

View File

@ -3,7 +3,6 @@ import React, { useState, useEffect } from "react";
import { Product } from "../lib/data/products";
import { useCartStore } from "../lib/store/cartStore";
import { useUserStore } from "../lib/store/userStore";
import { useSettingsStore } from "../lib/store/settingsStore";
import { productService } from "../lib/services/productService";
import { motion, AnimatePresence } from "motion/react";
import {
@ -128,29 +127,27 @@ export default function B2BPortal({ onClose }: { onClose: () => void }) {
</p>
{!isWholesaleVerified && (
<div className="bg-white/10 p-4 rounded-2xl border border-white/20 mt-4 font-vazir">
<h4 className="text-xs font-black mb-2 text-amber-300">درخواست مشاوره و عضویت همکار B2B</h4>
<p className="text-[11px] text-white/80 mb-3 leading-relaxed">
جهت دریافت شرایط همکاری و فعال‌سازی دسترسی خرید عمده، شماره تماس خود را وارد کنید تا کارشناسان فروش با شما تماس بگیرند.
</p>
<div className="bg-white/10 p-4 rounded-2xl border border-white/20 mt-4">
<h4 className="text-xs font-black mb-2 text-amber-300">درخواست تایید حساب همکار</h4>
<p className="text-[11px] text-white/80 mb-3">جهت مشاهده و خرید با قیمت عمده، شماره پروانه نظام دامپزشکی خود را وارد کنید.</p>
<form onSubmit={async (e) => {
e.preventDefault();
const form = e.target as HTMLFormElement;
const bName = (form.elements.namedItem('bName') as HTMLInputElement).value;
const phone = (form.elements.namedItem('phone') as HTMLInputElement).value;
const lNum = (form.elements.namedItem('lNum') as HTMLInputElement).value;
try {
const api = (await import('../lib/services/api')).default;
await api.post('/wholesale/apply', { businessName: bName, licenseNumber: phone });
alert('درخواست شما با موفقیت ثبت شد. کارشناسان پشتیبانی B2B کانینا به زودی جهت تایید تلفنی با شما تماس خواهند گرفت.');
await api.post('/wholesale/apply', { businessName: bName, licenseNumber: lNum });
alert('درخواست ثبت‌نام همکار با موفقیت ارسال شد و به زودی توسط ادمین تایید می‌شود.');
form.reset();
} catch (err) {
alert('خطا در ثبت درخواست. لطفاً دوباره تلاش کنید.');
alert('لطفاً ابتدا وارد حساب کاربری خود شوید.');
}
}} className="space-y-2">
<input name="bName" required placeholder="نام مجموعه / کلینیک / داروخانه" className="w-full bg-white/20 text-white text-xs px-3 py-2.5 rounded-xl outline-none placeholder:text-white/50" />
<input name="phone" required type="tel" placeholder="شماره تماس همراه" className="w-full bg-white/20 text-white text-xs px-3 py-2.5 rounded-xl outline-none placeholder:text-white/50 dir-ltr text-right" />
<button type="submit" className="w-full bg-amber-400 hover:bg-amber-500 text-gray-900 font-black text-xs py-2.5 rounded-xl transition-colors">
ثبت درخواست تماس و تایید B2B
<input name="bName" required placeholder="نام کلینیک / داروخانه" className="w-full bg-white/20 text-white text-xs px-3 py-2 rounded-xl outline-none placeholder:text-white/50" />
<input name="lNum" required placeholder="شماره پروانه / نظام" className="w-full bg-white/20 text-white text-xs px-3 py-2 rounded-xl outline-none placeholder:text-white/50" />
<button type="submit" className="w-full bg-amber-400 hover:bg-amber-500 text-gray-900 font-black text-xs py-2 rounded-xl transition-colors">
ثبت درخواست همکار
</button>
</form>
</div>
@ -212,11 +209,7 @@ export default function B2BPortal({ onClose }: { onClose: () => void }) {
<tbody className="divide-y divide-medical-gray-100">
{filteredProducts.map(product => {
const basePrice = product.priceValue || 0;
// Priority 1: Specific product wholesalePrice, Priority 2: General settings percentage discount (default 30%)
const wholesaleDiscountPercent = Number(useSettingsStore.getState().getText('B2B_DISCOUNT_PERCENT', '30')) || 30;
const wholesalePrice = (product as any).wholesalePrice
? Number((product as any).wholesalePrice)
: Math.round(basePrice * (1 - wholesaleDiscountPercent / 100));
const wholesalePrice = basePrice * 0.7; // 30% discount
return (
<tr key={product.id} className="hover:bg-medical-gray-50/50 transition-colors">
<td className="px-6 py-4">

View File

@ -51,18 +51,6 @@ export default function CartDrawer({ isOpen, onClose, onCheckout, onShopNavigate
}
}, [hasLachsOl, hasCanhydrox]);
// Lock background body scroll when cart drawer is open
useEffect(() => {
if (isOpen) {
document.body.style.overflow = "hidden";
} else {
document.body.style.overflow = "unset";
}
return () => {
document.body.style.overflow = "unset";
};
}, [isOpen]);
return (
<AnimatePresence>
{isOpen && (

View File

@ -26,7 +26,6 @@ import { useSettingsStore } from "../lib/store/settingsStore";
import { productService } from "../lib/services/productService";
import TopUpModal from "./TopUpModal";
import AddressModal from "./AddressModal";
import SearchableSelect from "./SearchableSelect";
import { IRAN_PROVINCES, PROVINCE_CITIES } from "../lib/data/provinces";
import { toast } from "sonner";
import { useRouter } from 'next/navigation';
@ -51,7 +50,6 @@ export default function CheckoutPage() {
const [manualPhone, setManualPhone] = useState('');
const [manualProvince, setManualProvince] = useState('');
const [manualCity, setManualCity] = useState('');
const [manualZipCode, setManualZipCode] = useState('');
const [manualAddress, setManualAddress] = useState('');
const handleCopy = (text: string, title: string) => {
@ -122,10 +120,10 @@ export default function CheckoutPage() {
const selectedAddr = profile.addresses?.find(a => a.id === selectedAddressId);
let shippingAddressStr = '';
if (selectedAddr) {
shippingAddressStr = `${selectedAddr.province}، ${selectedAddr.city}، ${selectedAddr.detail}${selectedAddr.zipCode ? ` (کد پستی: ${selectedAddr.zipCode})` : ''} (گیرنده: ${selectedAddr.receptorName} - ${toPersian(selectedAddr.phone)})`;
shippingAddressStr = `${selectedAddr.province}، ${selectedAddr.city}، ${selectedAddr.detail} (گیرنده: ${selectedAddr.receptorName} - ${toPersian(selectedAddr.phone)})`;
} else if (manualAddress) {
const provCity = [manualProvince, manualCity].filter(Boolean).join('، ');
shippingAddressStr = `${provCity ? provCity + '، ' : ''}${manualAddress}${manualZipCode ? ` (کد پستی: ${manualZipCode})` : ''}${manualName ? ` (گیرنده: ${manualName}${manualPhone ? ` - ${toPersian(manualPhone)}` : ''})` : ''}`;
shippingAddressStr = `${provCity ? provCity + '، ' : ''}${manualAddress}${manualName ? ` (گیرنده: ${manualName}${manualPhone ? ` - ${toPersian(manualPhone)}` : ''})` : ''}`;
}
const orderId = await addOrder({
@ -316,30 +314,37 @@ export default function CheckoutPage() {
</div>
<div className="space-y-2">
<label htmlFor="chk-province" className="text-[10px] font-black text-medical-gray-400 uppercase tracking-widest block">استان *</label>
<SearchableSelect
<select
id="chk-province"
options={IRAN_PROVINCES}
value={manualProvince}
placeholder="انتخاب استان..."
searchPlaceholder="جستجوی استان..."
onChange={(prov) => {
onChange={(e) => {
const prov = e.target.value;
const cities = PROVINCE_CITIES[prov] || [];
setManualProvince(prov);
setManualCity(cities[0] || '');
}}
/>
className="w-full bg-white border border-medical-gray-200 rounded-2xl py-3 sm:py-4 px-4 sm:px-6 text-xs sm:text-sm focus:outline-none focus:ring-2 focus:ring-canina-blue/20 font-bold"
>
<option value="">انتخاب استان...</option>
{IRAN_PROVINCES.map((prov) => (
<option key={prov} value={prov}>{prov}</option>
))}
</select>
</div>
<div className="space-y-2">
<label htmlFor="chk-city" className="text-[10px] font-black text-medical-gray-400 uppercase tracking-widest block">شهر *</label>
{manualProvince && PROVINCE_CITIES[manualProvince] ? (
<SearchableSelect
<select
id="chk-city"
options={PROVINCE_CITIES[manualProvince]}
value={manualCity}
placeholder="انتخاب شهر..."
searchPlaceholder="جستجوی شهر..."
onChange={(c) => setManualCity(c)}
/>
onChange={(e) => setManualCity(e.target.value)}
className="w-full bg-white border border-medical-gray-200 rounded-2xl py-3 sm:py-4 px-4 sm:px-6 text-xs sm:text-sm focus:outline-none focus:ring-2 focus:ring-canina-blue/20 font-bold"
>
<option value="">انتخاب شهر...</option>
{PROVINCE_CITIES[manualProvince].map((c) => (
<option key={c} value={c}>{c}</option>
))}
</select>
) : (
<input
id="chk-city"
@ -363,18 +368,6 @@ export default function CheckoutPage() {
placeholder="خیابان، کوچه، پلاک، واحد..."
/>
</div>
<div className="md:col-span-2 space-y-2">
<label htmlFor="chk-zipcode" className="text-[10px] font-black text-medical-gray-400 uppercase tracking-widest block">کد پستی ۱۰ رقمی</label>
<input
id="chk-zipcode"
type="text"
maxLength={10}
value={manualZipCode}
onChange={(e) => setManualZipCode(e.target.value.replace(/[^0-9]/g, ''))}
className="w-full bg-medical-gray-50 border border-medical-gray-200 rounded-2xl py-3 sm:py-4 px-4 sm:px-6 text-xs sm:text-sm focus:outline-none focus:ring-2 focus:ring-canina-blue/20 dir-ltr text-right"
placeholder="۱۲۳۴۵۶۷۸۹۰"
/>
</div>
</div>
</div>
)}
@ -389,80 +382,40 @@ export default function CheckoutPage() {
</div>
<div className="grid grid-cols-1 sm:grid-cols-2 gap-3 sm:gap-4">
{(() => {
const getText = useSettingsStore.getState().getText;
const allGateways = [
{[
{
id: 'card',
label: getText('PAY_GATEWAY_CARD_LABEL', 'کارت به کارت (واریز مستقیم)'),
desc: getText('PAY_GATEWAY_CARD_DESC', 'واریز به شماره کارت بانک سامان'),
icon: <CreditCard className="w-5 h-5 sm:w-6 sm:h-6" />,
enabled: getText('PAY_GATEWAY_CARD_ENABLE', 'true') === 'true'
label: 'کارت به کارت (واریز مستقیم)',
desc: 'واریز به شماره کارت بانک سامان',
icon: <CreditCard className="w-5 h-5 sm:w-6 sm:h-6" />
},
{
id: 'wallet',
label: getText('PAY_GATEWAY_WALLET_LABEL', 'اعتبار حساب (کیف پول)'),
label: 'اعتبار حساب (کیف پول)',
desc: `موجودی: ${toPersian((profile.walletBalance || 0).toLocaleString())} تومان`,
icon: <Wallet className="w-5 h-5 sm:w-6 sm:h-6" />,
enabled: getText('PAY_GATEWAY_WALLET_ENABLE', 'true') === 'true'
},
{
id: 'online',
label: getText('PAY_GATEWAY_ONLINE_LABEL', 'درگاه پرداخت آنلاین (شتاب)'),
desc: getText('PAY_GATEWAY_ONLINE_DESC', 'پرداخت مستقیم با کلیه کارت‌های شتاب'),
icon: <ShieldCheck className="w-5 h-5 sm:w-6 sm:h-6" />,
enabled: getText('PAY_GATEWAY_ONLINE_ENABLE', 'false') === 'true'
},
{
id: 'cod',
label: getText('PAY_GATEWAY_COD_LABEL', 'پرداخت در محل (کارتخوان)'),
desc: getText('PAY_GATEWAY_COD_DESC', 'تحویل کالا و پرداخت درب منزل'),
icon: <Truck className="w-5 h-5 sm:w-6 sm:h-6" />,
enabled: getText('PAY_GATEWAY_COD_ENABLE', 'false') === 'true'
icon: <Wallet className="w-5 h-5 sm:w-6 sm:h-6" />
}
];
const sortedGateways = [...allGateways].sort((a, b) => (b.enabled ? 1 : 0) - (a.enabled ? 1 : 0));
return sortedGateways.map((pay) => (
].map((pay) => (
<div
key={pay.id}
onClick={() => {
if (pay.enabled) {
setPaymentMethod(pay.id);
} else {
toast.info("این روش پرداخت به زودی فعال خواهد شد.");
}
}}
className={cn(
"p-4 sm:p-6 rounded-2xl sm:rounded-3xl border-2 transition-all group flex sm:flex-col items-center sm:items-start gap-4 sm:gap-0 relative",
pay.enabled
? (paymentMethod === pay.id ? "border-canina-blue bg-canina-blue/5 cursor-pointer" : "border-medical-gray-100 hover:border-canina-blue cursor-pointer")
: "border-medical-gray-100 bg-medical-gray-50/60 opacity-60 cursor-not-allowed"
)}
onClick={() => setPaymentMethod(pay.id)}
className={cn("p-4 sm:p-6 rounded-2xl sm:rounded-3xl border-2 cursor-pointer transition-all group flex sm:flex-col items-center sm:items-start gap-4 sm:gap-0 relative", paymentMethod === pay.id ? "border-canina-blue bg-canina-blue/5" : "border-medical-gray-100 hover:border-canina-blue")}
>
<div className="w-10 h-10 sm:w-12 sm:h-12 bg-medical-gray-50 rounded-xl sm:rounded-2xl flex items-center justify-center text-medical-gray-400 group-hover:text-canina-blue group-hover:bg-canina-blue/10 sm:mb-4 transition-all flex-shrink-0">
{pay.icon}
</div>
<div className="min-w-0 flex-1 w-full">
<div className="flex items-center justify-between gap-2 mb-0.5 sm:mb-1">
<h4 className="font-black text-xs sm:text-sm text-medical-gray-900 truncate">{pay.label}</h4>
{!pay.enabled && (
<span className="text-[9px] font-black bg-amber-100 text-amber-800 px-2 py-0.5 rounded-full shrink-0 font-vazir">
به زودی
</span>
)}
</div>
<div className="min-w-0 flex-1">
<h4 className="font-black text-xs sm:text-sm text-medical-gray-900 mb-0.5 sm:mb-1 truncate">{pay.label}</h4>
<div className="flex items-center justify-between gap-2">
<p className={cn("text-[10px] font-bold truncate", pay.id === 'wallet' ? "text-canina-blue" : "text-medical-gray-400")}>{pay.desc}</p>
{pay.id === 'wallet' && pay.enabled && (profile.walletBalance || 0) === 0 && (
{pay.id === 'wallet' && (profile.walletBalance || 0) === 0 && (
<button
type="button"
onClick={(e) => {
e.stopPropagation();
setShowTopUpModal(true);
}}
className="text-[10px] bg-canina-blue text-white px-2 py-0.5 rounded-lg font-bold hover:bg-blue-700 transition-colors flex items-center gap-1 shrink-0 font-vazir"
className="text-[10px] bg-canina-blue text-white px-2 py-0.5 rounded-lg font-bold hover:bg-blue-700 transition-colors flex items-center gap-1"
>
<PlusCircle className="w-3 h-3" />
<span>افزایش موجودی</span>
@ -471,8 +424,7 @@ export default function CheckoutPage() {
</div>
</div>
</div>
));
})()}
))}
</div>
{paymentMethod === 'card' && (

View File

@ -134,7 +134,7 @@ export default function Footer({
</div>
<div>
<p className="text-[11px] text-slate-400 font-extrabold uppercase mb-1">{getText('footer_phone_label', "خط ویژه فروش")}</p>
<p className="text-lg font-extrabold tracking-widest text-left text-slate-200" dir="ltr">{getText('CONTACT_PHONE', getText('footer_phone', "۰۲۱-۸۸۸۸ ۴۴۴۴"))}</p>
<p className="text-lg font-extrabold tracking-widest text-left text-slate-200" dir="ltr">{getText('footer_phone', "۰۲۱-۸۸۸۸ ۴۴۴۴")}</p>
</div>
</div>
<div className="flex gap-4 group">
@ -143,7 +143,7 @@ export default function Footer({
</div>
<div>
<p className="text-[11px] text-slate-400 font-extrabold uppercase mb-1">{getText('footer_email_label', "مکاتبات رسمی")}</p>
<p className="text-sm font-bold text-slate-300">{getText('CONTACT_EMAIL', getText('footer_email', "info@canina-iran.com"))}</p>
<p className="text-sm font-bold text-slate-300">{getText('footer_email', "info@canina-iran.com")}</p>
</div>
</div>
</div>
@ -154,7 +154,7 @@ export default function Footer({
</div>
<div>
<p className="text-[11px] text-slate-400 font-extrabold uppercase mb-1">{getText('footer_address_label', "دفتر مرکزی")}</p>
<p className="text-sm font-bold leading-relaxed text-slate-300">{getText('CONTACT_ADDRESS', getText('footer_address', "تهران، جردن، خیابان سعیدی، ساختمان کانینا، طبقه ۵، واحد ۱۹"))}</p>
<p className="text-sm font-bold leading-relaxed text-slate-300">{getText('footer_address', "تهران، جردن، خیابان سعیدی، ساختمان کانینا، طبقه ۵، واحد ۱۹")}</p>
</div>
</div>
</div>

View File

@ -152,16 +152,16 @@ export default function Header({
{isMobileMenuOpen ? <X className="w-6 h-6" /> : <Menu className="w-6 h-6" />}
</button>
<Link href="/" className="flex items-center gap-2 sm:gap-3 group shrink-0 min-w-0">
<div className="w-10 h-10 sm:w-12 sm:h-12 min-w-[40px] min-h-[40px] sm:min-w-[48px] sm:min-h-[48px] bg-canina-blue rounded-2xl flex items-center justify-center text-white font-bold text-xl sm:text-2xl group-hover:bg-medical-gray-900 transition-all shadow-md italic shrink-0">C</div>
<div className="flex flex-col justify-center min-w-0">
<span className="text-canina-blue font-black text-base sm:text-2xl tracking-tighter italic font-sans flex items-center gap-1 leading-none truncate">
<Link href="/" className="flex items-center gap-3 group">
<div className="w-10 h-10 sm:w-12 sm:h-12 bg-canina-blue rounded-2xl flex items-center justify-center text-white font-bold text-xl sm:text-2xl group-hover:bg-medical-gray-900 transition-all shadow-md italic">C</div>
<div className="flex flex-col justify-center">
<span className="text-canina-blue font-black text-lg sm:text-2xl tracking-tighter italic font-sans flex items-center gap-1 leading-none">
Canina
<span className="text-[11px] sm:text-sm not-italic font-medium border-r border-medical-gray-300 pr-1.5 font-vazir text-medical-gray-700">
<span className="text-xs sm:text-sm not-italic font-medium border-r border-medical-gray-300 pr-1.5 font-vazir text-medical-gray-700">
{getText('brand_name_fa', "ایران")}
</span>
</span>
<span className="hidden sm:block text-[9px] text-medical-gray-400 font-bold uppercase tracking-wider leading-tight mt-0.5 truncate">
<span className="text-[9px] text-medical-gray-400 font-bold uppercase tracking-wider leading-tight mt-0.5">
نماینده رسمی CANINA PHARMA GMBH GERMANY
</span>
</div>
@ -185,7 +185,7 @@ export default function Header({
</div>
{/* Left Action Buttons */}
<div className="flex items-center gap-1.5 sm:gap-3 shrink-0">
<div className="flex items-center gap-2 sm:gap-3">
{/* Prescription Upload Button */}
<button
onClick={() => setIsPrescriptionModalOpen(true)}
@ -199,8 +199,7 @@ export default function Header({
{isLoggedIn ? (
<Link
href="/dashboard"
className="flex items-center justify-center p-2.5 sm:px-3 sm:py-2 bg-medical-gray-50 hover:bg-medical-gray-100 border border-medical-gray-200 rounded-xl text-xs font-black text-medical-gray-900 transition-all"
title="حساب کاربری"
className="flex items-center gap-2 px-3 py-2 bg-medical-gray-50 hover:bg-medical-gray-100 border border-medical-gray-200 rounded-xl text-xs font-black text-medical-gray-900 transition-all"
>
<User className="w-4 h-4 text-canina-blue" />
<span className="hidden sm:inline">{profile.firstName || 'حساب کاربری'}</span>
@ -208,11 +207,10 @@ export default function Header({
) : (
<button
onClick={() => setIsAuthModalOpen(true)}
className="flex items-center gap-1.5 px-2.5 py-2 sm:px-3.5 sm:py-2 bg-medical-gray-900 text-white hover:bg-canina-blue rounded-xl text-[11px] sm:text-xs font-black transition-all shadow-xs whitespace-nowrap"
className="flex items-center gap-2 px-3.5 py-2 bg-medical-gray-900 text-white hover:bg-canina-blue rounded-xl text-xs font-black transition-all shadow-xs"
>
<LogIn className="w-4 h-4 shrink-0" />
<span className="hidden xs:inline sm:inline">ورود / ثبت‌نام</span>
<span className="xs:hidden sm:hidden">ورود</span>
<LogIn className="w-4 h-4" />
<span>ورود / ثبت‌نام</span>
</button>
)}
@ -372,15 +370,11 @@ export default function Header({
<ChevronDown className="w-3.5 h-3.5" />
</button>
{activeDropdown === 'company' && (
<div className="absolute top-full right-0 w-60 bg-white border border-medical-gray-200 shadow-xl rounded-xl p-2 z-50 space-y-1 text-xs">
<div className="absolute top-full right-0 w-56 bg-white border border-medical-gray-200 shadow-xl rounded-xl p-2 z-50 space-y-1 text-xs">
<Link href="/about" className="flex items-center gap-2 px-3 py-2 hover:bg-canina-blue/5 hover:text-canina-blue rounded-lg font-bold">
<Award className="w-4 h-4 text-canina-blue" />
درباره کمپانی کانینا آلمان
</Link>
<Link href="/trust-seals" className="flex items-center gap-2 px-3 py-2 hover:bg-canina-blue/5 hover:text-canina-blue rounded-lg font-bold text-emerald-600">
<ShieldCheck className="w-4 h-4 text-emerald-600" />
نمادهای اعتماد و مجوزهای رسمی
</Link>
<button
onClick={onB2BOpen}
className="w-full text-right flex items-center gap-2 px-3 py-2 hover:bg-canina-blue/5 hover:text-canina-blue rounded-lg font-bold"

View File

@ -185,16 +185,16 @@ export default function ProductPage({ productSlug }: { productSlug: string }) {
<div className="min-h-screen bg-medical-gray-50 pt-2 pb-36 sm:pb-20 px-4 sm:px-6 lg:px-8 font-vazir" dir="rtl">
<div className="max-w-7xl mx-auto w-full">
{/* Standard Breadcrumb Navigation & Integrated Back Button */}
<div className="flex flex-col sm:flex-row items-stretch sm:items-center justify-between gap-4 mb-8 pb-4 border-b border-medical-gray-200/60 font-vazir" dir="rtl">
<div className="flex items-center gap-2 text-xs font-bold text-medical-gray-400 overflow-x-auto py-1 sleek-hscroll">
<span className="cursor-pointer hover:text-canina-blue transition-colors shrink-0" onClick={() => router.push('/')}>خانه</span>
<ChevronLeft className="w-3 h-3 text-medical-gray-300 shrink-0" />
<span className="cursor-pointer hover:text-canina-blue transition-colors shrink-0" onClick={() => router.push('/shop')}>فروشگاه</span>
<ChevronLeft className="w-3 h-3 text-medical-gray-300 shrink-0" />
<span className="text-canina-blue font-black truncate">{product.nameFa || product.name}</span>
<div className="flex items-center justify-between mb-8 pb-4 border-b border-medical-gray-200/60 font-vazir" dir="rtl">
<div className="flex items-center gap-2 text-xs font-bold text-medical-gray-400 whitespace-nowrap">
<span className="cursor-pointer hover:text-canina-blue transition-colors" onClick={() => router.push('/')}>خانه</span>
<ChevronLeft className="w-3 h-3 text-medical-gray-300" />
<span className="cursor-pointer hover:text-canina-blue transition-colors" onClick={() => router.push('/shop')}>فروشگاه</span>
<ChevronLeft className="w-3 h-3 text-medical-gray-300" />
<span className="text-canina-blue font-black">{product.nameFa || product.name}</span>
</div>
<div className="flex items-center justify-end gap-2 shrink-0">
<div className="flex items-center gap-2">
<button
onClick={() => {
if (typeof window !== 'undefined' && navigator.clipboard) {
@ -202,14 +202,14 @@ export default function ProductPage({ productSlug }: { productSlug: string }) {
toast.success("لینک مشخصات و دوز دارویی محصول کپی شد");
}
}}
className="flex-1 sm:flex-none px-3.5 py-2 bg-canina-blue/5 border border-canina-blue/20 rounded-xl text-canina-blue shadow-xs flex items-center justify-center gap-1.5 font-bold text-xs hover:bg-canina-blue hover:text-white transition-all whitespace-nowrap"
className="px-3.5 py-1.5 bg-canina-blue/5 border border-canina-blue/20 rounded-lg text-canina-blue shadow-xs flex items-center gap-1.5 font-bold text-xs hover:bg-canina-blue hover:text-white transition-all whitespace-nowrap"
>
<Share2 className="w-3.5 h-3.5" />
<span>اشتراک‌گذاری دوز</span>
</button>
<button
onClick={() => router.back()}
className="flex-1 sm:flex-none px-3.5 py-2 bg-white border border-medical-gray-200 rounded-xl text-medical-gray-600 shadow-xs flex items-center justify-center gap-1.5 font-bold text-xs hover:border-canina-blue hover:text-canina-blue transition-all whitespace-nowrap"
className="px-3.5 py-1.5 bg-white border border-medical-gray-200 rounded-lg text-medical-gray-600 shadow-xs flex items-center gap-1.5 font-bold text-xs hover:border-canina-blue hover:text-canina-blue transition-all whitespace-nowrap"
>
<ChevronRight className="w-3.5 h-3.5" />
<span>بازگشت</span>

View File

@ -26,13 +26,24 @@ export default function SafeImage({
if (!src || error) {
return (
<div className={cn(
"flex flex-col items-center justify-center bg-medical-gray-50/80 border border-medical-gray-100 p-1.5 text-center w-full h-full rounded-2xl relative overflow-hidden select-none",
"flex flex-col items-center justify-center bg-white border border-medical-gray-100 p-4 text-center min-h-[120px] rounded-3xl shadow-inner relative overflow-hidden",
className
)}>
<div className="w-8 h-8 sm:w-10 sm:h-10 bg-canina-blue rounded-xl flex items-center justify-center text-white font-black text-base sm:text-lg shadow-sm italic shrink-0">
C
{/* Subtle Brand Pattern Background */}
<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>
<span className="text-[8px] font-black text-canina-blue/70 font-vazir leading-tight mt-1 line-clamp-1">
</div>
<div className="w-16 h-16 bg-canina-blue rounded-2xl flex items-center justify-center text-white font-black text-3xl mb-4 shadow-xl shadow-canina-blue/20 italic transform -rotate-6">C</div>
<div className="relative">
<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" />
</div>
<span className="text-[9px] font-black text-canina-blue/60 uppercase tracking-[0.2em] font-vazir leading-relaxed">
{fallbackText}
</span>
</div>

View File

@ -1,114 +0,0 @@
"use client";
import React, { useState, useRef, useEffect } from "react";
import { ChevronDown, Search, X } from "lucide-react";
import { cn } from "../lib/utils";
interface SearchableSelectProps {
id?: string;
options: string[];
value: string;
onChange: (value: string) => void;
placeholder?: string;
searchPlaceholder?: string;
disabled?: boolean;
className?: string;
}
export default function SearchableSelect({
id,
options,
value,
onChange,
placeholder = "انتخاب کنید...",
searchPlaceholder = "جستجو...",
disabled = false,
className
}: SearchableSelectProps) {
const [isOpen, setIsOpen] = useState(false);
const [searchQuery, setSearchQuery] = useState("");
const containerRef = useRef<HTMLDivElement>(null);
useEffect(() => {
const handleClickOutside = (e: MouseEvent) => {
if (containerRef.current && !containerRef.current.contains(e.target as Node)) {
setIsOpen(false);
}
};
document.addEventListener("mousedown", handleClickOutside);
return () => document.removeEventListener("mousedown", handleClickOutside);
}, []);
const filteredOptions = options.filter(opt =>
opt.toLowerCase().includes(searchQuery.toLowerCase())
);
return (
<div ref={containerRef} className={cn("relative w-full", className)}>
<button
id={id}
type="button"
disabled={disabled}
onClick={() => setIsOpen(!isOpen)}
className={cn(
"w-full bg-white border border-medical-gray-200 rounded-2xl py-3 px-4 text-xs sm:text-sm font-bold flex items-center justify-between transition-all outline-none focus:ring-2 focus:ring-canina-blue/20",
disabled && "bg-medical-gray-50 opacity-60 cursor-not-allowed",
value ? "text-medical-gray-900" : "text-medical-gray-400"
)}
>
<span className="truncate">{value || placeholder}</span>
<ChevronDown className={cn("w-4 h-4 text-medical-gray-400 transition-transform", isOpen && "rotate-180")} />
</button>
{isOpen && (
<div className="absolute z-50 top-full left-0 right-0 mt-1 bg-white border border-medical-gray-200 rounded-2xl shadow-xl overflow-hidden max-h-60 flex flex-col font-vazir animate-in fade-in slide-in-from-top-2 duration-150">
<div className="p-2 border-b border-medical-gray-100 relative flex items-center">
<Search className="w-3.5 h-3.5 text-medical-gray-400 absolute right-4" />
<input
type="text"
autoFocus
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}
placeholder={searchPlaceholder}
className="w-full bg-medical-gray-50 border border-medical-gray-200 rounded-xl py-1.5 pr-8 pl-3 text-xs font-bold text-medical-gray-900 outline-none focus:border-canina-blue"
/>
{searchQuery && (
<button
type="button"
onClick={() => setSearchQuery("")}
className="absolute left-4 text-medical-gray-400 hover:text-medical-gray-600"
>
<X className="w-3 h-3" />
</button>
)}
</div>
<div className="overflow-y-auto flex-1 p-1">
{filteredOptions.length === 0 ? (
<div className="p-3 text-center text-xs text-medical-gray-400 font-bold">
موردی یافت نشد
</div>
) : (
filteredOptions.map((opt) => (
<button
key={opt}
type="button"
onClick={() => {
onChange(opt);
setIsOpen(false);
setSearchQuery("");
}}
className={cn(
"w-full text-right px-3 py-2 rounded-xl text-xs font-bold transition-colors flex items-center justify-between",
value === opt ? "bg-canina-blue/10 text-canina-blue" : "hover:bg-medical-gray-50 text-medical-gray-700"
)}
>
<span>{opt}</span>
{value === opt && <span className="w-1.5 h-1.5 rounded-full bg-canina-blue" />}
</button>
))
)}
</div>
</div>
)}
</div>
);
}