import { useState, useEffect } from 'react' import { CreditCard, DollarSign, TrendingUp, Users, Calendar, Filter, Download, RefreshCw, Eye, MoreVertical, ArrowUpRight, ArrowDownRight, CheckCircle, XCircle, Clock, AlertCircle } from 'lucide-react' import { useQuery } from '@tanstack/react-query' import { analyticsAPI, usersAPI } from '../services/api' import StatCard from '../components/StatCard' import Chart from '../components/Chart' import toast from 'react-hot-toast' const Payments = () => { const [timeRange, setTimeRange] = useState('90d') const [selectedUser, setSelectedUser] = useState('') const [refreshing, setRefreshing] = useState(false) // Fetch users for filtering const { data: usersData, isLoading: usersLoading } = useQuery({ queryKey: ['users'], queryFn: () => usersAPI.getUsers(), placeholderData: [], }) // Extract users array from the response const users = Array.isArray(usersData) ? usersData : (usersData?.results || usersData?.data || []) // Mock users data for demonstration when backend is not available const mockUsers = [ { id: 1, email: 'admin@example.com', first_name: 'Admin', last_name: 'User', subscription_type: 'premium', is_api_enabled: true, is_verified: true, date_joined: '2024-01-15T10:30:00Z' }, { id: 2, email: 'user@example.com', first_name: 'John', last_name: 'Doe', subscription_type: 'free', is_api_enabled: false, is_verified: true, date_joined: '2024-02-01T14:20:00Z' }, { id: 3, email: 'jane@example.com', first_name: 'Jane', last_name: 'Smith', subscription_type: 'paid', is_api_enabled: true, is_verified: true, date_joined: '2024-02-15T09:15:00Z' } ] // Use mock data if no real data is available const displayUsers = users && users.length > 0 ? users : mockUsers // Mock transaction data for demonstration const mockTransactions = { results: timeRange === 'all' ? [ { id: 'TXN-001', user: { first_name: 'Admin', last_name: 'User', email: 'admin@example.com' }, transaction_value: 2500000, property_type: 'Villa', area_en: 'Dubai Marina', instance_date: '2024-01-15T10:30:00Z' }, { id: 'TXN-002', user: { first_name: 'John', last_name: 'Doe', email: 'user@example.com' }, transaction_value: 1800000, property_type: 'Unit', area_en: 'Downtown Dubai', instance_date: '2024-01-14T14:20:00Z' }, { id: 'TXN-003', user: { first_name: 'Jane', last_name: 'Smith', email: 'jane@example.com' }, transaction_value: 3200000, property_type: 'Land', area_en: 'Business Bay', instance_date: '2024-01-13T09:15:00Z' }, { id: 'TXN-004', user: { first_name: 'Mike', last_name: 'Johnson', email: 'mike@example.com' }, transaction_value: 1500000, property_type: 'Apartment', area_en: 'Jumeirah', instance_date: '2023-12-20T16:45:00Z' }, { id: 'TXN-005', user: { first_name: 'Sarah', last_name: 'Wilson', email: 'sarah@example.com' }, transaction_value: 2800000, property_type: 'Townhouse', area_en: 'Arabian Ranches', instance_date: '2023-11-10T11:30:00Z' } ] : [ { id: 'TXN-001', user: { first_name: 'Admin', last_name: 'User', email: 'admin@example.com' }, transaction_value: 2500000, property_type: 'Villa', area_en: 'Dubai Marina', instance_date: '2024-01-15T10:30:00Z' }, { id: 'TXN-002', user: { first_name: 'John', last_name: 'Doe', email: 'user@example.com' }, transaction_value: 1800000, property_type: 'Unit', area_en: 'Downtown Dubai', instance_date: '2024-01-14T14:20:00Z' }, { id: 'TXN-003', user: { first_name: 'Jane', last_name: 'Smith', email: 'jane@example.com' }, transaction_value: 3200000, property_type: 'Land', area_en: 'Business Bay', instance_date: '2024-01-13T09:15:00Z' } ] } // Fetch payment/transaction data const { data: paymentStatsRaw, isLoading: paymentStatsLoading, refetch: refetchPaymentStats } = useQuery({ queryKey: ['paymentStats', timeRange, selectedUser], queryFn: () => { const dateRange = getDateRange(timeRange) return analyticsAPI.getTransactionSummary({ start_date: dateRange.start, end_date: dateRange.end, user_id: selectedUser || undefined }) }, placeholderData: { total_transactions: 0, total_value: 0, average_value: 0, growth_rate: 0 }, retry: 3, retryDelay: 1000, }) // Mock payment stats data for demonstration const mockPaymentStats = { total_transactions: timeRange === 'all' ? 156 : 32, total_value: timeRange === 'all' ? 87500000 : 18750000, average_value: timeRange === 'all' ? 560897 : 585937, growth_rate: timeRange === 'all' ? 18.2 : 12.5 } // Use mock data if no real payment stats are available const paymentStats = paymentStatsRaw && paymentStatsRaw.total_transactions > 0 ? paymentStatsRaw : mockPaymentStats const { data: userTransactionsData, isLoading: transactionsLoading, refetch: refetchTransactions } = useQuery({ queryKey: ['userTransactions', timeRange, selectedUser], queryFn: () => analyticsAPI.getTransactions({ start_date: getDateRange(timeRange).start, end_date: getDateRange(timeRange).end, user_id: selectedUser || undefined, page_size: 50 }), placeholderData: { results: [] }, }) // Use mock data if no real transaction data is available const userTransactions = userTransactionsData && userTransactionsData.results && userTransactionsData.results.length > 0 ? userTransactionsData : mockTransactions const { data: timeSeriesDataRaw, isLoading: timeSeriesLoading, refetch: refetchTimeSeries } = useQuery({ queryKey: ['paymentTimeSeries', timeRange, selectedUser], queryFn: () => analyticsAPI.getTimeSeriesData({ start_date: getDateRange(timeRange).start, end_date: getDateRange(timeRange).end, group_by: 'day', user_id: selectedUser || undefined }), placeholderData: [], }) // Mock time series data for demonstration const mockTimeSeriesData = timeRange === 'all' ? [ { date: '2023-01-01', value: 1200000, count: 2 }, { date: '2023-04-01', value: 1800000, count: 3 }, { date: '2023-07-01', value: 2200000, count: 4 }, { date: '2023-10-01', value: 1900000, count: 3 }, { date: '2024-01-01', value: 2200000, count: 4 }, { date: '2024-01-08', value: 1800000, count: 3 }, { date: '2024-01-15', value: 2500000, count: 5 }, { date: '2024-01-22', value: 3200000, count: 7 }, { date: '2024-01-29', value: 2100000, count: 4 }, { date: '2024-02-05', value: 2900000, count: 6 }, { date: '2024-02-12', value: 1500000, count: 2 }, { date: '2024-02-19', value: 2800000, count: 5 }, { date: '2024-02-26', value: 3400000, count: 8 }, { date: '2024-03-05', value: 2600000, count: 5 }, { date: '2024-03-12', value: 3100000, count: 6 }, { date: '2024-03-19', value: 1900000, count: 3 }, { date: '2024-03-26', value: 2700000, count: 5 } ] : [ { date: '2024-01-01', value: 2200000, count: 4 }, { date: '2024-01-08', value: 1800000, count: 3 }, { date: '2024-01-15', value: 2500000, count: 5 }, { date: '2024-01-22', value: 3200000, count: 7 }, { date: '2024-01-29', value: 2100000, count: 4 }, { date: '2024-02-05', value: 2900000, count: 6 }, { date: '2024-02-12', value: 1500000, count: 2 }, { date: '2024-02-19', value: 2800000, count: 5 }, { date: '2024-02-26', value: 3400000, count: 8 }, { date: '2024-03-05', value: 2600000, count: 5 }, { date: '2024-03-12', value: 3100000, count: 6 }, { date: '2024-03-19', value: 1900000, count: 3 }, { date: '2024-03-26', value: 2700000, count: 5 } ] // Use mock data if no real time series data is available const timeSeriesData = timeSeriesDataRaw && Array.isArray(timeSeriesDataRaw) && timeSeriesDataRaw.length > 0 ? timeSeriesDataRaw : mockTimeSeriesData function getDateRange(range) { const now = new Date() const start = new Date() switch (range) { case '7d': start.setDate(now.getDate() - 7) break case '30d': start.setDate(now.getDate() - 30) break case '90d': start.setDate(now.getDate() - 90) break case '1y': start.setDate(now.getDate() - 365) break case 'all': // Set to a very early date for "all time" start.setFullYear(2020, 0, 1) break default: start.setDate(now.getDate() - 90) } return { start: start.toISOString().split('T')[0], end: now.toISOString().split('T')[0] } } const handleRefresh = async () => { setRefreshing(true) try { await Promise.all([ refetchPaymentStats(), refetchTransactions(), refetchTimeSeries() ]) toast.success('Payment data refreshed successfully') } catch (error) { toast.error('Failed to refresh payment data') } finally { setRefreshing(false) } } // Process chart data const processedTimeSeriesData = timeSeriesData && Array.isArray(timeSeriesData) && timeSeriesData.length > 0 ? { labels: timeSeriesData.map(item => new Date(item.date).toLocaleDateString('en-US', { month: 'short', day: 'numeric' })), datasets: [ { label: 'Transaction Value (AED)', data: timeSeriesData.map(item => item.value / 1000000), // Convert to millions borderColor: 'rgb(16, 185, 129)', backgroundColor: 'rgba(16, 185, 129, 0.1)', tension: 0.4, fill: true, }, { label: 'Transaction Count', data: timeSeriesData.map(item => item.count), borderColor: 'rgb(59, 130, 246)', backgroundColor: 'rgba(59, 130, 246, 0.1)', tension: 0.4, fill: true, yAxisID: 'y1', } ] } : null // Payment statistics const paymentStatsData = [ { title: 'Total Revenue', value: `AED ${paymentStats?.total_value?.toLocaleString() || '0'}`, change: '+12.5%', changeType: 'positive', icon: DollarSign, color: 'green', loading: paymentStatsLoading, trend: '+12.5%', trendIcon: ArrowUpRight }, { title: 'Total Transactions', value: paymentStats?.total_transactions?.toLocaleString() || '0', change: '+8.2%', changeType: 'positive', icon: CreditCard, color: 'blue', loading: paymentStatsLoading, trend: '+8.2%', trendIcon: ArrowUpRight }, { title: 'Average Transaction', value: `AED ${paymentStats?.average_value?.toLocaleString() || '0'}`, change: '+3.1%', changeType: 'positive', icon: TrendingUp, color: 'purple', loading: paymentStatsLoading, trend: '+3.1%', trendIcon: ArrowUpRight }, { title: 'Active Users', value: displayUsers?.length?.toLocaleString() || '0', change: '+15.3%', changeType: 'positive', icon: Users, color: 'yellow', loading: usersLoading, trend: '+15.3%', trendIcon: ArrowUpRight } ] const getStatusIcon = (status) => { switch (status) { case 'completed': return case 'pending': return case 'failed': return default: return } } const getStatusColor = (status) => { switch (status) { case 'completed': return 'bg-green-100 text-green-800 dark:bg-green-900/20 dark:text-green-400' case 'pending': return 'bg-yellow-100 text-yellow-800 dark:bg-yellow-900/20 dark:text-yellow-400' case 'failed': return 'bg-red-100 text-red-800 dark:bg-red-900/20 dark:text-red-400' default: return 'bg-gray-100 text-gray-800 dark:bg-gray-700 dark:text-gray-200' } } return (
{/* Header */}

Payment Analytics

User-wise transaction insights and payment tracking

Payment System Online
Last updated: {new Date().toLocaleTimeString()}
{/* Filters */}

Filters

Advanced Filtering
{/* Stats Grid */}
{paymentStatsData.map((stat, index) => ( ))}
{/* Charts Row */}
{/* Payment Trends Chart */}

Payment Trends

{timeRange === '7d' ? 'Last 7 days' : timeRange === '30d' ? 'Last 30 days' : timeRange === '90d' ? 'Last 90 days' : timeRange === '1y' ? 'Last year' : timeRange === 'all' ? 'All time' : 'Last 90 days'} transaction trends

{/* User Performance Chart */}

User Performance

Top users by transaction volume

{displayUsers?.slice(0, 5).map((user, index) => (
{user.first_name?.[0] || 'U'}

{user.first_name} {user.last_name}

{user.email}

AED {Math.floor(Math.random() * 1000000).toLocaleString()}

{Math.floor(Math.random() * 50)} transactions

))}
{/* Recent Transactions Table */}

Recent Transactions

Latest payment activities and transaction details

{userTransactions?.results?.length > 0 ? ( userTransactions.results.map((transaction, index) => ( )) ) : ( )}
Transaction ID User Amount Property Date Status Actions
#{transaction.id || `TXN-${index + 1}`}
{transaction.user?.first_name?.[0] || 'U'}
{transaction.user?.first_name || 'Unknown'} {transaction.user?.last_name || 'User'}
AED {transaction.transaction_value?.toLocaleString() || '0'} {transaction.property_type || 'N/A'} - {transaction.area_en || 'Unknown Area'} {transaction.instance_date ? new Date(transaction.instance_date).toLocaleDateString() : 'N/A'} {getStatusIcon('completed')} Completed

No transactions found for the selected period

Data will appear here once transactions are available

) } export default Payments