import { redirect } from 'next/navigation' import Link from 'next/link' import { createClient } from '@/lib/supabase/server' import type { FinancialVisibility, Payment, Space } from '@/lib/types' export const dynamic = 'force-dynamic' const DOLLAR = new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }) function isVisible(viz: FinancialVisibility, role: string | null): boolean { if (viz === 'all_members_visible') return true if (viz === 'board_visible') return role === 'admin' || role === 'board' || role === 'treasurer' // treasurer_only return role === 'admin' || role === 'board' || role === 'treasurer' } export default async function FinancialsPage() { const supabase = await createClient() const { data: { user } } = await supabase.auth.getUser() if (!user) redirect('/login') const { data: member } = await supabase .from('space_members') .select('space_id, role') .eq('user_id', user.id) .in('status', ['current', 'unverified', 'late']) .maybeSingle() if (!member?.space_id) redirect('/signup') const { data: spaceRaw } = await supabase .from('spaces') .select('id, name, financial_visibility') .eq('id', member.space_id) .maybeSingle() const space = spaceRaw as unknown as Pick & { financial_visibility: FinancialVisibility } | null if (!space) { return

Space not found.

} if (!isVisible(space.financial_visibility, member.role)) { return (

Financial data is not visible to your role.

Visibility is currently set to {space.financial_visibility.replace(/_/g, ' ')}. Ask an admin to change it from Settings if your space wants broader transparency.

) } const { data: paymentsRaw } = await supabase .from('payments') .select('*') .eq('space_id', member.space_id) .order('transaction_date', { ascending: false }) const payments = (paymentsRaw ?? []) as unknown as Payment[] const now = new Date() const startOfMonth = new Date(now.getFullYear(), now.getMonth(), 1) const startOfYear = new Date(now.getFullYear(), 0, 1) let lifetime = 0 let thisYear = 0 let thisMonth = 0 let linked = 0 let unlinked = 0 const byPlatform: Record = {} const byMonth: Record = {} for (const p of payments) { const amount = Number(p.amount ?? 0) lifetime += amount const tx = p.transaction_date ? new Date(p.transaction_date) : null if (tx) { if (tx >= startOfYear) thisYear += amount if (tx >= startOfMonth) thisMonth += amount const key = `${tx.getFullYear()}-${String(tx.getMonth() + 1).padStart(2, '0')}` byMonth[key] = (byMonth[key] ?? 0) + amount } if (p.link_status === 'linked') linked++ else unlinked++ const platform = String(p.platform ?? 'unknown') byPlatform[platform] = (byPlatform[platform] ?? 0) + amount } const monthlyRows = Object.entries(byMonth) .sort(([a], [b]) => b.localeCompare(a)) .slice(0, 12) const platformRows = Object.entries(byPlatform).sort(([, a], [, b]) => b - a) const maxPlatform = Math.max(1, ...platformRows.map(([, v]) => v)) return (

Visibility: {space.financial_visibility.replace(/_/g, ' ')} {member.role === 'admin' && ( <> {' · '} change in Settings )}

0} />

By platform

{platformRows.length === 0 ? (

No payments recorded yet.

) : (
    {platformRows.map(([platform, total]) => { const pct = Math.round((total / maxPlatform) * 100) return (
  • {platform} {DOLLAR.format(total)}
  • ) })}
)}

Last 12 months

{monthlyRows.length === 0 ? (

No monthly breakdown yet.

) : (
{monthlyRows.map(([month, total]) => { const [y, m] = month.split('-') const label = new Date(Number(y), Number(m) - 1, 1).toLocaleDateString('en-US', { year: 'numeric', month: 'short' }) return (
{label} {DOLLAR.format(total)}
) })}
)}
) } function PageShell({ title, children }: { title: string; children: React.ReactNode }) { return (

{title}

{children}
) } function StatCard({ label, value, sub, warn }: { label: string; value: string; sub: string; warn?: boolean }) { return (

{label}

{value}

{sub}

) }