import React, { useState, useMemo, useCallback } from 'react';
import { StyleSheet, Text, TouchableOpacity, type ViewStyle } from 'react-native';
import { useDubsTheme } from '../theme';
import { useDubs } from '../../provider';
import { useGame } from '../../hooks/useGame';
import { useHasClaimed } from '../../hooks/useHasClaimed';
import { ClaimPrizeSheet } from './ClaimPrizeSheet';
import type { ClaimMutationResult } from '../../hooks/useClaim';
export interface ClaimButtonProps {
gameId: string;
style?: ViewStyle;
onSuccess?: (result: ClaimMutationResult) => void;
onError?: (error: Error) => void;
}
/**
* Drop-in claim button that handles eligibility checks, prize/refund display,
* and the claim sheet lifecycle internally.
*
* Renders nothing when the user is ineligible (lost, not resolved, not a bettor, etc.).
*/
export function ClaimButton({ gameId, style, onSuccess, onError }: ClaimButtonProps) {
const t = useDubsTheme();
const { wallet } = useDubs();
const game = useGame(gameId);
const claimStatus = useHasClaimed(gameId);
const [sheetVisible, setSheetVisible] = useState(false);
const walletAddress = wallet.publicKey?.toBase58() ?? null;
const myBet = useMemo(() => {
if (!walletAddress || !game.data?.bettors) return null;
return game.data.bettors.find(b => b.wallet === walletAddress) ?? null;
}, [walletAddress, game.data?.bettors]);
const isResolved = game.data?.isResolved ?? false;
const isRefund = isResolved && game.data?.winnerSide === null;
const isWinner = isResolved && myBet != null && myBet.team === game.data?.winnerSide;
const isEligible = myBet != null && isResolved && (isWinner || isRefund);
const prizeAmount = isRefund ? (myBet?.amount ?? 0) : (game.data?.totalPool ?? 0);
const handleSuccess = useCallback(
(result: ClaimMutationResult) => {
claimStatus.refetch();
onSuccess?.(result);
},
[claimStatus.refetch, onSuccess], // eslint-disable-line react-hooks/exhaustive-deps
);
// Don't render while loading or missing wallet/data
if (game.loading || claimStatus.loading || !game.data || !walletAddress) {
return null;
}
const label = isRefund ? 'Refund' : 'Prize';
// Already claimed — always show badge regardless of eligibility computation
if (claimStatus.hasClaimed) {
return (
{label} Claimed!
);
}
// Not eligible (lost, not resolved, not a bettor) — render nothing
if (!isEligible) {
return null;
}
return (
<>
setSheetVisible(true)}
>
Claim {label} — {prizeAmount} SOL
setSheetVisible(false)}
gameId={gameId}
prizeAmount={prizeAmount}
isRefund={isRefund}
onSuccess={handleSuccess}
onError={onError}
/>
>
);
}
const styles = StyleSheet.create({
button: {
height: 52,
borderRadius: 14,
justifyContent: 'center',
alignItems: 'center',
paddingHorizontal: 20,
},
buttonText: {
color: '#FFFFFF',
fontSize: 16,
fontWeight: '700',
},
badge: {
height: 52,
borderRadius: 14,
borderWidth: 2,
justifyContent: 'center',
alignItems: 'center',
paddingHorizontal: 20,
},
badgeText: {
fontSize: 16,
fontWeight: '700',
},
});