chore: format prices

This commit is contained in:
Arman
2024-01-30 18:19:44 +01:00
parent e11d9858ad
commit 2df0c7987f
14 changed files with 74 additions and 384 deletions
-339
View File
@@ -279,345 +279,6 @@ export const eventServices: Array<EventService> = [
}
];
export const usageRates = {
'tier-0': [
{
id: 'members',
resource: 'Organization members',
amount: 1,
unit: '',
rate: '$20/member'
},
{ id: 'bandwith', resource: 'Bandwidth', amount: 10, unit: 'GB', rate: '$0.04/GB' },
{ id: 'storage', resource: 'Storage', amount: 2, unit: 'GB', rate: '$0.025/GB' },
{
id: 'executions',
resource: 'Function executions',
amount: 750000,
unit: 'executions',
rate: '$2/1M executions'
},
{
id: 'users',
resource: 'Active users',
amount: 200000,
unit: 'AU',
rate: '$0.0012/user'
},
{
id: 'connections',
resource: 'Concurrent connections',
amount: 750,
unit: 'connections',
rate: '$5/1K connections'
}
],
'tier-1': [
{
id: 'members',
resource: 'Organization members',
amount: 'Unlimited',
unit: '',
rate: '$20/member'
},
{ id: 'bandwith', resource: 'Bandwidth', amount: 1, unit: 'TB', rate: '$0.04/GB' },
{ id: 'storage', resource: 'Storage', amount: 150, unit: 'GB', rate: '$0.025/GB' },
{
id: 'executions',
resource: 'Function executions',
amount: 3500000,
unit: 'executions',
rate: '$2/1M executions'
},
{
id: 'users',
resource: 'Active users',
amount: 200000,
unit: 'AU',
rate: '$0.0012/user'
},
{
id: 'connections',
resource: 'Concurrent connections',
amount: 750,
unit: 'connections',
rate: '$5/1K connections'
}
],
'tier-2': [
{
id: 'members',
resource: 'Organization members',
amount: 'Unlimited',
unit: '',
rate: '$20/member'
},
{ id: 'bandwith', resource: 'Bandwidth', amount: 1, unit: 'TB', rate: '$0.04/GB' },
{ id: 'storage', resource: 'Storage', amount: 150, unit: 'GB', rate: '$0.025/GB' },
{
id: 'executions',
resource: 'Function executions',
amount: 3500000,
unit: 'executions',
rate: '$2/1M executions'
},
{
id: 'users',
resource: 'Active users',
amount: 200000,
unit: 'AU',
rate: '$0.0012/user'
},
{
id: 'connections',
resource: 'Concurrent connections',
amount: 750,
unit: 'connections',
rate: '$5/1K connections'
}
]
};
//resources: bandwidth, buckets, file size limit, functions, executions, users,teams,logs, members, platforms, webhooks, databases, connections, messages
export const limitRates = {
'tier-0': [
{
id: 'bandwith',
amount: 10,
unit: 'GB'
},
{
id: 'buckets',
amount: 3,
unit: ''
},
{
id: 'file-size-limit',
amount: 1,
unit: 'MB'
},
{
id: 'storage',
amount: 5,
unit: 'GB'
},
{
id: 'functions',
amount: 1,
unit: ''
},
{
id: 'executions',
amount: 750000,
unit: 'executions'
},
{
id: 'users',
amount: 200000,
unit: 'AU'
},
{
id: 'teams',
amount: 1,
unit: ''
},
{
id: 'logs',
amount: 1,
unit: ''
},
{
id: 'members',
amount: 1,
unit: ''
},
{
id: 'platforms',
amount: 1,
unit: ''
},
{
id: 'webhooks',
amount: 1,
unit: ''
},
{
id: 'databases',
amount: 1,
unit: ''
},
{
id: 'connections',
amount: 1,
unit: ''
},
{
id: 'messages',
amount: 1,
unit: ''
}
],
'tier-1': [
{
id: 'bandwith',
amount: 10,
unit: 'GB'
},
{
id: 'buckets',
amount: 1,
unit: ''
},
{
id: 'file-size-limit',
amount: 5,
unit: 'MB'
},
{
id: 'storage',
amount: 5,
unit: 'GB'
},
{
id: 'functions',
amount: 1,
unit: ''
},
{
id: 'executions',
amount: 750000,
unit: 'executions'
},
{
id: 'users',
amount: 200000,
unit: 'AU'
},
{
id: 'teams',
amount: 1,
unit: ''
},
{
id: 'logs',
amount: 1,
unit: ''
},
{
id: 'members',
amount: 1,
unit: ''
},
{
id: 'platforms',
amount: 1,
unit: ''
},
{
id: 'webhooks',
amount: 1,
unit: ''
},
{
id: 'databases',
amount: 1,
unit: ''
},
{
id: 'connections',
amount: 1,
unit: ''
},
{
id: 'messages',
amount: 1,
unit: ''
}
],
'tier-2': [
{
id: 'bandwith',
amount: 10,
unit: 'GB'
},
{
id: 'buckets',
amount: 1,
unit: ''
},
{
id: 'file-size-limit',
amount: 5,
unit: 'MB'
},
{
id: 'storage',
amount: 5,
unit: 'GB'
},
{
id: 'functions',
amount: 1,
unit: ''
},
{
id: 'executions',
amount: 750000,
unit: 'executions'
},
{
id: 'users',
amount: 200000,
unit: 'AU'
},
{
id: 'teams',
amount: 1,
unit: ''
},
{
id: 'logs',
amount: 1,
unit: ''
},
{
id: 'members',
amount: 1,
unit: ''
},
{
id: 'platforms',
amount: 1,
unit: ''
},
{
id: 'webhooks',
amount: 1,
unit: ''
},
{
id: 'databases',
amount: 1,
unit: ''
},
{
id: 'connections',
amount: 1,
unit: ''
},
{
id: 'messages',
amount: 1,
unit: ''
}
]
};
export enum BillingPlan {
STARTER = 'tier-0',
PRO = 'tier-1',
+9
View File
@@ -20,3 +20,12 @@ export function formatNumberWithCommas(number: number): string {
const formatter = new Intl.NumberFormat('en');
return formatter.format(number);
}
export function formatCurrency(number: number, locale = 'en-US', currency = 'USD'): string {
if (isNaN(number)) return String(number);
const formatter = new Intl.NumberFormat(locale, {
style: 'currency',
currency
});
return formatter.format(number);
}
@@ -18,6 +18,7 @@
import AddCreditWizard from './addCreditWizard.svelte';
import { Button } from '$lib/elements/forms';
import AddCreditModal from './addCreditModal.svelte';
import { formatCurrency } from '$lib/helpers/numbers';
let offset = 0;
let creditList: CreditList = {
@@ -73,7 +74,7 @@
<div class="u-flex u-cross-center u-main-space-between">
<div class="u-flex u-gap-8 u-cross-center">
<h4 class="body-text-1 u-bold">Credit balance</h4>
<span class="inline-tag">${balance}</span>
<span class="inline-tag">{formatCurrency(balance)}</span>
</div>
{#if creditList?.total}
<Button secondary on:click={handleCredits}>
@@ -99,7 +100,7 @@
{toLocaleDate(credit.expiration)}
</TableCellText>
<TableCellText title="amount">
${credit.credits}
{formatCurrency(credit.credits)}
</TableCellText>
</TableRow>
{/each}
@@ -20,6 +20,7 @@
TableScroll
} from '$lib/elements/table';
import { toLocaleDate } from '$lib/helpers/date';
import { formatCurrency } from '$lib/helpers/numbers';
import type { InvoiceList } from '$lib/sdk/billing';
import { sdk } from '$lib/stores/sdk';
import { VARS } from '$lib/system';
@@ -87,7 +88,9 @@
{status === 'requires_authentication' ? 'failed' : status}
</Pill>
</TableCell>
<TableCellText title="due">${invoice.amount}</TableCellText>
<TableCellText title="due">
{formatCurrency(invoice.amount)}
</TableCellText>
<TableCell showOverflow>
<DropList
bind:show={showDropdown[i]}
@@ -12,7 +12,7 @@
import { sdk } from '$lib/stores/sdk';
import type { Invoice } from '$lib/sdk/billing';
import { Query } from '@appwrite.io/console';
import { abbreviateNumber, formatNumberWithCommas } from '$lib/helpers/numbers';
import { abbreviateNumber, formatCurrency, formatNumberWithCommas } from '$lib/helpers/numbers';
import { humanFileSize } from '$lib/helpers/sizeConvertion';
import { BillingPlan } from '$lib/constants';
import { trackEvent } from '$lib/actions/analytics';
@@ -63,7 +63,7 @@
<span class="text u-color-text-gray">Total to-date:</span>
{/if}
<span class="body-text-1">
${isTrial ? 0 : currentPlan?.price}
{isTrial ? formatCurrency(0) : formatCurrency(currentPlan?.price)}
</span>
</p>
</div>
@@ -78,7 +78,7 @@
<span> {extraMembers.value}</span>
{extraMembers.name}
</p>
<p class="text">${extraMembers.amount}</p>
<p class="text">{formatCurrency(extraMembers.amount)}</p>
</li>
</ul>
</div>
@@ -98,7 +98,7 @@
</span>
{excess.name}
</p>
<p class="text">${excess.amount}</p>
<p class="text">{formatCurrency(excess.amount)}</p>
</li>
{/if}
{#if ['users', 'executions'].includes(excess.name)}
@@ -108,13 +108,15 @@
>{abbreviateNumber(excess.value)}</span>
{excess.name}
</p>
<p class="text">${excess.amount}</p>
<p class="text">{formatCurrency(excess.amount)}</p>
</li>
{/if}
{/each}
<li class="u-flex u-main-space-between u-margin-block-start-16">
<p class="body-text-1 u-bold">Total to-date:</p>
<p class="body-text-1 u-bold">${currentInvoice?.amount}</p>
<p class="body-text-1 u-bold">
{formatCurrency(currentInvoice?.amount ?? 0)}
</p>
</li>
</ul>
</div>
@@ -11,6 +11,7 @@
import { Submit, trackEvent, trackError } from '$lib/actions/analytics';
import { isCloud } from '$lib/system';
import { plansInfo } from '$lib/stores/billing';
import { formatCurrency } from '$lib/helpers/numbers';
export let showCreate = false;
@@ -63,7 +64,7 @@
You can add unlimited organization members on the {plan.name} plan at no cost.
{:else if $organization?.billingPlan === BillingPlan.PRO}
You can add unlimited organization members on the {plan.name} plan for
<b>${plan.addons.member.price} each per billing period</b>.
<b>{formatCurrency(plan.addons.member.price)} each per billing period</b>.
{/if}
</Alert>
{/if}
@@ -4,6 +4,7 @@
import { BillingPlan } from '$lib/constants';
import { Pill } from '$lib/elements';
import { toLocaleDate } from '$lib/helpers/date';
import { formatCurrency } from '$lib/helpers/numbers';
import { WizardStep } from '$lib/layout';
import type { Coupon } from '$lib/sdk/billing';
import { plansInfo } from '$lib/stores/billing';
@@ -92,28 +93,30 @@
on:validation={(e) => ($createOrganization.couponCode = e.detail.code)} />
<span class="u-flex u-main-space-between">
<p class="text">{plan.name} plan</p>
<p class="text">${plan.price}</p>
<p class="text">{formatCurrency(plan.price)}</p>
</span>
<span class="u-flex u-main-space-between">
<p class="text">Additional members ({collaboratorsNumber})</p>
<p class="text">${collaboratorPrice * collaboratorsNumber}</p>
<p class="text">{formatCurrency(collaboratorPrice * collaboratorsNumber)}</p>
</span>
{#if couponData?.status === 'active'}
<span class="u-flex u-main-space-between">
<p class="text">Credits applied ({couponData.credits})</p>
<p class="text">-${couponData.credits}</p>
<p class="text">-{formatCurrency(couponData.credits)}</p>
</span>
{/if}
<div class="u-sep-block-start" />
{/if}
{@const estimatedTotal =
couponData?.status === 'active'
? totalExpences - couponData.credits >= 0
? totalExpences - couponData.credits
: 0
: totalExpences}
<span class="u-flex u-main-space-between">
<p class="text">Estimated total</p>
<p class="text">
${couponData?.status === 'active'
? totalExpences - couponData.credits >= 0
? totalExpences - couponData.credits
: 0
: totalExpences}
{formatCurrency(estimatedTotal)}
</p>
</span>
@@ -11,6 +11,7 @@
TableHeader,
TableRow
} from '$lib/elements/table';
import { formatCurrency } from '$lib/helpers/numbers';
import { WizardStep } from '$lib/layout';
import { plansInfo } from '$lib/stores/billing';
import { createOrganization } from './store';
@@ -47,8 +48,8 @@
added will receive an email invite to your organization on completion.
{:else if $createOrganization.billingPlan === BillingPlan.PRO}
You can add unlimited organization members on the {plan.name} plan for
<b>${plan.addons.member.price} each per month</b>. Each member added will receive an
email invite to your organization on completion.
<b>{formatCurrency(plan.addons.member.price)} each per month</b>. Each member added will
receive an email invite to your organization on completion.
{/if}
</Alert>
@@ -81,7 +82,7 @@
<TableRow>
<TableCellText title="collaborator">{collaborator}</TableCellText>
{#if $createOrganization.billingPlan === BillingPlan.PRO}
<TableCellText title="cost">15$</TableCellText>
<TableCellText title="cost">{formatCurrency(15)}</TableCellText>
{/if}
<TableCell>
<button
@@ -3,6 +3,7 @@
import { BillingPlan } from '$lib/constants';
import { Pill } from '$lib/elements';
import { InputText, FormList } from '$lib/elements/forms';
import { formatCurrency } from '$lib/helpers/numbers';
import { WizardStep } from '$lib/layout';
import { plansInfo, tierFree, tierPro, tierScale } from '$lib/stores/billing';
import { organizationList, type Organization } from '$lib/stores/organization';
@@ -87,7 +88,7 @@
class="u-flex u-flex-vertical u-gap-4 u-width-full-line"
class:u-opacity-50={disabled}>
<h4 class="body-text-2 u-bold">
{tierFree.name} - ${freePlan?.price}/month
{tierFree.name} - {formatCurrency(freePlan?.price ?? 0)}/month
</h4>
<p class="u-color-text-gray u-small">{tierFree.description}</p>
</div>
@@ -100,8 +101,8 @@
<svelte:fragment slot="custom">
<div class="u-flex u-flex-vertical u-gap-4 u-width-full-line">
<h4 class="body-text-2 u-bold">
{tierPro.name} - ${proPlan.price}/month per organization member + exta
usage
{tierPro.name} - {formatCurrency(proPlan?.price ?? 0)}/month per
organization member + exta usage
</h4>
<p class="u-color-text-gray u-small">
{tierPro.description}
@@ -122,7 +123,8 @@
class="u-flex u-flex-vertical u-gap-4 u-width-full-line"
class:u-opacity-50={disabled}>
<h4 class="body-text-2 u-bold">
{tierScale.name} - ${scalePlan.price}/month + extra usage
{tierScale.name} - {formatCurrency(scalePlan?.price ?? 0)}/month + extra
usage
</h4>
<p class="u-color-text-gray u-small">
{tierScale.description}
@@ -13,7 +13,7 @@
import { organization } from '$lib/stores/organization';
import { createOrganization } from './store';
import { plansInfo, type Tier } from '$lib/stores/billing';
import { abbreviateNumber } from '$lib/helpers/numbers';
import { abbreviateNumber, formatCurrency } from '$lib/helpers/numbers';
import { BillingPlan } from '$lib/constants';
export let show = false;
@@ -87,7 +87,7 @@
</TableCellText>
{#if !isFree}
<TableCellText title="rate">
${plan.addons.member.price}/{usage?.unit}
{formatCurrency(plan.addons.member.price)}/{usage?.unit}
</TableCellText>
{/if}
</TableRow>
@@ -100,7 +100,9 @@
</TableCellText>
{#if !isFree}
<TableCellText title="rate">
${addon?.price}/{['MB', 'GB', 'TB'].includes(addon?.unit)
{formatCurrency(addon?.price)}/{['MB', 'GB', 'TB'].includes(
addon?.unit
)
? addon?.value
: abbreviateNumber(addon?.value, 0)}{usage?.unit}
</TableCellText>
@@ -12,6 +12,7 @@
import { sizeToBytes } from '$lib/helpers/sizeConvertion';
import { Pill } from '$lib/elements';
import { BillingPlan } from '$lib/constants';
import { formatCurrency } from '$lib/helpers/numbers';
let usage: OrganizationUsage = null;
let members: Models.MembershipList = null;
@@ -127,7 +128,7 @@
class="u-flex u-flex-vertical u-gap-4 u-width-full-line"
class:u-opacity-50={disabled}>
<h4 class="body-text-2 u-bold">
{tierFree.name} - ${freePlan.price}/month
{tierFree.name} - {formatCurrency(freePlan.price)}/month
</h4>
<p class="u-color-text-gray u-small">{tierFree.description}</p>
</div>
@@ -150,8 +151,8 @@
class="u-flex u-flex-vertical u-gap-4 u-width-full-line"
class:u-opacity-50={disabled}>
<h4 class="body-text-2 u-bold">
{tierPro.name} - ${proPlan.price}/month per organization member + extra
usage
{tierPro.name} - {formatCurrency(proPlan.price)}/month per organization
member + extra usage
</h4>
<p class="u-color-text-gray u-small">
{tierPro.description}
@@ -178,7 +179,7 @@
class="u-flex u-flex-vertical u-gap-4 u-width-full-line"
class:u-opacity-50={disabled}>
<h4 class="body-text-2 u-bold">
{tierScale.name} - ${scalePlan.price}/month + extra usage
{tierScale.name} - {formatCurrency(scalePlan.price)}/month + extra usage
</h4>
<p class="u-color-text-gray u-small">
{tierScale.description}
@@ -4,6 +4,7 @@
import { BillingPlan } from '$lib/constants';
import { FormList, InputTextarea } from '$lib/elements/forms';
import { toLocaleDate } from '$lib/helpers/date';
import { formatCurrency } from '$lib/helpers/numbers';
import { WizardStep } from '$lib/layout';
import type { Coupon } from '$lib/sdk/billing';
import { plansInfo } from '$lib/stores/billing';
@@ -104,28 +105,30 @@
on:validation={(e) => ($changeOrganizationTier.couponCode = e.detail.code)} />
<span class="u-flex u-main-space-between">
<p class="text">{plan.name} plan</p>
<p class="text">${plan.price}</p>
<p class="text">{formatCurrency(plan.price)}</p>
</span>
<span class="u-flex u-main-space-between">
<p class="text">Additional members ({collaboratorsNumber})</p>
<p class="text">${collaboratorPrice * collaboratorsNumber}</p>
<p class="text">{formatCurrency(collaboratorPrice * collaboratorsNumber)}</p>
</span>
{#if couponData?.status === 'active'}
<span class="u-flex u-main-space-between">
<p class="text">Credits applied ({couponData.credits})</p>
<p class="text">-${couponData.credits}</p>
<p class="text">-{formatCurrency(couponData.credits)}</p>
</span>
{/if}
{/if}
{@const estimatedTotal =
couponData?.status === 'active'
? totalExpences - couponData.credits >= 0
? totalExpences - couponData.credits
: 0
: totalExpences}
<div class="u-sep-block-start" />
<span class="u-flex u-main-space-between">
<p class="text">Estimated total</p>
<p class="text">
${couponData?.status === 'active'
? totalExpences - couponData.credits >= 0
? totalExpences - couponData.credits
: 0
: totalExpences}
{formatCurrency(estimatedTotal)}
</p>
</span>
@@ -18,6 +18,7 @@
import { user } from '$lib/stores/user';
import { organization } from '$lib/stores/organization';
import { BillingPlan } from '$lib/constants';
import { formatCurrency } from '$lib/helpers/numbers';
const plan = $plansInfo.get($changeOrganizationTier.billingPlan);
@@ -63,8 +64,8 @@
added will receive an email invite to your organization on completion.
{:else if $changeOrganizationTier.billingPlan === BillingPlan.PRO}
You can add unlimited organization members on the {plan.name} plan for
<b>${plan.addons.member.price} each per month</b>. Each member added will receive an
email invite to your organization on completion.
<b>{formatCurrency(plan.addons.member.price)} each per month</b>. Each member added will
receive an email invite to your organization on completion.
{/if}
</Alert>
@@ -97,7 +98,7 @@
<TableRow>
<TableCellText title="collaborator">{collaborator}</TableCellText>
{#if $changeOrganizationTier.billingPlan === BillingPlan.PRO}
<TableCellText title="cost">15$</TableCellText>
<TableCellText title="cost">{formatCurrency(15)}</TableCellText>
{/if}
<TableCell>
<button
@@ -14,7 +14,7 @@
import { toLocaleDate } from '$lib/helpers/date';
import { Button } from '$lib/elements/forms';
import { humanFileSize } from '$lib/helpers/sizeConvertion';
import { abbreviateNumber } from '$lib/helpers/numbers';
import { abbreviateNumber, formatCurrency } from '$lib/helpers/numbers';
import { formatNum } from '$lib/helpers/string';
import { BillingPlan } from '$lib/constants';
@@ -28,7 +28,7 @@
export let currentTier: Tier;
const plan = $plansInfo?.get(currentTier);
const collaboratorPrice = plan?.addons.member?.price ?? 0;
const collaboratorPrice = formatCurrency(plan?.addons.member?.price ?? 0);
</script>
<Alert type="error">