diff --git a/app/org-settings/page.tsx b/app/org-settings/page.tsx index 25739a1..8e3bf2e 100644 --- a/app/org-settings/page.tsx +++ b/app/org-settings/page.tsx @@ -1,3 +1,4 @@ +import { Suspense } from 'react' import OrganizationSettings from '@/components/settings/OrganizationSettings' export const metadata = { @@ -9,7 +10,9 @@ export default function OrgSettingsPage() { return (
- + Loading...
}> + +
) diff --git a/app/page.tsx b/app/page.tsx index 33c8dab..9e8b8a9 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -285,12 +285,13 @@ export default function HomePage() {

--

-

Plan Status

-

- {subscriptionLoading - ? '...' - : (() => { - if (!subscription) return 'Free Plan' +

Plan & usage

+ {subscriptionLoading ? ( +

...

+ ) : subscription ? ( + <> +

+ {(() => { const raw = subscription.plan_id?.startsWith('price_') ? 'Pro' @@ -300,7 +301,33 @@ export default function HomePage() { const label = raw === 'Free' || raw === 'Pro' ? raw : raw.charAt(0).toUpperCase() + raw.slice(1) return `${label} Plan` })()} -

+

+ {(typeof subscription.sites_count === 'number' || (subscription.pageview_limit > 0 && typeof subscription.pageview_usage === 'number')) && ( +

+ {typeof subscription.sites_count === 'number' && ( + Sites: {subscription.plan_id === 'solo' && subscription.sites_count > 0 ? `${subscription.sites_count}/1` : subscription.sites_count} + )} + {typeof subscription.sites_count === 'number' && subscription.pageview_limit > 0 && typeof subscription.pageview_usage === 'number' && ' · '} + {subscription.pageview_limit > 0 && typeof subscription.pageview_usage === 'number' && ( + Pageviews: {subscription.pageview_usage.toLocaleString()}/{subscription.pageview_limit.toLocaleString()} + )} +

+ )} +
+ {subscription.has_payment_method ? ( + + Manage billing + + ) : ( + + Upgrade + + )} +
+ + ) : ( +

Free Plan

+ )}
diff --git a/components/settings/OrganizationSettings.tsx b/components/settings/OrganizationSettings.tsx index 0881c88..7ed2fe8 100644 --- a/components/settings/OrganizationSettings.tsx +++ b/components/settings/OrganizationSettings.tsx @@ -1,7 +1,7 @@ 'use client' import { useState, useEffect, useCallback } from 'react' -import { useRouter } from 'next/navigation' +import { useRouter, useSearchParams } from 'next/navigation' import { useAuth } from '@/lib/auth/context' import { deleteOrganization, @@ -38,7 +38,11 @@ import { Button, Input } from '@ciphera-net/ui' export default function OrganizationSettings() { const { user } = useAuth() const router = useRouter() - const [activeTab, setActiveTab] = useState<'general' | 'members' | 'billing'>('general') + const searchParams = useSearchParams() + const [activeTab, setActiveTab] = useState<'general' | 'members' | 'billing'>(() => { + const tab = searchParams.get('tab') + return tab === 'billing' || tab === 'members' ? tab : 'general' + }) const [showDeletePrompt, setShowDeletePrompt] = useState(false) const [deleteConfirm, setDeleteConfirm] = useState('') @@ -135,6 +139,13 @@ export default function OrganizationSettings() { } }, [currentOrgId, loadMembers]) + useEffect(() => { + const tab = searchParams.get('tab') + if ((tab === 'billing' || tab === 'members') && tab !== activeTab) { + setActiveTab(tab) + } + }, [searchParams, activeTab]) + useEffect(() => { if (activeTab === 'billing' && currentOrgId) { loadSubscription() @@ -593,7 +604,25 @@ export default function OrganizationSettings() { )} -
+
+
+
Sites
+
+ {typeof subscription.sites_count === 'number' + ? subscription.plan_id === 'solo' + ? `${subscription.sites_count} / 1` + : `${subscription.sites_count}` + : '—'} +
+
+
+
Pageviews this period
+
+ {subscription.pageview_limit > 0 && typeof subscription.pageview_usage === 'number' + ? `${subscription.pageview_usage.toLocaleString()} / ${subscription.pageview_limit.toLocaleString()}` + : '—'} +
+
Billing Interval
@@ -603,7 +632,7 @@ export default function OrganizationSettings() {
Pageview Limit
- {subscription.pageview_limit.toLocaleString()} / month + {subscription.pageview_limit > 0 ? `${subscription.pageview_limit.toLocaleString()} / month` : 'Unlimited'}
diff --git a/lib/api/billing.ts b/lib/api/billing.ts index 6d1e793..29b6d48 100644 --- a/lib/api/billing.ts +++ b/lib/api/billing.ts @@ -7,6 +7,10 @@ export interface SubscriptionDetails { billing_interval: string pageview_limit: number has_payment_method: boolean + /** Number of sites for the org (billing usage). Present when backend supports usage API. */ + sites_count?: number + /** Pageviews in current billing period (when pageview_limit > 0). Present when backend supports usage API. */ + pageview_usage?: number } async function billingFetch(endpoint: string, options: RequestInit = {}): Promise {