diff --git a/src/components/pro/UpgradeView.tsx b/src/components/pro/UpgradeView.tsx index 5ece996..4cb7781 100644 --- a/src/components/pro/UpgradeView.tsx +++ b/src/components/pro/UpgradeView.tsx @@ -4,18 +4,8 @@ import { useCallback, useEffect, useState } from 'react' import { useTranslation } from 'react-i18next' -import { - Check, - Crown, - ExternalLink, - Loader2, - Shield, -} from 'lucide-react' -import { - proFeatureLabel, - useEntitlementStore, - type ProFeature, -} from '../../stores/entitlementStore' +import { Check, Crown, ExternalLink, Loader2, Shield } from 'lucide-react' +import { proFeatureLabel, useEntitlementStore, type ProFeature } from '../../stores/entitlementStore' import { checkout as licenseCheckout } from '../../platform/licenseApi' import { createLogger } from '../../utils/logger' @@ -38,10 +28,7 @@ function looksLikeValidLicenseKey(value: string): boolean { return trimmed.startsWith('LIC-') || trimmed.startsWith('LICOFF-') || trimmed.length >= 8 } -function activatedLabel( - t: (key: string) => string, - planType: string | null -): string { +function activatedLabel(t: (key: string) => string, planType: string | null): string { switch (planType) { case 'yearly': return t('pro.activatedYearly') @@ -97,38 +84,39 @@ export default function UpgradeView({ feature, comingSoon }: UpgradeViewProps) { const highlight = feature ? proFeatureLabel(feature) : null - const startCheckout = useCallback(async (planChoice: 'yearly' | 'perpetual') => { - setSelectedPlan(planChoice) - setCheckoutLoading(true) - setCheckoutError(null) - const trimmedEmail = emailInput.trim() - if (!trimmedEmail || !trimmedEmail.includes('@')) { - setCheckoutError(t('pro.emailRequired')) - setCheckoutLoading(false) - return - } - try { - await setEmail(trimmedEmail) - const id = - deviceId || - (await window.opsxApi.licenseDeviceId().catch(() => '')) - const result = await licenseCheckout({ - customerEmail: trimmedEmail, - deviceId: id, - planType: planChoice, - }) - if (!result.checkoutUrl) { - throw new Error(t('pro.checkoutUnavailable', { status: 'no-url' })) + const startCheckout = useCallback( + async (planChoice: 'yearly' | 'perpetual') => { + setSelectedPlan(planChoice) + setCheckoutLoading(true) + setCheckoutError(null) + const trimmedEmail = emailInput.trim() + if (!trimmedEmail || !trimmedEmail.includes('@')) { + setCheckoutError(t('pro.emailRequired')) + setCheckoutLoading(false) + return } - await window.opsxApi.openExternal(result.checkoutUrl) - } catch (error) { - const message = error instanceof Error ? error.message : String(error) - logger.warn('checkout failed', message) - setCheckoutError(message) - } finally { - setCheckoutLoading(false) - } - }, [deviceId, emailInput, setEmail, t]) + try { + await setEmail(trimmedEmail) + const id = deviceId || (await window.opsxApi.licenseDeviceId().catch(() => '')) + const result = await licenseCheckout({ + customerEmail: trimmedEmail, + deviceId: id, + planType: planChoice, + }) + if (!result.checkoutUrl) { + throw new Error(t('pro.checkoutUnavailable', { status: 'no-url' })) + } + await window.opsxApi.openExternal(result.checkoutUrl) + } catch (error) { + const message = error instanceof Error ? error.message : String(error) + logger.warn('checkout failed', message) + setCheckoutError(message) + } finally { + setCheckoutLoading(false) + } + }, + [deviceId, emailInput, setEmail, t] + ) const handleActivate = useCallback(async () => { setActivateError(null) @@ -162,14 +150,12 @@ export default function UpgradeView({ feature, comingSoon }: UpgradeViewProps) { return (
{comingSoon && highlight ? t('pro.subtitleComingSoon', { feature: highlight }) @@ -189,7 +175,7 @@ export default function UpgradeView({ feature, comingSoon }: UpgradeViewProps) { ? t('pro.expiresAt', { date: new Date(expiresAt * 1000).toLocaleDateString() }) : t('pro.lifetime') : null} - {plan === 'pro' && maxDevices + {plan === 'pro' && maxDevices && maxDevices > 1 ? ` · ${t('pro.devices', { count: maxDevices })}` : null}
@@ -213,23 +199,15 @@ export default function UpgradeView({ feature, comingSoon }: UpgradeViewProps) { placeholder="you@example.com" className="w-full rounded-lg border border-dark-600 bg-dark-900 px-3 py-2 text-sm text-content-primary outline-none focus:border-accent-blue" /> - {checkoutError && ( -{checkoutError}
- )} + {checkoutError &&{checkoutError}
}