feat(me): my-payments self-view in the Membership tab (P3d)

New getMyPayments: payments SELECT is treasurer-scoped (RLS), so the
self-view uses the validated service client strictly scoped to the
caller's space_id + member_id (same convention as getMyBilling /
getMyNotifications). Read-only list (amount, date, platform, status)
in the Membership tab. Docs updated. 521 tests; build clean.
This commit is contained in:
Moheeb Zara
2026-05-18 15:50:34 -07:00
parent 6189e2023d
commit 2c847befeb
4 changed files with 72 additions and 1 deletions
+6 -1
View File
@@ -2,7 +2,7 @@ import { redirect } from 'next/navigation'
import { createClient } from '@/lib/supabase/server'
import { PageHeader, PageTitle } from '@/components/ui/page-title'
import { PERMISSIONS, PERMISSION_CODES } from '@/lib/permissions-catalog'
import { getMyClassSignups, getMyReservations, getMyCards, getMyVisits, getMyBilling, getMyNotifications } from '@/lib/actions'
import { getMyClassSignups, getMyReservations, getMyCards, getMyVisits, getMyBilling, getMyNotifications, getMyPayments } from '@/lib/actions'
import {
MePortalClient,
type Grant,
@@ -11,6 +11,7 @@ import {
type MyCard,
type MyVisit,
type MyNotif,
type MyPayment,
} from './me-portal-client'
export const dynamic = 'force-dynamic'
@@ -97,6 +98,9 @@ export default async function MePage() {
const notifsRes = await getMyNotifications()
const notifs: MyNotif[] = 'data' in notifsRes ? (notifsRes.data as MyNotif[]) : []
const paymentsRes = await getMyPayments()
const payments: MyPayment[] = 'data' in paymentsRes ? (paymentsRes.data as MyPayment[]) : []
return (
<>
<PageHeader>
@@ -108,6 +112,7 @@ export default async function MePage() {
grants={grants}
held={held}
billing={billing}
payments={payments}
notifs={notifs}
classSignups={classSignups}
reservations={reservations}