web/satellite/vuetify-poc: list invoices

This change lists invoices on the vuetifypoc billing history tab.
It also removes invoice filtering on the main app.

Issue: https://github.com/storj/storj/issues/6099

Change-Id: Id4cc2db003a0208775ddaefc87abf26f4b05106c
This commit is contained in:
Wilfred Asomani 2023-08-28 10:37:39 +00:00 committed by Storj Robot
parent 775db4aa3c
commit 3f1ea4a0b9
3 changed files with 147 additions and 38 deletions

View File

@ -58,9 +58,7 @@ const historyPage = computed((): PaymentHistoryPage => {
}); });
const historyItems = computed((): PaymentsHistoryItem[] => { const historyItems = computed((): PaymentsHistoryItem[] => {
return historyPage.value.items.filter((item: PaymentsHistoryItem) => { return historyPage.value.items;
return item.status !== PaymentsHistoryItemStatus.Draft;
});
}); });
async function fetchHistory(endingBefore = '', startingAfter = ''): Promise<void> { async function fetchHistory(endingBefore = '', startingAfter = ''): Promise<void> {
@ -81,18 +79,18 @@ async function sizeChanged(size: number) {
} }
async function nextClicked(): Promise<void> { async function nextClicked(): Promise<void> {
const length = historyPage.value.items.length; const length = historyItems.value.length;
if (!historyPage.value.hasNext || !length) { if (!historyPage.value.hasNext || !length) {
return; return;
} }
await fetchHistory('', historyPage.value.items[length - 1].id); await fetchHistory('', historyItems.value[length - 1].id);
} }
async function previousClicked(): Promise<void> { async function previousClicked(): Promise<void> {
if (!historyPage.value.hasPrevious || !historyPage.value.items.length) { if (!historyPage.value.hasPrevious || !historyItems.value.length) {
return; return;
} }
await fetchHistory(historyPage.value.items[0].id, ''); await fetchHistory(historyItems.value[0].id, '');
} }
onMounted(() => { onMounted(() => {

View File

@ -0,0 +1,140 @@
// Copyright (C) 2023 Storj Labs, Inc.
// See LICENSE for copying information.
<template>
<v-card variant="flat" :border="true" rounded="xlg">
<v-data-table
:loading="isLoading"
:headers="headers"
:items="historyItems"
:must-sort="false"
class="elevation-1"
hover
>
<template #item.amount="{ item }">
<span>
{{ centsToDollars(item.raw.amount) }}
</span>
</template>
<template #item.formattedStart="{ item }">
<span class="font-weight-bold">
{{ item.raw.formattedStart }}
</span>
</template>
<template #item.formattedStatus="{ item }">
<v-chip :color="getColor(item.raw.formattedStatus)" variant="tonal" size="small" rounded="xl" class="font-weight-bold">
{{ item.raw.formattedStatus }}
</v-chip>
</template>
<template #item.link="{ item }">
<v-btn v-if="item.raw.link" variant="flat" size="small" :href="item.raw.link">
Download
</v-btn>
</template>
<template #bottom>
<div class="v-data-table-footer">
<v-row justify="end" align="center" class="pa-2">
<v-col cols="auto">
<v-btn-group density="compact">
<v-btn :disabled="!historyPage.hasPrevious" icon="mdi-chevron-left" @click="previousClicked" />
<v-btn :disabled="!historyPage.hasNext" icon="mdi-chevron-right" @click="nextClicked" />
</v-btn-group>
</v-col>
<v-col cols="auto">
<v-select
v-model="limit"
density="compact"
:items="pageSizes"
variant="outlined"
@update:model-value="sizeChanged"
/>
</v-col>
</v-row>
</div>
</template>
</v-data-table>
</v-card>
</template>
<script setup lang="ts">
import { VBtn, VBtnGroup, VCard, VChip, VCol, VRow, VSelect, VWindowItem } from 'vuetify/components';
import { computed, onMounted, ref } from 'vue';
import { VDataTable } from 'vuetify/labs/components';
import { centsToDollars } from '@/utils/strings';
import { useBillingStore } from '@/store/modules/billingStore';
import { useNotify } from '@/utils/hooks';
import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames';
import { PaymentHistoryPage, PaymentsHistoryItem, PaymentsHistoryItemStatus } from '@/types/payments';
import { useLoading } from '@/composables/useLoading';
import { DEFAULT_PAGE_LIMIT } from '@/types/pagination';
const billingStore = useBillingStore();
const notify = useNotify();
const { isLoading, withLoading } = useLoading();
const limit = ref(DEFAULT_PAGE_LIMIT);
const headers = [
{ title: 'Date', key: 'formattedStart', sortable: false },
{ title: 'Amount', key: 'amount', sortable: false },
{ title: 'Status', key: 'formattedStatus', sortable: false },
{ title: '', key: 'link', sortable: false, width: 0 },
];
const pageSizes = [DEFAULT_PAGE_LIMIT, 25, 50, 100];
const historyPage = computed((): PaymentHistoryPage => {
return billingStore.state.paymentsHistory;
});
const historyItems = computed((): PaymentsHistoryItem[] => {
return historyPage.value.items;
});
function getColor(status: string): string {
if (status === 'Paid') return 'success';
if (status === 'Open') return 'warning';
if (status === 'Pending') return 'warning';
return 'error';
}
function fetchHistory(endingBefore = '', startingAfter = ''): void {
withLoading(async () => {
try {
await billingStore.getPaymentsHistory({
limit: limit.value,
startingAfter,
endingBefore,
});
} catch (error) {
notify.notifyError(error, AnalyticsErrorEventSource.BILLING_HISTORY_TAB);
}
});
}
async function nextClicked(): Promise<void> {
const length = historyItems.value.length;
if (!historyPage.value.hasNext || !length) {
return;
}
fetchHistory('', historyItems.value[length - 1].id);
}
async function previousClicked(): Promise<void> {
if (!historyPage.value.hasPrevious || !historyItems.value.length) {
return;
}
fetchHistory(historyItems.value[0].id, '');
}
async function sizeChanged(size: number) {
limit.value = size;
fetchHistory();
}
onMounted(() => {
fetchHistory();
});
</script>

View File

@ -173,37 +173,7 @@
</v-window-item> </v-window-item>
<v-window-item> <v-window-item>
<v-card variant="flat" :border="true" rounded="xlg"> <billing-history-tab />
<v-text-field
v-model="search"
label="Search"
prepend-inner-icon="mdi-magnify"
single-line
hide-details
/>
<v-data-table
v-model="selected"
:sort-by="sortBy"
:headers="headers"
:items="invoices"
:search="search"
class="elevation-1"
show-select
hover
>
<template #item.date="{ item }">
<span class="font-weight-bold">
{{ item.raw.date }}
</span>
</template>
<template #item.status="{ item }">
<v-chip :color="getColor(item.raw.status)" variant="tonal" size="small" rounded="xl" class="font-weight-bold">
{{ item.raw.status }}
</v-chip>
</template>
</v-data-table>
</v-card>
</v-window-item> </v-window-item>
<v-window-item> <v-window-item>
@ -256,6 +226,7 @@ import { useProjectsStore } from '@/store/modules/projectsStore';
import CreditCardComponent from '@poc/components/CreditCardComponent.vue'; import CreditCardComponent from '@poc/components/CreditCardComponent.vue';
import AddCreditCardComponent from '@poc/components/AddCreditCardComponent.vue'; import AddCreditCardComponent from '@poc/components/AddCreditCardComponent.vue';
import BillingHistoryTab from '@poc/components/billing/BillingHistoryTab.vue';
import UsageAndChargesComponent from '@poc/components/billing/UsageAndChargesComponent.vue'; import UsageAndChargesComponent from '@poc/components/billing/UsageAndChargesComponent.vue';
import StorjTokenCardComponent from '@poc/components/StorjTokenCardComponent.vue'; import StorjTokenCardComponent from '@poc/components/StorjTokenCardComponent.vue';