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:
29
client/pages/redirect/billing-portal.vue
Normal file
29
client/pages/redirect/billing-portal.vue
Normal 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>
|
||||
62
client/pages/redirect/checkout.vue
Normal file
62
client/pages/redirect/checkout.vue
Normal 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>
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user