diff --git a/components/settings/OrganizationSettings.tsx b/components/settings/OrganizationSettings.tsx index ff5d5af..435cc1b 100644 --- a/components/settings/OrganizationSettings.tsx +++ b/components/settings/OrganizationSettings.tsx @@ -708,10 +708,10 @@ export default function OrganizationSettings() { )} {activeTab === 'billing' && ( -
+

Billing & Subscription

-

Manage your subscription plan and payment methods.

+

Manage your plan, usage, and payment details.

{isLoadingSubscription ? ( @@ -721,60 +721,82 @@ export default function OrganizationSettings() { ) : !subscription ? (

Could not load subscription details.

- +
) : ( -
- {/* Current Plan */} -
-
-
-

Current Plan

-
- - {subscription.plan_id?.startsWith('price_') ? 'Pro' : (subscription.plan_id === 'free' || !subscription.plan_id ? 'Free' : subscription.plan_id)} Plan +
+ + {/* Trial notice */} + {subscription.subscription_status === 'trialing' && ( +
+
+

+ Your free trial ends on{' '} + + {(() => { + const d = subscription.current_period_end ? new Date(subscription.current_period_end as string) : null + return d && !Number.isNaN(d.getTime()) ? d.toLocaleDateString(undefined, { month: 'long', day: 'numeric', year: 'numeric' }) : '—' + })()} - - {subscription.subscription_status === 'trialing' ? 'Trial Active' : (subscription.subscription_status || 'Free')} - -

-
-
- - {subscription.has_payment_method && ( - - )} +

+

+ After the trial you'll be charged automatically unless you cancel before then. +

+ )} -
+ {/* Cancel-at-period-end notice */} + {subscription.cancel_at_period_end && ( +
+

+ Your subscription will end on{' '} + + {(() => { + const d = subscription.current_period_end ? new Date(subscription.current_period_end as string) : null + return d && !Number.isNaN(d.getTime()) ? d.toLocaleDateString(undefined, { month: 'long', day: 'numeric', year: 'numeric' }) : '—' + })()} + +

+

+ You keep full access until then. Your data is retained for 30 days after. Use "Change plan" to resubscribe. +

+
+ )} + + {/* Plan & Usage card */} +
+ {/* Plan header */} +
+
+ + {subscription.plan_id?.startsWith('price_') ? 'Pro' : (subscription.plan_id === 'free' || !subscription.plan_id ? 'Free' : subscription.plan_id)} Plan + + + {subscription.subscription_status === 'trialing' ? 'Trial' : (subscription.subscription_status || 'Free')} + + {subscription.billing_interval && ( + + Billed {subscription.billing_interval}ly + + )} +
+ +
+ + {/* Usage stats */} +
-
Sites
-
+
Sites
+
{typeof subscription.sites_count === 'number' ? subscription.plan_id === 'solo' ? `${subscription.sites_count} / 1` @@ -783,109 +805,81 @@ export default function OrganizationSettings() {
-
Pageviews this period
-
+
Pageviews
+
{subscription.pageview_limit > 0 && typeof subscription.pageview_usage === 'number' ? `${subscription.pageview_usage.toLocaleString()} / ${subscription.pageview_limit.toLocaleString()}` : '—'}
-
Billing Interval
-
- {subscription.billing_interval ? `${subscription.billing_interval}ly` : '—'} +
+ {subscription.subscription_status === 'trialing' ? 'Trial ends' : (subscription.cancel_at_period_end ? 'Access until' : 'Renews')}
-
-
-
Pageview Limit
-
- {subscription.pageview_limit > 0 ? `${subscription.pageview_limit.toLocaleString()} / month` : 'Unlimited'} -
-
-
-
- {subscription.subscription_status === 'trialing' ? 'Trial Ends On' : 'Renews On'} -
-
+
{(() => { - const raw = subscription.current_period_end - const d = raw ? new Date(raw as string) : null - const ts = d ? d.getTime() : NaN - return raw && !Number.isNaN(ts) && ts !== 0 ? (d as Date).toLocaleDateString() : '—' + const d = subscription.current_period_end ? new Date(subscription.current_period_end as string) : null + return d && !Number.isNaN(d.getTime()) && d.getTime() !== 0 ? d.toLocaleDateString(undefined, { month: 'short', day: 'numeric', year: 'numeric' }) : '—' })()}
+
+
Limit
+
+ {subscription.pageview_limit > 0 ? `${subscription.pageview_limit.toLocaleString()} / mo` : 'Unlimited'} +
+
- {/* Cancel-at-period-end notice or Cancel subscription action */} - {subscription.has_payment_method && (subscription.subscription_status === 'active' || subscription.subscription_status === 'trialing') && ( - <> - {subscription.cancel_at_period_end ? ( -
-

Subscription set to cancel

-

- Your subscription will end on{' '} - {(() => { - const raw = subscription.current_period_end - const d = raw ? new Date(raw as string) : null - return raw && d && !Number.isNaN(d.getTime()) ? d.toLocaleDateString() : '—' - })()} - . You can use the app until then. -

-

- Your data is retained for 30 days after access ends. You can resubscribe anytime using Change plan above. -

-
- ) : ( -
-
-

Cancel subscription

-

- After cancellation, you can use the app until the end of your billing period. Your data is retained for 30 days after access ends. -

-
- -
- )} - - )} + {/* Quick actions */} +
+ {subscription.has_payment_method && ( + + )} + {subscription.has_payment_method && (subscription.subscription_status === 'active' || subscription.subscription_status === 'trialing') && !subscription.cancel_at_period_end && ( + + )} +
{/* Invoice History */} -
-

Invoice History

-
- {isLoadingInvoices ? ( -
-
-
- ) : invoices.length === 0 ? ( -
No invoices found.
- ) : ( -
- {invoices.map((invoice) => ( -
-
-
- -
+ {invoices.length > 0 && ( +
+

Recent invoices

+
+ {isLoadingInvoices ? ( +
+
+
+ ) : ( + invoices.map((invoice) => ( +
+
-
+ {(invoice.amount_paid / 100).toLocaleString('en-US', { style: 'currency', currency: invoice.currency.toUpperCase() })} -
-
- {new Date(invoice.created * 1000).toLocaleDateString()} -
+ + + {new Date(invoice.created * 1000).toLocaleDateString(undefined, { month: 'short', day: 'numeric', year: 'numeric' })} +
-
- + {invoice.invoice_pdf && ( - - + + )} {invoice.hosted_invoice_url && ( - - + + )}
- ))} -
- )} + )) + )} +
-
+ )}
)}