mirror of
https://github.com/appwrite/console.git
synced 2026-06-06 19:27:48 +00:00
fix: invoices and usage
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import type { Client } from '@appwrite.io/console';
|
||||
import type { Organization } from './organization';
|
||||
import type { PaymentMethod } from '@stripe/stripe-js';
|
||||
import type { P } from 'vitest/dist/types-fafda418';
|
||||
|
||||
export type PaymentMethodData = {
|
||||
$id: string;
|
||||
@@ -17,6 +18,19 @@ export type PaymentList = {
|
||||
total: number;
|
||||
};
|
||||
|
||||
export type Invoice = {
|
||||
$id: string;
|
||||
amount: number;
|
||||
currency: string;
|
||||
date: number;
|
||||
status: string;
|
||||
paymentMethod: PaymentMethodData;
|
||||
};
|
||||
|
||||
export type InvoiceList = {
|
||||
invoices: Invoice[];
|
||||
total: number;
|
||||
};
|
||||
export class Billing {
|
||||
client: Client;
|
||||
|
||||
@@ -140,10 +154,10 @@ export class Billing {
|
||||
|
||||
async listInvoices(
|
||||
organizationId: string,
|
||||
queries: [] = [],
|
||||
queries: string[] = [],
|
||||
search: string = ''
|
||||
): Promise<string> {
|
||||
const path = `/organizations/${organizationId}/plan`;
|
||||
): Promise<InvoiceList> {
|
||||
const path = `/organizations/${organizationId}/invoices`;
|
||||
const params = {
|
||||
organizationId,
|
||||
queries,
|
||||
@@ -160,7 +174,7 @@ export class Billing {
|
||||
);
|
||||
}
|
||||
|
||||
async getInvoice(organizationId: string, invoiceId: string) {
|
||||
async getInvoice(organizationId: string, invoiceId: string): Promise<Invoice> {
|
||||
const path = `/organizations/${organizationId}/invoices/${invoiceId}`;
|
||||
const params = {
|
||||
organizationId,
|
||||
@@ -177,7 +191,7 @@ export class Billing {
|
||||
);
|
||||
}
|
||||
|
||||
async getInvoiceView(organizationId: string, invoiceId: string) {
|
||||
async getInvoiceView(organizationId: string, invoiceId: string): Promise<URL> {
|
||||
const path = `/organizations/${organizationId}/invoices/${invoiceId}/view`;
|
||||
const params = {
|
||||
organizationId,
|
||||
@@ -194,7 +208,7 @@ export class Billing {
|
||||
);
|
||||
}
|
||||
|
||||
async downloadInvoice(organizationId: string, invoiceId: string) {
|
||||
async downloadInvoice(organizationId: string, invoiceId: string): Promise<URL> {
|
||||
const path = `/organizations/${organizationId}/invoices/${invoiceId}/download`;
|
||||
const params = {
|
||||
organizationId,
|
||||
@@ -211,6 +225,46 @@ export class Billing {
|
||||
);
|
||||
}
|
||||
|
||||
async listUsage(
|
||||
organizationId: string,
|
||||
queries: string[] = []
|
||||
): Promise<Record<string, unknown>> {
|
||||
const path = `/organizations/${organizationId}/aggregations`;
|
||||
const params = {
|
||||
organizationId,
|
||||
queries
|
||||
};
|
||||
const uri = new URL(this.client.config.endpoint + path);
|
||||
return await this.client.call(
|
||||
'get',
|
||||
uri,
|
||||
{
|
||||
'content-type': 'application/json'
|
||||
},
|
||||
params
|
||||
);
|
||||
}
|
||||
|
||||
async getUsage(
|
||||
organizationId: string,
|
||||
aggregationId: string
|
||||
): Promise<Record<string, unknown>> {
|
||||
const path = `/organizations/${organizationId}/aggregations/${aggregationId}`;
|
||||
const params = {
|
||||
organizationId,
|
||||
aggregationId
|
||||
};
|
||||
const uri = new URL(this.client.config.endpoint + path);
|
||||
return await this.client.call(
|
||||
'get',
|
||||
uri,
|
||||
{
|
||||
'content-type': 'application/json'
|
||||
},
|
||||
params
|
||||
);
|
||||
}
|
||||
|
||||
//ACCOUNT
|
||||
|
||||
async listPaymentMethods(queries: [] = []): Promise<PaymentList> {
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
const path = `/console/account`;
|
||||
|
||||
const permanentTabs = [
|
||||
$: permanentTabs = [
|
||||
{
|
||||
href: path,
|
||||
title: 'Overview',
|
||||
|
||||
@@ -29,8 +29,7 @@
|
||||
$: avatars = $members.memberships?.map((m) => m.userName) ?? [];
|
||||
$: organizationId = $page.params.organization;
|
||||
$: path = `/console/organization-${organizationId}`;
|
||||
|
||||
const permanentTabs = [
|
||||
$: permanentTabs = [
|
||||
{
|
||||
href: path,
|
||||
title: 'Projects',
|
||||
@@ -47,17 +46,17 @@
|
||||
href: `${path}/settings`,
|
||||
event: 'settings',
|
||||
title: 'Settings'
|
||||
},
|
||||
{
|
||||
href: `${path}/usage`,
|
||||
event: 'usage',
|
||||
title: 'Usage',
|
||||
hasChildren: true
|
||||
}
|
||||
];
|
||||
$: tabs = isCloud
|
||||
? [
|
||||
...permanentTabs,
|
||||
{
|
||||
href: `${path}/usage`,
|
||||
event: 'usage',
|
||||
title: 'Usage',
|
||||
hasChildren: true
|
||||
},
|
||||
{
|
||||
href: `${path}/billing`,
|
||||
event: 'billing',
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<script lang="ts">
|
||||
import { page } from '$app/stores';
|
||||
import {
|
||||
DropList,
|
||||
DropListItem,
|
||||
@@ -8,6 +9,7 @@
|
||||
PaginationInline
|
||||
} from '$lib/components';
|
||||
import { Pill } from '$lib/elements';
|
||||
import { Button } from '$lib/elements/forms/index.js';
|
||||
import {
|
||||
TableBody,
|
||||
TableCell,
|
||||
@@ -18,18 +20,28 @@
|
||||
TableScroll
|
||||
} from '$lib/elements/table';
|
||||
import { Container } from '$lib/layout';
|
||||
import { sdk } from '$lib/stores/sdk.js';
|
||||
|
||||
export let data;
|
||||
export let offset = 0;
|
||||
|
||||
let showDropdown = [];
|
||||
let selectedInvoice: string;
|
||||
|
||||
async function download() {
|
||||
sdk.forConsole.billing.downloadInvoice($page.params.organization, selectedInvoice);
|
||||
}
|
||||
|
||||
async function view() {
|
||||
sdk.forConsole.billing.getInvoiceView($page.params.organization, selectedInvoice);
|
||||
}
|
||||
</script>
|
||||
|
||||
<Container>
|
||||
<div class="common-section">
|
||||
<Heading tag="h2" size="5">Invoices</Heading>
|
||||
</div>
|
||||
{#if data.invoices?.total}
|
||||
{#if data?.invoices?.total}
|
||||
<TableScroll>
|
||||
<TableHeader>
|
||||
<TableCellHead width={100}>Date</TableCellHead>
|
||||
@@ -39,33 +51,39 @@
|
||||
<TableCellHead width={40} />
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
<!-- {#each data.invoices?.invoices as invoice, i} -->
|
||||
{#each [] as invoice, i}
|
||||
{#each data.invoices?.invoices as invoice, i}
|
||||
<TableRow>
|
||||
<TableCellText title="date">test</TableCellText>
|
||||
<TableCell title="status">
|
||||
<Pill>test</Pill>
|
||||
</TableCell>
|
||||
<TableCellText title="due">$1BILLION</TableCellText>
|
||||
<TableCellText title="due">{invoice}</TableCellText>
|
||||
<TableCellText title="invoice number">test</TableCellText>
|
||||
<TableCell showOverflow>
|
||||
<DropList bind:show={showDropdown[i]} placement="bottom-start" noArrow>
|
||||
<button
|
||||
class="button is-only-icon is-text"
|
||||
aria-label="More options"
|
||||
on:click|preventDefault={() => {
|
||||
<Button
|
||||
round
|
||||
text
|
||||
ariaLabel="More options"
|
||||
on:click={() => {
|
||||
showDropdown[i] = !showDropdown[i];
|
||||
}}>
|
||||
<span class="icon-dots-horizontal" aria-hidden="true" />
|
||||
</button>
|
||||
</Button>
|
||||
<svelte:fragment slot="list">
|
||||
<DropListLink icon="external-link" href="#/">
|
||||
<DropListItem
|
||||
icon="external-link"
|
||||
on:click={() => {
|
||||
selectedInvoice = invoice.$id;
|
||||
view();
|
||||
}}>
|
||||
View invoice
|
||||
</DropListLink>
|
||||
</DropListItem>
|
||||
<DropListItem
|
||||
icon="download"
|
||||
on:click={() => {
|
||||
console.log('test');
|
||||
selectedInvoice = invoice.$id;
|
||||
download();
|
||||
}}>Download PDF</DropListItem>
|
||||
</svelte:fragment>
|
||||
</DropList>
|
||||
|
||||
@@ -1,21 +1,23 @@
|
||||
import { Query } from '@appwrite.io/console';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { getPage, pageToOffset } from '$lib/helpers/load';
|
||||
import { getLimit, getPage, pageToOffset } from '$lib/helpers/load';
|
||||
import { PAGE_LIMIT } from '$lib/constants';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load: PageLoad = async ({ params, url }) => {
|
||||
export const load: PageLoad = async ({ params, url, route }) => {
|
||||
const page = getPage(url);
|
||||
// const limit = getLimit(url, route, CARD_LIMIT);
|
||||
const limit = getLimit(url, route, PAGE_LIMIT);
|
||||
const offset = pageToOffset(page, PAGE_LIMIT);
|
||||
|
||||
const invoices = await sdk.forConsole.billing.listInvoices(params.organization, [
|
||||
Query.offset(offset),
|
||||
Query.limit(limit),
|
||||
Query.orderDesc('$createdAt')
|
||||
]);
|
||||
|
||||
console.log(invoices);
|
||||
return {
|
||||
offset,
|
||||
invoices: await sdk.forConsole.projects.list([
|
||||
Query.offset(offset),
|
||||
Query.limit(PAGE_LIMIT),
|
||||
Query.equal('teamId', params.organization),
|
||||
Query.orderDesc('$createdAt')
|
||||
])
|
||||
invoices
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { Query } from '@appwrite.io/console';
|
||||
import type { PageLoad } from './$types';
|
||||
import { error } from '@sveltejs/kit';
|
||||
|
||||
@@ -63,9 +65,9 @@ const MOCKDATA = [
|
||||
];
|
||||
|
||||
export const load: PageLoad = async ({ params }) => {
|
||||
try {
|
||||
return { usageData: MOCKDATA };
|
||||
} catch (e) {
|
||||
throw error(e.code, e.message);
|
||||
}
|
||||
const usage = await sdk.forConsole.billing.listUsage(params.organization);
|
||||
console.log(usage);
|
||||
return {
|
||||
usage
|
||||
};
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user