Skip to content

Commit 4dda061

Browse files
authored
fix: pro plan paths (#9457)
* fix: pro plan paths * Cleanups
1 parent fc70be6 commit 4dda061

18 files changed

Lines changed: 220 additions & 536 deletions

web-admin/src/features/billing/BillingCTAHandler.ts

Lines changed: 13 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,13 @@
1-
import {
2-
getPaymentIssues,
3-
needsPaymentSetup,
4-
} from "@rilldata/web-admin/features/billing/issues/getMessageForPaymentIssues";
1+
import { needsPaymentSetup } from "@rilldata/web-admin/features/billing/issues/getMessageForPaymentIssues";
52
import type { BillingIssueMessage } from "@rilldata/web-admin/features/billing/issues/useBillingIssueMessage";
3+
import { fetchPaymentsPortalURL } from "@rilldata/web-admin/features/billing/plans/selectors";
64
import {
7-
fetchPaymentsPortalURL,
8-
fetchProPlan,
9-
} from "@rilldata/web-admin/features/billing/plans/selectors";
10-
import { fetchOrganizationBillingIssues } from "@rilldata/web-admin/features/billing/selectors";
5+
type CategorisedOrganizationBillingIssues,
6+
fetchOrganizationBillingIssues,
7+
} from "@rilldata/web-admin/features/billing/selectors";
118
import type { TeamPlanDialogTypes } from "@rilldata/web-admin/features/billing/plans/types";
129
import { writable } from "svelte/store";
13-
import { adminServiceUpdateBillingSubscription } from "@rilldata/web-admin/client";
10+
import { upgradeToPro } from "@rilldata/web-admin/features/billing/plans/upgrade-to-pro.ts";
1411

