import React, { useState, useEffect } from 'react'; import { useNavigate } from 'react-router-dom'; import { useTranslation } from 'react-i18next'; import { Card, CardContent } from '@/components/ui/card'; import { Button } from '@/components/ui/button'; import { Badge } from '@/components/ui/badge'; import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'; import { Avatar, AvatarFallback } from '@/components/ui/avatar'; import { ArrowLeft, Clock, CheckCircle2, XCircle, AlertTriangle, Loader2, ArrowUpRight, ArrowDownLeft, RefreshCw, FileText, } from 'lucide-react'; import { useP2PIdentity } from '@/contexts/P2PIdentityContext'; import { toast } from 'sonner'; import { supabase } from '@/lib/supabase'; import { type P2PFiatTrade, type P2PFiatOffer } from '@shared/lib/p2p-fiat'; // Trade status type type TradeStatus = 'pending' | 'payment_sent' | 'completed' | 'cancelled' | 'disputed' | 'refunded'; // Extended trade with offer details interface TradeWithOffer extends P2PFiatTrade { offer?: P2PFiatOffer; } export default function P2POrders() { const navigate = useNavigate(); const { t } = useTranslation(); const { userId } = useP2PIdentity(); const [trades, setTrades] = useState([]); const [loading, setLoading] = useState(true); const [activeTab, setActiveTab] = useState('active'); // Fetch user's trades const fetchTrades = async () => { if (!userId) { setLoading(false); return; } setLoading(true); try { // Fetch all trades where user is buyer or seller const { data: tradesData, error } = await supabase .from('p2p_fiat_trades') .select('*') .or(`seller_id.eq.${userId},buyer_id.eq.${userId}`) .order('created_at', { ascending: false }); if (error) throw error; // Fetch offer details for each trade const tradesWithOffers = await Promise.all( (tradesData || []).map(async (trade) => { const { data: offerData } = await supabase .from('p2p_fiat_offers') .select('*') .eq('id', trade.offer_id) .single(); return { ...trade, offer: offerData || undefined, }; }) ); setTrades(tradesWithOffers); } catch (error) { console.error('Fetch trades error:', error); toast.error(t('p2pOrders.failedToLoad')); } finally { setLoading(false); } }; useEffect(() => { fetchTrades(); // eslint-disable-next-line react-hooks/exhaustive-deps }, [userId]); // Filter trades by status const activeTrades = trades.filter(t => ['pending', 'payment_sent', 'disputed'].includes(t.status) ); const completedTrades = trades.filter(t => t.status === 'completed'); const cancelledTrades = trades.filter(t => ['cancelled', 'refunded'].includes(t.status) ); // Get status badge const getStatusBadge = (status: TradeStatus) => { switch (status) { case 'pending': return ( {t('p2pOrders.awaitingPayment')} ); case 'payment_sent': return ( {t('p2pOrders.paymentSent')} ); case 'completed': return ( {t('p2pOrders.completed')} ); case 'cancelled': return ( {t('p2pOrders.cancelled')} ); case 'disputed': return ( {t('p2pOrders.disputed')} ); case 'refunded': return ( {t('p2pOrders.refunded')} ); default: return {status}; } }; // Render trade card const renderTradeCard = (trade: TradeWithOffer) => { const isBuyer = trade.buyer_id === userId; const counterpartyWallet = isBuyer ? trade.offer?.seller_wallet || 'Unknown' : trade.buyer_wallet; const timeAgo = (date: string) => { const seconds = Math.floor((Date.now() - new Date(date).getTime()) / 1000); if (seconds < 60) return t('p2p.justNow'); const minutes = Math.floor(seconds / 60); if (minutes < 60) return t('p2p.minutesAgo', { count: minutes }); const hours = Math.floor(minutes / 60); if (hours < 24) return t('p2p.hoursAgo', { count: hours }); const days = Math.floor(hours / 24); return t('p2p.daysAgo', { count: days }); }; return ( navigate(`/p2p/trade/${trade.id}`)} >
{/* Direction Icon */}
{isBuyer ? ( ) : ( )}
{/* Trade Info */}
{isBuyer ? t('p2p.buy') : t('p2p.sell')} {trade.crypto_amount} {trade.offer?.token || 'HEZ'} {getStatusBadge(trade.status as TradeStatus)}
{counterpartyWallet.slice(0, 2).toUpperCase()} {counterpartyWallet.slice(0, 8)}...{counterpartyWallet.slice(-4)} {timeAgo(trade.created_at)}
{/* Amount */}

{trade.fiat_amount.toFixed(2)} {trade.offer?.fiat_currency || 'TRY'}

@ {trade.price_per_unit.toFixed(2)}/{trade.offer?.token || 'HEZ'}

{/* Deadline warning for pending trades */} {trade.status === 'pending' && trade.payment_deadline && (
{t('p2pOrders.paymentDeadline', { time: new Date(trade.payment_deadline).toLocaleTimeString() })}
)}
); }; // Render empty state const renderEmptyState = (message: string) => (

{message}

); if (!userId) { return (

{t('p2p.loginRequired')}

{t('p2p.loginToView')}

); } return (
{/* Header */}
{/* Title */}

{t('p2pOrders.title')}

{t('p2pOrders.subtitle')}

{/* Stats Cards */}

{activeTrades.length}

{t('p2pOrders.active')}

{completedTrades.length}

{t('p2pOrders.completed')}

{cancelledTrades.length}

{t('p2pOrders.cancelled')}

{/* Tabs */} {t('p2pOrders.active')} {activeTrades.length > 0 && ( {activeTrades.length} )} {t('p2pOrders.completed')} {t('p2pOrders.cancelled')} {loading ? (
) : ( <> {activeTrades.length === 0 ? renderEmptyState(t('p2pOrders.noActiveTrades')) : activeTrades.map(renderTradeCard) } {completedTrades.length === 0 ? renderEmptyState(t('p2pOrders.noCompletedTrades')) : completedTrades.map(renderTradeCard) } {cancelledTrades.length === 0 ? renderEmptyState(t('p2pOrders.noCancelledTrades')) : cancelledTrades.map(renderTradeCard) } )}
); }