mirror of
https://github.com/Unleash/unleash.git
synced 2025-10-27 11:02:16 +01:00
feat: add new dates and plan price (#10774)
<img width="2159" height="1617" alt="image" src="https://github.com/user-attachments/assets/478ea289-dc0f-439e-92e4-a22fa44a0650" />
This commit is contained in:
parent
8879cc4b46
commit
0d252558c4
@ -5,6 +5,8 @@ import { useInstanceStatus } from 'hooks/api/getters/useInstanceStatus/useInstan
|
||||
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
|
||||
import { InstanceState } from 'interfaces/instance';
|
||||
import { formatApiPath } from 'utils/formatPath';
|
||||
import { useDetailedInvoices } from 'hooks/api/getters/useDetailedInvoices/useDetailedInvoices';
|
||||
import { formatCurrency } from '../BillingInvoices/BillingInvoice/formatCurrency.js';
|
||||
const PORTAL_URL = formatApiPath('api/admin/invoices');
|
||||
|
||||
type BillingInfoProps = {};
|
||||
@ -63,6 +65,7 @@ export const BillingInfo: FC<BillingInfoProps> = () => {
|
||||
const {
|
||||
uiConfig: { billing },
|
||||
} = useUiConfig();
|
||||
const { planPrice, planCurrency } = useDetailedInvoices();
|
||||
|
||||
if (!instanceStatus) {
|
||||
return (
|
||||
@ -105,8 +108,13 @@ export const BillingInfo: FC<BillingInfoProps> = () => {
|
||||
</StyledRow>
|
||||
<StyledRow>
|
||||
<StyledItemTitle>Plan price</StyledItemTitle>{' '}
|
||||
{/* FIXME: where to take data from? */}
|
||||
<StyledItemValue>$450 / month</StyledItemValue>
|
||||
<StyledItemValue>
|
||||
{planPrice !== undefined
|
||||
? `${formatCurrency(planPrice, planCurrency)} ${
|
||||
isPAYG ? 'per seat' : '/ month'
|
||||
}`
|
||||
: '-'}
|
||||
</StyledItemValue>
|
||||
</StyledRow>
|
||||
<StyledDivider />
|
||||
<StyledButton
|
||||
|
||||
@ -5,7 +5,10 @@ import {
|
||||
Accordion,
|
||||
AccordionSummary,
|
||||
AccordionDetails,
|
||||
Button,
|
||||
} from '@mui/material';
|
||||
import ReceiptLongOutlinedIcon from '@mui/icons-material/ReceiptLongOutlined';
|
||||
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';
|
||||
@ -84,6 +87,13 @@ const StyledTableRow = styled('div')(({ theme }) => ({
|
||||
padding: theme.spacing(1, 0),
|
||||
}));
|
||||
|
||||
const CardActions = styled('div')(({ theme }) => ({
|
||||
display: 'flex',
|
||||
justifyContent: 'flex-end',
|
||||
gap: theme.spacing(1),
|
||||
padding: theme.spacing(1.5, 2, 2),
|
||||
}));
|
||||
|
||||
export const BillingInvoice = ({
|
||||
status,
|
||||
invoiceDate,
|
||||
@ -93,20 +103,20 @@ export const BillingInvoice = ({
|
||||
mainLines,
|
||||
usageLines,
|
||||
}: DetailedInvoicesSchemaInvoicesItem) => {
|
||||
const title = invoiceDate
|
||||
const currency = mainLines[0]?.currency || usageLines?.[0]?.currency;
|
||||
|
||||
const formattedTitle = invoiceDate
|
||||
? new Date(invoiceDate).toLocaleDateString(undefined, {
|
||||
month: 'long',
|
||||
day: 'numeric',
|
||||
})
|
||||
: '';
|
||||
|
||||
const currency = mainLines[0]?.currency || usageLines?.[0]?.currency;
|
||||
|
||||
return (
|
||||
<CardLikeAccordion defaultExpanded>
|
||||
<HeaderRoot
|
||||
expandIcon={<ExpandMoreIcon />}
|
||||
id={`billing-invoice-${title}-header`}
|
||||
id={`billing-invoice-${formattedTitle}-header`}
|
||||
>
|
||||
<HeaderLeft>
|
||||
<Typography
|
||||
@ -114,7 +124,7 @@ export const BillingInvoice = ({
|
||||
component='h3'
|
||||
sx={{ fontWeight: 700 }}
|
||||
>
|
||||
{title}
|
||||
{formattedTitle}
|
||||
</Typography>
|
||||
</HeaderLeft>
|
||||
<HeaderRight>
|
||||
@ -170,6 +180,30 @@ export const BillingInvoice = ({
|
||||
currency={currency}
|
||||
/>
|
||||
</StyledInvoiceGrid>
|
||||
<CardActions>
|
||||
{invoiceURL ? (
|
||||
<Button
|
||||
variant='outlined'
|
||||
href={invoiceURL}
|
||||
target='_blank'
|
||||
rel='noreferrer'
|
||||
startIcon={<ReceiptLongOutlinedIcon />}
|
||||
>
|
||||
View invoice
|
||||
</Button>
|
||||
) : null}
|
||||
{invoicePDF ? (
|
||||
<Button
|
||||
variant='outlined'
|
||||
href={invoicePDF}
|
||||
target='_blank'
|
||||
rel='noreferrer'
|
||||
startIcon={<DownloadOutlinedIcon />}
|
||||
>
|
||||
Download PDF
|
||||
</Button>
|
||||
) : null}
|
||||
</CardActions>
|
||||
</AccordionDetails>
|
||||
</CardLikeAccordion>
|
||||
);
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
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 { styled, Typography } from '@mui/material';
|
||||
import type { DetailedInvoicesLineSchema } from 'openapi';
|
||||
import { StyledAmountCell } from '../BillingInvoice.styles.tsx';
|
||||
|
||||
@ -19,6 +19,17 @@ type BillingInvoiceRowProps = {
|
||||
usage?: number;
|
||||
};
|
||||
|
||||
const StyledDescriptionCell = styled('div')(({ theme }) => ({
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
gap: theme.spacing(0.5),
|
||||
}));
|
||||
|
||||
const StyledSubText = styled(Typography)(({ theme }) => ({
|
||||
color: theme.palette.text.secondary,
|
||||
fontSize: theme.typography.body2.fontSize,
|
||||
}));
|
||||
|
||||
export const BillingInvoiceRow = ({
|
||||
quantity,
|
||||
consumption,
|
||||
@ -26,15 +37,37 @@ export const BillingInvoiceRow = ({
|
||||
description,
|
||||
currency,
|
||||
totalAmount,
|
||||
startDate,
|
||||
endDate,
|
||||
}: DetailedInvoicesLineSchema) => {
|
||||
const percentage =
|
||||
limit && limit > 0
|
||||
? Math.min(100, Math.round(((consumption || 0) / limit) * 100))
|
||||
: undefined;
|
||||
|
||||
const formattedStart = startDate
|
||||
? new Date(startDate).toLocaleDateString(undefined, {
|
||||
month: 'short',
|
||||
day: 'numeric',
|
||||
})
|
||||
: undefined;
|
||||
const formattedEnd = endDate
|
||||
? new Date(endDate).toLocaleDateString(undefined, {
|
||||
month: 'short',
|
||||
day: 'numeric',
|
||||
})
|
||||
: undefined;
|
||||
|
||||
return (
|
||||
<>
|
||||
<div>{description}</div>
|
||||
<StyledDescriptionCell>
|
||||
<div>{description}</div>
|
||||
{formattedStart || formattedEnd ? (
|
||||
<StyledSubText>
|
||||
{formattedStart} - {formattedEnd}
|
||||
</StyledSubText>
|
||||
) : null}
|
||||
</StyledDescriptionCell>
|
||||
<StyledCellWithIndicator>
|
||||
<ConsumptionIndicator percentage={percentage || 0} />
|
||||
{limit !== undefined ? formatLargeNumbers(limit) : '–'}
|
||||
|
||||
@ -20,6 +20,8 @@ export const useDetailedInvoices = (options: SWRConfiguration = {}) => {
|
||||
);
|
||||
|
||||
const invoices = useMemo(() => data?.invoices ?? [], [data]);
|
||||
const planPrice = data?.planPrice;
|
||||
const planCurrency = data?.planCurrency;
|
||||
|
||||
return { invoices, error, loading: isLoading };
|
||||
return { invoices, planPrice, planCurrency, error, loading: isLoading };
|
||||
};
|
||||
|
||||
@ -11,4 +11,8 @@ import type { DetailedInvoicesSchemaInvoicesItem } from './detailedInvoicesSchem
|
||||
export interface DetailedInvoicesSchema {
|
||||
/** List of invoices with their line items */
|
||||
invoices: DetailedInvoicesSchemaInvoicesItem[];
|
||||
/** The currency code for the plan price */
|
||||
planCurrency?: string;
|
||||
/** The plan price in minor currency units */
|
||||
planPrice?: number;
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user