Midtrans-Middleware/src/features/payments/components/PaymentMethodList.tsx

78 lines
4.0 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React from 'react'
import { CardLogosRow, GoPayLogosRow, CStoreLogosRow, LogoCpay } from './PaymentLogos'
import { Env } from '../../../lib/env'
export type PaymentMethod = 'bank_transfer' | 'credit_card' | 'gopay' | 'cstore' | 'cpay'
export interface PaymentMethodListProps {
selected?: PaymentMethod
onSelect: (m: PaymentMethod) => void
renderPanel?: (m: PaymentMethod) => React.ReactNode
disabled?: boolean
enabled?: Record<PaymentMethod, boolean>
}
const baseItems: Array<{ key: PaymentMethod; title: string; subtitle: string; icon?: React.ReactNode }> = [
{ key: 'bank_transfer', title: 'Transfer Bank', subtitle: 'BCA • BNI • BRI • CIMB • Mandiri • Permata', icon: <img src="/logos/logo-semua-bank.PNG" alt="Semua bank yang didukung" className="h-6 sm:h-8 object-contain" /> },
{ key: 'credit_card', title: 'Kartu kredit/debit', subtitle: 'Visa • MasterCard • JCB • Amex', icon: <CardLogosRow compact size="xs" /> },
{ key: 'gopay', title: 'Gopay/QRIS', subtitle: 'Scan & bayar via QR', icon: <GoPayLogosRow compact size="xs" /> },
{ key: 'cstore', title: 'Convenience Store', subtitle: '', icon: <CStoreLogosRow compact size="xs" /> },
{ key: 'cpay', title: 'cPay', subtitle: 'Bayar via aplikasi CIFO Token', icon: <LogoCpay compact size="md" /> },
]
export function PaymentMethodList({ selected, onSelect, renderPanel, disabled, enabled }: PaymentMethodListProps) {
const enabledMap: Record<PaymentMethod, boolean> = {
bank_transfer: enabled?.bank_transfer ?? Env.ENABLE_BANK_TRANSFER,
credit_card: enabled?.credit_card ?? Env.ENABLE_CREDIT_CARD,
gopay: enabled?.gopay ?? Env.ENABLE_GOPAY,
cstore: enabled?.cstore ?? Env.ENABLE_CSTORE,
cpay: enabled?.cpay ?? Env.ENABLE_CPAY,
}
const items = baseItems.filter((it) => enabledMap[it.key])
return (
<div className="space-y-2 sm:space-y-3">
<div className="text-xs sm:text-sm font-medium">Metode pembayaran</div>
<div className="rounded-lg border-2 border-black/30 divide-y-[2px] divide-black/20 bg-white">
{items.map((it) => (
<div key={it.key}>
<button
onClick={() => !disabled && onSelect(it.key)}
disabled={disabled}
className={`w-full text-left p-3 sm:p-4 min-h-[48px] sm:min-h-[52px] flex items-center justify-between ${disabled ? 'opacity-60 cursor-not-allowed' : 'cursor-pointer hover:bg-black/10'} ${selected === it.key ? 'bg-black/10' : ''} focus-visible:outline-none focus-visible:ring-[#2563EB] focus-visible:ring-[3px] focus-visible:ring-offset-2 focus-visible:ring-offset-white`}
aria-pressed={selected === it.key}
aria-expanded={selected === it.key}
aria-controls={`panel-${it.key}`}
>
<div className="flex-1">
<div className="text-sm sm:text-base font-semibold text-black">{it.title}</div>
{it.key === 'bank_transfer' && it.subtitle && (
<div className="mt-0.5 sm:mt-1 text-[10px] sm:text-xs text-black/60">
{it.subtitle}
</div>
)}
{it.key === 'cpay' && it.subtitle && (
<div className="mt-0.5 sm:mt-1 text-[10px] sm:text-xs text-black/60">
{it.subtitle}
</div>
)}
</div>
<div className="flex items-center gap-1.5 sm:gap-2">
{it.icon && (
<span aria-hidden>
{it.icon}
</span>
)}
<span aria-hidden className={`text-black/60 text-base sm:text-lg transition-transform ${selected === it.key ? 'rotate-90' : ''}`}></span>
</div>
</button>
{selected === it.key && renderPanel && (
<div id={`panel-${it.key}`} className="p-2.5 sm:p-3 bg-white">
{renderPanel(it.key)}
</div>
)}
</div>
))}
</div>
</div>
)
}