From 7929e15b65a7a0f775808f517975f1ef67584179 Mon Sep 17 00:00:00 2001 From: Usman Baig Date: Thu, 5 Feb 2026 11:29:38 +0100 Subject: [PATCH 1/3] feat: update subscription display and organization settings UI to include plan usage details and loading states --- app/org-settings/page.tsx | 5 ++- app/page.tsx | 41 ++++++++++++++++---- components/settings/OrganizationSettings.tsx | 35 +++++++++++++++-- lib/api/billing.ts | 4 ++ 4 files changed, 74 insertions(+), 11 deletions(-) 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..4484d7f 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}/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..930db7c 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') { + setActiveTab(tab) + } + }, [searchParams]) + 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
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 { From f13dfc437cda93fab7a4abba07a066b555ff6e01 Mon Sep 17 00:00:00 2001 From: Usman Baig Date: Thu, 5 Feb 2026 11:55:21 +0100 Subject: [PATCH 2/3] fix: refine subscription site count display logic and enhance active tab management in OrganizationSettings component --- app/page.tsx | 2 +- components/settings/OrganizationSettings.tsx | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/page.tsx b/app/page.tsx index 4484d7f..9e8b8a9 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -305,7 +305,7 @@ export default function HomePage() { {(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}/1` : subscription.sites_count} + 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' && ( diff --git a/components/settings/OrganizationSettings.tsx b/components/settings/OrganizationSettings.tsx index 930db7c..bf0f5ca 100644 --- a/components/settings/OrganizationSettings.tsx +++ b/components/settings/OrganizationSettings.tsx @@ -141,10 +141,10 @@ export default function OrganizationSettings() { useEffect(() => { const tab = searchParams.get('tab') - if (tab === 'billing' || tab === 'members') { + if ((tab === 'billing' || tab === 'members') && tab !== activeTab) { setActiveTab(tab) } - }, [searchParams]) + }, [searchParams, activeTab]) useEffect(() => { if (activeTab === 'billing' && currentOrgId) { From 7072049b5f2f198aeceaab712f9088415ab3cca7 Mon Sep 17 00:00:00 2001 From: Usman Baig Date: Thu, 5 Feb 2026 12:03:21 +0100 Subject: [PATCH 3/3] fix: update pageview limit display logic in OrganizationSettings to show 'Unlimited' for zero limits --- components/settings/OrganizationSettings.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/settings/OrganizationSettings.tsx b/components/settings/OrganizationSettings.tsx index bf0f5ca..7ed2fe8 100644 --- a/components/settings/OrganizationSettings.tsx +++ b/components/settings/OrganizationSettings.tsx @@ -632,7 +632,7 @@ export default function OrganizationSettings() {

Pageview Limit
- {subscription.pageview_limit.toLocaleString()} / month + {subscription.pageview_limit > 0 ? `${subscription.pageview_limit.toLocaleString()} / month` : 'Unlimited'}