feat(admin-panel) - add billing/usage section (#21672)

Add billing/usage section

<img width="740" height="763" alt="Screenshot 2026-06-16 at 14 39 51"
src="https://github.com/user-attachments/assets/42db4fe4-3158-4ab8-aee5-28121ea530cd"
/>


<!-- This is an auto-generated description by cubic. -->
<a
href="https://cubic.dev/pr/twentyhq/twenty/pull/21672?utm_source=github"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img
alt="Review in cubic"
src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a>
<!-- End of auto-generated description by cubic. -->
This commit is contained in:
Etienne
2026-06-16 15:18:43 +02:00
committed by GitHub
parent d5c7b735d2
commit 16a92f52a4
6 changed files with 176 additions and 5 deletions
@@ -1,6 +1,7 @@
import { useQuery } from '@apollo/client/react';
import { styled } from '@linaria/react';
import { useLingui } from '@lingui/react/macro';
import { useContext } from 'react';
import { isDefined } from 'twenty-shared/utils';
import { Tag } from 'twenty-ui-deprecated/components';
import {
@@ -8,6 +9,7 @@ import {
IconBox,
IconCalendarEvent,
IconCalendarRepeat,
IconChartBar,
IconCircleX,
IconCoins,
IconCreditCard,
@@ -19,7 +21,10 @@ import {
} from 'twenty-ui-deprecated/display';
import { Section } from 'twenty-ui-deprecated/layout';
import { type ThemeColor } from 'twenty-ui-deprecated/theme';
import { themeCssVariables } from 'twenty-ui-deprecated/theme-constants';
import {
ThemeContext,
themeCssVariables,
} from 'twenty-ui-deprecated/theme-constants';
import { useApolloAdminClient } from '@/settings/admin-panel/apollo/hooks/useApolloAdminClient';
import { GET_WORKSPACE_BILLING_ADMIN_PANEL } from '@/settings/admin-panel/graphql/queries/getWorkspaceBillingAdminPanel';
@@ -73,6 +78,10 @@ const StyledItemValue = styled.div`
gap: ${themeCssVariables.spacing[2]};
`;
const StyledProgressBarContainer = styled.div`
margin-bottom: ${themeCssVariables.spacing[3]};
`;
const STATUS_COLORS: Record<SubscriptionStatus, ThemeColor> = {
[SubscriptionStatus.Active]: 'green',
[SubscriptionStatus.Trialing]: 'blue',
@@ -137,6 +146,7 @@ export const SettingsAdminWorkspaceBillingContent = ({
}: SettingsAdminWorkspaceBillingContentProps) => {
const { t } = useLingui();
const { formatNumber } = useNumberFormat();
const { theme } = useContext(ThemeContext);
const apolloAdminClient = useApolloAdminClient();
const { data, loading } = useQuery<WorkspaceBillingAdminPanelQuery>(
@@ -171,7 +181,10 @@ export const SettingsAdminWorkspaceBillingContent = ({
);
}
const { stripeCustomerId, creditBalance, subscription } = billing;
const { stripeCustomerId, creditBalance, subscription, usage } = billing;
const formatCredits = (credits: number): string =>
formatNumber(credits, { abbreviate: true, decimals: 2 });
const customerItems = [
{
@@ -207,6 +220,39 @@ export const SettingsAdminWorkspaceBillingContent = ({
: null;
const isTrialing = subscription?.status === SubscriptionStatus.Trialing;
const usageItems = isDefined(usage)
? [
{
Icon: IconChartBar,
label: t`Credits used`,
value: `${formatCredits(usage.usedCredits)} / ${formatCredits(usage.totalGrantedCredits)}`,
},
...(!isTrialing
? [
{
Icon: IconCoins,
label: t`Base credits`,
value: formatCredits(usage.grantedCredits),
},
]
: []),
...(usage.rolloverCredits > 0
? [
{
Icon: IconCoins,
label: t`Rollover credits`,
value: formatCredits(usage.rolloverCredits),
},
]
: []),
{
Icon: IconCalendarRepeat,
label: t`Usage period`,
value: formatPeriod(usage.periodStart, usage.periodEnd),
},
]
: [];
const formatItemValue = (
item: NonNullable<typeof subscription>['items'][number],
): string => {
@@ -349,6 +395,24 @@ export const SettingsAdminWorkspaceBillingContent = ({
/>
</Section>
<Section>
<H2Title
title={t`Usage`}
description={
isDefined(usage)
? t`Credit consumption for the current period`
: t`No usage data is available for this workspace.`
}
/>
{isDefined(usage) && (
<SettingsTableCard
rounded
items={usageItems}
gridAutoColumns="3fr 8fr"
/>
)}
</Section>
<Section>
<H2Title
title={t`Subscription`}