78 lines
3.8 KiB
TypeScript
78 lines
3.8 KiB
TypeScript
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-3">
|
||
<div className="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-4 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-base font-semibold text-black">{it.title}</div>
|
||
{it.key === 'bank_transfer' && it.subtitle && (
|
||
<div className="mt-1 text-xs text-black/60">
|
||
{it.subtitle}
|
||
</div>
|
||
)}
|
||
{it.key === 'cpay' && it.subtitle && (
|
||
<div className="mt-1 text-xs text-black/60">
|
||
{it.subtitle}
|
||
</div>
|
||
)}
|
||
</div>
|
||
<div className="flex items-center gap-2">
|
||
{it.icon && (
|
||
<span aria-hidden>
|
||
{it.icon}
|
||
</span>
|
||
)}
|
||
<span aria-hidden className={`text-black/60 text-lg transition-transform ${selected === it.key ? 'rotate-90' : ''}`}>›</span>
|
||
</div>
|
||
</button>
|
||
{selected === it.key && renderPanel && (
|
||
<div id={`panel-${it.key}`} className="p-3 bg-white">
|
||
{renderPanel(it.key)}
|
||
</div>
|
||
)}
|
||
</div>
|
||
))}
|
||
</div>
|
||
</div>
|
||
)
|
||
} |