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:
parent
715119741b
commit
bffec9bc4d
@ -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}
|
||||
/>
|
||||
|
||||
@ -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)}
|
||||
@ -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>
|
||||
</>
|
||||
);
|
||||
};
|
||||
Loading…
Reference in New Issue
Block a user