diff --git a/frontend/admin-panel/src/pages/FinancialSettingsPage.tsx b/frontend/admin-panel/src/pages/FinancialSettingsPage.tsx index 1be7a16..288d463 100644 --- a/frontend/admin-panel/src/pages/FinancialSettingsPage.tsx +++ b/frontend/admin-panel/src/pages/FinancialSettingsPage.tsx @@ -15,6 +15,8 @@ export default function FinancialSettingsPage() { walletWithdrawalEnabled: false, }); const [charityStep, setCharityStep] = useState('10000'); + const [refillEnabled, setRefillEnabled] = useState(false); + const [refillPercent, setRefillPercent] = useState('5'); const [isLoading, setIsLoading] = useState(true); const [isSaving, setIsSaving] = useState(false); const [donationInput, setDonationInput] = useState(''); @@ -41,6 +43,8 @@ export default function FinancialSettingsPage() { } if (resAdmin.data?.success) { setCharityStep(resAdmin.data.data.CHARITY_ROUND_STEP || '10000'); + setRefillEnabled(resAdmin.data.data.REFILL_SUBSCRIPTION_ENABLED === 'true'); + setRefillPercent(resAdmin.data.data.REFILL_REWARD_PERCENT || '5'); } }) .catch((err) => { @@ -63,6 +67,8 @@ export default function FinancialSettingsPage() { api.put('/admin/settings', { TAX_PERCENTAGE: String(financial.taxPercentage), CHARITY_ROUND_STEP: charityStep, + REFILL_SUBSCRIPTION_ENABLED: refillEnabled ? 'true' : 'false', + REFILL_REWARD_PERCENT: refillPercent, }), ]); toast.success('تنظیمات مالی با موفقیت بروزرسانی شد'); @@ -191,6 +197,52 @@ export default function FinancialSettingsPage() { + {/* Refill Subscription and Reward Cashback */} +
+ + + {refillEnabled && ( +
+
+ +
+ setRefillPercent(e.target.value)} + className="w-full px-4 py-2.5 rounded-xl border border-gray-200 focus:border-indigo-500 outline-none font-bold text-xs" + dir="ltr" + /> + % +
+

پیش‌فرض: ۵ درصد

+
+
+ )} +
+ {/* Wallet Withdrawal Feature Toggle */}
{/* Subscription Toggle */} -
{ - if (!isLoggedIn && !isSubscribed) { - toast.info("برای فعال‌سازی سرویس تمدید خودکار و دریافت یادآورها، لطفاً ابتدا وارد حساب کاربری خود شوید."); - setIsAuthModalOpen(true); - return; - } - toggleSubscription(); - }} - className={`p-4 rounded-2xl border-2 transition-all cursor-pointer ${isSubscribed ? 'bg-canina-blue/5 border-canina-blue' : 'bg-white border-medical-gray-100 hover:border-canina-blue/30'}`} - > -
-
- -
-
-
سامانه تمدید هوشمند و ۵٪ پاداش Cashback
-

۵٪ شارژ هدیه کیف پول روی خرید تمدید بعدی همین محصول + ارسال اولویت‌دار

-

برنامه هوشمند وفاداری — یادآوری دقیق زمان اتمام مکمل پت بر اساس دوز دامپزشک + ۵٪ اعتبار هدیه بازگشت وجه

-
-
- {isSubscribed && } + {isRefillEnabled && ( +
{ + if (!isLoggedIn && !isSubscribed) { + toast.info("برای فعال‌سازی سرویس تمدید خودکار و دریافت یادآورها، لطفاً ابتدا وارد حساب کاربری خود شوید."); + setIsAuthModalOpen(true); + return; + } + toggleSubscription(); + }} + className={`p-4 rounded-2xl border-2 transition-all cursor-pointer ${isSubscribed ? 'bg-canina-blue/5 border-canina-blue' : 'bg-white border-medical-gray-100 hover:border-canina-blue/30'}`} + > +
+
+ +
+
+
سامانه تمدید هوشمند و {toPersian(refillPercent)}٪ پاداش Cashback
+

{toPersian(refillPercent)}٪ شارژ هدیه کیف پول روی خرید تمدید بعدی همین محصول + ارسال اولویت‌دار

+

برنامه هوشمند وفاداری — یادآوری دقیق زمان اتمام مکمل پت بر اساس دوز دامپزشک + {toPersian(refillPercent)}٪ اعتبار هدیه بازگشت وجه

+
+
+ {isSubscribed && } +
-
+ )} {/* Official Germany Catalog Authenticity Guarantee Banner */}
diff --git a/frontend/application/components/CheckoutPage.tsx b/frontend/application/components/CheckoutPage.tsx index ac957d3..a371cc6 100644 --- a/frontend/application/components/CheckoutPage.tsx +++ b/frontend/application/components/CheckoutPage.tsx @@ -243,7 +243,6 @@ export default function CheckoutPage() {
); } - if (items.length === 0) { return (
@@ -258,66 +257,67 @@ export default function CheckoutPage() { ); } + const isRefillEnabled = useSettingsStore((state) => state.getText('REFILL_SUBSCRIPTION_ENABLED', 'false') === 'true'); + const refillPercent = Number(useSettingsStore((state) => state.getText('REFILL_REWARD_PERCENT', '5'))) || 5; + return ( -
+
- {/* Mobile Navigation & Breadcrumbs */} -
- - -
+ {/* Navigation & Breadcrumbs */} +
+
+ + / router.push('/shop')}>سبد خرید - - نهایی‌سازی سفارش + / + تسویه‌حساب و پرداخت +
+
+ + پرداخت ۱۰۰٪ امن با پروتکل SSL
- {/* Desktop Breadcrumbs (Hidden on Mobile) */} -
- router.push('/')}>خانه - - درگاه پرداخت امن و نهایی‌سازی -
- -
- {/* Main Form */} -
+
+ {/* Main Content (8 cols) */} +
+ {/* Step 1: Shipping */} -
-
-
-
۱
-

