Billing flow redirect (#713)

* Billing flow redirect

* fix checkout url

* Refactor checkout and subscription flow

- Improve checkout URL generation with ref unwrapping
- Enhance user data handling in subscription modal
- Remove deprecated CheckoutDetailsModal component
- Update form field and register form styling
- Add more robust user data update mechanism

* Refactor checkout and subscription flow

- Improve checkout URL generation with ref unwrapping
- Enhance user data handling in subscription modal
- Remove deprecated CheckoutDetailsModal component
- Update form field and register form styling
- Add more robust user data update mechanism

* Fix accessibility and checkout URL generation

- Add proper label for terms and conditions checkbox in RegisterForm
- Refactor checkout URL generation in SubscriptionModal using computed refs
- Improve form input handling and reactivity

---------

Co-authored-by: Julien Nahum <julien@nahum.net>
This commit is contained in:
Chirag Chhatrala
2025-03-05 16:46:33 +05:30
committed by GitHub
parent b633f97ce1
commit a59b46665c
9 changed files with 193 additions and 221 deletions

View File

@@ -0,0 +1,29 @@
<template>
<div class="flex flex-col items-center justify-center min-h-screen gap-4">
<Loader class="w-8 h-8 text-blue-500" />
<p class="text-gray-500">
Redirecting to billing portal...
</p>
</div>
</template>
<script setup>
definePageMeta({
middleware: 'auth'
})
onMounted(async () => {
try {
const { portal_url } = await opnFetch('/subscription/billing-portal')
if (!portal_url) {
throw new Error('No portal URL returned')
}
window.location.href = portal_url
} catch (error) {
useAlert().error('Unable to access billing portal. Please try again or contact support.')
setTimeout(() => {
navigateTo({ name: 'settings-billing' })
}, 2000)
}
})
</script>

View File

@@ -0,0 +1,62 @@
<template>
<div class="flex flex-col items-center justify-center min-h-screen gap-4">
<Loader class="w-8 h-8 text-blue-500" />
<p class="text-gray-500">
Preparing your checkout...
</p>
</div>
</template>
<script setup>
definePageMeta({
middleware: 'auth'
})
const route = useRoute()
onMounted(async () => {
const { plan, yearly, trial_duration, currency, name, email } = route.query
if (!plan) {
useAlert().error('Missing plan information')
navigateTo({ name: 'pricing' })
return
}
try {
// Update customer details if provided
if (name && email) {
try {
await opnFetch('subscription/update-customer-details', {
method: 'PUT',
body: { name, email }
})
} catch (error) {
useAlert().error('Failed to update customer details, but proceeding with checkout')
}
}
// Get checkout URL
const params = { trial_duration, currency }
const { checkout_url } = await opnFetch(
`/subscription/new/${plan}/${yearly === 'true' ? 'yearly' : 'monthly'}/checkout/with-trial?${new URLSearchParams(params)}`
)
if (!checkout_url) {
throw new Error('No checkout URL returned')
}
// Log trial usage if applicable
if (trial_duration) {
useAmplitude().logEvent('extended_trial_used', { duration: trial_duration })
}
window.location.href = checkout_url
} catch (error) {
useAlert().error('Unable to start checkout process. Please try again or contact support.')
setTimeout(() => {
navigateTo({ name: 'pricing' })
}, 2000)
}
})
</script>

View File

@@ -19,7 +19,8 @@
color="gray"
icon="i-heroicons-credit-card"
:loading="billingLoading"
@click="openBillingDashboard"
:to="{ name: 'redirect-billing-portal' }"
target="_blank"
>
<span v-if="canCancel">Manage Subscription & Invoices</span>
<span else>Billing & Invoices</span>
@@ -117,15 +118,4 @@ const cancelSubscription = () => {
})
}
const openBillingDashboard = () => {
billingLoading.value = true
opnFetch('/subscription/billing-portal').then((data) => {
const url = data.portal_url
window.location = url
}).catch((error) => {
useAlert().error(error.data.message)
}).finally(() => {
billingLoading.value = false
})
}
</script>