580 lines
33 KiB
TypeScript
580 lines
33 KiB
TypeScript
import { useState, useEffect } from 'react';
|
||
import { Link } from 'react-router-dom';
|
||
import { Settings as SettingsIcon, Save, Truck, ShieldAlert, Percent, AlertCircle, CreditCard, Share2, MessageSquare } from 'lucide-react';
|
||
import { toast } from 'react-hot-toast';
|
||
import api from '../services/api';
|
||
import Spinner from '../components/ui/Spinner';
|
||
|
||
export default function Settings() {
|
||
const [settings, setSettings] = useState({
|
||
SHIPPING_FEE: '',
|
||
MIN_ORDER_AMOUNT: '',
|
||
B2B_DISCOUNT_PERCENT: '',
|
||
MAINTENANCE_MODE: 'false',
|
||
CATALOG_ONLY_MODE: 'false',
|
||
CATALOG_SHOW_PRICES: 'true',
|
||
CATALOG_ALLOW_CART: 'false',
|
||
CATALOG_ALLOW_CHECKOUT: 'false',
|
||
CATALOG_PREORDER_BTN: 'false',
|
||
CHARITY_ROUND_STEP: '10000',
|
||
PAY_GATEWAY_CARD_ENABLE: 'true',
|
||
PAY_GATEWAY_WALLET_ENABLE: 'true',
|
||
PAY_GATEWAY_ONLINE_ENABLE: 'true',
|
||
PAY_GATEWAY_COD_ENABLE: 'false',
|
||
ZIBAL_MERCHANT: 'zibal',
|
||
ZIBAL_SANDBOX: 'true',
|
||
FRONTEND_URL: 'https://canina.ir',
|
||
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: 'تهران، جردن، خیابان سعیدی، ساختمان کانینا، طبقه ۵، واحد ۱۹',
|
||
BRAND_LOGO_URL: '/logo.png',
|
||
ENAMAD_CODE: '',
|
||
THEME_PRIMARY_COLOR: '#7c3aed',
|
||
BRAND_TYPOGRAPHY: 'vazirmatn',
|
||
});
|
||
const [isLoading, setIsLoading] = useState(true);
|
||
const [isSaving, setIsSaving] = useState(false);
|
||
|
||
useEffect(() => {
|
||
let isSubscribed = true;
|
||
api.get('/admin/settings').then(response => {
|
||
if (!isSubscribed) return;
|
||
if (response.data?.success) {
|
||
setSettings({
|
||
SHIPPING_FEE: response.data.data.SHIPPING_FEE || '0',
|
||
MIN_ORDER_AMOUNT: response.data.data.MIN_ORDER_AMOUNT || '0',
|
||
B2B_DISCOUNT_PERCENT: response.data.data.B2B_DISCOUNT_PERCENT || '0',
|
||
MAINTENANCE_MODE: response.data.data.MAINTENANCE_MODE || 'false',
|
||
CATALOG_ONLY_MODE: response.data.data.CATALOG_ONLY_MODE || 'false',
|
||
CATALOG_SHOW_PRICES: response.data.data.CATALOG_SHOW_PRICES || 'true',
|
||
CATALOG_ALLOW_CART: response.data.data.CATALOG_ALLOW_CART || 'false',
|
||
CATALOG_ALLOW_CHECKOUT: response.data.data.CATALOG_ALLOW_CHECKOUT || 'false',
|
||
CATALOG_PREORDER_BTN: response.data.data.CATALOG_PREORDER_BTN || '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 || 'true',
|
||
PAY_GATEWAY_COD_ENABLE: response.data.data.PAY_GATEWAY_COD_ENABLE || 'false',
|
||
ZIBAL_MERCHANT: response.data.data.ZIBAL_MERCHANT || 'zibal',
|
||
ZIBAL_SANDBOX: response.data.data.ZIBAL_SANDBOX || 'true',
|
||
FRONTEND_URL: response.data.data.FRONTEND_URL || 'https://canina.ir',
|
||
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 || 'تهران، جردن، خیابان سعیدی، ساختمان کانینا، طبقه ۵، واحد ۱۹',
|
||
BRAND_LOGO_URL: response.data.data.BRAND_LOGO_URL || '/logo.png',
|
||
ENAMAD_CODE: response.data.data.ENAMAD_CODE || '',
|
||
THEME_PRIMARY_COLOR: response.data.data.THEME_PRIMARY_COLOR || '#7c3aed',
|
||
BRAND_TYPOGRAPHY: response.data.data.BRAND_TYPOGRAPHY || 'vazirmatn',
|
||
});
|
||
}
|
||
}).catch(err => {
|
||
console.error('Failed to fetch settings', err);
|
||
}).finally(() => {
|
||
if (isSubscribed) setIsLoading(false);
|
||
});
|
||
return () => {
|
||
isSubscribed = false;
|
||
};
|
||
}, []);
|
||
|
||
const handleSave = async (e: React.FormEvent) => {
|
||
e.preventDefault();
|
||
try {
|
||
setIsSaving(true);
|
||
await api.put('/admin/settings', settings);
|
||
toast.success('تنظیمات با موفقیت بروزرسانی شد.');
|
||
} catch (err) {
|
||
console.error('Failed to update settings', err);
|
||
toast.error('خطا در بروزرسانی تنظیمات');
|
||
} finally {
|
||
setIsSaving(false);
|
||
}
|
||
};
|
||
|
||
return (
|
||
<div className="space-y-6">
|
||
<div className="flex flex-col sm:flex-row sm:items-center justify-between gap-4">
|
||
<div>
|
||
<h2 className="text-2xl font-black text-gray-900 flex items-center gap-2">
|
||
<SettingsIcon className="w-6 h-6 text-purple-600" />
|
||
تنظیمات فروشگاه
|
||
</h2>
|
||
<p className="text-gray-500 font-medium mt-1">مدیریت پارامترهای اصلی و سیستمی کانینا</p>
|
||
</div>
|
||
<div className="flex items-center gap-2 flex-wrap">
|
||
<Link
|
||
to="/settings/sms"
|
||
className="bg-purple-50 text-purple-700 hover:bg-purple-100 border border-purple-200 text-xs font-bold px-4 py-2.5 rounded-xl transition-all flex items-center gap-2"
|
||
>
|
||
<MessageSquare className="w-4 h-4 text-purple-600" />
|
||
تنظیمات درگاه پیامک (MeliPayamak)
|
||
</Link>
|
||
</div>
|
||
</div>
|
||
|
||
{isLoading ? (
|
||
<div className="flex justify-center p-12"><Spinner size="lg" className="text-purple-600" /></div>
|
||
) : (
|
||
<form onSubmit={handleSave} className="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
||
|
||
{/* Financial Settings */}
|
||
<div className="bg-white p-6 rounded-2xl shadow-sm border border-gray-200 space-y-6">
|
||
<h3 className="text-lg font-bold text-gray-900 border-b border-gray-100 pb-4 flex items-center gap-2">
|
||
<Truck className="w-5 h-5 text-blue-500" />
|
||
تنظیمات مالی و ارسال
|
||
</h3>
|
||
|
||
<div className="space-y-5">
|
||
<div>
|
||
<label className="block text-sm font-bold text-gray-700 mb-2">هزینه ثابت ارسال (تومان)</label>
|
||
<input
|
||
type="number"
|
||
value={settings.SHIPPING_FEE}
|
||
onChange={(e) => setSettings({ ...settings, SHIPPING_FEE: e.target.value })}
|
||
className="w-full border border-gray-200 rounded-xl p-3 outline-none focus:ring-2 focus:ring-purple-500 font-bold"
|
||
dir="ltr"
|
||
/>
|
||
</div>
|
||
|
||
<div>
|
||
<label className="block text-sm font-bold text-gray-700 mb-2">حداقل مبلغ سفارش (تومان)</label>
|
||
<input
|
||
type="number"
|
||
value={settings.MIN_ORDER_AMOUNT}
|
||
onChange={(e) => setSettings({ ...settings, MIN_ORDER_AMOUNT: e.target.value })}
|
||
className="w-full border border-gray-200 rounded-xl p-3 outline-none focus:ring-2 focus:ring-purple-500 font-bold"
|
||
dir="ltr"
|
||
/>
|
||
<p className="text-xs text-gray-500 mt-2 font-medium">سفارشات زیر این مبلغ امکان ثبت نخواهند داشت (۰ = بدون محدودیت).</p>
|
||
</div>
|
||
|
||
<div>
|
||
<label className="block text-sm font-bold text-gray-700 mb-2">پله رند کردن ردپای مهربانی (تومان)</label>
|
||
<input
|
||
type="number"
|
||
step="1000"
|
||
value={settings.CHARITY_ROUND_STEP}
|
||
onChange={(e) => setSettings({ ...settings, CHARITY_ROUND_STEP: e.target.value })}
|
||
className="w-full border border-gray-200 rounded-xl p-3 outline-none focus:ring-2 focus:ring-purple-500 font-bold"
|
||
dir="ltr"
|
||
placeholder="10000"
|
||
/>
|
||
<p className="text-xs text-gray-500 mt-2 font-medium">مبلغ فاکتور به اولین ضریب این عدد (مثلاً ۱۰,۰۰۰ یا ۵۰,۰۰۰ تومان) رند میشود.</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
{/* B2B Settings */}
|
||
<div className="bg-white p-6 rounded-2xl shadow-sm border border-gray-200 space-y-6">
|
||
<h3 className="text-lg font-bold text-gray-900 border-b border-gray-100 pb-4 flex items-center gap-2">
|
||
<Percent className="w-5 h-5 text-green-500" />
|
||
همکاران B2B
|
||
</h3>
|
||
|
||
<div className="space-y-5">
|
||
<div>
|
||
<label className="block text-sm font-bold text-gray-700 mb-2">تخفیف پیشفرض همکار (درصد)</label>
|
||
<input
|
||
type="number"
|
||
value={settings.B2B_DISCOUNT_PERCENT}
|
||
onChange={(e) => setSettings({ ...settings, B2B_DISCOUNT_PERCENT: e.target.value })}
|
||
className="w-full border border-gray-200 rounded-xl p-3 outline-none focus:ring-2 focus:ring-purple-500 font-bold"
|
||
dir="ltr"
|
||
max="100"
|
||
min="0"
|
||
/>
|
||
<p className="text-xs text-gray-500 mt-2 font-medium">این درصد به صورت خودکار روی قیمت تمام محصولات برای کاربران تایید شده B2B اعمال میشود.</p>
|
||
</div>
|
||
</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>
|
||
|
||
{/* Zibal Specific Configuration */}
|
||
<div className="pt-4 border-t border-gray-100 space-y-4">
|
||
<div className="flex items-center gap-2 text-indigo-700 font-black text-sm">
|
||
<span>پیکربندی پایانه پرداخت اینترنتی زیبال (Zibal IPG)</span>
|
||
{settings.ZIBAL_MERCHANT === 'zibal' && (
|
||
<span className="bg-amber-100 text-amber-800 text-[10px] px-2 py-0.5 rounded-full font-bold">
|
||
حالت تستی (Sandbox: zibal)
|
||
</span>
|
||
)}
|
||
</div>
|
||
|
||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 bg-indigo-50/50 p-4 rounded-xl border border-indigo-100">
|
||
<div>
|
||
<label className="block text-xs font-bold text-gray-700 mb-1">
|
||
کد مرچنت زیبال (Merchant ID)
|
||
</label>
|
||
<input
|
||
type="text"
|
||
value={settings.ZIBAL_MERCHANT}
|
||
onChange={(e) => setSettings({ ...settings, ZIBAL_MERCHANT: e.target.value })}
|
||
placeholder="zibal"
|
||
className="w-full border border-gray-200 rounded-xl p-2.5 outline-none focus:ring-2 focus:ring-purple-500 text-xs font-mono font-bold bg-white"
|
||
dir="ltr"
|
||
/>
|
||
<p className="text-[11px] text-gray-500 mt-1">
|
||
برای حالت تستی و آزمایش درگاه از مقدار <code>zibal</code> استفاده کنید.
|
||
</p>
|
||
</div>
|
||
|
||
<div>
|
||
<label className="block text-xs font-bold text-gray-700 mb-1">
|
||
دامنه فرانتاند / آدرس بازگشت (Frontend Domain)
|
||
</label>
|
||
<input
|
||
type="text"
|
||
value={settings.FRONTEND_URL}
|
||
onChange={(e) => setSettings({ ...settings, FRONTEND_URL: e.target.value })}
|
||
placeholder="https://canina.ir"
|
||
className="w-full border border-gray-200 rounded-xl p-2.5 outline-none focus:ring-2 focus:ring-purple-500 text-xs font-mono font-bold bg-white"
|
||
dir="ltr"
|
||
/>
|
||
<p className="text-[11px] text-gray-500 mt-1">
|
||
آدرس دامنهای که کاربر پس از پرداخت از زیبال به آن بازگردانده میشود.
|
||
</p>
|
||
</div>
|
||
</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>
|
||
|
||
{/* Brand Identity & Theme 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">
|
||
<SettingsIcon className="w-5 h-5 text-purple-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">لینک لوگوی برند (Brand Logo URL)</label>
|
||
<div className="flex gap-2">
|
||
<input
|
||
type="text"
|
||
value={settings.BRAND_LOGO_URL}
|
||
onChange={(e) => setSettings({ ...settings, BRAND_LOGO_URL: e.target.value })}
|
||
className="flex-1 border border-gray-200 rounded-xl p-2.5 outline-none focus:ring-2 focus:ring-purple-500 text-xs font-mono"
|
||
placeholder="https://... یا /logo.png"
|
||
dir="ltr"
|
||
/>
|
||
{settings.BRAND_LOGO_URL && (
|
||
<div className="w-10 h-10 border rounded-lg bg-gray-50 flex items-center justify-center p-1 overflow-hidden shrink-0">
|
||
<img src={settings.BRAND_LOGO_URL} alt="Preview" className="max-w-full max-h-full object-contain" />
|
||
</div>
|
||
)}
|
||
</div>
|
||
<p className="text-[10px] text-gray-400 mt-1">این لوگو در صورت پر بودن، جایگزین تایپوگرافی هدر سایت در اپلیکیشن خواهد شد.</p>
|
||
</div>
|
||
|
||
<div className="md:col-span-2">
|
||
<label className="block text-xs font-bold text-gray-700 mb-1">کد و اسکریپت نماد اعتماد الکترونیکی (Enamad HTML/Embed Code)</label>
|
||
<textarea
|
||
rows={4}
|
||
value={settings.ENAMAD_CODE}
|
||
onChange={(e) => setSettings({ ...settings, ENAMAD_CODE: e.target.value })}
|
||
placeholder="<a referrerpolicy='origin' target='_blank' href='...'><img src='...' code='...' /></a>"
|
||
className="w-full border border-gray-200 rounded-xl p-3 outline-none focus:ring-2 focus:ring-purple-500 text-xs font-mono bg-slate-50"
|
||
dir="ltr"
|
||
/>
|
||
<p className="text-[11px] text-gray-500 mt-1">کد کامل HTML دریافت شده از سامانه اینماد (trustseal.enamad.ir) را مستقیماً وارد کنید.</p>
|
||
</div>
|
||
|
||
<div>
|
||
<label className="block text-xs font-bold text-gray-700 mb-1">رنگ اصلی تم سایت (Hex Color)</label>
|
||
<div className="flex gap-2">
|
||
<input
|
||
type="color"
|
||
value={settings.THEME_PRIMARY_COLOR}
|
||
onChange={(e) => setSettings({ ...settings, THEME_PRIMARY_COLOR: e.target.value })}
|
||
className="w-10 h-10 rounded-lg cursor-pointer border border-gray-200"
|
||
/>
|
||
<input
|
||
type="text"
|
||
value={settings.THEME_PRIMARY_COLOR}
|
||
onChange={(e) => setSettings({ ...settings, THEME_PRIMARY_COLOR: e.target.value })}
|
||
className="flex-1 border border-gray-200 rounded-xl p-2.5 outline-none focus:ring-2 focus:ring-purple-500 text-xs font-mono"
|
||
dir="ltr"
|
||
/>
|
||
</div>
|
||
</div>
|
||
|
||
<div>
|
||
<label className="block text-xs font-bold text-gray-700 mb-1">تایپوگرافی و فونت سایت</label>
|
||
<select
|
||
value={settings.BRAND_TYPOGRAPHY}
|
||
onChange={(e) => setSettings({ ...settings, BRAND_TYPOGRAPHY: 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"
|
||
>
|
||
<option value="vazirmatn">وزیرمتن (Vazirmatn)</option>
|
||
<option value="iransans">ایرانسانس (IRANSans)</option>
|
||
<option value="dana">دانا (Dana)</option>
|
||
<option value="shabnam">شبنم (Shabnam)</option>
|
||
</select>
|
||
</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">
|
||
<ShieldAlert className="w-5 h-5 text-orange-500" />
|
||
وضعیت سیستم و کنترل حالت کاتالوگ
|
||
</h3>
|
||
|
||
<div className="space-y-4">
|
||
<div className="flex items-center justify-between p-4 bg-orange-50 rounded-xl border border-orange-100">
|
||
<div className="flex items-center gap-3">
|
||
<AlertCircle className="w-6 h-6 text-orange-500" />
|
||
<div>
|
||
<h4 className="font-bold text-gray-900 text-sm">حالت تعمیرات (Maintenance Mode)</h4>
|
||
<p className="text-xs text-gray-600 mt-0.5">با فعال کردن این گزینه، سایت برای کاربران از دسترس خارج شده و صفحه اختصاصی «در حال بروزرسانی» نمایش داده میشود.</p>
|
||
</div>
|
||
</div>
|
||
<label className="relative inline-flex items-center cursor-pointer">
|
||
<input
|
||
type="checkbox"
|
||
className="sr-only peer"
|
||
checked={settings.MAINTENANCE_MODE === 'true'}
|
||
onChange={(e) => setSettings({ ...settings, MAINTENANCE_MODE: e.target.checked ? 'true' : 'false' })}
|
||
/>
|
||
<div className="w-14 h-7 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-6 after:w-6 after:transition-all peer-checked:bg-orange-500"></div>
|
||
</label>
|
||
</div>
|
||
|
||
<div className="p-4 bg-purple-50 rounded-xl border border-purple-100 space-y-4">
|
||
<div className="flex items-center justify-between">
|
||
<div className="flex items-center gap-3">
|
||
<AlertCircle className="w-6 h-6 text-purple-600" />
|
||
<div>
|
||
<h4 className="font-bold text-gray-900 text-sm">حالت کاتالوگ بدون خرید (Catalog Only Mode)</h4>
|
||
<p className="text-xs text-gray-600 mt-0.5">با فعالسازی این گزینه، فروش مستقیم کالا غیرفعال شده و سایت به کاتالوگ هوشمند آنلاین تبدیل میشود.</p>
|
||
</div>
|
||
</div>
|
||
<label className="relative inline-flex items-center cursor-pointer">
|
||
<input
|
||
type="checkbox"
|
||
className="sr-only peer"
|
||
checked={settings.CATALOG_ONLY_MODE === 'true'}
|
||
onChange={(e) => setSettings({ ...settings, CATALOG_ONLY_MODE: e.target.checked ? 'true' : 'false' })}
|
||
/>
|
||
<div className="w-14 h-7 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-6 after:w-6 after:transition-all peer-checked:bg-purple-600"></div>
|
||
</label>
|
||
</div>
|
||
|
||
{settings.CATALOG_ONLY_MODE === 'true' && (
|
||
<div className="pt-3 border-t border-purple-200/60 grid grid-cols-1 md:grid-cols-2 gap-3 text-xs">
|
||
<label className="flex items-center gap-2 font-bold text-gray-800 cursor-pointer">
|
||
<input
|
||
type="checkbox"
|
||
checked={settings.CATALOG_SHOW_PRICES === 'true'}
|
||
onChange={(e) => setSettings({ ...settings, CATALOG_SHOW_PRICES: e.target.checked ? 'true' : 'false' })}
|
||
className="rounded text-purple-600 focus:ring-purple-500"
|
||
/>
|
||
<span>نمایش قیمت محصولات در حالت کاتالوگ</span>
|
||
</label>
|
||
|
||
<label className="flex items-center gap-2 font-bold text-gray-800 cursor-pointer">
|
||
<input
|
||
type="checkbox"
|
||
checked={settings.CATALOG_ALLOW_CART === 'true'}
|
||
onChange={(e) => setSettings({ ...settings, CATALOG_ALLOW_CART: e.target.checked ? 'true' : 'false' })}
|
||
className="rounded text-purple-600 focus:ring-purple-500"
|
||
/>
|
||
<span>امکان افزودن به سبد خرید</span>
|
||
</label>
|
||
|
||
<label className="flex items-center gap-2 font-bold text-gray-800 cursor-pointer">
|
||
<input
|
||
type="checkbox"
|
||
checked={settings.CATALOG_ALLOW_CHECKOUT === 'true'}
|
||
onChange={(e) => setSettings({ ...settings, CATALOG_ALLOW_CHECKOUT: e.target.checked ? 'true' : 'false' })}
|
||
className="rounded text-purple-600 focus:ring-purple-500"
|
||
/>
|
||
<span>امکان ورود به صفحه تسویهحساب (ثبت فاکتور)</span>
|
||
</label>
|
||
|
||
<label className="flex items-center gap-2 font-bold text-gray-800 cursor-pointer">
|
||
<input
|
||
type="checkbox"
|
||
checked={settings.CATALOG_PREORDER_BTN === 'true'}
|
||
onChange={(e) => setSettings({ ...settings, CATALOG_PREORDER_BTN: e.target.checked ? 'true' : 'false' })}
|
||
className="rounded text-purple-600 focus:ring-purple-500"
|
||
/>
|
||
<span>نمایش دکمه «ثبت پیشخرید» به جای ثبت سفارش</span>
|
||
</label>
|
||
</div>
|
||
)}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div className="lg:col-span-2 flex justify-end">
|
||
<button
|
||
type="submit"
|
||
disabled={isSaving}
|
||
className="bg-purple-600 hover:bg-purple-700 text-white font-bold py-3 px-8 rounded-xl transition-colors flex items-center gap-2 shadow-md shadow-purple-200"
|
||
>
|
||
{isSaving ? <Spinner size="sm" /> : <Save className="w-5 h-5" />}
|
||
ذخیره تغییرات
|
||
</button>
|
||
</div>
|
||
</form>
|
||
)}
|
||
</div>
|
||
);
|
||
}
|