'use client'; import { useCallback, useMemo } from 'react'; import { cn, pressable, text, prefixClassName } from '../../styles/theme'; import { useAccount } from 'wagmi'; import { useAnalytics } from '../../core/analytics/hooks/useAnalytics'; import { FundEvent } from '../../core/analytics/types'; import { usePopupMonitor } from '@/buy/hooks/usePopupMonitor'; import { ErrorSvg } from '@/internal/svg/errorSvg'; import { openPopup } from '@/internal/utils/openPopup'; import { Spinner } from '../../internal/components/Spinner'; import { AddSvg } from '../../internal/svg/addSvg'; import { SuccessSvg } from '../../internal/svg/successSvg'; import { ConnectWallet } from '../../wallet/components/ConnectWallet'; import { useGetFundingUrl } from '../hooks/useGetFundingUrl'; import type { FundButtonProps } from '../types'; import { getFundingPopupSize } from '../utils/getFundingPopupSize'; export function FundButton({ className, children, disabled = false, fundingUrl, openIn = 'popup', popupSize = 'md', target, state: buttonState = 'default', fiatCurrency = 'USD', onPopupClose, onClick, render, sessionToken, }: FundButtonProps) { // If the fundingUrl prop is undefined, fallback to our recommended funding URL based on the wallet type const fallbackFundingUrl = useGetFundingUrl({ fiatCurrency, originComponentName: 'FundButton', sessionToken, }); const { address } = useAccount(); const fundingUrlToRender = fundingUrl ?? fallbackFundingUrl; const isDisabled = disabled || !fundingUrlToRender; const { startPopupMonitor } = usePopupMonitor(onPopupClose); const { sendAnalytics } = useAnalytics(); const handleAnalyticsInitiated = useCallback(() => { sendAnalytics(FundEvent.FundInitiated, { currency: fiatCurrency, }); }, [sendAnalytics, fiatCurrency]); const handleAnalyticsFailure = useCallback( (error: string) => { sendAnalytics(FundEvent.FundFailure, { error, metadata: { currency: fiatCurrency }, }); }, [sendAnalytics, fiatCurrency], ); const handleClick = useCallback( (e: React.MouseEvent) => { e.preventDefault(); if (fundingUrlToRender && openIn === 'tab') { handleAnalyticsInitiated(); onClick?.(); window.open(fundingUrlToRender, '_blank'); return; } if (fundingUrlToRender) { handleAnalyticsInitiated(); onClick?.(); const { height, width } = getFundingPopupSize( popupSize, fundingUrlToRender, ); const popupWindow = openPopup({ url: fundingUrlToRender, height, width, target, }); if (popupWindow) { startPopupMonitor(popupWindow); } else { handleAnalyticsFailure('Failed to open funding popup'); } } }, [ fundingUrlToRender, openIn, handleAnalyticsInitiated, onClick, popupSize, target, startPopupMonitor, handleAnalyticsFailure, ], ); const buttonColorClass = useMemo(() => { if (buttonState === 'error') { return prefixClassName('bg-ock-error'); } return pressable.primary; }, [buttonState]); const classNames = cn( buttonColorClass, 'rounded-ock-default px-4 py-3 inline-flex items-center justify-center space-x-2', { [pressable.disabled]: isDisabled, }, text.headline, 'text-ock-foreground-inverse', className, ); const buttonIcon = useMemo(() => { switch (buttonState) { case 'loading': return ''; case 'success': return ; case 'error': return ; default: return ; } }, [buttonState]); const buttonTextContent = useMemo(() => { switch (buttonState) { case 'loading': return ''; case 'success': return 'Success'; case 'error': return 'Something went wrong'; default: return 'Fund'; } }, [buttonState]); const buttonContent = useMemo(() => { if (buttonState === 'loading') { return ; } return ( <> {buttonIcon && ( {buttonIcon} )} {buttonTextContent} ); }, [buttonState, buttonIcon, buttonTextContent]); if (!address) { return ; } if (render) { return render({ status: buttonState, onClick: handleClick, isDisabled, }); } return ( ); }