Skip to content

Commit

Permalink
feat: [M3-6715] - Allow sorting by amount on billing activity table (l…
Browse files Browse the repository at this point in the history
…inode#10941)

* Add allow sorting by amount on billing activity table

* Added changeset: Allow sorting by amount on billing activity table

* Update getOrderedPaginatedData function

* refactor: use useMemo to optimize orderedPaginatedData

* Fix: Change colSpan 5 to 4

* Few fixes...

* Add default case to order data by date in descending order

* Use createDisplayPage to paginate ordered data list
  • Loading branch information
pmakode-akamai authored and hasyed-akamai committed Oct 9, 2024
1 parent 15471ee commit ceff170
Show file tree
Hide file tree
Showing 2 changed files with 108 additions and 93 deletions.
5 changes: 5 additions & 0 deletions packages/manager/.changeset/pr-10941-added-1726492437722.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@linode/manager": Added
---

Allow sorting by amount on billing activity table ([#10941](https://github.com/linode/manager/pull/10941))
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,17 @@ import { Currency } from 'src/components/Currency';
import { DateTimeDisplay } from 'src/components/DateTimeDisplay';
import { InlineMenuAction } from 'src/components/InlineMenuAction/InlineMenuAction';
import { Link } from 'src/components/Link';
import OrderBy from 'src/components/OrderBy';
import Paginate from 'src/components/Paginate';
import { createDisplayPage } from 'src/components/Paginate';
import { PaginationFooter } from 'src/components/PaginationFooter/PaginationFooter';
import { Table } from 'src/components/Table';
import { TableBody } from 'src/components/TableBody';
import { TableCell } from 'src/components/TableCell';
import { TableContentWrapper } from 'src/components/TableContentWrapper/TableContentWrapper';
import { TableHead } from 'src/components/TableHead';
import { TableRow } from 'src/components/TableRow';
import { TableRowEmpty } from 'src/components/TableRowEmpty/TableRowEmpty';
import { TableRowError } from 'src/components/TableRowError/TableRowError';
import { TableRowLoading } from 'src/components/TableRowLoading/TableRowLoading';
import { TableSortCell } from 'src/components/TableSortCell';
import { TextTooltip } from 'src/components/TextTooltip';
import { Typography } from 'src/components/Typography';
import { ISO_DATETIME_NO_TZ_FORMAT } from 'src/constants';
Expand All @@ -29,6 +31,8 @@ import {
printPayment,
} from 'src/features/Billing/PdfGenerator/PdfGenerator';
import { useFlags } from 'src/hooks/useFlags';
import { useOrder } from 'src/hooks/useOrder';
import { usePagination } from 'src/hooks/usePagination';
import { useSet } from 'src/hooks/useSet';
import { useAccount } from 'src/queries/account/account';
import {
Expand Down Expand Up @@ -168,6 +172,9 @@ const AkamaiBillingInvoiceText = (
// =============================================================================
// <BillingActivityPanel />
// =============================================================================

const NUM_COLS = 4;

export interface Props {
accountActiveSince?: string;
}
Expand All @@ -177,6 +184,10 @@ export const BillingActivityPanel = React.memo((props: Props) => {
const { data: profile } = useProfile();
const { data: account } = useAccount();
const { data: regions } = useRegionsQuery();

const pagination = usePagination(1, 'billing-activity');
const { handleOrderChange, order, orderBy } = useOrder();

const isAkamaiCustomer = account?.billing_source === 'akamai';
const { classes } = useStyles();
const flags = useFlags();
Expand Down Expand Up @@ -302,6 +313,65 @@ export const BillingActivityPanel = React.memo((props: Props) => {
);
}, [selectedTransactionType, combinedData]);

const data =
selectedTransactionType.value === 'all' ? combinedData : filteredData;

const orderedPaginatedData = React.useMemo(() => {
const orderedData = data.sort((a, b) => {
if (orderBy === 'total') {
return order === 'asc' ? a.total - b.total : b.total - a.total;
}
// Default: If no valid 'orderBy' is provided, sort the data by date in descending order.
return new Date(b.date).getTime() - new Date(a.date).getTime();
});

const displayPage = createDisplayPage<ActivityFeedItem>(
pagination.page,
pagination.pageSize
);

return displayPage(orderedData);
}, [data, orderBy, order, pagination.page, pagination.pageSize]);

const renderTableContent = () => {
if (accountPaymentsLoading || accountInvoicesLoading) {
return <TableRowLoading columns={NUM_COLS} rows={1} />;
}
if (accountPaymentsError || accountInvoicesError) {
return (
<TableRowError
colSpan={NUM_COLS}
message="There was an error retrieving your billing activity."
/>
);
}
if (orderedPaginatedData.length === 0) {
return (
<TableRowEmpty
colSpan={NUM_COLS}
message="No Billing & Payment History found."
/>
);
}
if (orderedPaginatedData.length > 0) {
return orderedPaginatedData.map((thisItem) => (
<ActivityFeedItem
downloadPDF={
thisItem.type === 'invoice'
? downloadInvoicePDF
: downloadPaymentPDF
}
hasError={pdfErrors.has(`${thisItem.type}-${thisItem.id}`)}
isLoading={pdfLoading.has(`${thisItem.type}-${thisItem.id}`)}
key={`${thisItem.type}-${thisItem.id}`}
{...thisItem}
/>
));
}

return null;
};

return (
<Grid data-qa-billing-activity-panel xs={12}>
<Paper variant="outlined">
Expand Down Expand Up @@ -368,96 +438,36 @@ export const BillingActivityPanel = React.memo((props: Props) => {
/>
</div>
</StyledBillingAndPaymentHistoryHeader>
<OrderBy
data={
selectedTransactionType.value === 'all'
? combinedData
: filteredData
}
order={'desc'}
orderBy={'date'}
>
{({ data: orderedData }) => (
<Paginate data={orderedData} pageSize={25} shouldScroll={false}>
{({
count,
data: paginatedAndOrderedData,
handlePageChange,
handlePageSizeChange,
page,
pageSize,
}) => (
<>
<Table aria-label="List of Invoices and Payments">
<TableHead>
<TableRow>
<TableCell className={classes.descriptionColumn}>
Description
</TableCell>
<TableCell className={classes.dateColumn}>
Date
</TableCell>
<TableCell className={classes.totalColumn}>
Amount
</TableCell>
<TableCell className={classes.pdfDownloadColumn} />
</TableRow>
</TableHead>
<TableBody>
<TableContentWrapper
error={
accountPaymentsError || accountInvoicesError
? [
{
reason:
'There was an error retrieving your billing activity.',
},
]
: undefined
}
loading={
accountPaymentsLoading || accountInvoicesLoading
}
loadingProps={{
columns: 4,
}}
length={paginatedAndOrderedData.length}
>
{paginatedAndOrderedData.map((thisItem) => {
return (
<ActivityFeedItem
downloadPDF={
thisItem.type === 'invoice'
? downloadInvoicePDF
: downloadPaymentPDF
}
hasError={pdfErrors.has(
`${thisItem.type}-${thisItem.id}`
)}
isLoading={pdfLoading.has(
`${thisItem.type}-${thisItem.id}`
)}
key={`${thisItem.type}-${thisItem.id}`}
{...thisItem}
/>
);
})}
</TableContentWrapper>
</TableBody>
</Table>
<PaginationFooter
count={count}
eventCategory="Billing Activity Table"
handlePageChange={handlePageChange}
handleSizeChange={handlePageSizeChange}
page={page}
pageSize={pageSize}
/>
</>
)}
</Paginate>
)}
</OrderBy>
<Table aria-label="List of Invoices and Payments">
<TableHead>
<TableRow>
<TableCell className={classes.descriptionColumn}>
Description
</TableCell>
<TableCell className={classes.dateColumn}>Date</TableCell>
<TableSortCell
active={orderBy === 'total'}
className={classes.totalColumn}
direction={order}
handleClick={handleOrderChange}
label="total"
>
Amount
</TableSortCell>

<TableCell className={classes.pdfDownloadColumn} />
</TableRow>
</TableHead>
<TableBody>{renderTableContent()}</TableBody>
</Table>
<PaginationFooter
count={data.length}
eventCategory="Billing Activity Table"
handlePageChange={pagination.handlePageChange}
handleSizeChange={pagination.handlePageSizeChange}
page={pagination.page}
pageSize={pagination.pageSize}
/>
</Paper>
</Grid>
);
Expand Down

0 comments on commit ceff170

Please sign in to comment.