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:
+66
-2
@@ -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`}
|
||||
|
||||
Reference in New Issue
Block a user