Pricing Upgrade Flow changes (#514)

* Pricing Upgrade Flow changes

* remove extra code

* Refactor subscription plan selection and billing management

* Polish the new pricing modal

---------

Co-authored-by: Julien Nahum <julien@nahum.net>
This commit is contained in:
Chirag Chhatrala
2024-08-23 15:53:01 +05:30
committed by GitHub
parent a73badb091
commit fedc382594
16 changed files with 1146 additions and 366 deletions

View File

@@ -4,18 +4,18 @@
<div
v-if="show"
ref="backdrop"
class="fixed z-30 top-0 inset-0 px-4 sm:px-0 flex items-top justify-center bg-gray-700/75 w-full h-screen overflow-y-scroll"
class="fixed z-30 top-0 inset-0 px-2 sm:px-4 flex items-top justify-center bg-gray-700/75 w-full h-screen overflow-y-scroll"
:class="{ 'backdrop-blur-sm': backdropBlur }"
@click.self="close"
>
<div
ref="content"
class="self-start bg-white dark:bg-notion-dark w-full relative my-6 rounded-xl shadow-xl"
class="self-start bg-white dark:bg-notion-dark w-full relative my-2 sm:my-6 rounded-xl shadow-xl"
:class="maxWidthClass"
>
<div
v-if="closeable"
class="absolute top-4 right-4 z-10"
class="absolute top-4 right-4"
>
<button
class="text-gray-500 hover:text-gray-900 cursor-pointer"
@@ -93,84 +93,85 @@
</template>
<script setup>
import { watch } from "vue"
import { default as _has } from "lodash/has"
import { watch } from 'vue'
import { default as _has } from 'lodash/has'
const props = defineProps({
show: {
type: Boolean,
default: false,
default: false
},
backdropBlur: {
type: Boolean,
default: false,
default: false
},
iconColor: {
type: String,
default: "blue",
default: 'blue'
},
maxWidth: {
type: String,
default: "2xl",
default: '2xl'
},
innerPadding: {
type: String,
default: "p-6",
default: 'p-6'
},
headerInnerPadding: {
type: String,
default: "p-6",
default: 'p-6'
},
footerInnerPadding: {
type: String,
default: "p-6",
default: 'p-6'
},
closeable: {
type: Boolean,
default: true,
default: true
},
compactHeader: {
default: false,
type: Boolean,
},
type: Boolean
}
})
const emit = defineEmits(["close"])
const emit = defineEmits(['close'])
useHead({
bodyAttrs: computed(() => {
return {
class: {
"overflow-hidden": props.show,
},
'overflow-hidden': props.show
}
}
}),
})
})
const closeOnEscape = (e) => {
if (e.key === "Escape" && props.show) {
if (e.key === 'Escape' && props.show) {
close()
}
}
onMounted(() => {
if (import.meta.server) return
document.addEventListener("keydown", closeOnEscape)
document.addEventListener('keydown', closeOnEscape)
initMotions()
})
onBeforeUnmount(() => {
if (import.meta.server) return
document.removeEventListener("keydown", closeOnEscape)
document.removeEventListener('keydown', closeOnEscape)
})
const maxWidthClass = computed(() => {
return {
sm: "sm:max-w-sm",
md: "sm:max-w-md",
lg: "sm:max-w-lg",
xl: "sm:max-w-xl",
"2xl": "sm:max-w-2xl",
sm: 'sm:max-w-sm',
md: 'sm:max-w-md',
lg: 'sm:max-w-lg',
xl: 'sm:max-w-xl',
'2xl': 'max-w-2xl',
'screen-lg': 'max-w-screen-lg'
}[props.maxWidth]
})
@@ -180,15 +181,15 @@ const motionFadeIn = {
transition: {
delay: 100,
duration: 200,
ease: "easeIn",
},
ease: 'easeIn'
}
},
enter: {
opacity: 1,
transition: {
duration: 200,
},
},
duration: 200
}
}
}
const motionSlideBottom = {
@@ -196,19 +197,19 @@ const motionSlideBottom = {
y: 150,
opacity: 0,
transition: {
ease: "easeIn",
duration: 200,
},
ease: 'easeIn',
duration: 200
}
},
enter: {
y: 0,
opacity: 1,
transition: {
duration: 250,
ease: "easeOut",
delay: 100,
},
},
ease: 'easeOut',
delay: 100
}
}
}
const onLeave = (el, done) => {
@@ -218,7 +219,7 @@ const onLeave = (el, done) => {
const close = () => {
if (props.closeable) {
emit("close")
emit('close')
}
}

View File

@@ -1,73 +1,45 @@
<template>
<div
<UTooltip
v-if="shouldDisplayProTag"
class="inline"
:text="upgradeModalTitle??'You need a Pro plan to use this feature'"
class="inline normal-case"
>
<UTooltip text="Upgrade to use this feature">
<div
role="button"
class="bg-nt-blue text-white px-2 text-xs uppercase inline rounded-full font-semibold cursor-pointer"
@click="showPremiumModal = true"
>
PRO
</div>
<modal
:show="showPremiumModal"
@close="showPremiumModal = false"
>
<h2 class="text-nt-blue">
OpnForm PRO
</h2>
<h4
v-if="user && user.is_subscribed"
class="text-center mt-5"
>
We're happy to have you as a Pro customer. If you're having any issue
with OpnForm, or if you have a feature request, please
<a href="mailto:contact@opnform.com">contact us</a>.
</h4>
<div
v-if="!user || !user.is_subscribed"
class="mt-4"
>
<p>
All the features with a<span
class="bg-nt-blue text-white px-2 text-xs uppercase inline rounded-full font-semibold mx-1"
>
PRO
</span>
tag are available in the Pro plan of OpnForm.
<b>You can play around and try all Pro features within the form
editor, but you can't use them in your real forms</b>. You can subscribe now to gain unlimited access to all our pro
features!
</p>
</div>
<div class="my-4 text-center">
<v-button
color="white"
@click="showPremiumModal = false"
>
Close
</v-button>
</div>
</modal>
</UTooltip>
</div>
<div
v-track.pro_tag_click="{title:upgradeModalTitle}"
class="bg-nt-blue text-white px-2 text-xs uppercase inline rounded-full font-semibold cursor-pointer"
@click.stop="onClick"
>
PRO
</div>
</UTooltip>
</template>
<script setup>
import { computed } from "vue"
const props = defineProps({
upgradeModalTitle: {
type: String
},
upgradeModalDescription: {
type: String
}
})
const subscriptionModalStore = useSubscriptionModalStore()
const authStore = useAuthStore()
const workspacesStore = useWorkspacesStore()
const user = computed(() => authStore.user)
const workspace = computed(() => workspacesStore.getCurrent)
const showPremiumModal = ref(false)
const shouldDisplayProTag = computed(() => {
if (!useRuntimeConfig().public.paidPlansEnabled) return false
if (!user.value || !workspace.value) return true
return !workspace.value.is_pro
})
function onClick () {
subscriptionModalStore.setModalContent(props.upgradeModalTitle, props.upgradeModalDescription)
subscriptionModalStore.openModal()
}
</script>