settings: move dues config (Stripe + payment links) into its own Dues tab
The Stripe recurring-dues panel and the external payment-links panel were rendered below the settings tab bar (outside SettingsClient), so they floated under every tab. Add a Dues tab (Space / Integrations / Dues / Webhooks) and render both panels there as standard tab cards. UI only.
This commit is contained in:
@@ -1,7 +1,5 @@
|
|||||||
import { createClient } from '@/lib/supabase/server'
|
import { createClient } from '@/lib/supabase/server'
|
||||||
import SettingsClient from './settings-client'
|
import SettingsClient from './settings-client'
|
||||||
import { StripeBillingPanel } from '@/components/settings/stripe-billing-panel'
|
|
||||||
import { DuesPaymentMethodsPanel } from '@/components/settings/dues-payment-methods-panel'
|
|
||||||
import { redirect } from 'next/navigation'
|
import { redirect } from 'next/navigation'
|
||||||
|
|
||||||
export default async function SettingsPage() {
|
export default async function SettingsPage() {
|
||||||
@@ -27,15 +25,11 @@ export default async function SettingsPage() {
|
|||||||
.from('integrations').select('*').eq('space_id', member.space_id)
|
.from('integrations').select('*').eq('space_id', member.space_id)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
|
||||||
<SettingsClient
|
<SettingsClient
|
||||||
space={space}
|
space={space}
|
||||||
isAdmin={isAdmin}
|
isAdmin={isAdmin}
|
||||||
integrations={integrations ?? []}
|
integrations={integrations ?? []}
|
||||||
currentRole={member.role}
|
currentRole={member.role}
|
||||||
/>
|
/>
|
||||||
<StripeBillingPanel spaceId={member.space_id} />
|
|
||||||
<DuesPaymentMethodsPanel />
|
|
||||||
</>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ import { financialVisibilities, directoryVisibilities } from '@/lib/validations'
|
|||||||
import type { Tables } from '@/types/database'
|
import type { Tables } from '@/types/database'
|
||||||
import { PageTitle } from '@/components/ui/page-title'
|
import { PageTitle } from '@/components/ui/page-title'
|
||||||
import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog'
|
import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog'
|
||||||
|
import { StripeBillingPanel } from '@/components/settings/stripe-billing-panel'
|
||||||
|
import { DuesPaymentMethodsPanel } from '@/components/settings/dues-payment-methods-panel'
|
||||||
|
|
||||||
type Space = Tables<'spaces'>
|
type Space = Tables<'spaces'>
|
||||||
type Integration = Tables<'integrations'>
|
type Integration = Tables<'integrations'>
|
||||||
@@ -88,7 +90,7 @@ const INTEGRATIONS_CONFIG = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
export default function SettingsClient({ space, isAdmin, integrations, currentRole }: Props) {
|
export default function SettingsClient({ space, isAdmin, integrations, currentRole }: Props) {
|
||||||
const [activeTab, setActiveTab] = useState<'space' | 'integrations' | 'webhooks'>('space')
|
const [activeTab, setActiveTab] = useState<'space' | 'integrations' | 'dues' | 'webhooks'>('space')
|
||||||
const [saving, setSaving] = useState(false)
|
const [saving, setSaving] = useState(false)
|
||||||
const [message, setMessage] = useState<{ type: 'success' | 'error'; text: string } | null>(null)
|
const [message, setMessage] = useState<{ type: 'success' | 'error'; text: string } | null>(null)
|
||||||
|
|
||||||
@@ -223,7 +225,7 @@ export default function SettingsClient({ space, isAdmin, integrations, currentRo
|
|||||||
<div className="flex-1 p-4 md:p-6">
|
<div className="flex-1 p-4 md:p-6">
|
||||||
{/* Tabs */}
|
{/* Tabs */}
|
||||||
<div className="bg-card border-b border-border flex gap-4 md:gap-6 px-2 mb-6 rounded-t overflow-x-auto">
|
<div className="bg-card border-b border-border flex gap-4 md:gap-6 px-2 mb-6 rounded-t overflow-x-auto">
|
||||||
{(['space', 'integrations', 'webhooks'] as const).map(tab => (
|
{(['space', 'integrations', 'dues', 'webhooks'] as const).map(tab => (
|
||||||
<button
|
<button
|
||||||
key={tab}
|
key={tab}
|
||||||
onClick={() => setActiveTab(tab)}
|
onClick={() => setActiveTab(tab)}
|
||||||
@@ -476,6 +478,14 @@ export default function SettingsClient({ space, isAdmin, integrations, currentRo
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{/* Dues Tab: how members pay dues (Stripe recurring + external links) */}
|
||||||
|
{activeTab === 'dues' && (
|
||||||
|
<div className="space-y-6">
|
||||||
|
<StripeBillingPanel spaceId={space.id} />
|
||||||
|
<DuesPaymentMethodsPanel />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
{/* Webhooks Tab */}
|
{/* Webhooks Tab */}
|
||||||
{activeTab === 'webhooks' && (
|
{activeTab === 'webhooks' && (
|
||||||
<div className="bg-card rounded border border-border p-6 space-y-6">
|
<div className="bg-card rounded border border-border p-6 space-y-6">
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ export function DuesPaymentMethodsPanel() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="p-4 md:p-6 border-t border-border">
|
<div className="bg-card rounded border border-border p-6">
|
||||||
<div className="max-w-2xl space-y-3">
|
<div className="max-w-2xl space-y-3">
|
||||||
<h2 className="font-mono text-[10px] uppercase tracking-widest text-muted-foreground">
|
<h2 className="font-mono text-[10px] uppercase tracking-widest text-muted-foreground">
|
||||||
Other ways to pay dues
|
Other ways to pay dues
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ export function StripeBillingPanel({ spaceId }: { spaceId: string }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="p-4 md:p-6 border-t border-border">
|
<div className="bg-card rounded border border-border p-6">
|
||||||
<div className="max-w-2xl space-y-3">
|
<div className="max-w-2xl space-y-3">
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<h2 className="font-mono text-[10px] uppercase tracking-widest text-muted-foreground">
|
<h2 className="font-mono text-[10px] uppercase tracking-widest text-muted-foreground">
|
||||||
|
|||||||
@@ -4,6 +4,12 @@ Append-only. Newest entries on top. Keep each entry to one screen.
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## 2026-05-20 (pass 60): /settings "Dues" tab (LOCAL, NOT deployed)
|
||||||
|
|
||||||
|
Branch `main`. The Stripe-dues config + external-payment-links panels were floating below the settings tab bar (rendered by page.tsx outside SettingsClient, shown regardless of the active tab). Moved both into a new **Dues** tab inside SettingsClient (tabs are now Space / Integrations / Dues / Webhooks); the panels render as standard `bg-card rounded border` tab cards instead of `border-t` page sections. page.tsx now renders only SettingsClient. UI-only, no schema/actions change. Build + 594 unit green. NOT deployed.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## 2026-05-20 (pass 59): PROD OUTAGE fix + in-app inbox + /me consolidation + style
|
## 2026-05-20 (pass 59): PROD OUTAGE fix + in-app inbox + /me consolidation + style
|
||||||
|
|
||||||
Branch `main`. Suite 594 unit, 40 integration, build clean.
|
Branch `main`. Suite 594 unit, 40 integration, build clean.
|
||||||
|
|||||||
Reference in New Issue
Block a user