import React, { useState } from 'react'; import { Card } from './ui/card'; import { Badge } from './ui/badge'; import { Button } from './ui/button'; import { Tabs, TabsContent, TabsList, TabsTrigger } from './ui/tabs'; import { Receipt, CreditCard, Heart, Calendar, ExternalLink, DollarSign } from 'lucide-react'; /** * TransactionHistory Component * Displays user transaction history including subscriptions and donations * * @param {Object} props * @param {Array} props.subscriptions - List of subscription transactions * @param {Array} props.donations - List of donation transactions * @param {number} props.totalSubscriptionCents - Total subscription amount in cents * @param {number} props.totalDonationCents - Total donation amount in cents * @param {boolean} props.loading - Loading state * @param {boolean} props.isAdmin - Whether viewing as admin (shows extra fields) */ const TransactionHistory = ({ subscriptions = [], donations = [], totalSubscriptionCents = 0, totalDonationCents = 0, loading = false, isAdmin = false }) => { const [activeTab, setActiveTab] = useState('all'); const formatAmount = (cents) => { if (!cents) return '$0.00'; return `$${(cents / 100).toFixed(2)}`; }; const formatDate = (dateString) => { if (!dateString) return 'N/A'; return new Date(dateString).toLocaleDateString('en-US', { year: 'numeric', month: 'short', day: 'numeric' }); }; const getStatusBadgeClass = (status) => { switch (status?.toLowerCase()) { case 'active': case 'completed': return 'bg-green-100 text-green-800 border-green-200'; case 'pending': return 'bg-yellow-100 text-yellow-800 border-yellow-200'; case 'cancelled': case 'failed': case 'expired': return 'bg-red-100 text-red-800 border-red-200'; default: return 'bg-gray-100 text-gray-800 border-gray-200'; } }; const allTransactions = [ ...subscriptions.map(s => ({ ...s, sortDate: s.created_at })), ...donations.map(d => ({ ...d, sortDate: d.created_at })) ].sort((a, b) => new Date(b.sortDate) - new Date(a.sortDate)); const TransactionRow = ({ transaction }) => { const isSubscription = transaction.type === 'subscription'; return (
{isSubscription ? ( ) : ( )}
{transaction.description} {transaction.status}
{formatDate(transaction.payment_completed_at || transaction.created_at)} {transaction.card_brand && transaction.card_last4 && ( <> {transaction.card_brand} ****{transaction.card_last4} )} {isSubscription && transaction.billing_cycle && ( <> {transaction.billing_cycle} )}
{isAdmin && transaction.manual_payment && (
Manual Payment {transaction.manual_payment_notes && `- ${transaction.manual_payment_notes}`}
)}
{formatAmount(transaction.amount_cents)}
{isSubscription && transaction.donation_cents > 0 && (
(incl. {formatAmount(transaction.donation_cents)} donation)
)}
{transaction.stripe_receipt_url && ( )}
); }; const EmptyState = ({ type }) => (
{type === 'subscription' ? ( ) : type === 'donation' ? ( ) : ( )}

{type === 'subscription' ? 'No subscription payments yet' : type === 'donation' ? 'No donations yet' : 'No transactions yet'}

); if (loading) { return (
); } return (

Transaction History

{/* Summary Cards */}
Total Subscriptions
{formatAmount(totalSubscriptionCents)}
{subscriptions.length} payment(s)
Total Donations
{formatAmount(totalDonationCents)}
{donations.length} donation(s)
{/* Tabs */} All ({allTransactions.length}) Subscriptions ({subscriptions.length}) Donations ({donations.length})
{allTransactions.length > 0 ? ( allTransactions.map((transaction) => ( )) ) : ( )} {subscriptions.length > 0 ? ( subscriptions.map((transaction) => ( )) ) : ( )} {donations.length > 0 ? ( donations.map((transaction) => ( )) ) : ( )}
); }; export default TransactionHistory;