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 {
|
import {
|
||||||
Typography,
|
Typography,
|
||||||
styled,
|
styled,
|
||||||
@ -17,7 +17,7 @@ import { BillingInvoiceFooter } from './BillingInvoiceFooter/BillingInvoiceFoote
|
|||||||
import { StyledAmountCell, StyledSubgrid } from './BillingInvoice.styles.tsx';
|
import { StyledAmountCell, StyledSubgrid } from './BillingInvoice.styles.tsx';
|
||||||
import type { DetailedInvoicesSchemaInvoicesItem } from 'openapi';
|
import type { DetailedInvoicesSchemaInvoicesItem } from 'openapi';
|
||||||
|
|
||||||
const CardLikeAccordion = styled(Accordion)(({ theme }) => ({
|
const StyledAccordion = styled(Accordion)(({ theme }) => ({
|
||||||
background: theme.palette.background.paper,
|
background: theme.palette.background.paper,
|
||||||
borderRadius: theme.shape.borderRadiusLarge,
|
borderRadius: theme.shape.borderRadiusLarge,
|
||||||
boxShadow: theme.boxShadows.card,
|
boxShadow: theme.boxShadows.card,
|
||||||
@ -94,6 +94,9 @@ const CardActions = styled('div')(({ theme }) => ({
|
|||||||
padding: theme.spacing(1.5, 2, 2),
|
padding: theme.spacing(1.5, 2, 2),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
type BillingInvoiceProps = DetailedInvoicesSchemaInvoicesItem &
|
||||||
|
Pick<ComponentProps<typeof Accordion>, 'defaultExpanded'>;
|
||||||
|
|
||||||
export const BillingInvoice = ({
|
export const BillingInvoice = ({
|
||||||
status,
|
status,
|
||||||
invoiceDate,
|
invoiceDate,
|
||||||
@ -102,8 +105,9 @@ export const BillingInvoice = ({
|
|||||||
totalAmount,
|
totalAmount,
|
||||||
mainLines,
|
mainLines,
|
||||||
usageLines,
|
usageLines,
|
||||||
}: DetailedInvoicesSchemaInvoicesItem) => {
|
defaultExpanded,
|
||||||
const currency = mainLines[0]?.currency || usageLines?.[0]?.currency;
|
}: BillingInvoiceProps) => {
|
||||||
|
const currency = mainLines?.[0]?.currency || usageLines?.[0]?.currency;
|
||||||
|
|
||||||
const formattedTitle = invoiceDate
|
const formattedTitle = invoiceDate
|
||||||
? new Date(invoiceDate).toLocaleDateString(undefined, {
|
? 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 (
|
return (
|
||||||
<CardLikeAccordion defaultExpanded>
|
<StyledAccordion defaultExpanded={Boolean(defaultExpanded)}>
|
||||||
<HeaderRoot
|
<HeaderRoot
|
||||||
expandIcon={<ExpandMoreIcon />}
|
expandIcon={<ExpandMoreIcon />}
|
||||||
id={`billing-invoice-${formattedTitle}-header`}
|
id={`billing-invoice-${formattedTitle}-header`}
|
||||||
@ -151,7 +159,11 @@ export const BillingInvoice = ({
|
|||||||
<StyledInvoiceGrid>
|
<StyledInvoiceGrid>
|
||||||
<StyledSubgrid>
|
<StyledSubgrid>
|
||||||
<HeaderCell>Description</HeaderCell>
|
<HeaderCell>Description</HeaderCell>
|
||||||
|
{hasLimitsColumn ? (
|
||||||
<HeaderCell>Included</HeaderCell>
|
<HeaderCell>Included</HeaderCell>
|
||||||
|
) : (
|
||||||
|
<HeaderCell />
|
||||||
|
)}
|
||||||
<HeaderCell>Quantity</HeaderCell>
|
<HeaderCell>Quantity</HeaderCell>
|
||||||
<HeaderCell>
|
<HeaderCell>
|
||||||
<StyledAmountCell>Amount</StyledAmountCell>
|
<StyledAmountCell>Amount</StyledAmountCell>
|
||||||
@ -160,7 +172,10 @@ export const BillingInvoice = ({
|
|||||||
{mainLines.map((line) => (
|
{mainLines.map((line) => (
|
||||||
<TableBody key={line.description}>
|
<TableBody key={line.description}>
|
||||||
<StyledTableRow key={line.description}>
|
<StyledTableRow key={line.description}>
|
||||||
<BillingInvoiceRow {...line} />
|
<BillingInvoiceRow
|
||||||
|
{...line}
|
||||||
|
showLimits={hasLimitsColumn}
|
||||||
|
/>
|
||||||
</StyledTableRow>
|
</StyledTableRow>
|
||||||
</TableBody>
|
</TableBody>
|
||||||
))}
|
))}
|
||||||
@ -169,7 +184,10 @@ export const BillingInvoice = ({
|
|||||||
<StyledSectionTitle>Usage</StyledSectionTitle>
|
<StyledSectionTitle>Usage</StyledSectionTitle>
|
||||||
{usageLines.map((line) => (
|
{usageLines.map((line) => (
|
||||||
<StyledTableRow key={line.description}>
|
<StyledTableRow key={line.description}>
|
||||||
<BillingInvoiceRow {...line} />
|
<BillingInvoiceRow
|
||||||
|
{...line}
|
||||||
|
showLimits={hasLimitsColumn}
|
||||||
|
/>
|
||||||
</StyledTableRow>
|
</StyledTableRow>
|
||||||
))}
|
))}
|
||||||
</TableBody>
|
</TableBody>
|
||||||
@ -205,6 +223,6 @@ export const BillingInvoice = ({
|
|||||||
) : null}
|
) : null}
|
||||||
</CardActions>
|
</CardActions>
|
||||||
</AccordionDetails>
|
</AccordionDetails>
|
||||||
</CardLikeAccordion>
|
</StyledAccordion>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -11,14 +11,6 @@ const StyledCellWithIndicator = styled('div')(({ theme }) => ({
|
|||||||
gap: theme.spacing(1),
|
gap: theme.spacing(1),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
type BillingInvoiceRowProps = {
|
|
||||||
description: string;
|
|
||||||
quantity?: number;
|
|
||||||
amount?: number;
|
|
||||||
quota?: number;
|
|
||||||
usage?: number;
|
|
||||||
};
|
|
||||||
|
|
||||||
const StyledDescriptionCell = styled('div')(({ theme }) => ({
|
const StyledDescriptionCell = styled('div')(({ theme }) => ({
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
flexDirection: 'column',
|
flexDirection: 'column',
|
||||||
@ -30,6 +22,10 @@ const StyledSubText = styled(Typography)(({ theme }) => ({
|
|||||||
fontSize: theme.typography.body2.fontSize,
|
fontSize: theme.typography.body2.fontSize,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
type BillingInvoiceRowProps = DetailedInvoicesLineSchema & {
|
||||||
|
showLimits?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
export const BillingInvoiceRow = ({
|
export const BillingInvoiceRow = ({
|
||||||
quantity,
|
quantity,
|
||||||
consumption,
|
consumption,
|
||||||
@ -39,7 +35,8 @@ export const BillingInvoiceRow = ({
|
|||||||
totalAmount,
|
totalAmount,
|
||||||
startDate,
|
startDate,
|
||||||
endDate,
|
endDate,
|
||||||
}: DetailedInvoicesLineSchema) => {
|
showLimits,
|
||||||
|
}: BillingInvoiceRowProps) => {
|
||||||
const percentage =
|
const percentage =
|
||||||
limit && limit > 0
|
limit && limit > 0
|
||||||
? Math.min(100, Math.round(((consumption || 0) / limit) * 100))
|
? Math.min(100, Math.round(((consumption || 0) / limit) * 100))
|
||||||
@ -68,11 +65,15 @@ export const BillingInvoiceRow = ({
|
|||||||
</StyledSubText>
|
</StyledSubText>
|
||||||
) : null}
|
) : null}
|
||||||
</StyledDescriptionCell>
|
</StyledDescriptionCell>
|
||||||
|
{showLimits ? (
|
||||||
<StyledCellWithIndicator>
|
<StyledCellWithIndicator>
|
||||||
<ConsumptionIndicator percentage={percentage || 0} />
|
<ConsumptionIndicator percentage={percentage || 0} />
|
||||||
{limit !== undefined ? formatLargeNumbers(limit) : '–'}
|
{limit !== undefined ? formatLargeNumbers(limit) : '–'}
|
||||||
{percentage !== undefined ? ` (${percentage}%)` : ''}
|
{percentage !== undefined ? ` (${percentage}%)` : ''}
|
||||||
</StyledCellWithIndicator>
|
</StyledCellWithIndicator>
|
||||||
|
) : (
|
||||||
|
<StyledCellWithIndicator />
|
||||||
|
)}
|
||||||
<div>{quantity ? formatLargeNumbers(quantity) : '–'}</div>
|
<div>{quantity ? formatLargeNumbers(quantity) : '–'}</div>
|
||||||
<StyledAmountCell>
|
<StyledAmountCell>
|
||||||
{formatCurrency(totalAmount || 0, currency)}
|
{formatCurrency(totalAmount || 0, currency)}
|
||||||
|
|||||||
@ -14,16 +14,17 @@ export const BillingInvoices: FC = () => {
|
|||||||
const { invoices, loading } = useDetailedInvoices();
|
const { invoices, loading } = useDetailedInvoices();
|
||||||
|
|
||||||
if (loading) {
|
if (loading) {
|
||||||
return null;
|
return <StyledContainer />;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledContainer>
|
<StyledContainer>
|
||||||
{invoices.length > 0 ? (
|
{invoices.length > 0 ? (
|
||||||
<>
|
<>
|
||||||
{invoices.map((invoice) => (
|
{invoices.map((invoice, index) => (
|
||||||
<BillingInvoice
|
<BillingInvoice
|
||||||
key={invoice.invoiceDate}
|
key={invoice.invoiceDate}
|
||||||
|
defaultExpanded={index === 0}
|
||||||
{...invoice}
|
{...invoice}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user