feat: failed payment and bug fixes

This commit is contained in:
Arman
2023-07-31 19:03:14 +02:00
parent 1903f9f14c
commit bbe341f68b
11 changed files with 95 additions and 43 deletions
+2 -2
View File
@@ -1,4 +1,4 @@
import type { Client } from '@appwrite.io/console';
import type { Client, Query } from '@appwrite.io/console';
import type { Organization } from '../stores/organization';
import type { PaymentMethod } from '@stripe/stripe-js';
@@ -297,7 +297,7 @@ export class Billing {
async listInvoices(
organizationId: string,
queries: string[] = [],
queries: Query[] = [],
search = ''
): Promise<InvoiceList> {
const path = `/organizations/${organizationId}/invoices`;
+2 -1
View File
@@ -3,10 +3,11 @@ import { derived, get } from 'svelte/store';
import { sdk } from './sdk';
import { limitRates } from '$lib/constants';
import { organization } from './organization';
import type { PaymentList } from '$lib/sdk/billing';
export type Tier = 'tier-0' | 'tier-1' | 'tier-2';
export const paymentMethods = derived(page, ($page) => $page.data.paymentMethods);
export const paymentMethods = derived(page, ($page) => $page.data.paymentMethods as PaymentList);
export function tierToPlan(tier: Tier) {
switch (tier) {
@@ -17,7 +17,7 @@
TableHeader,
TableRow
} from '$lib/elements/table';
import { paymentMethods } from './store';
import { paymentMethods } from '$lib/stores/billing';
import type { PaymentMethodData } from '$lib/sdk/billing';
import { organizationList, type Organization } from '$lib/stores/organization';
import { tooltip } from '$lib/actions/tooltip';
@@ -1,4 +0,0 @@
import { page } from '$app/stores';
import { derived } from 'svelte/store';
export const paymentMethods = derived(page, ($page) => $page.data.paymentMethods);
@@ -6,10 +6,14 @@
import { onMount } from 'svelte';
import { addNotification } from '$lib/stores/notifications';
import { toLocaleDate } from '$lib/helpers/date';
import { sdk } from '$lib/stores/sdk';
import { goto } from '$app/navigation';
import { base } from '$app/paths';
onMount(() => {
if (isCloud) {
checkForTrialEnding();
paymentExpired();
}
});
@@ -30,6 +34,32 @@
localStorage.setItem('trialEndingNotification', 'true');
}
}
//TODO: move this function
async function paymentExpired() {
if (localStorage.getItem('paymentExpiredNotification') === 'true') return;
const payment = await sdk.forConsole.billing.getPaymentMethod(
$organization.paymentMethodId
);
if (payment.expired) {
addNotification({
type: 'info',
isHtml: true,
dismissible: false,
message: `The default payment method for <b>${$organization.name}</b> has expired`,
buttons: [
{
name: 'Update payment details',
method: () => {
goto(`${base}/console/account/payments`);
}
}
]
});
localStorage.setItem('paymentExpiredNotification', 'true');
}
}
</script>
<svelte:head>
@@ -8,9 +8,27 @@
import PaymentMethods from './paymentMethods.svelte';
import AvailableCredit from './availableCredit.svelte';
import PaymentHistory from './paymentHistory.svelte';
import { Alert, Heading } from '$lib/components';
import { paymentMethods } from '$lib/stores/billing';
import type { PaymentMethodData } from '$lib/sdk/billing';
$: defaultPaymentMethod = $paymentMethods.paymentMethods.find(
(method: PaymentMethodData) => method.$id === $organization.paymentMethodId
);
</script>
<Container>
{#if defaultPaymentMethod.failed}
<Alert type="error">
<svelte:fragment slot="title">
The default payment method for {$organization.name} has expired
</svelte:fragment>
To avoid service disruptions in your projects, please update your payment details.
</Alert>
{/if}
<div class="common-section">
<Heading tag="h2" size="5">Billing</Heading>
</div>
<PlanSummary />
<PaymentHistory />
<PaymentMethods />
@@ -1,6 +1,5 @@
import { Dependencies } from '$lib/constants';
import { sdk } from '$lib/stores/sdk';
import { Query } from '@appwrite.io/console';
import type { PageLoad } from './$types';
export const load: PageLoad = async ({ params, parent, depends }) => {
@@ -11,10 +10,6 @@ export const load: PageLoad = async ({ params, parent, depends }) => {
depends(Dependencies.INVOICES);
return {
paymentMethods: await sdk.forConsole.billing.listPaymentMethods(),
creditList: await sdk.forConsole.billing.listCredits(params.organization),
invoiceList: await sdk.forConsole.billing.listInvoices(params.organization, [
Query.limit(5)
])
paymentMethods: await sdk.forConsole.billing.listPaymentMethods()
};
};
@@ -13,15 +13,25 @@
TableRow
} from '$lib/elements/table';
import { toLocaleDate } from '$lib/helpers/date';
import type { Credit } from '$lib/sdk/billing';
import type { Credit, CreditList } from '$lib/sdk/billing';
import { addNotification } from '$lib/stores/notifications';
import { organization } from '$lib/stores/organization';
import { sdk } from '$lib/stores/sdk';
import { Query } from '@appwrite.io/console';
import { creditList } from './store';
import { onMount } from 'svelte';
let coupon: string = null;
let offset = 0;
let creditList: CreditList = {
credits: [],
total: 0
};
onMount(async () => {
request();
});
const limit = 5;
async function redeem() {
try {
@@ -45,8 +55,8 @@
}
async function request() {
$creditList = await sdk.forConsole.billing.listCredits($organization.$id, [
Query.limit(5),
creditList = await sdk.forConsole.billing.listCredits($organization.$id, [
Query.limit(limit),
Query.offset(offset)
]);
}
@@ -55,7 +65,7 @@
request();
}
$: balance = $creditList?.credits?.reduce((acc: number, curr: Credit) => acc + curr.credits, 0);
$: balance = creditList?.credits?.reduce((acc: number, curr: Credit) => acc + curr.credits, 0);
</script>
<CardGrid>
@@ -80,7 +90,7 @@
</InputText>
</FormList>
</Form>
{#if $creditList?.total}
{#if creditList?.total}
<Table noStyles noMargin>
<TableHeader>
<TableCellHead>Date Added</TableCellHead>
@@ -88,7 +98,7 @@
<TableCellHead>Amount</TableCellHead>
</TableHeader>
<TableBody>
{#each $creditList.credits as credit}
{#each creditList.credits as credit}
<TableRow>
<TableCellText title="date added">
{toLocaleDate(credit.$createdAt)}
@@ -104,8 +114,8 @@
</TableBody>
</Table>
<div class="u-flex u-main-space-between">
<p class="text">Total results: {$creditList?.total}</p>
<PaginationInline limit={5} bind:offset sum={$creditList?.total} hidePages />
<p class="text">Total results: {creditList?.total}</p>
<PaginationInline {limit} bind:offset sum={creditList?.total} hidePages />
</div>
{/if}
</svelte:fragment>
@@ -20,17 +20,28 @@
TableRow
} from '$lib/elements/table';
import { toLocaleDate } from '$lib/helpers/date';
import type { InvoiceList } from '$lib/sdk/billing';
import { sdk } from '$lib/stores/sdk';
import { Query } from '@appwrite.io/console';
import { invoiceList } from './store';
import { onMount } from 'svelte';
let showDropdown = [];
let selectedInvoice: string;
let offset = 0;
let offset = 0;
let invoiceList: InvoiceList = {
invoices: [],
total: 0
};
let downloadLink: string;
let viewLink: string;
const limit = 5;
onMount(async () => {
request();
});
async function download() {
return await sdk.forConsole.billing.downloadInvoice(
$page.params.organization,
@@ -46,9 +57,10 @@
}
async function request() {
$invoiceList = await sdk.forConsole.billing.listInvoices($page.params.organization, [
Query.limit(5),
Query.offset(offset)
invoiceList = await sdk.forConsole.billing.listInvoices($page.params.organization, [
Query.limit(limit),
Query.offset(offset),
Query.orderDesc('$createdAt')
]);
}
@@ -74,7 +86,7 @@
payments.
</p>
<svelte:fragment slot="aside">
{#if $invoiceList.total}
{#if invoiceList.total}
<Table noMargin noStyles>
<TableHeader>
<TableCellHead>Due Date</TableCellHead>
@@ -84,7 +96,7 @@
<TableCellHead width={40} />
</TableHeader>
<TableBody>
{#each $invoiceList?.invoices as invoice, i}
{#each invoiceList?.invoices as invoice, i}
{@const status = invoice.status}
<TableRow>
<TableCellText title="date">
@@ -133,8 +145,8 @@
</TableBody>
</Table>
<div class="u-flex u-main-space-between">
<p class="text">Total results: {$invoiceList?.total}</p>
<PaginationInline limit={1} bind:offset sum={$invoiceList?.total} hidePages />
<p class="text">Total results: {invoiceList?.total}</p>
<PaginationInline {limit} bind:offset sum={invoiceList?.total} hidePages />
</div>
{:else}
<EmptySearch cardOnly>
@@ -1,10 +0,0 @@
import { page } from '$app/stores';
import type { CreditList, InvoiceList, PaymentList } from '$lib/sdk/billing';
import { derived, type Readable } from 'svelte/store';
export const paymentMethods: Readable<PaymentList> = derived(
page,
($page) => $page.data.paymentMethods
);
export const creditList: Readable<CreditList> = derived(page, ($page) => $page.data.creditList);
export const invoiceList: Readable<InvoiceList> = derived(page, ($page) => $page.data.invoiceList);
@@ -35,7 +35,7 @@
<RegionCard
name="region"
bind:group={$createProject.region}
value={region.name}
value={region.$id}
disabled={region.disabled}>
<div
class="u-flex u-flex-vertical u-gap-12 u-justify-main-center u-cross-center u-margin-inline-auto">