74 lines
2.2 KiB
TypeScript
74 lines
2.2 KiB
TypeScript
'use client'
|
|
|
|
import { useEffect, useCallback } from 'react'
|
|
|
|
interface TransakWidgetProps {
|
|
widgetUrl: string
|
|
onClose: () => void
|
|
onComplete?: (orderId: string) => void
|
|
}
|
|
|
|
export default function TransakWidget({ widgetUrl, onClose, onComplete }: TransakWidgetProps) {
|
|
const handleMessage = useCallback(
|
|
(event: MessageEvent) => {
|
|
// Transak sends postMessage events from its iframe
|
|
const data = event.data
|
|
if (!data || typeof data !== 'object') return
|
|
|
|
switch (data.event_id || data.eventName) {
|
|
case 'TRANSAK_ORDER_SUCCESSFUL': {
|
|
const orderId = data.data?.id || data.data?.orderId || 'unknown'
|
|
onComplete?.(orderId)
|
|
onClose()
|
|
break
|
|
}
|
|
case 'TRANSAK_ORDER_FAILED': {
|
|
// Brief display then close — the parent can show a status message
|
|
onClose()
|
|
break
|
|
}
|
|
case 'TRANSAK_WIDGET_CLOSE': {
|
|
onClose()
|
|
break
|
|
}
|
|
}
|
|
},
|
|
[onClose, onComplete]
|
|
)
|
|
|
|
useEffect(() => {
|
|
window.addEventListener('message', handleMessage)
|
|
return () => window.removeEventListener('message', handleMessage)
|
|
}, [handleMessage])
|
|
|
|
return (
|
|
<div
|
|
className="fixed inset-0 bg-black/60 flex items-center justify-center z-[70]"
|
|
onClick={onClose}
|
|
>
|
|
<div
|
|
className="relative bg-white rounded-2xl shadow-2xl overflow-hidden"
|
|
style={{ width: 500, height: 650 }}
|
|
onClick={(e) => e.stopPropagation()}
|
|
>
|
|
{/* Close button */}
|
|
<button
|
|
onClick={onClose}
|
|
className="absolute top-3 right-3 z-10 w-8 h-8 bg-white/90 hover:bg-white rounded-full flex items-center justify-center shadow-md transition-colors"
|
|
>
|
|
<svg className="w-4 h-4 text-slate-600" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
|
|
</svg>
|
|
</button>
|
|
|
|
<iframe
|
|
src={widgetUrl}
|
|
title="Transak On-Ramp"
|
|
className="w-full h-full border-0"
|
|
allow="camera;microphone;payment"
|
|
/>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|