diff --git a/app/src/components/OpenhumanLinkModal.tsx b/app/src/components/OpenhumanLinkModal.tsx index 5cd92bca6..f8386f5ec 100644 --- a/app/src/components/OpenhumanLinkModal.tsx +++ b/app/src/components/OpenhumanLinkModal.tsx @@ -18,6 +18,7 @@ import { purgeWebviewAccount } from '../services/webviewAccountService'; import { addAccount, removeAccount } from '../store/accountsSlice'; import { useAppDispatch, useAppSelector } from '../store/hooks'; import { type Account, type AccountProvider, PROVIDERS } from '../types/accounts'; +import { BILLING_DASHBOARD_URL } from '../utils/links'; import { openUrl } from '../utils/openUrl'; import { ProviderIcon } from './accounts/providerIcons'; import ChannelSetupModal from './channels/ChannelSetupModal'; @@ -243,7 +244,7 @@ const BillingBody = ({ close }: { close: () => void }) => { + ))} + + ) : null + } + /> - {selectedTab === 'plans' && ( - - )} +
+
+
+

+ Billing moved to the web +

+

Open billing dashboard

+

+ Subscription changes, payment methods, credits, and invoices are now managed at + TinyHumans on the web. +

+
- {selectedTab === 'payments' && ( - - )} +
+ + +
- {selectedTab === 'history' && ( - - )} + {status === 'opening' && ( +

Opening your browser…

+ )} + {status === 'idle' && ( +

+ If your browser did not open, use the button above. +

+ )} + {status === 'error' && ( +

+ The browser could not be opened automatically. Use the button above. +

+ )} +
+
); diff --git a/app/src/components/upsell/GlobalUpsellBanner.tsx b/app/src/components/upsell/GlobalUpsellBanner.tsx index 05941946d..4fa9b826e 100644 --- a/app/src/components/upsell/GlobalUpsellBanner.tsx +++ b/app/src/components/upsell/GlobalUpsellBanner.tsx @@ -1,10 +1,9 @@ -import { useNavigate } from 'react-router-dom'; - import { useUsageState } from '../../hooks/useUsageState'; +import { BILLING_DASHBOARD_URL } from '../../utils/links'; +import { openUrl } from '../../utils/openUrl'; import UpsellBanner from './UpsellBanner'; export default function GlobalUpsellBanner() { - const navigate = useNavigate(); const { teamUsage, isLoading, isAtLimit, isNearLimit, isFreeTier, usagePct10h, usagePct7d } = useUsageState(); @@ -19,7 +18,9 @@ export default function GlobalUpsellBanner() { message="Upgrade your plan or top up credits to continue" ctaLabel="Upgrade" rounded={false} - onCtaClick={() => navigate('/settings/billing')} + onCtaClick={() => { + void openUrl(BILLING_DASHBOARD_URL); + }} /> ); @@ -35,7 +36,9 @@ export default function GlobalUpsellBanner() { message={`You've used ${pct}% of your usage limit. Upgrade for higher limits.`} ctaLabel="Upgrade" rounded={false} - onCtaClick={() => navigate('/settings/billing')} + onCtaClick={() => { + void openUrl(BILLING_DASHBOARD_URL); + }} /> ); diff --git a/app/src/components/upsell/UsageLimitModal.tsx b/app/src/components/upsell/UsageLimitModal.tsx index 83cd777b5..bafa32623 100644 --- a/app/src/components/upsell/UsageLimitModal.tsx +++ b/app/src/components/upsell/UsageLimitModal.tsx @@ -1,6 +1,6 @@ -import { useNavigate } from 'react-router-dom'; - import type { PlanTier } from '../../types/api'; +import { BILLING_DASHBOARD_URL } from '../../utils/links'; +import { openUrl } from '../../utils/openUrl'; import { PLANS } from '../settings/panels/billingHelpers'; interface UsageLimitModalProps { @@ -37,7 +37,6 @@ export default function UsageLimitModal({ resetTime, currentTier, }: UsageLimitModalProps) { - const navigate = useNavigate(); const nextPlan = getNextPlan(currentTier); if (!open) return null; @@ -91,7 +90,7 @@ export default function UsageLimitModal({ diff --git a/app/src/utils/desktopDeepLinkListener.ts b/app/src/utils/desktopDeepLinkListener.ts index 88fa87881..6f0a5873a 100644 --- a/app/src/utils/desktopDeepLinkListener.ts +++ b/app/src/utils/desktopDeepLinkListener.ts @@ -10,6 +10,7 @@ import { completeDeepLinkAuthProcessing, failDeepLinkAuthProcessing, } from '../store/deepLinkAuthState'; +import { BILLING_DASHBOARD_URL } from './links'; import { evaluateOAuthAppVersionGate } from './oauthAppVersionGate'; import { openUrl } from './openUrl'; import { storeSession } from './tauriCommands'; @@ -98,15 +99,17 @@ const handlePaymentDeepLink = async (parsed: URL) => { console.log('[DeepLink] Payment success, session_id:', sessionId); - // Broadcast to the app so billing components can react + // Broadcast to the app in case any listeners still care about legacy + // payment completion events. window.dispatchEvent(new CustomEvent('payment:success', { detail: { sessionId } })); - // Navigate to billing settings to show confirmation - window.location.hash = '/settings/billing'; + await openUrl(BILLING_DASHBOARD_URL); + window.location.hash = '/home'; } else if (path === 'cancel') { console.log('[DeepLink] Payment cancelled'); window.dispatchEvent(new CustomEvent('payment:cancel', {})); - window.location.hash = '/settings/billing'; + await openUrl(BILLING_DASHBOARD_URL); + window.location.hash = '/home'; } else { console.warn('[DeepLink] Unknown payment path:', path); } diff --git a/app/src/utils/links.ts b/app/src/utils/links.ts index 156db1a7f..3aa1fa4f8 100644 --- a/app/src/utils/links.ts +++ b/app/src/utils/links.ts @@ -1 +1,2 @@ export const DISCORD_INVITE_URL = 'https://discord.tinyhumans.ai'; +export const BILLING_DASHBOARD_URL = 'https://tinyhumans.ai/dashboard';