1
0
mirror of https://github.com/Unleash/unleash.git synced 2026-01-05 20:06:22 +01:00

feat: align billing page design with figma (#10801)

1. Splitting main row and usage row, as they have so much different
logic already now.
2. Main lines, keep only included, remove quantity
3. Add correct headers for usage lines
4. Add current consumption also as number


Old design
<img width="1502" height="906" alt="image"
src="https://github.com/user-attachments/assets/ab4fdca9-1a04-4381-88a6-9ce643f71d78"
/>

New design
<img width="1502" height="906" alt="Screenshot from 2025-10-15 10-36-16"
src="https://github.com/user-attachments/assets/2607a91d-22de-4f72-9e59-d2212b1f5888"
/>
This commit is contained in:
Jaanus Sellin 2025-10-15 11:28:51 +03:00 committed by GitHub
parent 715119741b
commit bffec9bc4d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 79 additions and 45 deletions

View File

@ -12,7 +12,8 @@ import DownloadOutlinedIcon from '@mui/icons-material/DownloadOutlined';
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
import { formatCurrency } from './formatCurrency.ts';
import { Badge } from 'component/common/Badge/Badge.tsx';
import { BillingInvoiceRow } from './BillingInvoiceRow/BillingInvoiceRow.tsx';
import { BillingInvoiceMainRow } from './BillingInvoiceMainRow/BillingInvoiceMainRow.tsx';
import { BillingInvoiceUsageRow } from './BillingInvoiceUsageRow/BillingInvoiceUsageRow.tsx';
import { BillingInvoiceFooter } from './BillingInvoiceFooter/BillingInvoiceFooter.tsx';
import { StyledAmountCell, StyledSubgrid } from './BillingInvoice.styles.tsx';
import type { DetailedInvoicesSchemaInvoicesItem } from 'openapi';
@ -105,6 +106,7 @@ export const BillingInvoice = ({
totalAmount,
mainLines,
usageLines,
monthText,
defaultExpanded,
}: BillingInvoiceProps) => {
const currency = mainLines?.[0]?.currency || usageLines?.[0]?.currency;
@ -116,9 +118,7 @@ export const BillingInvoice = ({
})
: '';
const hasLimitsColumn =
mainLines?.some((line) => line.limit) ||
usageLines?.some((line) => line.limit);
const hasLimitsColumn = usageLines.some((line) => line.limit);
return (
<StyledAccordion defaultExpanded={Boolean(defaultExpanded)}>
@ -159,11 +159,7 @@ export const BillingInvoice = ({
<StyledInvoiceGrid>
<StyledSubgrid>
<HeaderCell>Description</HeaderCell>
{hasLimitsColumn ? (
<HeaderCell>Included</HeaderCell>
) : (
<HeaderCell />
)}
<HeaderCell />
<HeaderCell>Quantity</HeaderCell>
<HeaderCell>
<StyledAmountCell>Amount</StyledAmountCell>
@ -172,19 +168,27 @@ export const BillingInvoice = ({
{mainLines.map((line) => (
<TableBody key={line.description}>
<StyledTableRow key={line.description}>
<BillingInvoiceRow
{...line}
showLimits={hasLimitsColumn}
/>
<BillingInvoiceMainRow {...line} />
</StyledTableRow>
</TableBody>
))}
{usageLines.length ? (
<TableBody key='usage' title='Usage'>
<StyledSectionTitle>Usage</StyledSectionTitle>
<StyledTableRow>
<HeaderCell>Usage {monthText}</HeaderCell>
{hasLimitsColumn ? (
<HeaderCell>Included</HeaderCell>
) : (
<HeaderCell />
)}
<HeaderCell>Overages</HeaderCell>
<HeaderCell>
<StyledAmountCell>Amount</StyledAmountCell>
</HeaderCell>
</StyledTableRow>
{usageLines.map((line) => (
<StyledTableRow key={line.description}>
<BillingInvoiceRow
<BillingInvoiceUsageRow
{...line}
showLimits={hasLimitsColumn}
/>

View File

@ -1,16 +1,9 @@
import { formatLargeNumbers } from 'component/impact-metrics/metricsFormatters.ts';
import { formatCurrency } from '../formatCurrency.ts';
import { ConsumptionIndicator } from '../ConsumptionIndicator/ConsumptionIndicator.tsx';
import { styled, Typography } from '@mui/material';
import type { DetailedInvoicesLineSchema } from 'openapi';
import { StyledAmountCell } from '../BillingInvoice.styles.tsx';
const StyledCellWithIndicator = styled('div')(({ theme }) => ({
display: 'flex',
alignItems: 'center',
gap: theme.spacing(1),
}));
const StyledDescriptionCell = styled('div')(({ theme }) => ({
display: 'flex',
flexDirection: 'column',
@ -22,26 +15,14 @@ const StyledSubText = styled(Typography)(({ theme }) => ({
fontSize: theme.typography.body2.fontSize,
}));
type BillingInvoiceRowProps = DetailedInvoicesLineSchema & {
showLimits?: boolean;
};
export const BillingInvoiceRow = ({
export const BillingInvoiceMainRow = ({
quantity,
consumption,
limit,
description,
currency,
totalAmount,
startDate,
endDate,
showLimits,
}: BillingInvoiceRowProps) => {
const percentage =
limit && limit > 0
? Math.min(100, Math.round(((consumption || 0) / limit) * 100))
: undefined;
}: DetailedInvoicesLineSchema) => {
const formattedStart = startDate
? new Date(startDate).toLocaleDateString(undefined, {
month: 'short',
@ -65,15 +46,7 @@ export const BillingInvoiceRow = ({
</StyledSubText>
) : null}
</StyledDescriptionCell>
{showLimits ? (
<StyledCellWithIndicator>
<ConsumptionIndicator percentage={percentage || 0} />
{limit !== undefined ? formatLargeNumbers(limit) : ''}
{percentage !== undefined ? ` (${percentage}%)` : ''}
</StyledCellWithIndicator>
) : (
<StyledCellWithIndicator />
)}
<div />
<div>{quantity ? formatLargeNumbers(quantity) : ''}</div>
<StyledAmountCell>
{formatCurrency(totalAmount || 0, currency)}

View File

@ -0,0 +1,57 @@
import { formatLargeNumbers } from 'component/impact-metrics/metricsFormatters.ts';
import { formatCurrency } from '../formatCurrency.ts';
import { ConsumptionIndicator } from '../ConsumptionIndicator/ConsumptionIndicator.tsx';
import { styled } from '@mui/material';
import type { DetailedInvoicesLineSchema } from 'openapi';
import { StyledAmountCell } from '../BillingInvoice.styles.tsx';
const StyledCellWithIndicator = styled('div')(({ theme }) => ({
display: 'flex',
alignItems: 'center',
gap: theme.spacing(1),
}));
type BillingInvoiceRowProps = DetailedInvoicesLineSchema & {
showLimits: boolean;
};
export const BillingInvoiceUsageRow = ({
quantity,
consumption,
limit,
description,
currency,
totalAmount,
showLimits,
}: BillingInvoiceRowProps) => {
const percentage =
limit && limit > 0
? Math.min(100, Math.round(((consumption || 0) / limit) * 100))
: undefined;
return (
<>
<div>{description}</div>
{showLimits ? (
<StyledCellWithIndicator>
<ConsumptionIndicator percentage={percentage || 0} />
<div>
{consumption !== undefined && limit !== undefined
? `${formatLargeNumbers(consumption)}/${formatLargeNumbers(limit)}`
: consumption !== undefined
? formatLargeNumbers(consumption)
: limit !== undefined
? formatLargeNumbers(limit)
: ''}
</div>
</StyledCellWithIndicator>
) : (
<StyledCellWithIndicator />
)}
<div>{quantity ? formatLargeNumbers(quantity) : ''}</div>
<StyledAmountCell>
{formatCurrency(totalAmount || 0, currency)}
</StyledAmountCell>
</>
);
};