mirror of
https://github.com/appwrite/console.git
synced 2026-06-06 19:27:48 +00:00
chore: format prices
This commit is contained in:
@@ -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',
|
||||
|
||||
@@ -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">
|
||||
|
||||
Reference in New Issue
Block a user