Skip to content

Commit 41b6398

Browse files
committed
update: simplify billing context & checks.
1 parent e5ab426 commit 41b6398

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+215
-327
lines changed

src/lib/components/backupDatabaseAlert.svelte

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
<script lang="ts">
22
import { page } from '$app/stores';
3-
import { BillingPlan } from '$lib/constants';
43
import { Button } from '$lib/elements/forms';
54
import { organization } from '$lib/stores/organization';
65
import { HeaderAlert } from '$lib/layout';
76
import { isCloud } from '$lib/system';
8-
import { upgradeURL } from '$lib/stores/billing';
7+
import { isFreeTier, upgradeURL } from '$lib/stores/billing';
98
import { hideNotification } from '$lib/helpers/notifications';
109
import { backupsBannerId, showPolicyAlert } from '$lib/stores/database';
1110
@@ -16,7 +15,7 @@
1615
</script>
1716

1817
{#if $showPolicyAlert && isCloud && $organization?.$id && $page.url.pathname.match(/\/databases\/database-[^/]+$/)}
19-
{@const isFreePlan = $organization?.billingPlan === BillingPlan.FREE}
18+
{@const isFreePlan = isFreeTier($organization?.billingPlan)}
2019

2120
{@const subtitle = isFreePlan
2221
? 'Upgrade your plan to ensure your data stays safe and backed up'

src/lib/components/backupRestoreBox.svelte

+3-2
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,15 @@
44
import { onMount } from 'svelte';
55
import { isCloud, isSelfHosted } from '$lib/system';
66
import { organization } from '$lib/stores/organization';
7-
import { BillingPlan, Dependencies } from '$lib/constants';
7+
import { Dependencies } from '$lib/constants';
88
import type { BackupArchive, BackupRestoration } from '$lib/sdk/backups';
99
import { goto, invalidate } from '$app/navigation';
1010
import { page } from '$app/stores';
1111
import { addNotification } from '$lib/stores/notifications';
1212
import { base } from '$app/paths';
1313
import { getProjectId } from '$lib/helpers/project';
1414
import { toLocaleDate } from '$lib/helpers/date';
15+
import { isFreeTier } from '$lib/stores/billing';
1516
1617
const backupRestoreItems: {
1718
archives: Map<string, BackupArchive>;
@@ -120,7 +121,7 @@
120121
121122
onMount(() => {
122123
// fast path: don't subscribe if org is on a free plan or is self-hosted.
123-
if (isSelfHosted || (isCloud && $organization.billingPlan === BillingPlan.FREE)) return;
124+
if (isSelfHosted || (isCloud && isFreeTier($organization.billingPlan))) return;
124125
125126
return sdk.forConsole.client.subscribe('console', (response) => {
126127
if (!response.channels.includes(`projects.${getProjectId()}`)) return;

src/lib/components/billing/alerts/limitReached.svelte

+8-2
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,17 @@
55
import { BillingPlan } from '$lib/constants';
66
import { Button } from '$lib/elements/forms';
77
import { HeaderAlert } from '$lib/layout';
8-
import { hideBillingHeaderRoutes, readOnly, tierToPlan, upgradeURL } from '$lib/stores/billing';
8+
import {
9+
hideBillingHeaderRoutes,
10+
isFreeTier,
11+
readOnly,
12+
tierToPlan,
13+
upgradeURL
14+
} from '$lib/stores/billing';
915
import { organization } from '$lib/stores/organization';
1016
</script>
1117

12-
{#if $organization?.$id && $organization?.billingPlan === BillingPlan.FREE && $readOnly && !hideBillingHeaderRoutes.includes($page.url.pathname)}
18+
{#if $organization?.$id && isFreeTier($organization?.billingPlan) && $readOnly && !hideBillingHeaderRoutes.includes($page.url.pathname)}
1319
<HeaderAlert
1420
type="error"
1521
title={`${$organization.name} usage has reached the ${tierToPlan($organization.billingPlan).name} plan limit`}>

src/lib/components/billing/alerts/newDevUpgradePro.svelte

+3-2
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,12 @@
22
import { base } from '$app/paths';
33
import { page } from '$app/stores';
44
import { trackEvent } from '$lib/actions/analytics';
5-
import { BillingPlan, NEW_DEV_PRO_UPGRADE_COUPON } from '$lib/constants';
5+
import { NEW_DEV_PRO_UPGRADE_COUPON } from '$lib/constants';
66
import { Button } from '$lib/elements/forms';
77
import { organization } from '$lib/stores/organization';
88
import { activeHeaderAlert } from '$routes/(console)/store';
99
import GradientBanner from '../gradientBanner.svelte';
10+
import { isFreeTier } from '$lib/stores/billing';
1011
1112
let show = true;
1213
@@ -21,7 +22,7 @@
2122
}
2223
</script>
2324

24-
{#if show && $organization?.$id && $organization?.billingPlan === BillingPlan.FREE && !$page.url.pathname.includes('/console/account')}
25+
{#if show && $organization?.$id && isFreeTier($organization?.billingPlan) && !$page.url.pathname.includes('/console/account')}
2526
<GradientBanner on:close={handleClose}>
2627
<div class="u-flex u-gap-24 u-main-center u-cross-center u-flex-vertical-mobile">
2728
<span class="body-text-1">Get $50 Cloud credits for Appwrite Pro.</span>

src/lib/components/billing/planComparisonBox.svelte

+12-18
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,32 @@
11
<script lang="ts">
22
import { BillingPlan } from '$lib/constants';
33
import { formatNum } from '$lib/helpers/string';
4-
import { plansInfo, tierFree, tierPro, tierScale, type Tier } from '$lib/stores/billing';
4+
import { isFreeTier, plansInfo, type Tier } from '$lib/stores/billing';
55
import { Card, SecondaryTabs, SecondaryTabsItem } from '..';
66
7-
let selectedTab: Tier = BillingPlan.FREE;
87
export let downgrade = false;
98
9+
// get the first available tier as default.
10+
let selectedTab: Tier = $plansInfo.keys().next().value;
11+
1012
$: plan = $plansInfo.get(selectedTab);
1113
</script>
1214

1315
<Card style="--card-padding: 1.5rem">
1416
<div class="comparison-box">
1517
<SecondaryTabs stretch>
16-
<SecondaryTabsItem
17-
disabled={selectedTab === BillingPlan.FREE}
18-
on:click={() => (selectedTab = BillingPlan.FREE)}>
19-
{tierFree.name}
20-
</SecondaryTabsItem>
21-
<SecondaryTabsItem
22-
disabled={selectedTab === BillingPlan.PRO}
23-
on:click={() => (selectedTab = BillingPlan.PRO)}>
24-
{tierPro.name}
25-
</SecondaryTabsItem>
26-
<SecondaryTabsItem
27-
disabled={selectedTab === BillingPlan.SCALE}
28-
on:click={() => (selectedTab = BillingPlan.SCALE)}>
29-
{tierScale.name}
30-
</SecondaryTabsItem>
18+
{#each $plansInfo.entries() as [tier, plan] (tier)}
19+
<SecondaryTabsItem
20+
disabled={selectedTab === tier}
21+
on:click={() => (selectedTab = tier)}>
22+
{plan.name}
23+
</SecondaryTabsItem>
24+
{/each}
3125
</SecondaryTabs>
3226
</div>
3327

3428
<div class="u-margin-block-start-24">
35-
{#if selectedTab === BillingPlan.FREE}
29+
{#if isFreeTier(selectedTab)}
3630
<h3 class="u-bold body-text-1">{plan.name} plan</h3>
3731
{#if downgrade}
3832
<ul class="u-margin-block-start-8 list u-gap-4 u-small">
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
<script lang="ts">
2-
import { BillingPlan } from '$lib/constants';
32
import { formatCurrency } from '$lib/helpers/numbers';
4-
import { plansInfo, tierFree, tierPro, tierScale, type Tier } from '$lib/stores/billing';
3+
import { isFreeTier, plansInfo, type Tier } from '$lib/stores/billing';
54
import { organization } from '$lib/stores/organization';
65
import { LabelCard } from '..';
76
@@ -11,97 +10,40 @@
1110
export let selfService = true;
1211
let classes: string = '';
1312
export { classes as class };
14-
15-
$: freePlan = $plansInfo.get(BillingPlan.FREE);
16-
$: proPlan = $plansInfo.get(BillingPlan.PRO);
17-
$: scalePlan = $plansInfo.get(BillingPlan.SCALE);
1813
</script>
1914

2015
{#if billingPlan}
2116
<ul class="u-flex u-flex-vertical u-gap-16 u-margin-block-start-8 {classes}">
22-
<li>
23-
<LabelCard
24-
name="plan"
25-
bind:group={billingPlan}
26-
disabled={anyOrgFree || !selfService}
27-
value={BillingPlan.FREE}
28-
tooltipShow={anyOrgFree}
29-
tooltipText="You are limited to 1 Free organization per account."
30-
padding={1.5}>
31-
<svelte:fragment slot="custom" let:disabled>
32-
<div
33-
class="u-flex u-flex-vertical u-gap-4 u-width-full-line"
34-
class:u-opacity-50={disabled}>
35-
<h4 class="body-text-2 u-bold">
36-
{tierFree.name}
37-
{#if $organization?.billingPlan === BillingPlan.FREE && !isNewOrg}
38-
<span class="inline-tag">Current plan</span>
39-
{/if}
40-
</h4>
41-
<p class="u-color-text-offline u-small">
42-
{tierFree.description}
43-
</p>
44-
<p>
45-
{formatCurrency(freePlan?.price ?? 0)}
46-
</p>
47-
</div>
48-
</svelte:fragment>
49-
</LabelCard>
50-
</li>
51-
52-
<li>
53-
<LabelCard
54-
name="plan"
55-
disabled={!selfService}
56-
bind:group={billingPlan}
57-
value={BillingPlan.PRO}
58-
padding={1.5}>
59-
<svelte:fragment slot="custom" let:disabled>
60-
<div
61-
class="u-flex u-flex-vertical u-gap-4 u-width-full-line"
62-
class:u-opacity-50={disabled}>
63-
<h4 class="body-text-2 u-bold">
64-
{tierPro.name}
65-
{#if $organization?.billingPlan === BillingPlan.PRO && !isNewOrg}
66-
<span class="inline-tag">Current plan</span>
67-
{/if}
68-
</h4>
69-
<p class="u-color-text-offline u-small">
70-
{tierPro.description}
71-
</p>
72-
<p>
73-
{formatCurrency(proPlan?.price ?? 0)} per member/month + usage
74-
</p>
75-
</div>
76-
</svelte:fragment>
77-
</LabelCard>
78-
</li>
79-
<li>
80-
<LabelCard
81-
name="plan"
82-
bind:group={billingPlan}
83-
value={BillingPlan.SCALE}
84-
padding={1.5}
85-
disabled={!selfService}>
86-
<svelte:fragment slot="custom" let:disabled>
87-
<div
88-
class="u-flex u-flex-vertical u-gap-4 u-width-full-line"
89-
class:u-opacity-50={disabled}>
90-
<h4 class="body-text-2 u-bold">
91-
{tierScale.name}
92-
{#if $organization?.billingPlan === BillingPlan.SCALE && !isNewOrg}
93-
<span class="inline-tag">Current plan</span>
94-
{/if}
95-
</h4>
96-
<p class="u-color-text-offline u-small">
97-
{tierScale.description}
98-
</p>
99-
<p>
100-
{formatCurrency(scalePlan?.price ?? 0)} per month + usage
101-
</p>
102-
</div>
103-
</svelte:fragment>
104-
</LabelCard>
105-
</li>
17+
{#each $plansInfo.entries() as [tier, plan] (tier)}
18+
<li>
19+
<LabelCard
20+
name="plan"
21+
bind:group={billingPlan}
22+
disabled={anyOrgFree || !selfService}
23+
value={tier}
24+
tooltipShow={anyOrgFree}
25+
tooltipText="You are limited to 1 Free organization per account."
26+
padding={1.5}>
27+
<svelte:fragment slot="custom" let:disabled>
28+
<div
29+
class="u-flex u-flex-vertical u-gap-4 u-width-full-line"
30+
class:u-opacity-50={disabled}>
31+
<h4 class="body-text-2 u-bold">
32+
{plan.name}
33+
{#if isFreeTier($organization?.billingPlan) && !isNewOrg}
34+
<span class="inline-tag">Current plan</span>
35+
{/if}
36+
</h4>
37+
<p class="u-color-text-offline u-small">
38+
{plan.desc}
39+
</p>
40+
<p>
41+
{formatCurrency(plan?.price ?? 0)}
42+
</p>
43+
</div>
44+
</svelte:fragment>
45+
</LabelCard>
46+
</li>
47+
{/each}
10648
</ul>
10749
{/if}

src/lib/components/billing/selectPlan.svelte

+6-7
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
<script lang="ts">
2-
import { BillingPlan } from '$lib/constants';
32
import { formatCurrency } from '$lib/helpers/numbers';
4-
import { plansInfo } from '$lib/stores/billing';
3+
import { isFreeTier, plansInfo } from '$lib/stores/billing';
54
import { organization } from '$lib/stores/organization';
65
import { LabelCard } from '..';
76
@@ -14,15 +13,15 @@
1413

1514
{#if billingPlan}
1615
<ul class="u-flex u-flex-vertical u-gap-16 u-margin-block-start-8 {classes}">
17-
{#each $plansInfo.values() as plan}
16+
{#each $plansInfo.entries() as [tier, plan]}
1817
<li>
1918
<LabelCard
2019
name="plan"
2120
bind:group={billingPlan}
22-
disabled={(plan.$id === BillingPlan.FREE && anyOrgFree) || !plan.selfService}
23-
value={plan.$id}
24-
tooltipShow={plan.$id === BillingPlan.FREE && anyOrgFree}
25-
tooltipText={plan.$id === BillingPlan.FREE
21+
disabled={(isFreeTier(tier) && anyOrgFree) || !plan.selfService}
22+
value={tier}
23+
tooltipShow={isFreeTier(tier) && anyOrgFree}
24+
tooltipText={isFreeTier(tier)
2625
? 'You are limited to 1 Free organization per account.'
2726
: ''}
2827
padding={1.5}>

src/lib/components/billing/usageRates.svelte

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
} from '$lib/elements/table';
1212
import { toLocaleDate } from '$lib/helpers/date';
1313
import { organization, type Organization } from '$lib/stores/organization';
14-
import { plansInfo } from '$lib/stores/billing';
14+
import { isFreeTier, plansInfo } from '$lib/stores/billing';
1515
import { abbreviateNumber, formatCurrency } from '$lib/helpers/numbers';
1616
import { BillingPlan } from '$lib/constants';
1717
@@ -49,7 +49,7 @@
4949
}
5050
];
5151
52-
$: isFree = org.billingPlan === BillingPlan.FREE;
52+
$: isFree = isFreeTier(org.billingPlan);
5353
</script>
5454

5555
<Modal bind:show size="big" headerDivider={false} title="Usage rates">

src/lib/components/bottomModalAlert.svelte

+3-5
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
import { onMount } from 'svelte';
1212
import { organization } from '$lib/stores/organization';
1313
import { BillingPlan } from '$lib/constants';
14-
import { upgradeURL } from '$lib/stores/billing';
14+
import { isFreeTier, upgradeURL } from '$lib/stores/billing';
1515
import { addBottomModalAlerts } from '$routes/(console)/bottomAlerts';
1616
import { project } from '$routes/(console)/project-[project]/store';
1717
import { page } from '$app/stores';
@@ -74,11 +74,9 @@
7474
case 'free':
7575
return false;
7676
case 'pro':
77-
return organizationPlan === BillingPlan.FREE;
77+
return isFreeTier(organizationPlan);
7878
case 'scale':
79-
return (
80-
organizationPlan === BillingPlan.FREE || organizationPlan === BillingPlan.PRO
81-
);
79+
return isFreeTier(organizationPlan) || organizationPlan === BillingPlan.PRO;
8280
}
8381
}
8482

src/lib/components/emptyCardImageCloud.svelte

+1-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
<script>
2-
import { getNextTier, tierToPlan } from '$lib/stores/billing';
3-
import { organization } from '$lib/stores/organization';
42
import Card from './card.svelte';
53
64
export let source = 'empty_state_card';
@@ -22,7 +20,7 @@
2220
<div class="u-stretch u-flex-vertical u-main-center">
2321
<h3 class="body-text-2 u-bold"><slot name="title" /></h3>
2422
<p class="u-margin-block-start-8">
25-
<slot nextTier={tierToPlan(getNextTier($organization.billingPlan)).name} />
23+
<slot />
2624
</p>
2725
<slot name="cta" {source} />
2826
</div>

src/lib/components/roles/upgrade.svelte

+4-5
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,18 @@
11
<script>
22
import Base from './base.svelte';
3-
import { upgradeURL } from '$lib/stores/billing';
3+
import { isFreeTier, upgradeURL } from '$lib/stores/billing';
44
import { isCloud } from '$lib/system';
55
import { organization } from '$lib/stores/organization';
6-
import { BillingPlan } from '$lib/constants';
76
import Button from '$lib/elements/forms/button.svelte';
87
</script>
98

109
<Base>
1110
{#if isCloud}
12-
{#if $organization?.billingPlan !== BillingPlan.FREE}
11+
{#if !isFreeTier($organization?.billingPlan)}
1312
<div class="u-flex-vertical u-gap-8">
1413
<p>
1514
<span class="u-bold">Roles</span>
16-
{#if $organization?.billingPlan === BillingPlan.FREE}
15+
{#if isFreeTier($organization?.billingPlan)}
1716
<span class="inline-tag u-normal u-x-small">Pro plan</span>
1817
{/if}
1918
</p>
@@ -27,7 +26,7 @@
2726
<div class="u-flex-vertical u-gap-8">
2827
<p>
2928
<span class="u-bold">Roles</span>
30-
{#if $organization?.billingPlan === BillingPlan.FREE}
29+
{#if isFreeTier($organization?.billingPlan)}
3130
<span class="inline-tag u-normal u-x-small">Pro plan</span>
3231
{/if}
3332
</p>

0 commit comments

Comments
 (0)