From f5608372dcba57eaf98e5ccd41e866bab910aeb5 Mon Sep 17 00:00:00 2001 From: Antigravity Date: Thu, 28 May 2026 19:49:26 +0000 Subject: [PATCH] fix(billing): filter out free plan for paid users, add direct cancel subscription button, and handle portal errors without crashing Next.js overlay --- .../components/settings/billing-plans.tsx | 45 ++++++++++++++----- memento-note/locales/en.json | 1 + memento-note/locales/fr.json | 1 + 3 files changed, 35 insertions(+), 12 deletions(-) diff --git a/memento-note/components/settings/billing-plans.tsx b/memento-note/components/settings/billing-plans.tsx index 6fdc03f..d4b6c48 100644 --- a/memento-note/components/settings/billing-plans.tsx +++ b/memento-note/components/settings/billing-plans.tsx @@ -117,7 +117,10 @@ export function BillingPlans() { try { const res = await fetch('/api/billing/portal', { method: 'POST' }); const data = await res.json(); - if (!res.ok) throw new Error(data.error ?? 'Failed to open portal'); + if (!res.ok) { + toast.error(data.error || 'Failed to open billing portal.'); + return; + } window.location.href = data.url; } catch (err) { console.error('[BillingPlans] portal error:', err); @@ -237,6 +240,8 @@ export function BillingPlans() { }, ]; + const plansToShow = isPaid ? plans.filter((p) => p.id !== 'free') : plans; + const formatDate = (dateStr: string | null | undefined) => { if (!dateStr) return '—'; try { @@ -339,15 +344,28 @@ export function BillingPlans() { {isPaid && ( - +
+ + + {status?.hasStripeSubscription && ( + + )} +
)} @@ -490,8 +508,11 @@ export function BillingPlans() { )} -
- {plans.map((plan) => ( +
+ {plansToShow.map((plan) => (