1512
export class BillingCTAHandler {
1613
public showStartTeamPlanDialog = writable(false);
@@ -35,32 +32,16 @@ export class BillingCTAHandler {
3532
return instance;
3633
}
3734

38-
public async handle(issueMessage: BillingIssueMessage) {
35+
public async handle(
36+
issueMessage: BillingIssueMessage,
37+
categorisedIssues: CategorisedOrganizationBillingIssues,
38+
) {
3939
if (!issueMessage.cta) return;
40+
// TODO: propagate errors
4041
switch (issueMessage.cta.type) {
41-
case "upgrade": {
42-
const issues = await fetchOrganizationBillingIssues(this.organization);
43-
const paymentIssues = getPaymentIssues(issues);
44-
if (paymentIssues.length > 0) {
45-
const setup = needsPaymentSetup(issues);
46-
window.open(
47-
await fetchPaymentsPortalURL(
48-
this.organization,
49-
window.location.href,
50-
setup,
51-
),
52-
"_self",
53-
);
54-
break;
55-
}
56-
57-
const proPlan = await fetchProPlan();
58-
if (!proPlan) return;
59-
await adminServiceUpdateBillingSubscription(this.organization, {
60-
planName: proPlan.name,
61-
});
42+
case "upgrade":
43+
await upgradeToPro(this.organization, categorisedIssues, null);
6244
break;
63-
}
6445

6546
case "show-upgrade":
6647
this.showStartTeamPlanDialog.set(true);

web-admin/src/features/billing/banner/BillingBannerManagerForAdmins.svelte

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,13 @@
44
type BillingIssueMessage,
55
useBillingIssueMessage,
66
} from "@rilldata/web-admin/features/billing/issues/useBillingIssueMessage";
7-
import StartTeamPlanDialog from "@rilldata/web-admin/features/billing/plans/StartTeamPlanDialog.svelte";
7+
import StartTeamPlanDialog from "@rilldata/web-admin/features/billing/plans/dialog/StartTeamPlanDialog.svelte";
88
import {
99
BillingBannerID,
1010
BillingBannerPriority,
1111
} from "@rilldata/web-common/components/banner/constants";
1212
import { eventBus } from "@rilldata/web-common/lib/event-bus/event-bus";
13+
import { useCategorisedOrganizationBillingIssues } from "@rilldata/web-admin/features/billing/selectors.ts";
1314
1415
export let organization: string;
1516
@@ -18,6 +19,10 @@
1819
$: ({ showStartTeamPlanDialog, startTeamPlanType, teamPlanEndDate } =
1920
billingCTAHandler);
2021
22+
$: categorisedIssuesQuery =
23+
useCategorisedOrganizationBillingIssues(organization);
24+
$: categorisedIssues = $categorisedIssuesQuery.data;
25+
2126
function showBillingIssueBanner(message: BillingIssueMessage | undefined) {
2227
if (!message) {
2328
eventBus.emit("remove-banner", BillingBannerID);
@@ -37,7 +42,7 @@
3742
type: "button",
3843
text: message.cta.text + " ->",
3944
onClick() {
40-
return billingCTAHandler.handle(message);
45+
return billingCTAHandler.handle(message, categorisedIssues);
4146
},
4247
},
4348
}

web-admin/src/features/billing/issues/getMessageForPaymentIssues.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,10 @@ export const PaymentBillingIssueTypes: Partial<
1212
long: "Input a valid payment to maintain access.",
1313
short: "payment method",
1414
},
15-
// [V1BillingIssueType.BILLING_ISSUE_TYPE_NO_BILLABLE_ADDRESS]: {
16-
// long: "Input a valid billing address to maintain access.",
17-
// short: "billing address",
18-
// },
15+
[V1BillingIssueType.BILLING_ISSUE_TYPE_NO_BILLABLE_ADDRESS]: {
16+
long: "Input a valid billing address to maintain access.",
17+
short: "billing address",
18+
},
1919
};
2020

2121
export function needsPaymentSetup(issues: V1BillingIssue[]): boolean {

web-admin/src/features/billing/plans/FreePlan.svelte

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
import PlanContainer from "@rilldata/web-admin/features/billing/plans/PlanContainer.svelte";
33
import { formatCredit } from "@rilldata/web-admin/features/billing/plans/utils.ts";
44
import { getPlanCredits } from "@rilldata/web-admin/features/billing/plans/selectors.ts";
5-
import CostAndUsage from "@rilldata/web-admin/features/billing/plans/modules/CostAndUsage.svelte";
65
import { useCategorisedOrganizationBillingIssues } from "@rilldata/web-admin/features/billing/selectors.ts";
76
87
let {
@@ -66,10 +65,6 @@
6665
</svg>
6766
</a>
6867
</div>
69-
70-
{#snippet footer()}
71-
<CostAndUsage {organization} />
72-
{/snippet}
7368
</PlanContainer>
7469

7570
<style lang="postcss">

web-admin/src/features/billing/plans/POCPlan.svelte

Lines changed: 0 additions & 61 deletions
This file was deleted.

web-admin/src/features/billing/plans/Plan.svelte

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,8 @@
99
TeamPlanDialogTypes,
1010
} from "@rilldata/web-admin/features/billing/plans/types";
1111
import { useCategorisedOrganizationBillingIssues } from "@rilldata/web-admin/features/billing/selectors";
12-
import StartTeamPlanDialog from "@rilldata/web-admin/features/billing/plans/StartTeamPlanDialog.svelte";
12+
import StartTeamPlanDialog from "@rilldata/web-admin/features/billing/plans/dialog/StartTeamPlanDialog.svelte";
1313
import CancelPlanDialog from "@rilldata/web-admin/features/billing/plans/dialog/CancelPlanDialog.svelte";
14-
import UpgradeToProDialog from "@rilldata/web-admin/features/billing/plans/dialog/UpgradeToProDialog.svelte";
1514
import ProPlan from "@rilldata/web-admin/features/billing/plans/ProPlan.svelte";
1615
import LegacyTeamPlan from "@rilldata/web-admin/features/billing/plans/LegacyTeamPlan.svelte";
1716
import FreePlan from "@rilldata/web-admin/features/billing/plans/FreePlan.svelte";
@@ -69,18 +68,15 @@
6968
if (showUpgradeDialog) upgradeDialogOpen = true;
7069
});
7170
72-
// Pro upgrade confirmation
73-
let upgradeProDialogOpen = $state(false);
74-
7571
function showUpgradeProDialog() {
76-
upgradeProDialogOpen = true;
72+
upgradeDialogOpen = true;
7773
}
7874
</script>
7975

8076
{#if currentPlan === "free"}
8177
<FreePlan {organization} upgrade={showUpgradeProDialog} />
8278
{:else if currentPlan === "pro"}
83-
<ProPlan {organization} {subscription} {billingPortalUrl} />
79+
<ProPlan {billingPortalUrl} />
8480
{:else if currentPlan === "trial"}
8581
<LegacyTrialPlan
8682
{organization}
@@ -103,5 +99,3 @@
10399
type={dialogType}
104100
endDate={renewEndDate}
105101
/>
106-
107-
<UpgradeToProDialog bind:open={upgradeProDialogOpen} {organization} />

web-admin/src/features/billing/plans/PlanCards.svelte

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<script lang="ts">
2-
import StartTeamPlanDialog from "@rilldata/web-admin/features/billing/plans/StartTeamPlanDialog.svelte";
2+
import StartTeamPlanDialog from "@rilldata/web-admin/features/billing/plans/dialog/StartTeamPlanDialog.svelte";
33
import { fetchPaymentsPortalURL } from "@rilldata/web-admin/features/billing/plans/selectors";
44
import type {
55
PlanTier,

web-admin/src/features/billing/plans/ProPlan.svelte

Lines changed: 3 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,11 @@
11
<script lang="ts">
2-
import type { V1Subscription } from "@rilldata/web-admin/client";
3-
import {
4-
getBillingCycleDates,
5-
getBillingStatsForOrg,
6-
getPlanCredits,
7-
} from "@rilldata/web-admin/features/billing/plans/selectors";
82
import PlanContainer from "@rilldata/web-admin/features/billing/plans/PlanContainer.svelte";
9-
import { formatCredit } from "@rilldata/web-admin/features/billing/plans/utils.ts";
10-
import CostAndUsage from "@rilldata/web-admin/features/billing/plans/modules/CostAndUsage.svelte";
113
124
let {
13-
organization,
14-
subscription,
155
billingPortalUrl,
166
}: {
17-
organization: string;
18-
subscription: V1Subscription;
197
billingPortalUrl: string | undefined;
208
} = $props();
21-
22-
let billingStats = $derived(getBillingStatsForOrg(organization));
23-
let dailyRunRate = $derived(
24-
$billingStats.prodDailyCost + $billingStats.devDailyCost,
25-
);
26-
27-
// Pro plan credit + post-credit estimate. Available credit is hard-zero
28-
// until the billing usage API exposes the remaining trial credit balance.
29-
let planCredits = $derived(getPlanCredits(organization, undefined));
30-
let { availableCredit } = $derived($planCredits);
31-
let proEstimatedCost = $derived(Math.max(dailyRunRate - availableCredit, 0));
32-
33-
// Billing cycle
34-
let { formattedPeriodStart, formattedPeriodEnd, formattedDueDate } = $derived(
35-
getBillingCycleDates(subscription),
36-
);
379
</script>
3810

3911
<PlanContainer badge="Pro" description="Usage based pricing">
@@ -63,78 +35,13 @@
6335
$0.15/unit/hr · $1/GB storage/mo. Cancel anytime.
6436
{/snippet}
6537

66-
<div class="pro-stats">
67-
<div class="pro-stat-col">
68-
<span class="pro-stat-label">Current period estimate</span>
69-
<span class="pro-stat-amount text-fg-secondary"
70-
>{formatCredit(dailyRunRate)}</span
71-
>
72-
<span class="pro-stat-sub">
73-
{formattedPeriodStart} – {formattedPeriodEnd}
74-
</span>
75-
</div>
76-
<div class="pro-stat-col border-l pl-6">
77-
<span class="pro-stat-label">Available credit</span>
78-
<span class="pro-stat-amount text-green-700"
79-
>{formatCredit(availableCredit)}</span
80-
>
81-
<span class="credit-pill">
82-
<svg viewBox="0 0 12 12" fill="none" class="w-3 h-3 shrink-0">
83-
<path
84-
d="M10 3L4.5 8.5 2 6"
85-
stroke="currentColor"
86-
stroke-width="1.5"
87-
stroke-linecap="round"
88-
stroke-linejoin="round"
89-
/>
90-
</svg>
91-
Trial credit applied to your bill
92-
</span>
93-
</div>
94-
<div class="pro-stat-col border-l pl-6">
95-
<span class="pro-stat-label">Estimated cost after applied credit</span>
96-
<span class="pro-stat-amount text-fg-primary"
97-
>{formatCredit(proEstimatedCost)}</span
98-
>
99-
{#if formattedDueDate}
100-
<span class="pro-stat-sub">Due {formattedDueDate}</span>
101-
{/if}
102-
</div>
38+
<div class="text-sm text-fg-tertiary mt-4 pb-4">
39+
You'll be billed monthly based on usage at $0.15/compute unit/hr and $1/GB
40+
storage/mo.
10341
</div>
104-
105-
{#snippet footer()}
106-
<CostAndUsage {organization} />
107-
{/snippet}
10842
</PlanContainer>
10943

11044
<style lang="postcss">
111-
.pro-stats {
112-
@apply flex gap-6 mt-4 pt-4 border-t;
113-
min-height: 92px;
114-
}
115-
116-
.pro-stat-col {
117-
@apply flex flex-col gap-2 flex-1 justify-center;
118-
}
119-
120-
.pro-stat-label {
121-
@apply text-xs font-semibold text-fg-tertiary;
122-
line-height: 1;
123-
}
124-
125-
.pro-stat-amount {
126-
@apply text-4xl font-semibold leading-none;
127-
}
128-
129-
.pro-stat-sub {
130-
@apply text-sm font-medium text-fg-tertiary;
131-
line-height: 1;
132-
}
133-
134-
.credit-pill {
135-
@apply inline-flex items-center gap-1 text-sm font-medium text-green-700 bg-green-50 rounded-full px-2.5 py-1;
136-
}
137-
13845
.pricing-link-top {
13946
@apply inline-flex items-center gap-1;
14047
@apply text-sm font-medium text-primary-600 no-underline;

0 commit comments

Comments
 (0)