import { useState, useEffect, useCallback } from 'react'; import { DollarSign, ExternalLink } from 'lucide-react'; import { DataTable } from '../../components/ui/DataTable'; import { Badge } from '../../components/ui/Badge'; import { GradientButton } from '../../components/ui/GradientButton'; import { StatCard } from '../../components/ui/StatCard'; import { api } from '../../api/client'; import type { Payout } from '../../types/rental'; interface AccountStatus { connected: boolean; chargesEnabled: boolean; payoutsEnabled: boolean; onboardingUrl?: string; } export function LandlordPayoutsPage() { const [payouts, setPayouts] = useState([]); const [total, setTotal] = useState(0); const [page, setPage] = useState(1); const [accountStatus, setAccountStatus] = useState(null); const [connectLoading, setConnectLoading] = useState(false); const fetchPayouts = useCallback(async () => { try { const params = new URLSearchParams({ page: String(page), pageSize: '20' }); const res = await api.get(`/payouts?${params}`); setPayouts(res); setTotal(res.length); } catch { // silently fail } }, [page]); useEffect(() => { fetchPayouts(); api.get('/payouts/account-status').then(setAccountStatus).catch(() => {}); }, [fetchPayouts]); const handleSetupStripe = async () => { setConnectLoading(true); try { const { url } = await api.post<{ url: string }>('/payouts/setup-account'); window.location.href = url; } catch { setConnectLoading(false); } }; const statusBadge = (status: string) => { const map: Record = { COMPLETED: 'success', PROCESSING: 'info', PENDING: 'warning', FAILED: 'error', }; return {status}; }; const totalEarned = payouts.filter((p) => p.status === 'COMPLETED').reduce((sum, p) => sum + p.netAmount, 0); const pendingAmount = payouts.filter((p) => p.status === 'PENDING' || p.status === 'PROCESSING').reduce((sum, p) => sum + p.netAmount, 0); return (

Payouts

{/* Stripe Connect status */} {accountStatus && !accountStatus.payoutsEnabled && (

{accountStatus.connected ? 'Complete Stripe Setup' : 'Set Up Payouts'}

{accountStatus.connected ? 'Your Stripe account needs additional information before payouts can be processed.' : 'Connect your Stripe account to receive payouts for your rental bookings.'}

{accountStatus.connected ? 'Complete Setup' : 'Connect Stripe'}
)}
(

{p.booking?.rentalListing?.title || 'Unknown Listing'}

{p.booking?.tenant?.fullName || 'Unknown Tenant'}

), }, { key: 'dates', header: 'Period', render: (p: Payout) => (
{p.booking ? ( <>
{new Date(p.booking.startDate).toLocaleDateString()}
to {new Date(p.booking.endDate).toLocaleDateString()}
) : ( -- )}
), }, { key: 'gross', header: 'Gross', render: (p: Payout) => ${p.grossAmount.toFixed(2)}, }, { key: 'commission', header: 'Commission', render: (p: Payout) => -${p.commissionAmount.toFixed(2)}, }, { key: 'net', header: 'Net', render: (p: Payout) => ${p.netAmount.toFixed(2)}, }, { key: 'status', header: 'Status', render: (p: Payout) => statusBadge(p.status), }, { key: 'date', header: 'Date', render: (p: Payout) => new Date(p.createdAt).toLocaleDateString(), }, ]} data={payouts} total={total} page={page} pageSize={20} onPageChange={setPage} />
); }