اطلاعات ارسال

+
+
+
+
۱
+

اطلاعات تحویل و گیرنده

+
+ {isLoggedIn && ( + + )}
{isLoggedIn && profile.addresses && profile.addresses.length > 0 ? ( -
-
-

انتخاب آدرس جهت تحویل سفارش:

- -
-
+
+
{profile.addresses.map((addr) => (
setSelectedAddressId(addr.id)} className={cn( - "p-3 sm:p-4 rounded-2xl border-2 cursor-pointer transition-all flex items-start gap-2.5 sm:gap-3 w-full min-w-0 max-w-full overflow-hidden", - selectedAddressId === addr.id ? "border-canina-blue bg-canina-blue/5" : "border-medical-gray-100 hover:border-medical-gray-200" + "p-3 rounded-xl border transition-all flex items-start gap-2.5 cursor-pointer", + selectedAddressId === addr.id ? "border-canina-blue bg-canina-blue/5 shadow-xs" : "border-medical-gray-200 hover:border-medical-gray-300" )} > setSelectedAddressId(addr.id)} - className="mt-1 shrink-0" + className="mt-1 shrink-0 cursor-pointer" /> -
-
- {addr.title} +
+
+ {addr.title} {addr.isDefault && ( - پیش‌فرض + پیش‌فرض )}
-

{addr.province}، {addr.city}، {addr.detail}

-

گیرنده: {addr.receptorName} | همراه: {toPersian(addr.phone)}

+

{addr.province}، {addr.city}، {addr.detail}

+

گیرنده: {addr.receptorName} ({toPersian(addr.phone)})

))}
) : ( -
- {isLoggedIn && ( -
- -
- )} -
-
- - setManualName(e.target.value)} - 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" - placeholder="مثلاً: پارسا آقایی" - /> -
-
- - setManualPhone(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="۰۹۱۲XXXXXXX" - /> -
-
- +
+
+ + setManualName(e.target.value)} + className="w-full bg-medical-gray-50/70 border border-medical-gray-200 rounded-xl py-2 px-3 text-xs focus:ring-1 focus:ring-canina-blue outline-none" + placeholder="مثلاً: پارسا آقایی" + /> +
+
+ + setManualPhone(e.target.value.replace(/[^0-9]/g, ''))} + className="w-full bg-medical-gray-50/70 border border-medical-gray-200 rounded-xl py-2 px-3 text-xs focus:ring-1 focus:ring-canina-blue outline-none dir-ltr text-right" + placeholder="۰۹۱۲XXXXXXX" + /> +
+
+ + { + const cities = PROVINCE_CITIES[prov] || []; + setManualProvince(prov); + setManualCity(cities[0] || ''); + }} + /> +
+
+ + {manualProvince && PROVINCE_CITIES[manualProvince] ? ( { - const cities = PROVINCE_CITIES[prov] || []; - setManualProvince(prov); - setManualCity(cities[0] || ''); - }} + id="chk-city" + options={PROVINCE_CITIES[manualProvince]} + value={manualCity} + placeholder="انتخاب شهر..." + searchPlaceholder="جستجوی شهر..." + onChange={(c) => setManualCity(c)} /> -
-
- - {manualProvince && PROVINCE_CITIES[manualProvince] ? ( - setManualCity(c)} - /> - ) : ( - setManualCity(e.target.value)} - 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" - placeholder="نام شهر..." - /> - )} -
-
- -