mirror of
https://github.com/Unleash/unleash.git
synced 2025-11-10 01:19:53 +01:00
feat: enhance billing invoice components (#10799)
## About the changes - Hide "included usage" column if an invoice doesn't have any items that have lines with `limit` - Minor component types refactors - Only open (extend accordion) for the first invoice on the list
This commit is contained in:
parent
f9ed38ca98
commit
38bb9b3bfc
@ -1,4 +1,4 @@
|
||||
import type { FC, ReactNode } from 'react';
|
||||
import type { ComponentProps, FC, ReactNode } from 'react';
|
||||
import {
|
||||
Typography,
|
||||
styled,
|
||||
@ -17,7 +17,7 @@ import { BillingInvoiceFooter } from './BillingInvoiceFooter/BillingInvoiceFoote
|
||||
import { StyledAmountCell, StyledSubgrid } from './BillingInvoice.styles.tsx';
|
||||
import type { DetailedInvoicesSchemaInvoicesItem } from 'openapi';
|
||||
|
||||
const CardLikeAccordion = styled(Accordion)(({ theme }) => ({
|
||||
const StyledAccordion = styled(Accordion)(({ theme }) => ({
|
||||
background: theme.palette.background.paper,
|
||||
borderRadius: theme.shape.borderRadiusLarge,
|
||||
boxShadow: theme.boxShadows.card,
|
||||
@ -94,6 +94,9 @@ const CardActions = styled('div')(({ theme }) => ({
|
||||
padding: theme.spacing(1.5, 2, 2),
|
||||
}));
|
||||
|
||||
type BillingInvoiceProps = DetailedInvoicesSchemaInvoicesItem &
|
||||
Pick<ComponentProps<typeof Accordion>, 'defaultExpanded'>;
|
||||
|
||||
export const BillingInvoice = ({
|
||||
status,
|
||||
invoiceDate,
|
||||
@ -102,8 +105,9 @@ export const BillingInvoice = ({
|
||||
totalAmount,
|
||||
mainLines,
|
||||
usageLines,
|
||||
}: DetailedInvoicesSchemaInvoicesItem) => {
|
||||
const currency = mainLines[0]?.currency || usageLines?.[0]?.currency;
|
||||
defaultExpanded,
|
||||
}: BillingInvoiceProps) => {
|
||||
const currency = mainLines?.[0]?.currency || usageLines?.[0]?.currency;
|
||||
|
||||
const formattedTitle = invoiceDate
|
||||
? new Date(invoiceDate).toLocaleDateString(undefined, {
|
||||
@ -112,8 +116,12 @@ export const BillingInvoice = ({
|
||||
})
|
||||
: '';
|
||||
|
||||
const hasLimitsColumn =
|
||||
mainLines?.some((line) => line.limit) ||
|
||||
usageLines?.some((line) => line.limit);
|
||||
|
||||
return (
|
||||
<CardLikeAccordion defaultExpanded>
|
||||
<StyledAccordion defaultExpanded={Boolean(defaultExpanded)}>
|
||||
<HeaderRoot
|
||||
expandIcon={<ExpandMoreIcon />}
|
||||
id={`billing-invoice-${formattedTitle}-header`}
|
||||
@ -151,7 +159,11 @@ export const BillingInvoice = ({
|
||||
<StyledInvoiceGrid>
|
||||
<StyledSubgrid>
|
||||
<HeaderCell>Description</HeaderCell>
|
||||
<HeaderCell>Included</HeaderCell>
|
||||
{hasLimitsColumn ? (
|
||||
<HeaderCell>Included</HeaderCell>
|
||||
) : (
|
||||
<HeaderCell />
|
||||
)}
|
||||
<HeaderCell>Quantity</HeaderCell>
|
||||
<HeaderCell>
|
||||
<StyledAmountCell>Amount</StyledAmountCell>
|
||||
@ -160,7 +172,10 @@ export const BillingInvoice = ({
|
||||
{mainLines.map((line) => (
|
||||
<TableBody key={line.description}>
|
||||
<StyledTableRow key={line.description}>
|
||||
<BillingInvoiceRow {...line} />
|
||||
<BillingInvoiceRow
|
||||
{...line}
|
||||
showLimits={hasLimitsColumn}
|
||||
/>
|
||||
</StyledTableRow>
|
||||
</TableBody>
|
||||
))}
|
||||
@ -169,7 +184,10 @@ export const BillingInvoice = ({
|
||||
<StyledSectionTitle>Usage</StyledSectionTitle>
|
||||
{usageLines.map((line) => (
|
||||
<StyledTableRow key={line.description}>
|
||||
<BillingInvoiceRow {...line} />
|
||||
<BillingInvoiceRow
|
||||
{...line}
|
||||
showLimits={hasLimitsColumn}
|
||||
/>
|
||||
</StyledTableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
@ -205,6 +223,6 @@ export const BillingInvoice = ({
|
||||
) : null}
|
||||
</CardActions>
|
||||
</AccordionDetails>
|
||||
</CardLikeAccordion>
|
||||
</StyledAccordion>
|
||||
);
|
||||
};
|
||||
|
||||
@ -11,14 +11,6 @@ const StyledCellWithIndicator = styled('div')(({ theme }) => ({
|
||||
gap: theme.spacing(1),
|
||||
}));
|
||||
|
||||
type BillingInvoiceRowProps = {
|
||||
description: string;
|
||||
quantity?: number;
|
||||
amount?: number;
|
||||
quota?: number;
|
||||
usage?: number;
|
||||
};
|
||||
|
||||
const StyledDescriptionCell = styled('div')(({ theme }) => ({
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
@ -30,6 +22,10 @@ const StyledSubText = styled(Typography)(({ theme }) => ({
|
||||
fontSize: theme.typography.body2.fontSize,
|
||||
}));
|
||||
|
||||
type BillingInvoiceRowProps = DetailedInvoicesLineSchema & {
|
||||
showLimits?: boolean;
|
||||
};
|
||||
|
||||
export const BillingInvoiceRow = ({
|
||||
quantity,
|
||||
consumption,
|
||||
@ -39,7 +35,8 @@ export const BillingInvoiceRow = ({
|
||||
totalAmount,
|
||||
startDate,
|
||||
endDate,
|
||||
}: DetailedInvoicesLineSchema) => {
|
||||
showLimits,
|
||||
}: BillingInvoiceRowProps) => {
|
||||
const percentage =
|
||||
limit && limit > 0
|
||||
? Math.min(100, Math.round(((consumption || 0) / limit) * 100))
|
||||
@ -68,11 +65,15 @@ export const BillingInvoiceRow = ({
|
||||
</StyledSubText>
|
||||
) : null}
|
||||
</StyledDescriptionCell>
|
||||
<StyledCellWithIndicator>
|
||||
<ConsumptionIndicator percentage={percentage || 0} />
|
||||
{limit !== undefined ? formatLargeNumbers(limit) : '–'}
|
||||
{percentage !== undefined ? ` (${percentage}%)` : ''}
|
||||
</StyledCellWithIndicator>
|
||||
{showLimits ? (
|
||||
<StyledCellWithIndicator>
|
||||
<ConsumptionIndicator percentage={percentage || 0} />
|
||||
{limit !== undefined ? formatLargeNumbers(limit) : '–'}
|
||||
{percentage !== undefined ? ` (${percentage}%)` : ''}
|
||||
</StyledCellWithIndicator>
|
||||
) : (
|
||||
<StyledCellWithIndicator />
|
||||
)}
|
||||
<div>{quantity ? formatLargeNumbers(quantity) : '–'}</div>
|
||||
<StyledAmountCell>
|
||||
{formatCurrency(totalAmount || 0, currency)}
|
||||
|
||||
@ -14,16 +14,17 @@ export const BillingInvoices: FC = () => {
|
||||
const { invoices, loading } = useDetailedInvoices();
|
||||
|
||||
if (loading) {
|
||||
return null;
|
||||
return <StyledContainer />;
|
||||
}
|
||||
|
||||
return (
|
||||
<StyledContainer>
|
||||
{invoices.length > 0 ? (
|
||||
<>
|
||||
{invoices.map((invoice) => (
|
||||
{invoices.map((invoice, index) => (
|
||||
<BillingInvoice
|
||||
key={invoice.invoiceDate}
|
||||
defaultExpanded={index === 0}
|
||||
{...invoice}
|
||||
/>
|
||||
))}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user