feat: dashboard billing (#193)

* feat: move plans into sharable json

* remove unused code

* update pnpm lock

* update plans.json

* implement early adopter pricing

* docs: update meta title and description

* Finished the UI for upgrading plans

* Updated the pricing plans

* Updated the cards ui

* use relative import

* improve styling of upgrade plan card

* styling improvements, lemonsqueezy setup

* trigger lemonsqueezy payment and add webhook

* update pnpm lock

* add logout route

* feat: complete billing functionality

* generate lock file

* make crypto false on browser

* feat: adding upgrade prompts to org

* chore: add upgrade icon to upload video

* feat: add upgrade prompt to certificate and settings

* feat: implement onboarding setup page (#229)

* working on the onboarding setup

* working on the onboarding page

* Almost done with the onboarding UI

* finished the UI of the onBoarding setup

* finished the UI of the onBoarding setup

* Implementing the functions to carryout the logic of updating the UI onmount if a user has carried out a certain step or not

* Implementing the functions to carryout the logic of updating the UI onmount if a user has carried out a certain step or not

* making some chnages

* finished the onBoarding task

* updated some logic

* Removed the uneeded svg from the static folder

* fixed isCoursePublished not returning a boolean

* improved the setup link protection

* chore: make menuItems reactive

* improve formatting

* format supabase queries

---------

Co-authored-by: Rotimi Best <best@classroomio.com>

* revamp setup

* improve the upgrade experience

* migration

* feat: add lemonsqueezy customer portal

---------

Co-authored-by: emmanuel <chifez1@gmail.com>
This commit is contained in:
Rotimi Best
2024-04-07 06:08:34 +01:00
committed by GitHub
co-authored by emmanuel
parent 136e057954
commit fcd0bcc656
105 changed files with 1743 additions and 463 deletions
@@ -1,158 +1,141 @@
<script>
import Checkmark from 'carbon-icons-svelte/lib/Checkmark.svelte';
import PLANS from 'shared-constants/src/plans/data.json';
let prices = false;
let isYearlyPlan = false;
function handlePriceChange() {
prices = !prices;
function toggleIsYearlyPlan() {
isYearlyPlan = !isYearlyPlan;
}
const freeFeatures = [
'Unlimited Courses',
'Unlimited Conversations',
'50 Students',
'AI Course Builder (no video upload)',
'Course Landing Page',
'Live chat & Live polls',
'20 AI Prompts'
];
const proFeatures = [
'Everything in Free',
'1000 Students',
'Advanced AI Course Builder (video upload)',
'Lesson/Course PDF Download',
'Certificates',
'2000 AI Prompts',
'Remove ClassroomIO Branding',
'Email Support'
];
const teamFeatures = [
'Everything in Pro',
'Unlimited students',
'Unlimited AI Prompts',
'White Labelling',
'Priority Support'
];
</script>
<section id="pricing" class="py-[12%]">
<div class="px-[6%] flex flex-col justify-center items-center">
<div class="text-center mb-[3%]">
<h1 id="pricing" class="text-blue-700 text-md font-semibold tracking-wide">Pricing</h1>
<h2 class="my-5 lg:my-4 font-semibold tracking-tight text-gray-900 text-3xl lg:text-4xl">
<div class="flex flex-col items-center justify-center px-[6%]">
<div class="mb-[3%] text-center">
<h1 id="pricing" class="text-md font-semibold tracking-wide text-blue-700">Pricing</h1>
<h2 class="my-5 text-3xl font-semibold tracking-tight text-gray-900 lg:my-4 lg:text-4xl">
For teams and individuals
</h2>
<p class="mt-4 text-lg text-gray-500 tracking-normal lg:tracking-wide">
<p class="mt-4 text-lg tracking-normal text-gray-500 lg:tracking-wide">
Customizable LMS, AI integration for productive educators and many more...
</p>
</div>
<div
class="flex items-center border-[2px] rounded-[30px] p-[2px] relative lg:scale-100 mt-10 lg:mt-0"
class="relative mt-10 flex items-center rounded-[30px] border-[2px] p-[2px] lg:mt-0 lg:scale-100"
>
<button
style="background-color: {prices ? 'initial' : '#1D4EE2'}; color: {prices
style="background-color: {isYearlyPlan ? 'initial' : '#1D4EE2'}; color: {isYearlyPlan
? '#5e636b'
: '#fff'}"
class="bg-blue-700 text-white rounded-[30px] py-1 px-3 lg:py-2 lg:px-4 text-xs"
on:click={handlePriceChange}>Monthly</button
class="rounded-[30px] bg-blue-700 px-3 py-1 text-xs text-white lg:px-4 lg:py-2"
on:click={toggleIsYearlyPlan}>Monthly</button
>
<button
style="background-color: {prices ? '#1D4EE2' : ''}; color: {prices ? '#fff' : '#5e636b'}"
class="text-white rounded-[30px] py-1 lg:py-2 px-3 lg:px-4 text-xs"
on:click={handlePriceChange}>Annually</button
style="background-color: {isYearlyPlan ? '#1D4EE2' : ''}; color: {isYearlyPlan
? '#fff'
: '#5e636b'}"
class="rounded-[30px] px-3 py-1 text-xs text-white lg:px-4 lg:py-2"
on:click={toggleIsYearlyPlan}>Annually</button
>
<div
class="absolute top-[-85%] right-[-40%] lg:top-[-75%] lg:right-[-43%] bg-[#006600] text-xs text-white px-3.5 py-1.5 rounded-full scale-[90%] lg:scale-100"
class="absolute right-[-40%] top-[-85%] scale-[90%] rounded-full bg-[#006600] px-3.5 py-1.5 text-xs text-white lg:right-[-43%] lg:top-[-75%] lg:scale-100"
>
Save 2 months
</div>
</div>
<div class="isolate mt-10 grid gap-10 grid-cols-1 lg:grid-cols-3">
<!-- card 1 -->
<div class="ring-gray-200 rounded-3xl p-8 ring-1 xl:p-9 max-w-xl lg:max-w-sm">
<p class="text-gray-900 text-lg lg:text-xl font-semibold leading-8">Hobby</p>
<p class="text-gray-500 font-light mt-4 text-sm lg:text-md leading-6 lg:leading-6">
For personal use. Hobby plan is free for up to 5 courses forever, no credit card required.
<div class="isolate mt-10 grid grid-cols-1 gap-10 lg:grid-cols-3">
<!-- Card 1 -->
<div class="max-w-xl rounded-3xl p-8 ring-1 ring-gray-200 lg:max-w-sm xl:p-9">
<p class="text-lg font-semibold leading-8 text-gray-900 lg:text-xl">
{PLANS.BASIC.NAME}
</p>
<p class="mt-6 flex items-baseline gap-x-1 text-4xl lg:text-4xl font-medium">
$0 <sub class="text-base">/mo</sub>
<p class="lg:text-md mt-4 text-sm font-light leading-6 text-gray-500 lg:leading-6">
{PLANS.BASIC.DESCRIPTION}
</p>
<button
class="font-medium lg:font-semibold text-md lg:text-lg text-white py-3 lg:py-3 w-full bg-slate-900 hover:bg-slate-700 rounded-md lg:rounded-md mt-10"
data-cal-config={"{'layout':'month_view'}"}
data-cal-link="classroomio/demo"
<p class="mt-6 flex items-baseline gap-x-1 text-4xl font-medium lg:text-4xl">
${PLANS.BASIC.PRICE.MONTHLY}
<!-- <sub class="text-base">/mo</sub> -->
</p>
<a
class="text-md mt-10 block w-full rounded-md bg-slate-900 py-3 text-center font-medium text-white hover:bg-slate-700 lg:rounded-md lg:py-3 lg:text-lg lg:font-semibold"
href={PLANS.BASIC.CTA.LINK}
target="_blank"
>
Get started
</button>
<ul class="text-gray-600 mt-8 space-y-2 lg:space-y-5 text-sm xl:mt-10">
{#each freeFeatures as freeFeature}
{PLANS.BASIC.CTA.LABEL}
</a>
<ul class="mt-8 space-y-2 text-sm text-gray-600 lg:space-y-5 xl:mt-10">
{#each PLANS.BASIC.FEATURES as feature}
<li class="flex items-center">
<Checkmark
size={24}
fill="#1D4EE2"
class="mr-2 lg:mr-3 scale-[70%] lg:scale-[100%]"
class="mr-2 scale-[70%] lg:mr-3 lg:scale-[100%]"
/>
{freeFeature}
{feature}
</li>
{/each}
</ul>
</div>
<!-- card 2 -->
<div class="bg-gray-900 rounded-3xl p-8 xl:p-9 max-w-xl lg:max-w-lg">
<p class="text-white text-lg lg:text-xl font-semibold leading-8">Pro</p>
<p class="text-white font-light mt-4 text-sm lg:text-md leading-6 lg:leading-6">
Advanced features for small teaching businesses. Built for scale.
<!-- Card 2 -->
<div class="max-w-xl rounded-3xl bg-gray-900 p-8 lg:max-w-lg xl:p-9">
<p class="text-lg font-semibold leading-8 text-white lg:text-xl">
{PLANS.EARLY_ADOPTER.NAME}
</p>
<p class="mt-6 text-white flex items-baseline gap-x-1 text-4xl lg:text-4xl font-medium">
${prices ? '12' : '15'} <sub class="text-base">/member</sub>
<p class="lg:text-md mt-4 text-sm font-light leading-6 text-white lg:leading-6">
{PLANS.EARLY_ADOPTER.DESCRIPTION}
</p>
<button
class="font-medium lg:font-semibold text-md lg:text-lg text-slate-900 py-3 lg:py-3 w-full bg-white hover:bg-indigo-50 rounded-md lg:rounded-md mt-10"
data-cal-config={"{'layout':'month_view'}"}
data-cal-link="classroomio/demo"
<p class="mt-6 flex items-baseline gap-x-1 text-4xl font-medium text-white lg:text-4xl">
${isYearlyPlan ? PLANS.EARLY_ADOPTER.PRICE.YEARLY : PLANS.EARLY_ADOPTER.PRICE.MONTHLY}
<!-- <sub class="text-base">/mo</sub> -->
</p>
<a
class="text-md mt-10 block w-full rounded-md bg-white py-3 text-center font-medium text-slate-900 hover:bg-indigo-50 lg:rounded-md lg:py-3 lg:text-lg lg:font-semibold"
href={PLANS.EARLY_ADOPTER.CTA.LINK}
target="_blank"
>
Get Started
</button>
<ul class="text-white mt-8 space-y-3 font-light lg:space-y-5 text-sm xl:mt-10">
{#each proFeatures as proFeature}
{PLANS.EARLY_ADOPTER.CTA.LABEL}
</a>
<ul class="mt-8 space-y-3 text-sm font-light text-white lg:space-y-5 xl:mt-10">
{#each PLANS.EARLY_ADOPTER.FEATURES as features}
<li class="flex items-center">
<Checkmark size={24} fill="#fff" class="mr-2 lg:mr-3 scale-[70%] lg:scale-[100%]" />
{proFeature}
<Checkmark size={24} fill="#fff" class="mr-2 scale-[70%] lg:mr-3 lg:scale-[100%]" />
{features}
</li>
{/each}
</ul>
</div>
<!-- card 3 -->
<div class="ring-gray-200 rounded-3xl p-8 ring-1 xl:p-9 max-w-xl lg:max-w-sm">
<p class="text-gray-900 text-lg lg:text-xl font-semibold leading-8">Team</p>
<p class="text-gray-500 font-light mt-4 text-sm lg:text-md leading-6 lg:leading-6">
Best suited for teams and larger businesses that need more control.
<!-- Card 3 -->
<div class="max-w-xl rounded-3xl p-8 ring-1 ring-gray-200 lg:max-w-sm xl:p-9">
<p class="text-lg font-semibold leading-8 text-gray-900 lg:text-xl">
{PLANS.ENTERPRISE.NAME}
</p>
<p class="mt-6 lg:mt-6 flex items-baseline gap-x-1 text-4xl lg:text-4xl font-medium">
${prices ? '42' : '50'} <sub class="text-base">/member</sub>
<p class="lg:text-md mt-4 text-sm font-light leading-6 text-gray-500 lg:leading-6">
{PLANS.ENTERPRISE.DESCRIPTION}
</p>
<p class="mt-6 flex items-baseline gap-x-1 text-xl font-medium lg:mt-6 lg:text-xl">
Request Pricing
</p>
<button
class="font-medium lg:font-semibold text-md lg:text-lg text-white py-3 lg:py-3 w-full bg-slate-900 hover:bg-slate-700 rounded-md lg:rounded-md mt-10"
class="text-md mt-10 w-full rounded-md bg-slate-900 py-3 font-medium text-white hover:bg-slate-700 lg:rounded-md lg:py-3 lg:text-lg lg:font-semibold"
data-cal-config={"{'layout':'month_view'}"}
data-cal-link="classroomio/demo"
data-cal-link="classroomio/enterprise"
>
Get started
{PLANS.ENTERPRISE.CTA.LABEL}
</button>
<ul class="text-gray-600 mt-8 space-y-2 lg:space-y-5 text-sm xl:mt-10">
{#each teamFeatures as teamFeature}
<ul class="mt-8 space-y-2 text-sm text-gray-600 lg:space-y-5 xl:mt-10">
{#each PLANS.ENTERPRISE.FEATURES as features}
<li class="flex items-center">
<Checkmark
size={24}
fill="#1D4EE2"
class="mr-2 lg:mr-3 scale-[70%] lg:scale-[100%]"
class="mr-2 scale-[70%] lg:mr-3 lg:scale-[100%]"
/>
{teamFeature}
{features}
</li>
{/each}
</ul>
@@ -172,7 +155,7 @@
class="m-0 lg:mt-1 text-md leading-7 lg:leading-6 text-gray-600"
>
For personal use. Hobby plan is free for up to 5 courses forever, no
credit card required.
credit Card required.
</p>
</div>
<button