import React, { useState, useEffect, useRef } from 'react'; import { StyleSheet, TouchableOpacity, Image } from 'react-native'; import { View, Text, useTheme } from '@bettoredge/styles'; import { Ionicons } from '@expo/vector-icons'; import type { CalcuttaAuctionItemProps, CalcuttaBidProps } from '@bettoredge/types'; import { formatCurrency, getStatusLabel, getItemStatusColor, getBidStatusColor } from '../helpers/formatting'; import { CalcuttaBidInput } from './CalcuttaBidInput'; export interface CalcuttaAuctionItemComponentProps { item: CalcuttaAuctionItemProps; my_bid?: CalcuttaBidProps; auction_type: 'sealed_bid' | 'live'; min_bid: number; bid_increment: number; escrow_balance: number; onPlaceBid: (amount: number) => void; is_active_item?: boolean; is_paused?: boolean; itemImage?: { url: string }; highest_bidder?: { username?: string; profile_pic?: string; is_me?: boolean }; winner?: { username?: string; profile_pic?: string; is_me?: boolean }; } const getTimerColor = (secondsLeft: number, theme: any) => { if (secondsLeft > 30) return theme.colors.status.success; if (secondsLeft > 10) return '#F59E0B'; // amber/yellow return theme.colors.status.error; }; export const CalcuttaAuctionItem: React.FC = ({ item, my_bid, auction_type, min_bid, bid_increment, escrow_balance, onPlaceBid, is_active_item, is_paused, itemImage, highest_bidder, winner, }) => { const { theme } = useTheme(); const [expanded, setExpanded] = useState(!!is_active_item); // Auto-expand when this item becomes active useEffect(() => { if (is_active_item) setExpanded(true); }, [is_active_item]); // Per-item countdown for live auction const [secondsLeft, setSecondsLeft] = useState(null); const countdownRef = useRef | null>(null); useEffect(() => { if (countdownRef.current) clearInterval(countdownRef.current); setSecondsLeft(null); if (!item.item_deadline || item.status !== 'active' || is_paused) return; const updateTimer = () => { const deadline = new Date(item.item_deadline).getTime(); const diff = Math.max(0, (deadline - Date.now()) / 1000); setSecondsLeft(diff); if (diff <= 0 && countdownRef.current) { clearInterval(countdownRef.current); } }; updateTimer(); countdownRef.current = setInterval(updateTimer, 100); return () => { if (countdownRef.current) clearInterval(countdownRef.current); }; }, [item.item_deadline, item.status, is_paused]); const canBid = auction_type === 'live' ? item.status === 'active' && is_active_item && !is_paused : (item.status === 'active' || item.status === 'pending') && !is_paused; const statusColor = getItemStatusColor(item.status); const isSold = item.status === 'sold'; const isUpcoming = auction_type === 'live' && item.status === 'pending'; const itemOpacity = (isSold || item.status === 'unsold') ? 0.5 : isUpcoming ? 0.7 : 1; // Format seconds to display const formatCountdown = (s: number) => { if (s >= 60) { const min = Math.floor(s / 60); const sec = Math.floor(s % 60); return `${min}:${sec.toString().padStart(2, '0')}`; } return s.toFixed(1); }; // ══════════════════════════════════════ // ACTIVE ITEM — hero card, always expanded // ══════════════════════════════════════ if (is_active_item && auction_type === 'live') { const timerColor = secondsLeft != null && secondsLeft > 0 ? getTimerColor(secondsLeft, theme) : theme.colors.text.tertiary; const isUrgent = secondsLeft != null && secondsLeft <= 10 && secondsLeft > 0; return ( {/* Top bar: item info + timer */} {(itemImage?.url || item.item_image?.url) ? ( ) : ( )} {item.item_name} {item.seed != null && Seed #{item.seed}} {highest_bidder && item.current_bid > 0 && ( {highest_bidder.profile_pic ? ( ) : ( {(highest_bidder.username || '?').charAt(0).toUpperCase()} )} {highest_bidder.is_me ? 'You' : highest_bidder.username || 'Unknown'} {highest_bidder.is_me && ( )} )} {/* Current bid + highest bidder + timer row */} Current Bid {item.current_bid > 0 ? formatCurrency(item.current_bid) : 'No bids yet'} {secondsLeft != null && secondsLeft > 0 && !is_paused && ( {formatCountdown(secondsLeft)} {isUrgent && item.current_bid > 0 && ( Going! )} )} {/* Bid input — always visible */} {canBid && ( )} ); } // ══════════════════════════════════════ // INACTIVE ITEMS — compact rows // ══════════════════════════════════════ return ( canBid && setExpanded(!expanded)} disabled={!canBid} > {(itemImage?.url || item.item_image?.url) ? ( ) : ( )} {item.item_name}{item.seed != null ? ` #${item.seed}` : ''} {getStatusLabel(item.status)} {my_bid && ( {getStatusLabel(my_bid.bid_status)} )} {isSold && item.winning_bid > 0 && ( Sold: {formatCurrency(item.winning_bid)} )} {isSold && winner && ( {winner.profile_pic ? ( ) : ( {(winner.username || '?').charAt(0).toUpperCase()} )} {winner.is_me ? 'You' : winner.username || 'Unknown'} )} {auction_type === 'sealed_bid' ? 'Your Bid' : isSold ? 'Winning Bid' : 'Current Bid'} {auction_type === 'sealed_bid' ? my_bid ? formatCurrency(my_bid.bid_amount) : '-' : (isSold ? item.winning_bid : item.current_bid) > 0 ? formatCurrency(isSold ? item.winning_bid : item.current_bid) : '-'} {canBid && } {expanded && canBid && ( )} ); }; const styles = StyleSheet.create({ // ── Active item hero card ── activeCard: { marginHorizontal: 12, marginVertical: 8, borderRadius: 16, borderWidth: 1.5, padding: 16, }, activeHeader: { flexDirection: 'row', alignItems: 'center', }, activeImage: { width: 52, height: 52, borderRadius: 12, alignItems: 'center', justifyContent: 'center', }, activeBidRow: { flexDirection: 'row', alignItems: 'center', marginTop: 14, paddingTop: 14, borderTopWidth: 1, borderTopColor: 'rgba(128,128,128,0.15)', }, activeBidAmount: { fontSize: 28, lineHeight: 37, fontWeight: '800', marginTop: 2, }, activeTimerBox: { flexDirection: 'row', alignItems: 'center', paddingHorizontal: 12, paddingVertical: 8, borderRadius: 10, borderWidth: 1, }, activeTimerText: { fontSize: 20, lineHeight: 26, fontWeight: '800', marginLeft: 6, }, // ── Inactive item rows ── container: { borderBottomWidth: 1, }, row: { flexDirection: 'row', alignItems: 'center', padding: 12, }, imageContainer: { height: 36, width: 36, borderRadius: 8, alignItems: 'center', justifyContent: 'center', }, info: { flex: 1, marginLeft: 10, marginRight: 10, }, statusRow: { flexDirection: 'row', alignItems: 'center', flexWrap: 'wrap', marginTop: 3, }, statusBadge: { paddingHorizontal: 6, paddingVertical: 2, borderRadius: 4, }, bidStatus: { flexDirection: 'row', alignItems: 'center', marginLeft: 6, }, rightColumn: { alignItems: 'flex-end', minWidth: 70, }, bidInputContainer: { paddingHorizontal: 12, paddingBottom: 12, borderTopWidth: 1, }, });