@@ -12,7 +12,6 @@ import {
1212 AlertDialogTitle ,
1313} from '@/components/ui/alert-dialog'
1414import { Button } from '@/components/ui/button'
15- import { Tooltip , TooltipContent , TooltipProvider , TooltipTrigger } from '@/components/ui/tooltip'
1615import { useSession , useSubscription } from '@/lib/auth-client'
1716import { createLogger } from '@/lib/logs/console/logger'
1817import { getBaseUrl } from '@/lib/urls/utils'
@@ -30,6 +29,7 @@ interface CancelSubscriptionProps {
3029 }
3130 subscriptionData ?: {
3231 periodEnd ?: Date | null
32+ cancelAtPeriodEnd ?: boolean
3333 }
3434}
3535
@@ -127,35 +127,48 @@ export function CancelSubscription({ subscription, subscriptionData }: CancelSub
127127 const subscriptionStatus = getSubscriptionStatus ( )
128128 const activeOrgId = activeOrganization ?. id
129129
130- // For team/enterprise plans, get the subscription ID from organization store
131- if ( ( subscriptionStatus . isTeam || subscriptionStatus . isEnterprise ) && activeOrgId ) {
132- const orgSubscription = useOrganizationStore . getState ( ) . subscriptionData
130+ if ( isCancelAtPeriodEnd ) {
131+ if ( ! betterAuthSubscription . restore ) {
132+ throw new Error ( 'Subscription restore not available' )
133+ }
134+
135+ let referenceId : string
136+ let subscriptionId : string | undefined
137+
138+ if ( ( subscriptionStatus . isTeam || subscriptionStatus . isEnterprise ) && activeOrgId ) {
139+ const orgSubscription = useOrganizationStore . getState ( ) . subscriptionData
140+ referenceId = activeOrgId
141+ subscriptionId = orgSubscription ?. id
142+ } else {
143+ // For personal subscriptions, use user ID and let better-auth find the subscription
144+ referenceId = session . user . id
145+ subscriptionId = undefined
146+ }
147+
148+ logger . info ( 'Restoring subscription' , { referenceId, subscriptionId } )
133149
134- if ( orgSubscription ?. id && orgSubscription ?. cancelAtPeriodEnd ) {
135- // Restore the organization subscription
136- if ( ! betterAuthSubscription . restore ) {
137- throw new Error ( 'Subscription restore not available' )
138- }
139-
140- const result = await betterAuthSubscription . restore ( {
141- referenceId : activeOrgId ,
142- subscriptionId : orgSubscription . id ,
143- } )
144- logger . info ( 'Organization subscription restored successfully' , result )
150+ // Build restore params - only include subscriptionId if we have one (team/enterprise)
151+ const restoreParams : any = { referenceId }
152+ if ( subscriptionId ) {
153+ restoreParams . subscriptionId = subscriptionId
145154 }
155+
156+ const result = await betterAuthSubscription . restore ( restoreParams )
157+
158+ logger . info ( 'Subscription restored successfully' , result )
146159 }
147160
148- // Refresh state and close
149161 await refresh ( )
150162 if ( activeOrgId ) {
151163 await loadOrganizationSubscription ( activeOrgId )
152164 await refreshOrganization ( ) . catch ( ( ) => { } )
153165 }
166+
154167 setIsDialogOpen ( false )
155168 } catch ( error ) {
156- const errorMessage = error instanceof Error ? error . message : 'Failed to keep subscription'
169+ const errorMessage = error instanceof Error ? error . message : 'Failed to restore subscription'
157170 setError ( errorMessage )
158- logger . error ( 'Failed to keep subscription' , { error } )
171+ logger . error ( 'Failed to restore subscription' , { error } )
159172 } finally {
160173 setIsLoading ( false )
161174 }
@@ -190,19 +203,15 @@ export function CancelSubscription({ subscription, subscriptionData }: CancelSub
190203 const periodEndDate = getPeriodEndDate ( )
191204
192205 // Check if subscription is set to cancel at period end
193- const isCancelAtPeriodEnd = ( ( ) => {
194- const subscriptionStatus = getSubscriptionStatus ( )
195- if ( subscriptionStatus . isTeam || subscriptionStatus . isEnterprise ) {
196- return useOrganizationStore . getState ( ) . subscriptionData ?. cancelAtPeriodEnd === true
197- }
198- return false
199- } ) ( )
206+ const isCancelAtPeriodEnd = subscriptionData ?. cancelAtPeriodEnd === true
200207
201208 return (
202209 < >
203210 < div className = 'flex items-center justify-between' >
204211 < div >
205- < span className = 'font-medium text-sm' > Manage Subscription</ span >
212+ < span className = 'font-medium text-sm' >
213+ { isCancelAtPeriodEnd ? 'Restore Subscription' : 'Manage Subscription' }
214+ </ span >
206215 { isCancelAtPeriodEnd && (
207216 < p className = 'mt-1 text-muted-foreground text-xs' >
208217 You'll keep access until { formatDate ( periodEndDate ) }
@@ -217,22 +226,24 @@ export function CancelSubscription({ subscription, subscriptionData }: CancelSub
217226 'h-8 rounded-[8px] font-medium text-xs transition-all duration-200' ,
218227 error
219228 ? 'border-red-500 text-red-500 dark:border-red-500 dark:text-red-500'
220- : 'text-muted-foreground hover:border-red-500 hover:bg-red-500 hover:text-white dark:hover:border-red-500 dark:hover:bg-red-500'
229+ : isCancelAtPeriodEnd
230+ ? 'text-muted-foreground hover:border-green-500 hover:bg-green-500 hover:text-white dark:hover:border-green-500 dark:hover:bg-green-500'
231+ : 'text-muted-foreground hover:border-red-500 hover:bg-red-500 hover:text-white dark:hover:border-red-500 dark:hover:bg-red-500'
221232 ) }
222233 >
223- { error ? 'Error' : 'Manage' }
234+ { error ? 'Error' : isCancelAtPeriodEnd ? 'Restore' : 'Manage' }
224235 </ Button >
225236 </ div >
226237
227238 < AlertDialog open = { isDialogOpen } onOpenChange = { setIsDialogOpen } >
228239 < AlertDialogContent >
229240 < AlertDialogHeader >
230241 < AlertDialogTitle >
231- { isCancelAtPeriodEnd ? 'Manage ' : 'Cancel' } { subscription . plan } subscription?
242+ { isCancelAtPeriodEnd ? 'Restore ' : 'Cancel' } { subscription . plan } subscription?
232243 </ AlertDialogTitle >
233244 < AlertDialogDescription >
234245 { isCancelAtPeriodEnd
235- ? 'Your subscription is set to cancel at the end of the billing period. You can reactivate it or manage other settings. '
246+ ? 'Your subscription is set to cancel at the end of the billing period. Would you like to keep your subscription active? '
236247 : `You'll be redirected to Stripe to manage your subscription. You'll keep access until ${ formatDate (
237248 periodEndDate
238249 ) } , then downgrade to free plan.`} { ' ' }
@@ -260,38 +271,23 @@ export function CancelSubscription({ subscription, subscriptionData }: CancelSub
260271 < AlertDialogFooter className = 'flex' >
261272 < AlertDialogCancel
262273 className = 'h-9 w-full rounded-[8px]'
263- onClick = { handleKeep }
274+ onClick = { isCancelAtPeriodEnd ? ( ) => setIsDialogOpen ( false ) : handleKeep }
264275 disabled = { isLoading }
265276 >
266- Keep Subscription
277+ { isCancelAtPeriodEnd ? 'Cancel' : ' Keep Subscription' }
267278 </ AlertDialogCancel >
268279
269280 { ( ( ) => {
270281 const subscriptionStatus = getSubscriptionStatus ( )
271- if (
272- subscriptionStatus . isPaid &&
273- ( activeOrganization ?. id
274- ? useOrganizationStore . getState ( ) . subscriptionData ?. cancelAtPeriodEnd
275- : false )
276- ) {
282+ if ( subscriptionStatus . isPaid && isCancelAtPeriodEnd ) {
277283 return (
278- < TooltipProvider delayDuration = { 0 } >
279- < Tooltip >
280- < TooltipTrigger asChild >
281- < div className = 'w-full' >
282- < AlertDialogAction
283- disabled
284- className = 'h-9 w-full cursor-not-allowed rounded-[8px] bg-muted text-muted-foreground opacity-50'
285- >
286- Continue
287- </ AlertDialogAction >
288- </ div >
289- </ TooltipTrigger >
290- < TooltipContent side = 'top' >
291- < p > Subscription will be cancelled at end of billing period</ p >
292- </ TooltipContent >
293- </ Tooltip >
294- </ TooltipProvider >
284+ < AlertDialogAction
285+ onClick = { handleKeep }
286+ className = 'h-9 w-full rounded-[8px] bg-green-500 text-white transition-all duration-200 hover:bg-green-600 dark:bg-green-500 dark:hover:bg-green-600'
287+ disabled = { isLoading }
288+ >
289+ { isLoading ? 'Restoring...' : 'Restore Subscription' }
290+ </ AlertDialogAction >
295291 )
296292 }
297293 return (
0 commit comments