Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Billing UI changes #1552

Open
wants to merge 15 commits into
base: main
Choose a base branch
from
2 changes: 1 addition & 1 deletion src/lib/components/billing/usageRates.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@
following rates. Next billing period: {toLocaleDate(nextDate)}.
</p>
{/if}
<Table noStyles>
<Table noStyles noMargin>
<TableHeader>
<TableCellHead>Resource</TableCellHead>
<TableCellHead>Limit</TableCellHead>
Expand Down
7 changes: 5 additions & 2 deletions src/lib/components/collapsibleItem.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,15 @@
export let noContent = false;
export let isInfo = false;
export let gap = 16;

export let style = null;
export let wrapperStyle = null;
</script>

<li class="collapsible-item" class:is-info={isInfo}>
{#if noContent}
<div class="collapsible-wrapper">
<div class={`collapsible-button u-gap-${gap}`}>
<div class="collapsible-wrapper" style={wrapperStyle}>
<div class={`collapsible-button u-gap-${gap}`} {style}>
<slot />
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
import { confirmPayment } from '$lib/stores/stripe';
import { sdk } from '$lib/stores/sdk';
import { toLocaleDate } from '$lib/helpers/date';
import { BillingPlan } from '$lib/constants';
import RetryPaymentModal from './retryPaymentModal.svelte';
import { selectedInvoice, showRetryModal } from './store';
import { Button } from '$lib/elements/forms';
Expand Down Expand Up @@ -130,9 +129,7 @@
<BillingAddress billingAddress={data?.billingAddress} />
<TaxId />
<BudgetCap />
{#if $organization?.billingPlan !== BillingPlan.FREE && !!$organization?.billingBudget}
<BudgetAlert />
{/if}
<BudgetAlert />
<AvailableCredit />
</Container>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,9 @@
</script>

<CardGrid hideFooter={$organization?.billingPlan !== BillingPlan.FREE}>
<Heading tag="h2" size="6">Available credit</Heading>
<Heading tag="h2" size="6">
{$organization?.billingPlan === BillingPlan.FREE ? 'Credits' : 'Available credit'}
</Heading>

<p class="text">Appwrite credit will automatically be applied to your next invoice.</p>
<svelte:fragment slot="aside">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
<script lang="ts">
import { invalidate } from '$app/navigation';
import { Submit, trackError, trackEvent } from '$lib/actions/analytics';
import { CardGrid, Heading } from '$lib/components';
import { Dependencies } from '$lib/constants';
import { Alert, CardGrid, Heading } from '$lib/components';
import { BillingPlan, Dependencies } from '$lib/constants';
import { upgradeURL } from '$lib/stores/billing';
import { Button, Form, FormList, InputSelectSearch } from '$lib/elements/forms';
import {
Table,
Expand Down Expand Up @@ -39,7 +40,7 @@
if (alerts.some((alert) => alert === selectedAlert)) {
return;
}
if (alerts.length <= 2) {
if (alerts.length <= 3) {
alerts = [...alerts, selectedAlert ? selectedAlert : parseInt(search)];
search = '';
selectedAlert = null;
Expand All @@ -59,7 +60,7 @@
addNotification({
type: 'success',
isHtml: true,
message: `<span>A budget alert has been added to <b>${$organization.name}</b></span>`
message: `<span> ${alerts.length === 0 ? 'Budget alerts removed from' : alerts.length > 1 ? `Budget alerts added to` : 'A budget alert has been added to'} <b>${$organization.name}</b> </span>`
});
trackEvent(Submit.BudgetAlertsUpdate, {
alerts
Expand All @@ -78,65 +79,98 @@

<Form onSubmit={updateBudget}>
<CardGrid>
<Heading tag="h2" size="6">Budget alerts</Heading>
<Heading tag="h2" size="6">Billing alerts</Heading>

<p class="text">
Get notified by email when your organization reaches or exceeds a percent of your
specified budget cap. You can set a maximum of 3 alerts.
{#if $organization?.billingPlan === BillingPlan.FREE}
Get notified by email when your organization meets a percentage of your budget cap. <b
>Free organizations will receive one notification at 75% resource usage.</b>
{:else}
Get notified by email when your organization meets or exceeds a percentage of your
specified billing alert(s).
{/if}
</p>
<svelte:fragment slot="aside">
<FormList>
<div class="u-flex u-gap-16">
<InputSelectSearch
label="Percentage (%) of budget cap"
placeholder="Select a percentage"
id="alerts"
{options}
bind:search
bind:value={selectedAlert}
on:select={() => (search = selectedAlert.toString())} />
<div style="align-self: flex-end">
<Button
secondary
disabled={alerts.length > 2 || (!search && !selectedAlert)}
on:click={addAlert}>
Add alert
</Button>
{#if $organization?.billingPlan === BillingPlan.FREE}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We shouldn't check for features based on the plan name, but check the currentPlan to see if a feature is there or not. Because does Education have the billing alert feature?

Copy link
Member Author

@ItzNotABug ItzNotABug Jan 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think currentPlan has billingAlerts flag setup on backend and sdk atm. Regarding Education plan, its disabled via Cloud's plans config.

<Alert type="info">
<svelte:fragment slot="title"
>Billing alerts are a Pro plan feature
</svelte:fragment>
Upgrade to a Pro plan to manage when you receive billing alerts for your organization.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we mention Scale here as well?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Scale isn't directly available as an option on upgrade when the current plan is on Free, right?

</Alert>
{:else}
<FormList>
<Alert type="info">
You can set a maximum of 4 billing alerts per organization.
</Alert>

<div class="u-flex u-gap-16">
<InputSelectSearch
label="Percentage (%) of budget cap"
placeholder="Select a percentage"
id="alerts"
{options}
bind:search
interactiveOutput
bind:value={selectedAlert}
on:select={() => (search = selectedAlert.toString())} />
<div style="align-self: flex-end">
<Button
secondary
disabled={alerts.length > 3 || (!search && !selectedAlert)}
on:click={addAlert}>
Add alert
</Button>
</div>
</div>
</div>
</FormList>
</FormList>

{#if alerts.length}
<Table noMargin noStyles transparent>
<TableHeader>
<TableCellHead>Alert at budget cap %</TableCellHead>
<TableCellHead width={30} />
</TableHeader>
<TableBody>
{#each alerts.sort() as alert}
<TableRow>
<TableCellText title="Percentage">
{alert}%
</TableCellText>
<TableCell>
<Button
text
round
ariaLabel="remove alert"
on:click={() =>
(alerts = alerts.filter((a) => a !== alert))}>
<span class="icon-x" aria-hidden="true" />
</Button>
</TableCell>
</TableRow>
{/each}
</TableBody>
</Table>
{#if alerts.length}
<Table noMargin noStyles transparent>
<TableHeader>
<TableCellHead>Alert at budget cap %</TableCellHead>
<TableCellHead width={30} />
</TableHeader>
<TableBody>
{#each alerts.sort() as alert}
<TableRow>
<TableCellText title="Percentage">
{alert}%
</TableCellText>
<TableCell>
<Button
text
round
ariaLabel="remove alert"
on:click={() =>
(alerts = alerts.filter((a) => a !== alert))}>
<span class="icon-x" aria-hidden="true" />
</Button>
</TableCell>
</TableRow>
{/each}
</TableBody>
</Table>
{/if}
{/if}
</svelte:fragment>

<svelte:fragment slot="actions">
<Button disabled={isButtonDisabled} submit>Update</Button>
{#if $organization?.billingPlan === BillingPlan.FREE}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should you also be able to upgrade from Education plan?

<Button
secondary
href={$upgradeURL}
on:click={() => {
trackEvent('click_organization_upgrade', {
from: 'button',
source: 'billing_alerts_card'
});
}}
>Upgrade to Pro
</Button>
{:else}
<Button disabled={isButtonDisabled} submit>Update</Button>
{/if}
</svelte:fragment>
</CardGrid>
</Form>
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,8 @@
<Heading tag="h2" size="6">Budget cap</Heading>

<p class="text">
Restrict your resource usage by setting a budget cap. <button
on:click={() => ($showUsageRatesModal = true)}
type="button"
class="link">Learn more about usage rates.</button>
Restrict your resource usage by setting a budget cap. Cap usage is reset at the
beginning of each billing cycle.
</p>
<svelte:fragment slot="aside">
{#if !$currentPlan.budgeting}
Expand All @@ -76,8 +74,12 @@
<FormList>
<InputSwitch id="cap-active" label="Enable budget cap" bind:value={capActive}>
<svelte:fragment slot="description">
Budget cap limits do not include the base amount of your plan. Cap usage
is reset at the beginning of each billing cycle.
Budget cap limits do not include the base amount of your plan. <button
class="link"
type="button"
on:click={() => ($showUsageRatesModal = true)}
>Learn more about usage rates.
</button>
</svelte:fragment>
</InputSwitch>
{#if capActive}
Expand All @@ -102,7 +104,9 @@
from: 'button',
source: 'billing_budget_cap'
});
}}>Upgrade to Pro</Button>
}}
>Upgrade to Pro
</Button>
{:else}
<Button disabled={$organization?.billingBudget === budget} submit>Update</Button>
{/if}
Expand Down
Loading
Loading