feat: B2B wholesale pricing per product & discount setting, dynamic payment gateways enable/disable & coming soon badges, B2B phone verification, trust seals menu link, dynamic contact info
Some checks failed
Deploy Canina / deploy (push) Failing after 15s

This commit is contained in:
parsa aghaei 2026-08-01 12:47:41 +03:30
parent f8e9ebfc44
commit 7bf6c47ee6
6 changed files with 292 additions and 62 deletions

View File

@ -128,6 +128,7 @@ 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),
@ -145,7 +146,7 @@ export default function Products() {
setEditingProduct(null);
setFormData({
artNo: '', nameFa: '', nameEn: '', scientificTagline: '', description: '', shortDescription: '', categoryId: '',
priceValue: 0, priceDisplay: '', unit: '', packageSize: 0, dosageLogic: '', suitableFor: 'سگ و گربه',
priceValue: 0, wholesalePrice: '', priceDisplay: '', unit: '', packageSize: 0, dosageLogic: '', suitableFor: 'سگ و گربه',
imageUrl: '', metaTitle: '', metaDescription: '', keywords: '', canonicalUrl: '', slug: '',
symptoms: []
});
@ -535,6 +536,13 @@ 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 } from 'lucide-react';
import { Settings as SettingsIcon, Save, Truck, ShieldAlert, Percent, AlertCircle, CreditCard, Share2 } from 'lucide-react';
import api from '../services/api';
import Spinner from '../components/ui/Spinner';
@ -10,6 +10,16 @@ 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);
@ -25,6 +35,16 @@ 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) {
@ -139,6 +159,156 @@ 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

@ -3,6 +3,7 @@ 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 {
@ -127,27 +128,29 @@ export default function B2BPortal({ onClose }: { onClose: () => void }) {
</p>
{!isWholesaleVerified && (
<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>
<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>
<form onSubmit={async (e) => {
e.preventDefault();
const form = e.target as HTMLFormElement;
const bName = (form.elements.namedItem('bName') as HTMLInputElement).value;
const lNum = (form.elements.namedItem('lNum') as HTMLInputElement).value;
const phone = (form.elements.namedItem('phone') as HTMLInputElement).value;
try {
const api = (await import('../lib/services/api')).default;
await api.post('/wholesale/apply', { businessName: bName, licenseNumber: lNum });
alert('درخواست ثبت‌نام همکار با موفقیت ارسال شد و به زودی توسط ادمین تایید می‌شود.');
await api.post('/wholesale/apply', { businessName: bName, licenseNumber: phone });
alert('درخواست شما با موفقیت ثبت شد. کارشناسان پشتیبانی B2B کانینا به زودی جهت تایید تلفنی با شما تماس خواهند گرفت.');
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 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">
ثبت درخواست همکار
<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
</button>
</form>
</div>
@ -209,7 +212,11 @@ export default function B2BPortal({ onClose }: { onClose: () => void }) {
<tbody className="divide-y divide-medical-gray-100">
{filteredProducts.map(product => {
const basePrice = product.priceValue || 0;
const wholesalePrice = basePrice * 0.7; // 30% discount
// 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));
return (
<tr key={product.id} className="hover:bg-medical-gray-50/50 transition-colors">
<td className="px-6 py-4">

View File

@ -388,51 +388,92 @@ export default function CheckoutPage() {
<h2 className="text-xl sm:text-2xl font-black text-medical-gray-900 italic">شیوه پرداخت</h2>
</div>
<div className="grid grid-cols-1 sm:grid-cols-2 gap-3 sm:gap-4">
{[
{
id: 'card',
label: 'کارت به کارت (واریز مستقیم)',
desc: 'واریز به شماره کارت بانک سامان',
icon: <CreditCard className="w-5 h-5 sm:w-6 sm:h-6" />
},
{
id: 'wallet',
label: 'اعتبار حساب (کیف پول)',
desc: `موجودی: ${toPersian((profile.walletBalance || 0).toLocaleString())} تومان`,
icon: <Wallet className="w-5 h-5 sm:w-6 sm:h-6" />
}
].map((pay) => (
<div
key={pay.id}
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 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'
},
{
id: 'wallet',
label: getText('PAY_GATEWAY_WALLET_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'
}
];
const sortedGateways = [...allGateways].sort((a, b) => (b.enabled ? 1 : 0) - (a.enabled ? 1 : 0));
return sortedGateways.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"
)}
>
<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="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 && (
<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"
>
<PlusCircle className="w-3 h-3" />
<span>افزایش موجودی</span>
</button>
)}
</div>
</div>
</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' && (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"
>
<PlusCircle className="w-3 h-3" />
<span>افزایش موجودی</span>
</button>
)}
</div>
</div>
</div>
))}
</div>
));
})()}
</div>
{paymentMethod === 'card' && (
<div className="mt-6 bg-blue-50/80 border border-blue-200 rounded-2xl p-5 space-y-3 font-vazir">

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('footer_phone', "۰۲۱-۸۸۸۸ ۴۴۴۴")}</p>
<p className="text-lg font-extrabold tracking-widest text-left text-slate-200" dir="ltr">{getText('CONTACT_PHONE', 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('footer_email', "info@canina-iran.com")}</p>
<p className="text-sm font-bold text-slate-300">{getText('CONTACT_EMAIL', 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('footer_address', "تهران، جردن، خیابان سعیدی، ساختمان کانینا، طبقه ۵، واحد ۱۹")}</p>
<p className="text-sm font-bold leading-relaxed text-slate-300">{getText('CONTACT_ADDRESS', getText('footer_address', "تهران، جردن، خیابان سعیدی، ساختمان کانینا، طبقه ۵، واحد ۱۹"))}</p>
</div>
</div>
</div>

View File

@ -372,11 +372,15 @@ export default function Header({
<ChevronDown className="w-3.5 h-3.5" />
</button>
{activeDropdown === 'company' && (
<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">
<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">
<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"