11import { useSearch } from '@tanstack/react-router'
2- import ConfettiExplosion from 'react-confetti-explosion'
3- import { useAtom } from 'jotai'
2+ import { get as getPath } from 'lodash-es'
43import { useCallback , useState } from 'react'
4+ import ConfettiExplosion from 'react-confetti-explosion'
55import { Toaster } from 'react-hot-toast'
66import { useTranslation } from 'react-i18next'
77import Button from '~app/components/Button'
88import DiscountBadge from '~app/components/Premium/DiscountBadge'
99import FeatureList from '~app/components/Premium/FeatureList'
1010import PriceSection from '~app/components/Premium/PriceSection'
1111import { usePremium } from '~app/hooks/use-premium'
12+ import { useDiscountCode } from '~app/hooks/use-purchase-info'
1213import { trackEvent } from '~app/plausible'
1314import { premiumRoute } from '~app/router'
14- import { licenseKeyAtom } from '~app/state'
15- import { deactivateLicenseKey } from '~services/premium'
16- import { useDiscountCode } from '~app/hooks/use-purchase-info'
15+ import { activatePremium , deactivatePremium } from '~services/premium'
1716
1817function PremiumPage ( ) {
1918 const { t } = useTranslation ( )
20- const [ licenseKey , setLicenseKey ] = useAtom ( licenseKeyAtom )
2119 const premiumState = usePremium ( )
20+ const [ activating , setActivating ] = useState ( false )
2221 const [ deactivating , setDeactivating ] = useState ( false )
22+ const [ activationError , setActivationError ] = useState ( '' )
2323 const { source } = useSearch ( { from : premiumRoute . id } )
2424 const [ isExploding , setIsExploding ] = useState ( false )
2525 const discountCode = useDiscountCode ( )
2626
27- const activateLicense = useCallback ( ( ) => {
27+ const activate = useCallback ( async ( ) => {
2828 const key = window . prompt ( 'Enter your license key' , '' )
29- if ( key ) {
30- setLicenseKey ( key )
29+ if ( ! key ) {
30+ return
3131 }
32- } , [ setLicenseKey ] )
33-
34- const deactivateLicense = useCallback ( async ( ) => {
35- if ( ! licenseKey ) {
32+ setActivationError ( '' )
33+ setActivating ( true )
34+ trackEvent ( 'activate_license' )
35+ try {
36+ await activatePremium ( key )
37+ } catch ( err ) {
38+ console . error ( 'activation' , err )
39+ setActivationError ( getPath ( err , 'data.error' ) || 'Activation failed' )
40+ setActivating ( false )
3641 return
3742 }
43+ setTimeout ( ( ) => location . reload ( ) , 500 )
44+ } , [ ] )
45+
46+ const deactivateLicense = useCallback ( async ( ) => {
3847 if ( ! window . confirm ( 'Are you sure to deactivate this device?' ) ) {
3948 return
4049 }
4150 setDeactivating ( true )
42- await deactivateLicenseKey ( licenseKey )
43- setLicenseKey ( '' )
51+ trackEvent ( 'deactivate_license' )
52+ await deactivatePremium ( )
4453 setTimeout ( ( ) => location . reload ( ) , 500 )
45- } , [ licenseKey , setLicenseKey ] )
54+ } , [ ] )
4655
4756 return (
4857 < div className = "flex flex-col bg-primary-background dark:text-primary-text rounded-[20px] h-full p-[50px] overflow-y-auto" >
@@ -86,8 +95,8 @@ function PremiumPage() {
8695 text = { t ( 'Activate license' ) }
8796 color = "flat"
8897 className = "w-fit !py-2 rounded-lg"
89- onClick = { activateLicense }
90- isLoading = { premiumState . isLoading }
98+ onClick = { activate }
99+ isLoading = { activating || premiumState . isLoading }
91100 />
92101 </ >
93102 ) }
@@ -100,7 +109,9 @@ function PremiumPage() {
100109 { t ( 'Manage order and devices' ) }
101110 </ a >
102111 </ div >
103- { ! ! premiumState . error && < span className = "mt-3 text-red-500 font-medium" > { premiumState . error } </ span > }
112+ { ! ! ( premiumState . error || activationError ) && (
113+ < span className = "mt-3 text-red-500 font-medium" > { premiumState . error || activationError } </ span >
114+ ) }
104115 < Toaster position = "top-right" />
105116 { isExploding && < ConfettiExplosion duration = { 3000 } onComplete = { ( ) => setIsExploding ( false ) } /> }
106117 </ div >
0 commit comments