Billing and usage page updates to support different kinds of users and plans
This commit is contained in:
parent
bbbf8bfc0b
commit
ba5ed65e03
|
@ -1,6 +1,6 @@
|
|||
<script>
|
||||
import { Body, ProgressBar, Heading, Icon, Link } from "@budibase/bbui"
|
||||
import { admin } from "../../stores/portal"
|
||||
import { admin, auth } from "../../stores/portal"
|
||||
import { onMount } from "svelte"
|
||||
export let usage
|
||||
export let warnWhenFull = false
|
||||
|
@ -9,6 +9,8 @@
|
|||
let unlimited = false
|
||||
let showWarning = false
|
||||
|
||||
$: accountPortalAccess = $auth?.user?.accountPortalAccess
|
||||
|
||||
const isUnlimited = () => {
|
||||
if (usage.total === -1) {
|
||||
return true
|
||||
|
@ -66,7 +68,12 @@
|
|||
{/if}
|
||||
{#if showWarning}
|
||||
<Body size="S">
|
||||
To get more queries <Link href={upgradeUrl}>upgrade your plan</Link>
|
||||
To get more {usage.name.toLowerCase()}
|
||||
{#if accountPortalAccess}
|
||||
<Link href={upgradeUrl}>upgrade your plan</Link>
|
||||
{:else}
|
||||
contact your account holder
|
||||
{/if}
|
||||
</Body>
|
||||
{/if}
|
||||
</div>
|
||||
|
|
|
@ -3,12 +3,11 @@
|
|||
|
||||
export let description = ""
|
||||
export let title = ""
|
||||
export let subtitle = ""
|
||||
export let primaryAction
|
||||
export let secondaryAction
|
||||
export let primaryActionText
|
||||
export let secondaryActionText
|
||||
export let primaryCta = false
|
||||
export let primaryCta = true
|
||||
export let textRows = []
|
||||
|
||||
$: primaryDefined = primaryAction && primaryActionText
|
||||
|
@ -23,14 +22,13 @@
|
|||
<Detail size="M">{description}</Detail>
|
||||
</div>
|
||||
<Heading size="M">{title}</Heading>
|
||||
<div class="dash-card-title">
|
||||
<Detail size="M">{subtitle}</Detail>
|
||||
</div>
|
||||
<div class="text-rows">
|
||||
{#each textRows as row}
|
||||
<Body>{row}</Body>
|
||||
{/each}
|
||||
</div>
|
||||
{#if textRows.length}
|
||||
<div class="text-rows">
|
||||
{#each textRows as row}
|
||||
<Body>{row}</Body>
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
</Layout>
|
||||
</div>
|
||||
<div class="header-actions">
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
Heading,
|
||||
Layout,
|
||||
notifications,
|
||||
Page,
|
||||
Detail,
|
||||
Link,
|
||||
} from "@budibase/bbui"
|
||||
import { onMount } from "svelte"
|
||||
import { admin, auth, licensing } from "../../../../stores/portal"
|
||||
|
@ -15,29 +15,20 @@
|
|||
|
||||
let staticUsage = []
|
||||
let monthlyUsage = []
|
||||
let price
|
||||
let lastPayment
|
||||
let cancelAt
|
||||
let nextPayment
|
||||
let balance
|
||||
let loaded = false
|
||||
let textRows = []
|
||||
let daysRemainingInMonth
|
||||
let primaryActionText
|
||||
|
||||
const upgradeUrl = `${$admin.accountPortalUrl}/portal/upgrade`
|
||||
const manageUrl = `${$admin.accountPortalUrl}/portal/billing`
|
||||
|
||||
const warnUsage = ["Queries", "Automations", "Rows"]
|
||||
const warnUsage = ["Queries", "Automations", "Rows", "Day Passes"]
|
||||
|
||||
$: quotaUsage = $licensing.quotaUsage
|
||||
$: license = $auth.user?.license
|
||||
|
||||
const numberFormatter = new Intl.NumberFormat("en-US", {
|
||||
style: "currency",
|
||||
currency: "USD",
|
||||
minimumFractionDigits: 0,
|
||||
maximumFractionDigits: 0,
|
||||
})
|
||||
$: accountPortalAccess = $auth?.user?.accountPortalAccess
|
||||
|
||||
const setMonthlyUsage = () => {
|
||||
monthlyUsage = []
|
||||
|
@ -71,49 +62,8 @@
|
|||
staticUsage = staticUsage.sort((a, b) => a.name.localeCompare(b.name))
|
||||
}
|
||||
|
||||
const setNextPayment = () => {
|
||||
const periodEnd = license?.billing.subscription?.currentPeriodEnd
|
||||
const cancelAt = license?.billing.subscription?.cancelAt
|
||||
if (periodEnd) {
|
||||
if (cancelAt && periodEnd <= cancelAt) {
|
||||
return
|
||||
}
|
||||
nextPayment = `Next payment: ${getLocaleDataString(periodEnd)}`
|
||||
}
|
||||
}
|
||||
|
||||
const setCancelAt = () => {
|
||||
cancelAt = license?.billing.subscription?.cancelAt
|
||||
}
|
||||
|
||||
const setLastPayment = () => {
|
||||
const periodStart = license?.billing.subscription?.currentPeriodStart
|
||||
if (periodStart) {
|
||||
lastPayment = `Last payment: ${getLocaleDataString(periodStart)}`
|
||||
}
|
||||
}
|
||||
|
||||
const setBalance = () => {
|
||||
const customerBalance = license?.billing.customer.balance
|
||||
if (customerBalance) {
|
||||
balance = `Balance: ${numberFormatter.format(
|
||||
(customerBalance / 100) * -1
|
||||
)}`
|
||||
}
|
||||
}
|
||||
|
||||
const getLocaleDataString = epoch => {
|
||||
const date = new Date(epoch * 1000)
|
||||
return date.toLocaleDateString("default", {
|
||||
day: "numeric",
|
||||
month: "long",
|
||||
year: "numeric",
|
||||
})
|
||||
}
|
||||
|
||||
const setPrice = () => {
|
||||
const planPrice = license.plan.price
|
||||
price = `${numberFormatter.format(planPrice.amountMonthly / 100)} per month`
|
||||
cancelAt = license?.billing?.subscription?.cancelAt
|
||||
}
|
||||
|
||||
const capitalise = string => {
|
||||
|
@ -126,10 +76,6 @@
|
|||
return capitalise(license?.plan.type)
|
||||
}
|
||||
|
||||
const planSubtitle = () => {
|
||||
return `${license?.plan.price.sessions} day passes`
|
||||
}
|
||||
|
||||
const getDaysRemaining = timestamp => {
|
||||
if (!timestamp) {
|
||||
return
|
||||
|
@ -153,16 +99,6 @@
|
|||
if (cancelAt) {
|
||||
textRows.push("Subscription has been cancelled")
|
||||
textRows.push(`${getDaysRemaining(cancelAt * 1000)} days remaining`)
|
||||
} else {
|
||||
if (price) {
|
||||
textRows.push(price)
|
||||
}
|
||||
if (lastPayment) {
|
||||
textRows.push(lastPayment)
|
||||
}
|
||||
if (nextPayment) {
|
||||
textRows.push(nextPayment)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -185,6 +121,19 @@
|
|||
}
|
||||
}
|
||||
|
||||
const setPrimaryActionText = () => {
|
||||
if (license?.plan.type === PlanType.FREE) {
|
||||
primaryActionText = "Upgrade"
|
||||
return
|
||||
}
|
||||
|
||||
if (cancelAt) {
|
||||
primaryActionText = "Renew"
|
||||
} else {
|
||||
primaryActionText = "Manage"
|
||||
}
|
||||
}
|
||||
|
||||
const init = async () => {
|
||||
try {
|
||||
await licensing.getQuotaUsage()
|
||||
|
@ -201,10 +150,7 @@
|
|||
|
||||
$: {
|
||||
if (license) {
|
||||
setPrice()
|
||||
setBalance()
|
||||
setLastPayment()
|
||||
setNextPayment()
|
||||
setPrimaryActionText()
|
||||
setCancelAt()
|
||||
setTextRows()
|
||||
setDaysRemainingInMonth()
|
||||
|
@ -217,67 +163,71 @@
|
|||
}
|
||||
</script>
|
||||
|
||||
<Page maxWidth={"100ch"}>
|
||||
{#if loaded}
|
||||
<Layout>
|
||||
<Layout noPadding gap="S">
|
||||
<Heading>Billing</Heading>
|
||||
<Body
|
||||
>Get information about your current usage and manage your plan</Body
|
||||
>
|
||||
</Layout>
|
||||
<Divider />
|
||||
<DashCard
|
||||
description="YOUR CURRENT PLAN"
|
||||
title={planTitle()}
|
||||
subtitle={planSubtitle()}
|
||||
primaryActionText={cancelAt ? "Upgrade" : "Manage"}
|
||||
primaryAction={goToAccountPortal}
|
||||
{textRows}
|
||||
>
|
||||
<Layout gap="S" noPadding>
|
||||
<Layout gap="S">
|
||||
<div class="usages">
|
||||
<Layout noPadding>
|
||||
{#each staticUsage as usage}
|
||||
<div class="usage">
|
||||
<Usage
|
||||
{usage}
|
||||
warnWhenFull={warnUsage.includes(usage.name)}
|
||||
/>
|
||||
</div>
|
||||
{/each}
|
||||
</Layout>
|
||||
</div>
|
||||
</Layout>
|
||||
{#if monthlyUsage.length}
|
||||
<div class="monthly-container">
|
||||
<Layout gap="S">
|
||||
<Heading size="S" weight="light">Monthly</Heading>
|
||||
<div class="detail">
|
||||
<Detail size="M">Resets in {daysRemainingInMonth} days</Detail
|
||||
>
|
||||
</div>
|
||||
<div class="usages">
|
||||
<Layout noPadding>
|
||||
{#each monthlyUsage as usage}
|
||||
<div class="usage">
|
||||
<Usage
|
||||
{usage}
|
||||
warnWhenFull={warnUsage.includes(usage.name)}
|
||||
/>
|
||||
</div>
|
||||
{/each}
|
||||
</Layout>
|
||||
</div>
|
||||
</Layout>
|
||||
</div>
|
||||
{/if}
|
||||
</Layout>
|
||||
</DashCard>
|
||||
{#if loaded}
|
||||
<Layout>
|
||||
<Layout noPadding gap="S">
|
||||
<Heading>Usage</Heading>
|
||||
<Body
|
||||
>Get information about your current usage within Budibase.
|
||||
{#if accountPortalAccess}
|
||||
To upgrade your plan and usage limits visit your <Link
|
||||
on:click={goToAccountPortal}
|
||||
size="L">Account</Link
|
||||
>
|
||||
{:else}
|
||||
To upgrade your plan and usage limits contact your account holder
|
||||
{/if}
|
||||
</Body>
|
||||
</Layout>
|
||||
{/if}
|
||||
</Page>
|
||||
<Divider />
|
||||
<DashCard
|
||||
description="YOUR CURRENT PLAN"
|
||||
title={planTitle()}
|
||||
{primaryActionText}
|
||||
primaryAction={accountPortalAccess ? goToAccountPortal : undefined}
|
||||
{textRows}
|
||||
>
|
||||
<Layout gap="S" noPadding>
|
||||
<Layout gap="S">
|
||||
<div class="usages">
|
||||
<Layout noPadding>
|
||||
{#each staticUsage as usage}
|
||||
<div class="usage">
|
||||
<Usage
|
||||
{usage}
|
||||
warnWhenFull={warnUsage.includes(usage.name)}
|
||||
/>
|
||||
</div>
|
||||
{/each}
|
||||
</Layout>
|
||||
</div>
|
||||
</Layout>
|
||||
{#if monthlyUsage.length}
|
||||
<div class="monthly-container">
|
||||
<Layout gap="S">
|
||||
<Heading size="S" weight="light">Monthly</Heading>
|
||||
<div class="detail">
|
||||
<Detail size="M">Resets in {daysRemainingInMonth} days</Detail>
|
||||
</div>
|
||||
<div class="usages">
|
||||
<Layout noPadding>
|
||||
{#each monthlyUsage as usage}
|
||||
<div class="usage">
|
||||
<Usage
|
||||
{usage}
|
||||
warnWhenFull={warnUsage.includes(usage.name)}
|
||||
/>
|
||||
</div>
|
||||
{/each}
|
||||
</Layout>
|
||||
</div>
|
||||
</Layout>
|
||||
</div>
|
||||
{/if}
|
||||
</Layout>
|
||||
</DashCard>
|
||||
</Layout>
|
||||
{/if}
|
||||
|
||||
<style>
|
||||
.usages {
|
||||
|
@ -289,10 +239,4 @@
|
|||
margin-bottom: 5px;
|
||||
margin-top: -8px;
|
||||
}
|
||||
/*.monthly-container {*/
|
||||
/* margin-top: -35px;*/
|
||||
/*}*/
|
||||
.card-container {
|
||||
margin-top: 25px;
|
||||
}
|
||||
</style>
|
||||
|
|
Loading…
Reference in New Issue