feat(payment): add official eNamad seal, card-to-card payment method, and wallet deposit instructions
Some checks failed
Deploy Canina / deploy (push) Failing after 15s

This commit is contained in:
parsa aghaei 2026-08-01 11:15:14 +03:30
parent 2de442dbae
commit a6f6a4708c
5 changed files with 109 additions and 81 deletions

View File

@ -70,7 +70,7 @@ export default function TrustSealsPage() {
{/* Seals Grid */}
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-16">
<EnamadBadge code="392817" domain="canina.ir" />
<EnamadBadge />
{licenses.slice(1).map((lic, idx) => {
const IconComponent = lic.icon;

View File

@ -35,7 +35,7 @@ export default function CheckoutPage() {
const [loading, setLoading] = useState(false);
const [useRoundUp, setUseRoundUp] = useState(false);
const [dbProducts, setDbProducts] = useState<Product[]>([]);
const [paymentMethod, setPaymentMethod] = useState<string>('online');
const [paymentMethod, setPaymentMethod] = useState<string>('card');
const [selectedAddressId, setSelectedAddressId] = useState<string>('');
const [showNewAddressForm, setShowNewAddressForm] = useState(false);
@ -314,32 +314,59 @@ 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-3 gap-3 sm:gap-4">
{[
{ id: 'online', 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" />
},
{ id: 'cod', label: 'پرداخت در محل', desc: 'فقط تهران', icon: <Truck 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", 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">
<h4 className="font-black text-xs sm:text-sm text-medical-gray-900 mb-0.5 sm:mb-1 truncate">{pay.label}</h4>
<p className={cn("text-[10px] font-bold truncate", pay.id === 'wallet' ? "text-canina-blue" : "text-medical-gray-400")}>{pay.desc}</p>
</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", 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">
<h4 className="font-black text-xs sm:text-sm text-medical-gray-900 mb-0.5 sm:mb-1 truncate">{pay.label}</h4>
<p className={cn("text-[10px] font-bold truncate", pay.id === 'wallet' ? "text-canina-blue" : "text-medical-gray-400")}>{pay.desc}</p>
</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-shabnam">
<div className="flex items-center gap-2 text-canina-blue font-bold text-sm">
<CreditCard className="w-5 h-5" />
<span>اطلاعات کارت جهت واریز وجه سفارش:</span>
</div>
))}
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 text-xs bg-white p-4 rounded-xl border border-blue-100 shadow-sm">
<div>
<span className="text-gray-500 block mb-1">شماره کارت (بانک سامان):</span>
<span className="font-mono text-base font-extrabold text-blue-900 tracking-wider dir-ltr block">۶۲۱۹-۸۶۱۹-۷۴۰۱-۲۰۷۱</span>
</div>
<div>
<span className="text-gray-500 block mb-1">شماره شبا:</span>
<span className="font-mono text-xs font-bold text-gray-800 dir-ltr block">IR-65 0560 6118 2800 5725 1015 01</span>
</div>
<div className="md:col-span-2 pt-2 border-t border-gray-100 flex items-center justify-between text-gray-700 font-bold">
<span>به نام: پارسا آقایی</span>
<span className="text-canina-blue text-[11px]">پس از ثبت سفارش، کارشناسان فروش جهت تایید فیش با شما تماس میگیرند.</span>
</div>
</div>
</div>
)}
</section>
{/* Step 3: Charity Section */}

View File

@ -1,59 +1,34 @@
'use client';
import React, { useState } from 'react';
import Image from 'next/image';
interface EnamadBadgeProps {
code?: string;
domain?: string;
}
export default function EnamadBadge({ code = 'demo-enamad-code', domain = 'canina.ir' }: EnamadBadgeProps) {
const [isLoading, setIsLoading] = useState(true);
const [hasError, setHasError] = useState(false);
import React from 'react';
export default function EnamadBadge() {
return (
<div className="relative flex flex-col items-center justify-center p-6 bg-white/80 backdrop-blur-md rounded-2xl border border-gray-100 shadow-sm hover:shadow-md transition-all duration-300">
<div className="relative flex flex-col items-center justify-center p-6 bg-white/90 backdrop-blur-md rounded-2xl border border-gray-100 shadow-sm hover:shadow-md transition-all duration-300">
<div className="text-xs font-semibold text-teal-600 bg-teal-50 px-3 py-1 rounded-full mb-3">
نماد اعتماد الکترونیکی (eNamad)
</div>
<div className="relative w-36 h-36 flex items-center justify-center bg-gray-50 rounded-xl overflow-hidden border border-gray-100">
{isLoading && (
<div className="absolute inset-0 flex items-center justify-center bg-white/90 z-10">
<div className="w-8 h-8 border-3 border-teal-500 border-t-transparent rounded-full animate-spin"></div>
</div>
)}
{!hasError ? (
<a
<div className="relative w-36 h-36 flex items-center justify-center bg-white rounded-xl overflow-hidden border border-gray-100 p-2">
<a
referrerPolicy="origin"
target="_blank"
rel="noopener noreferrer"
href="https://trustseal.enamad.ir/?id=765218&Code=dOdphRTqZwp3Kep5m07XwaqA0DTFh5ny"
className="w-full h-full flex items-center justify-center"
>
<img
referrerPolicy="origin"
target="_blank"
rel="noopener noreferrer"
href={`https://trustseal.enamad.ir/?id=${code}&Code=${code}`}
className="w-full h-full flex items-center justify-center p-2 group"
>
{/* Real eNamad Seal Graphic */}
<div className="relative w-full h-full flex flex-col items-center justify-center">
<div className="w-20 h-20 relative mb-1">
<div className="absolute inset-0 bg-gradient-to-tr from-amber-400 to-teal-500 rounded-full blur-sm opacity-20 group-hover:opacity-40 transition-opacity"></div>
<div className="relative w-full h-full rounded-full border-2 border-teal-500/30 flex items-center justify-center bg-white p-2">
<span className="text-3xl font-extrabold text-teal-700 tracking-wider">e</span>
</div>
</div>
<span className="text-[11px] font-bold text-gray-700">اعتبار سنجی اینماد</span>
<span className="text-[9px] text-gray-400 font-mono mt-0.5">{domain}</span>
</div>
</a>
) : (
<div className="text-center p-3 text-xs text-gray-500">
امکان دریافت آنلاین نماد وجود ندارد.
</div>
)}
src="https://trustseal.enamad.ir/logo.aspx?id=765218&Code=dOdphRTqZwp3Kep5m07XwaqA0DTFh5ny"
alt="نماد اعتماد الکترونیکی کانینا"
style={{ cursor: 'pointer' }}
className="max-w-full max-h-full object-contain"
/>
</a>
</div>
<p className="text-xs text-gray-500 mt-4 text-center leading-relaxed">
صادر شده توسط مرکز توسعه تجارت الکترونیکی وزارت صمت
<p className="text-xs text-gray-500 mt-4 text-center leading-relaxed font-medium">
صادر شده توسط مرکز توسعه تجارت الکترونیکی (وزارت صمت)
</p>
</div>
);

View File

@ -159,17 +159,33 @@ export default function Footer({
</div>
</div>
<div className="mt-10 p-6 bg-white/5 rounded-[2rem] border border-white/10 flex items-center justify-between">
<div className="mt-10 p-6 bg-white/5 rounded-[2rem] border border-white/10 flex flex-col sm:flex-row items-center justify-between gap-6">
<div className="flex items-center gap-4">
<div className="w-10 h-10 bg-green-500/20 text-green-500 rounded-full flex items-center justify-center">
<div className="w-10 h-10 bg-green-500/20 text-green-500 rounded-full flex items-center justify-center flex-shrink-0">
<ShieldCheck className="w-6 h-6" />
</div>
<div>
<h5 className="text-sm font-bold text-white">{getText('footer_auth_title', "اصالت کالا تضمین می‌شود")}</h5>
<p className="text-[10px] text-slate-400 font-bold">{getText('footer_auth_desc', "تمامی محصولات دارای لیبل اصالت وزارت بهداشت و QR Code اختصاصی هستند.")}</p>
<p className="text-[10px] text-slate-400 font-bold">{getText('footer_auth_desc', "تمامی محصولات دارای لیبل اصالت سازمان دامپزشکی و نماد اعتماد الکترونیکی هستند.")}</p>
</div>
</div>
<div className="text-sm font-bold text-slate-200 self-center font-lalezar tracking-wide">{getText('footer_auth_badge', "اصالت آلمانی کانینا")}</div>
{/* Official eNamad Clickable Seal */}
<div className="bg-white p-2 rounded-xl shadow-md flex items-center justify-center flex-shrink-0 hover:scale-105 transition-transform">
<a
referrerPolicy='origin'
target='_blank'
rel="noopener noreferrer"
href='https://trustseal.enamad.ir/?id=765218&Code=dOdphRTqZwp3Kep5m07XwaqA0DTFh5ny'
>
<img
referrerPolicy='origin'
src='https://trustseal.enamad.ir/logo.aspx?id=765218&Code=dOdphRTqZwp3Kep5m07XwaqA0DTFh5ny'
alt='نماد اعتماد الکترونیکی کانینا'
style={{ cursor: 'pointer', width: '65px', height: '65px' }}
/>
</a>
</div>
</div>
</div>

View File

@ -127,22 +127,32 @@ export default function TopUpModal({ isOpen, onClose, onConfirm }: TopUpModalPro
</div>
</div>
<div className="bg-blue-50 border border-blue-100 rounded-2xl p-4 flex gap-3">
<Sparkles className="w-5 h-5 text-canina-blue shrink-0" />
<p className="text-[10px] font-bold text-canina-blue leading-relaxed">با شارژ کیف پول، از هدیههای هوشمند کانینا و اولویت در ارسال سفارشها بهرهمند شوید.</p>
<div className="bg-blue-50 border border-blue-200 rounded-2xl p-4 space-y-2 text-right">
<div className="flex items-center gap-2 text-canina-blue font-bold text-xs">
<CreditCard className="w-4 h-4" />
<span>اطلاعات کارت جهت کارتبهکارت و شارژ کیفپول:</span>
</div>
<div className="text-[11px] text-gray-700 space-y-1 font-mono dir-ltr bg-white p-2.5 rounded-xl border border-blue-100">
<div>کارت: <strong>۶۲۱۹-۸۶۱۹-۷۴۰۱-۲۰۷۱</strong> (بانک سامان)</div>
<div>شبا: <strong>IR-65 0560 6118 2800 5725 1015 01</strong></div>
<div className="text-gray-500 font-sans text-[10px] pt-1 border-t">به نام: پارسا آقایی</div>
</div>
<p className="text-[10px] font-bold text-blue-800 leading-relaxed pt-1">
پس از ثبت درخواست شارژ، فیش شما بررسی و موجودی کیف پول به صورت دستی شارژ میشود.
</p>
</div>
<button
type="submit"
disabled={loading || !amount}
className="w-full py-5 bg-medical-gray-900 text-white rounded-[2rem] font-black text-lg flex items-center justify-center gap-3 hover:bg-canina-blue transition-all shadow-xl shadow-black/10 disabled:opacity-50 disabled:cursor-not-allowed group"
className="w-full py-5 bg-medical-gray-900 text-white rounded-[2rem] font-black text-base flex items-center justify-center gap-3 hover:bg-canina-blue transition-all shadow-xl shadow-black/10 disabled:opacity-50 disabled:cursor-not-allowed group"
>
{loading ? (
<div className="w-6 h-6 border-4 border-white/20 border-t-white rounded-full animate-spin" />
) : (
<>
<CreditCard className="w-6 h-6 group-hover:scale-110 transition-transform" />
اتصال به درگاه بانکی
ثبت درخواست واریز و شارژ کیف پول
</>
)}
</button>