mirror of
https://github.com/appwrite/console.git
synced 2026-06-06 19:27:48 +00:00
feat: creditCardInfo component, create & change org fixes, small stuff
This commit is contained in:
@@ -1,8 +1,10 @@
|
||||
<script lang="ts">
|
||||
import { Button } from '$lib/elements/forms';
|
||||
import type { PaymentMethodData } from '$lib/sdk/billing';
|
||||
import { getCreditCardImage } from '$lib/stores/billing';
|
||||
import { DropList, DropListItem } from '.';
|
||||
|
||||
export let isBox = false;
|
||||
export let paymentMethod: PaymentMethodData;
|
||||
export let isEditDisabled = false;
|
||||
export let isDeleteDisabled = false;
|
||||
@@ -10,47 +12,55 @@
|
||||
let showDropdown = false;
|
||||
</script>
|
||||
|
||||
<div class="box u-flex u-main-space-between u-cross-start">
|
||||
<div>
|
||||
<p class="text">
|
||||
Card ending in {paymentMethod?.last4}
|
||||
<span>{paymentMethod?.brand}</span>
|
||||
</p>
|
||||
<div class:box={isBox} class="u-flex u-main-space-between u-cross-start">
|
||||
<div class="u-line-height-1-5">
|
||||
<span class="u-flex u-cross-center u-gap-8">
|
||||
<p class="text u-bold">
|
||||
<span class="u-capitalize">{paymentMethod?.brand}</span> ending in {paymentMethod?.last4}
|
||||
</p>
|
||||
<img
|
||||
width="23"
|
||||
height="16"
|
||||
src={getCreditCardImage(paymentMethod?.brand)}
|
||||
alt={paymentMethod?.brand} />
|
||||
</span>
|
||||
<p class="text">
|
||||
Expires {paymentMethod?.expiryMonth}/{paymentMethod?.expiryYear}
|
||||
</p>
|
||||
<p class="text">
|
||||
<!-- <p class="text">
|
||||
{paymentMethod?.name}
|
||||
</p>
|
||||
</p> -->
|
||||
</div>
|
||||
|
||||
<DropList bind:show={showDropdown} placement="bottom-start" noArrow>
|
||||
<Button
|
||||
round
|
||||
text
|
||||
ariaLabel="More options"
|
||||
on:click={() => {
|
||||
showDropdown = !showDropdown;
|
||||
}}>
|
||||
<span class="icon-dots-horizontal" aria-hidden="true" />
|
||||
</Button>
|
||||
<svelte:fragment slot="list">
|
||||
<DropListItem
|
||||
icon="pencil"
|
||||
disabled={isEditDisabled}
|
||||
<slot>
|
||||
<DropList bind:show={showDropdown} placement="bottom-start" noArrow>
|
||||
<Button
|
||||
round
|
||||
text
|
||||
ariaLabel="More options"
|
||||
on:click={() => {
|
||||
console.log('test');
|
||||
showDropdown = !showDropdown;
|
||||
}}>
|
||||
Edit
|
||||
</DropListItem>
|
||||
<DropListItem
|
||||
icon="trash"
|
||||
disabled={isDeleteDisabled}
|
||||
on:click={() => {
|
||||
console.log('test');
|
||||
}}>
|
||||
Delete
|
||||
</DropListItem>
|
||||
</svelte:fragment>
|
||||
</DropList>
|
||||
<span class="icon-dots-horizontal" aria-hidden="true" />
|
||||
</Button>
|
||||
<svelte:fragment slot="list">
|
||||
<DropListItem
|
||||
icon="pencil"
|
||||
disabled={isEditDisabled}
|
||||
on:click={() => {
|
||||
console.log('test');
|
||||
}}>
|
||||
Edit
|
||||
</DropListItem>
|
||||
<DropListItem
|
||||
icon="trash"
|
||||
disabled={isDeleteDisabled}
|
||||
on:click={() => {
|
||||
console.log('test');
|
||||
}}>
|
||||
Delete
|
||||
</DropListItem>
|
||||
</svelte:fragment>
|
||||
</DropList>
|
||||
</slot>
|
||||
</div>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { FormItem, Helper, Label } from '.';
|
||||
|
||||
export let label: string;
|
||||
export let label: string = null;
|
||||
export let showLabel = true;
|
||||
export let id: string;
|
||||
export let group: string;
|
||||
@@ -41,7 +41,11 @@
|
||||
bind:this={element}
|
||||
on:invalid={handleInvalid} />
|
||||
<Label {required} hide={!showLabel} for={id}>
|
||||
{label}
|
||||
{#if label}
|
||||
{label}
|
||||
{:else}
|
||||
<slot />
|
||||
{/if}
|
||||
</Label>
|
||||
</div>
|
||||
{#if error}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { page } from '$app/stores';
|
||||
import { derived } from 'svelte/store';
|
||||
import { sdk } from './sdk';
|
||||
|
||||
export type Tier = 'tier-0' | 'tier-1' | 'tier-2';
|
||||
|
||||
@@ -18,6 +19,11 @@ export function tierToPlan(tier: Tier) {
|
||||
}
|
||||
}
|
||||
|
||||
export function getCreditCardImage(brand: string, width = 46, height = 32) {
|
||||
if (!brand) return '';
|
||||
return sdk.forConsole.avatars.getCreditCard(brand, width, height).toString();
|
||||
}
|
||||
|
||||
export const tierFree = {
|
||||
price: 0,
|
||||
name: 'Free',
|
||||
|
||||
@@ -2,7 +2,7 @@ import { hasStripePublicKey, VARS } from '$lib/system';
|
||||
import { loadStripe, type Stripe, type StripeCardElement } from '@stripe/stripe-js';
|
||||
import { sdk } from './sdk';
|
||||
import { app } from './app';
|
||||
import { get } from 'svelte/store';
|
||||
import { get, writable } from 'svelte/store';
|
||||
import { apperanceDark, apperanceLight } from './billing';
|
||||
import type { PaymentMethodData } from '$lib/sdk/billing';
|
||||
|
||||
@@ -11,10 +11,12 @@ let paymentMethod: PaymentMethodData;
|
||||
let clientSecret: string;
|
||||
let paymentElement: StripeCardElement;
|
||||
|
||||
export async function initializeStripe(isStripeInitialized: boolean) {
|
||||
export const isStripeInitialized = writable(false);
|
||||
|
||||
export async function initializeStripe() {
|
||||
if (!hasStripePublicKey) return;
|
||||
stripe = await loadStripe(VARS.STRIPE_PUBLIC_KEY);
|
||||
isStripeInitialized = true;
|
||||
isStripeInitialized.set(true);
|
||||
|
||||
try {
|
||||
const methods = await sdk.forConsole.billing.listPaymentMethods();
|
||||
@@ -39,7 +41,6 @@ export async function initializeStripe(isStripeInitialized: boolean) {
|
||||
const elements = stripe.elements(options);
|
||||
paymentElement = elements.create('card');
|
||||
paymentElement.mount('#payment-element');
|
||||
return isStripeInitialized;
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
@@ -64,12 +65,12 @@ export async function submitStripeCard(name: string) {
|
||||
});
|
||||
|
||||
if (setupIntent && setupIntent.status === 'succeeded') {
|
||||
await sdk.forConsole.billing.updatePaymentMethod(
|
||||
const method = await sdk.forConsole.billing.updatePaymentMethod(
|
||||
paymentMethod.$id,
|
||||
setupIntent.payment_method
|
||||
);
|
||||
|
||||
paymentElement.destroy();
|
||||
return method;
|
||||
} else console.log('something went wrong');
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
<script lang="ts">
|
||||
import { CardGrid, DropList, DropListItem, Empty, Heading } from '$lib/components';
|
||||
import {
|
||||
CardGrid,
|
||||
CreditCardInfo,
|
||||
DropList,
|
||||
DropListItem,
|
||||
Empty,
|
||||
Heading
|
||||
} from '$lib/components';
|
||||
import { Pill } from '$lib/elements';
|
||||
import { Button } from '$lib/elements/forms';
|
||||
import {
|
||||
@@ -19,6 +26,8 @@
|
||||
let showDelete = false;
|
||||
|
||||
console.log($paymentMethods);
|
||||
|
||||
$: filteredMethods = $paymentMethods?.paymentMethods.filter((method) => !!method?.last4);
|
||||
</script>
|
||||
|
||||
<CardGrid>
|
||||
@@ -33,65 +42,47 @@
|
||||
<Table noMargin noStyles>
|
||||
<TableHeader>
|
||||
<TableCellHead>Payment methods</TableCellHead>
|
||||
<TableCellHead width={220} />
|
||||
<TableCellHead width={50} />
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{#each $paymentMethods.paymentMethods as paymentMethod, i}
|
||||
{#each filteredMethods as paymentMethod, i}
|
||||
<TableRow>
|
||||
<TableCell>
|
||||
<p class="text u-bold">
|
||||
{paymentMethod.brand} ending in {paymentMethod.last4}
|
||||
<span>{paymentMethod.brand}</span>
|
||||
</p>
|
||||
<p class="text">
|
||||
Expires {paymentMethod.expiryMonth}/{paymentMethod.expiryYear}
|
||||
</p>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
{#if paymentMethod.default}
|
||||
<Pill>
|
||||
<span class="icon-info" /> default payment method
|
||||
</Pill>
|
||||
{/if}
|
||||
{#if paymentMethod.backup}
|
||||
<Pill>
|
||||
<span class="icon-info" /> backup payment method
|
||||
</Pill>
|
||||
{/if}
|
||||
</TableCell>
|
||||
<TableCell showOverflow>
|
||||
<DropList
|
||||
bind:show={showDropdown[i]}
|
||||
placement="bottom-start"
|
||||
noArrow>
|
||||
<Button
|
||||
round
|
||||
text
|
||||
on:click={() => {
|
||||
showDropdown[i] = !showDropdown[i];
|
||||
}}>
|
||||
<span class="icon-dots-horizontal" />
|
||||
</Button>
|
||||
<svelte:fragment slot="list">
|
||||
<DropListItem
|
||||
icon="pencil"
|
||||
on:click={() => {
|
||||
console.log('test');
|
||||
}}>
|
||||
Edit
|
||||
</DropListItem>
|
||||
<DropListItem
|
||||
icon="trash"
|
||||
on:click={() => {
|
||||
selectedMethod = paymentMethod.$id;
|
||||
showDelete = true;
|
||||
showDropdown[i] = false;
|
||||
}}>
|
||||
Delete
|
||||
</DropListItem>
|
||||
</svelte:fragment>
|
||||
</DropList>
|
||||
<CreditCardInfo {paymentMethod}>
|
||||
<div class="u-flex u-gap-16">
|
||||
<Pill>test</Pill>
|
||||
<DropList
|
||||
bind:show={showDropdown[i]}
|
||||
placement="bottom-start"
|
||||
noArrow>
|
||||
<Button
|
||||
round
|
||||
text
|
||||
on:click={() => {
|
||||
showDropdown[i] = !showDropdown[i];
|
||||
}}>
|
||||
<span class="icon-dots-horizontal" />
|
||||
</Button>
|
||||
<svelte:fragment slot="list">
|
||||
<DropListItem
|
||||
icon="pencil"
|
||||
on:click={() => {
|
||||
console.log('test');
|
||||
}}>
|
||||
Edit
|
||||
</DropListItem>
|
||||
<DropListItem
|
||||
icon="trash"
|
||||
on:click={() => {
|
||||
selectedMethod = paymentMethod.$id;
|
||||
showDelete = true;
|
||||
showDropdown[i] = false;
|
||||
}}>
|
||||
Delete
|
||||
</DropListItem>
|
||||
</svelte:fragment>
|
||||
</DropList>
|
||||
</div>
|
||||
</CreditCardInfo>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
{/each}
|
||||
|
||||
@@ -12,10 +12,8 @@
|
||||
let name: string;
|
||||
let error: string;
|
||||
|
||||
let isStripeInitialized = false;
|
||||
|
||||
onMount(async () => {
|
||||
await initializeStripe(isStripeInitialized);
|
||||
await initializeStripe();
|
||||
});
|
||||
|
||||
async function handleSubmit() {
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
import { Button } from '$lib/elements/forms';
|
||||
import PaymentModal from '$routes/console/account/payments/paymentModal.svelte';
|
||||
import { hasStripePublicKey, isCloud } from '$lib/system';
|
||||
import { paymentMethods } from '$lib/stores/billing';
|
||||
import { getCreditCardImage, paymentMethods } from '$lib/stores/billing';
|
||||
import { onMount } from 'svelte';
|
||||
import type { PaymentMethodData } from '$lib/sdk/billing';
|
||||
|
||||
@@ -127,6 +127,7 @@
|
||||
<h4 class="u-bold body-text-2">Default</h4>
|
||||
{#if $organization?.paymentMethodId}
|
||||
<CreditCardInfo
|
||||
isBox
|
||||
paymentMethod={defaultPaymentMethod}
|
||||
isDeleteDisabled={!$organization?.backupPaymentMethodId} />
|
||||
{:else}
|
||||
@@ -139,13 +140,19 @@
|
||||
</Button>
|
||||
<svelte:fragment slot="list">
|
||||
{#if $paymentMethods.total}
|
||||
{#each $paymentMethods.paymentMethods.filter((o) => o.$id !== $organization.backupPaymentMethodId) as paymentMethod}
|
||||
{#each $paymentMethods.paymentMethods.filter((o) => !!o.last4 && o.$id !== $organization.backupPaymentMethodId) as paymentMethod}
|
||||
<DropListItem
|
||||
on:click={() => addPaymentMethod(paymentMethod?.$id)}>
|
||||
<p class="text">
|
||||
Card ending in {paymentMethod.last4}
|
||||
<span>{paymentMethod.brand}</span>
|
||||
</p>
|
||||
<span class="u-flex u-cross-center u-gap-8">
|
||||
<p class="text">
|
||||
Card ending in {paymentMethod.last4}
|
||||
</p>
|
||||
<img
|
||||
width="23"
|
||||
height="16"
|
||||
src={getCreditCardImage(paymentMethod?.brand)}
|
||||
alt={paymentMethod?.brand} />
|
||||
</span>
|
||||
</DropListItem>
|
||||
{/each}
|
||||
{/if}
|
||||
@@ -176,14 +183,20 @@
|
||||
</Button>
|
||||
<svelte:fragment slot="list">
|
||||
{#if $paymentMethods.total}
|
||||
{#each $paymentMethods.paymentMethods.filter((o) => o.$id !== $organization?.paymentMethodId) as paymentMethod}
|
||||
{#each $paymentMethods.paymentMethods.filter((o) => !!o.last4 && o.$id !== $organization?.paymentMethodId) as paymentMethod}
|
||||
<DropListItem
|
||||
on:click={() =>
|
||||
addBackupPaymentMethod(paymentMethod?.$id)}>
|
||||
<p class="text">
|
||||
Card ending in {paymentMethod.last4}
|
||||
<span>{paymentMethod.brand}</span>
|
||||
</p>
|
||||
<span class="u-flex u-cross-center u-gap-8">
|
||||
<p class="text">
|
||||
Card ending in {paymentMethod.last4}
|
||||
</p>
|
||||
<img
|
||||
width="23"
|
||||
height="16"
|
||||
src={getCreditCardImage(paymentMethod?.brand)}
|
||||
alt={paymentMethod?.brand} />
|
||||
</span>
|
||||
</DropListItem>
|
||||
{/each}
|
||||
{/if}
|
||||
|
||||
@@ -9,38 +9,42 @@
|
||||
import { organization } from '$lib/stores/organization';
|
||||
import { invalidate } from '$app/navigation';
|
||||
import { Dependencies } from '$lib/constants';
|
||||
import { initializeStripe, submitStripeCard } from '$lib/stores/stripe';
|
||||
import { initializeStripe, isStripeInitialized, submitStripeCard } from '$lib/stores/stripe';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { getCreditCardImage } from '$lib/stores/billing';
|
||||
|
||||
let methods: PaymentList;
|
||||
let name: string;
|
||||
let budgetEnabled = false;
|
||||
let showRates = false;
|
||||
|
||||
let isStripeInitialized = false;
|
||||
|
||||
onMount(async () => {
|
||||
methods = await sdk.forConsole.billing.listPaymentMethods();
|
||||
$createOrganization.paymentMethodId =
|
||||
methods.paymentMethods.find((method) => !!method?.last4)?.$id ?? null;
|
||||
|
||||
isStripeInitialized = await initializeStripe(isStripeInitialized);
|
||||
// await initializeStripe();
|
||||
});
|
||||
|
||||
async function handleSubmit() {
|
||||
try {
|
||||
await submitStripeCard(name);
|
||||
const method = await submitStripeCard(name);
|
||||
$createOrganization.paymentMethodId = method.$id;
|
||||
invalidate(Dependencies.PAYMENT_METHODS);
|
||||
} catch (e) {
|
||||
console.log(e.message);
|
||||
}
|
||||
}
|
||||
|
||||
$: if ($createOrganization.paymentMethodId === null && !isStripeInitialized) {
|
||||
initializeStripe(isStripeInitialized);
|
||||
$: if ($createOrganization.paymentMethodId === null && !$isStripeInitialized) {
|
||||
initializeStripe();
|
||||
}
|
||||
|
||||
$: if ($createOrganization.paymentMethodId) {
|
||||
isStripeInitialized = false;
|
||||
isStripeInitialized.set(false);
|
||||
}
|
||||
|
||||
$: filteredMethods = methods?.paymentMethods.filter((method) => !!method?.last4);
|
||||
</script>
|
||||
|
||||
<WizardStep beforeSubmit={handleSubmit}>
|
||||
@@ -50,14 +54,23 @@
|
||||
<FormList>
|
||||
<div class:boxes-wrapper={methods?.total}>
|
||||
{#if methods?.total}
|
||||
{#each methods.paymentMethods as method}
|
||||
{#each filteredMethods as method}
|
||||
<div class="box">
|
||||
<InputRadio
|
||||
id={`payment-method-${method.last4}`}
|
||||
label={`${method.brand} ending in ${method.last4}`}
|
||||
value={method.$id}
|
||||
name="payment"
|
||||
bind:group={$createOrganization.paymentMethodId} />
|
||||
bind:group={$createOrganization.paymentMethodId}>
|
||||
<span class="u-flex u-cross-center u-gap-8">
|
||||
<span>
|
||||
<span class="u-capitalize">{method.brand}</span> ending in {method.last4}</span>
|
||||
<img
|
||||
width="23"
|
||||
height="16"
|
||||
src={getCreditCardImage(method.brand)}
|
||||
alt={method.brand} />
|
||||
</span>
|
||||
</InputRadio>
|
||||
</div>
|
||||
{/each}
|
||||
{/if}
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
const card = await sdk.forConsole.billing.getPaymentMethod(
|
||||
$createOrganization.paymentMethodId
|
||||
);
|
||||
console.log(card);
|
||||
return card;
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
@@ -39,33 +40,36 @@
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<div class="u-margin-block-start-32">
|
||||
<p class="body-text-1 u-bold">Organization members</p>
|
||||
<p class="text">{collaboratorsNumber} invited</p>
|
||||
</div>
|
||||
<div class="u-margin-block-start-32">
|
||||
<p class="body-text-1 u-bold">Payment</p>
|
||||
{#await fetchCard()}
|
||||
<div class="u-flex u-margin-block-start-4">
|
||||
<div class="loader is-small" />
|
||||
</div>
|
||||
{:then card}
|
||||
<p class="text">Card ending in {card.last4} {card.brand}</p>
|
||||
{/await}
|
||||
</div>
|
||||
|
||||
{#if $createOrganization.billingPlan !== 'tier-0'}
|
||||
<div class="u-margin-block-start-32">
|
||||
<p class="body-text-1 u-bold">Organization members</p>
|
||||
<p class="text">{collaboratorsNumber} invited</p>
|
||||
</div>
|
||||
<div class="u-margin-block-start-32">
|
||||
<p class="body-text-1 u-bold">Payment</p>
|
||||
{#await fetchCard()}
|
||||
<div class="u-flex u-margin-block-start-4">
|
||||
<div class="loader is-small" />
|
||||
</div>
|
||||
{:then card}
|
||||
<p class="text">Card ending in {card.last4} {card.brand}</p>
|
||||
{/await}
|
||||
</div>
|
||||
{/if}
|
||||
<div class="box u-margin-block-start-32 u-flex u-flex-vertical u-gap-16">
|
||||
<span class="u-flex u-main-space-between">
|
||||
<p class="text">{plan.name} plan</p>
|
||||
<p class="text">${plan.price}</p>
|
||||
</span>
|
||||
<span class="u-flex u-main-space-between">
|
||||
<p class="text">Invited members</p>
|
||||
<p class="text">${plan.collaboratorPrice * collaboratorsNumber}</p>
|
||||
</span>
|
||||
{#if $createOrganization.billingPlan !== 'tier-0'}
|
||||
<span class="u-flex u-main-space-between">
|
||||
<p class="text">{plan.name} plan</p>
|
||||
<p class="text">${plan.price}</p>
|
||||
</span>
|
||||
<span class="u-flex u-main-space-between">
|
||||
<p class="text">Invited members</p>
|
||||
<p class="text">${plan.collaboratorPrice * collaboratorsNumber}</p>
|
||||
</span>
|
||||
{/if}
|
||||
<div class="u-sep-block-start" />
|
||||
<span class="u-flex u-main-space-between">
|
||||
<p class="text">Estimated total</p>
|
||||
<p class="text">Estimated total (in USD)</p>
|
||||
<p class="text">${totalExpences}</p>
|
||||
</span>
|
||||
|
||||
|
||||
@@ -9,7 +9,8 @@
|
||||
import type { PaymentList } from '$lib/sdk/billing';
|
||||
import { invalidate } from '$app/navigation';
|
||||
import { Dependencies } from '$lib/constants';
|
||||
import { initializeStripe, submitStripeCard } from '$lib/stores/stripe';
|
||||
import { initializeStripe, isStripeInitialized, submitStripeCard } from '$lib/stores/stripe';
|
||||
import { organization } from '$lib/stores/organization';
|
||||
|
||||
let methods: PaymentList;
|
||||
let name: string;
|
||||
@@ -18,12 +19,10 @@
|
||||
|
||||
// let error: string;
|
||||
|
||||
let isStripeInitialized = false;
|
||||
|
||||
onMount(async () => {
|
||||
methods = await sdk.forConsole.billing.listPaymentMethods();
|
||||
|
||||
isStripeInitialized = await initializeStripe(isStripeInitialized);
|
||||
$changeOrganizationTier.paymentMethodId =
|
||||
$organization?.backupPaymentMethodId ?? methods.paymentMethods[0]?.$id ?? null;
|
||||
});
|
||||
|
||||
async function handleSubmit() {
|
||||
@@ -35,13 +34,15 @@
|
||||
}
|
||||
}
|
||||
|
||||
$: if ($changeOrganizationTier.paymentMethodId === null && !isStripeInitialized) {
|
||||
initializeStripe(isStripeInitialized);
|
||||
$: if ($changeOrganizationTier.paymentMethodId === null && !$isStripeInitialized) {
|
||||
initializeStripe();
|
||||
}
|
||||
|
||||
$: if ($changeOrganizationTier.paymentMethodId) {
|
||||
isStripeInitialized = false;
|
||||
isStripeInitialized.set(false);
|
||||
}
|
||||
|
||||
$: filteredMethods = methods?.paymentMethods.filter((method) => !!method?.last4);
|
||||
</script>
|
||||
|
||||
<WizardStep beforeSubmit={handleSubmit}>
|
||||
@@ -51,7 +52,7 @@
|
||||
<FormList>
|
||||
<div class:boxes-wrapper={methods?.total}>
|
||||
{#if methods?.total}
|
||||
{#each methods.paymentMethods as method}
|
||||
{#each filteredMethods as method}
|
||||
<div class="box">
|
||||
<InputRadio
|
||||
id={`payment-method-${method.last4}`}
|
||||
|
||||
@@ -40,30 +40,34 @@
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<div class="u-margin-block-start-32">
|
||||
<p class="body-text-1 u-bold">Organization members</p>
|
||||
<p class="text">{collaboratorsNumber} invited</p>
|
||||
</div>
|
||||
<div class="u-margin-block-start-32">
|
||||
<p class="body-text-1 u-bold">Payment</p>
|
||||
{#await fetchCard()}
|
||||
<div class="u-flex u-margin-block-start-4">
|
||||
<div class="loader is-small" />
|
||||
</div>
|
||||
{:then card}
|
||||
<p class="text">Card ending in {card.last4} {card.brand}</p>
|
||||
{/await}
|
||||
</div>
|
||||
{#if $changeOrganizationTier.billingPlan !== 'tier-0'}
|
||||
<div class="u-margin-block-start-32">
|
||||
<p class="body-text-1 u-bold">Organization members</p>
|
||||
<p class="text">{collaboratorsNumber} invited</p>
|
||||
</div>
|
||||
<div class="u-margin-block-start-32">
|
||||
<p class="body-text-1 u-bold">Payment</p>
|
||||
{#await fetchCard()}
|
||||
<div class="u-flex u-margin-block-start-4">
|
||||
<div class="loader is-small" />
|
||||
</div>
|
||||
{:then card}
|
||||
<p class="text">Card ending in {card.last4} {card.brand}</p>
|
||||
{/await}
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<div class="box u-margin-block-start-32 u-flex u-flex-vertical u-gap-16">
|
||||
<span class="u-flex u-main-space-between">
|
||||
<p class="text">{plan.name} plan</p>
|
||||
<p class="text">${plan.price}</p>
|
||||
</span>
|
||||
<span class="u-flex u-main-space-between">
|
||||
<p class="text">Invited members</p>
|
||||
<p class="text">${plan.collaboratorPrice * collaboratorsNumber}</p>
|
||||
</span>
|
||||
{#if $changeOrganizationTier.billingPlan !== 'tier-0'}
|
||||
<span class="u-flex u-main-space-between">
|
||||
<p class="text">{plan.name} plan</p>
|
||||
<p class="text">${plan.price}</p>
|
||||
</span>
|
||||
<span class="u-flex u-main-space-between">
|
||||
<p class="text">Invited members</p>
|
||||
<p class="text">${plan.collaboratorPrice * collaboratorsNumber}</p>
|
||||
</span>
|
||||
{/if}
|
||||
<div class="u-sep-block-start" />
|
||||
<span class="u-flex u-main-space-between">
|
||||
<p class="text">Estimated total</p>
|
||||
|
||||
Reference in New Issue
Block a user