refactor: add usage limit and update card style
This commit is contained in:
parent
71f75c27dd
commit
34f9fe6957
@ -10,6 +10,7 @@ import { CommonHeader } from '@/components/CommonHeader';
|
||||
import { Card, CardContent, CardHeader } from '@/components/ui/card';
|
||||
import dayjs from 'dayjs';
|
||||
import { formatNumber } from '@/utils/common';
|
||||
import { UsageCard } from '@/components/UsageCard';
|
||||
|
||||
export const Route = createFileRoute('/settings/usage')({
|
||||
beforeLoad: routeAuthBeforeLoad,
|
||||
@ -34,6 +35,10 @@ function PageComponent() {
|
||||
endAt: endDate.valueOf(),
|
||||
});
|
||||
|
||||
const { data: limit } = trpc.billing.limit.useQuery({
|
||||
workspaceId,
|
||||
});
|
||||
|
||||
return (
|
||||
<CommonWrapper header={<CommonHeader title={t('Usage')} />}>
|
||||
<ScrollArea className="h-full overflow-hidden p-4">
|
||||
@ -49,85 +54,61 @@ function PageComponent() {
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="grid grid-cols-2 gap-2 sm:grid-cols-3">
|
||||
<Card className="flex-1">
|
||||
<CardHeader className="text-muted-foreground">
|
||||
{t('Website Count')}
|
||||
</CardHeader>
|
||||
<CardContent>{serviceCountData?.website ?? 0}</CardContent>
|
||||
</Card>
|
||||
<UsageCard
|
||||
title={t('Website Count')}
|
||||
current={serviceCountData?.website ?? 0}
|
||||
limit={limit?.maxWebsiteCount}
|
||||
/>
|
||||
|
||||
<Card className="flex-1">
|
||||
<CardHeader className="text-muted-foreground">
|
||||
{t('Monitor Count')}
|
||||
</CardHeader>
|
||||
<CardContent>{serviceCountData?.monitor ?? 0}</CardContent>
|
||||
</Card>
|
||||
<UsageCard
|
||||
title={t('Monitor Count')}
|
||||
current={serviceCountData?.monitor ?? 0}
|
||||
/>
|
||||
|
||||
<Card className="flex-1">
|
||||
<CardHeader className="text-muted-foreground">
|
||||
{t('Survey Count')}
|
||||
</CardHeader>
|
||||
<CardContent>{serviceCountData?.survey ?? 0}</CardContent>
|
||||
</Card>
|
||||
<UsageCard
|
||||
title={t('Survey Count')}
|
||||
current={serviceCountData?.survey ?? 0}
|
||||
/>
|
||||
|
||||
<Card className="flex-1">
|
||||
<CardHeader className="text-muted-foreground">
|
||||
{t('Page Count')}
|
||||
</CardHeader>
|
||||
<CardContent>{serviceCountData?.page ?? 0}</CardContent>
|
||||
</Card>
|
||||
<UsageCard
|
||||
title={t('Page Count')}
|
||||
current={serviceCountData?.page ?? 0}
|
||||
/>
|
||||
|
||||
<Card className="flex-1">
|
||||
<CardHeader className="text-muted-foreground">
|
||||
{t('Feed Channel Count')}
|
||||
</CardHeader>
|
||||
<CardContent>{serviceCountData?.feed ?? 0}</CardContent>
|
||||
</Card>
|
||||
<UsageCard
|
||||
title={t('Feed Channel Count')}
|
||||
current={serviceCountData?.feed ?? 0}
|
||||
limit={limit?.maxFeedChannelCount}
|
||||
/>
|
||||
|
||||
<Card className="flex-1">
|
||||
<CardHeader className="text-muted-foreground">
|
||||
{t('Website Accepted Count')}
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
{formatNumber(billingUsageData?.websiteAcceptedCount ?? 0)}
|
||||
</CardContent>
|
||||
</Card>
|
||||
<UsageCard
|
||||
title={t('Website Accepted Count')}
|
||||
current={billingUsageData?.websiteAcceptedCount ?? 0}
|
||||
/>
|
||||
|
||||
<Card className="flex-1">
|
||||
<CardHeader className="text-muted-foreground">
|
||||
{t('Website Event Count')}
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
{formatNumber(billingUsageData?.websiteEventCount ?? 0)}
|
||||
</CardContent>
|
||||
</Card>
|
||||
<UsageCard
|
||||
title={t('Website Event Count')}
|
||||
current={billingUsageData?.websiteEventCount ?? 0}
|
||||
limit={limit?.maxWebsiteEventCount}
|
||||
/>
|
||||
|
||||
<Card className="flex-1">
|
||||
<CardHeader className="text-muted-foreground">
|
||||
{t('Monitor Execution Count')}
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
{formatNumber(billingUsageData?.monitorExecutionCount ?? 0)}
|
||||
</CardContent>
|
||||
</Card>
|
||||
<UsageCard
|
||||
title={t('Monitor Execution Count')}
|
||||
current={billingUsageData?.monitorExecutionCount ?? 0}
|
||||
limit={limit?.maxMonitorExecutionCount}
|
||||
/>
|
||||
|
||||
<Card className="flex-1">
|
||||
<CardHeader className="text-muted-foreground">
|
||||
{t('Survey Count')}
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
{formatNumber(billingUsageData?.surveyCount ?? 0)}
|
||||
</CardContent>
|
||||
</Card>
|
||||
<UsageCard
|
||||
title={t('Survey Count')}
|
||||
current={billingUsageData?.surveyCount ?? 0}
|
||||
limit={limit?.maxSurveyCount}
|
||||
/>
|
||||
|
||||
<Card className="flex-1">
|
||||
<CardHeader className="text-muted-foreground">
|
||||
{t('Feed Event Count')}
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
{formatNumber(billingUsageData?.feedEventCount ?? 0)}
|
||||
</CardContent>
|
||||
</Card>
|
||||
<UsageCard
|
||||
title={t('Feed Event Count')}
|
||||
current={billingUsageData?.feedEventCount ?? 0}
|
||||
limit={limit?.maxFeedEventCount}
|
||||
/>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
@ -1,13 +1,16 @@
|
||||
import { WorkspaceSubscriptionTier } from '@prisma/client';
|
||||
import { z } from 'zod';
|
||||
|
||||
interface TierLimit {
|
||||
maxWebsiteCount: number;
|
||||
maxWebsiteEventCount: number;
|
||||
maxMonitorExecutionCount: number;
|
||||
maxSurveyCount: number;
|
||||
maxFeedChannelCount: number;
|
||||
maxFeedEventCount: number;
|
||||
}
|
||||
export const TierLimitSchema = z.object({
|
||||
maxWebsiteCount: z.number(),
|
||||
maxWebsiteEventCount: z.number(),
|
||||
maxMonitorExecutionCount: z.number(),
|
||||
maxSurveyCount: z.number(),
|
||||
maxFeedChannelCount: z.number(),
|
||||
maxFeedEventCount: z.number(),
|
||||
});
|
||||
|
||||
type TierLimit = z.infer<typeof TierLimitSchema>;
|
||||
|
||||
/**
|
||||
* Limit, Every month
|
||||
|
@ -16,7 +16,11 @@ import {
|
||||
SubscriptionTierType,
|
||||
} from '../../model/billing/index.js';
|
||||
import { LemonSqueezySubscriptionModelSchema } from '../../prisma/zod/lemonsqueezysubscription.js';
|
||||
import { getWorkspaceUsage } from '../../model/billing/workspace.js';
|
||||
import {
|
||||
getWorkspaceSubscription,
|
||||
getWorkspaceUsage,
|
||||
} from '../../model/billing/workspace.js';
|
||||
import { getTierLimit, TierLimitSchema } from '../../model/billing/limit.js';
|
||||
|
||||
export const billingRouter = router({
|
||||
usage: workspaceProcedure
|
||||
@ -47,6 +51,21 @@ export const billingRouter = router({
|
||||
|
||||
return getWorkspaceUsage(workspaceId, startAt, endAt);
|
||||
}),
|
||||
limit: workspaceProcedure
|
||||
.meta(
|
||||
buildBillingOpenapi({
|
||||
method: 'GET',
|
||||
path: '/limit',
|
||||
description: 'get workspace subscription limit',
|
||||
})
|
||||
)
|
||||
.output(TierLimitSchema)
|
||||
.query(async ({ input }) => {
|
||||
const { workspaceId } = input;
|
||||
const tier = await getWorkspaceSubscription(workspaceId);
|
||||
|
||||
return getTierLimit(tier);
|
||||
}),
|
||||
currentSubscription: workspaceProcedure
|
||||
.meta(
|
||||
buildBillingOpenapi({
|
||||
|
Loading…
Reference in New Issue
Block a user