From c4f536eb05d5c169e00d53bca340e1650aed7978 Mon Sep 17 00:00:00 2001 From: web Date: Wed, 3 Sep 2025 07:17:21 -0700 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20feat:=20Add=20batch=20delete=20func?= =?UTF-8?q?tionality=20and=20enhance=20chart=20tooltips=20in=20statistics?= =?UTF-8?q?=20cards?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/admin/app/dashboard/servers/page.tsx | 17 +++ .../dashboard/revenue-statistics-card.tsx | 103 ++++++++++++++++-- .../dashboard/user-statistics-card.tsx | 29 ++++- 3 files changed, 134 insertions(+), 15 deletions(-) diff --git a/apps/admin/app/dashboard/servers/page.tsx b/apps/admin/app/dashboard/servers/page.tsx index 83e4c04..1756dbe 100644 --- a/apps/admin/app/dashboard/servers/page.tsx +++ b/apps/admin/app/dashboard/servers/page.tsx @@ -317,6 +317,23 @@ export default function ServersPage() { {t('copy')} , ], + batchRender(rows) { + return [ + {t('delete')}} + title={t('confirmDeleteTitle')} + description={t('confirmDeleteDesc')} + onConfirm={async () => { + await Promise.all(rows.map((r) => deleteServer({ id: r.id }))); + toast.success(t('deleted')); + ref.current?.refresh(); + }} + cancelText={t('cancel')} + confirmText={t('confirm')} + />, + ]; + }, }} onSort={async (source, target, items) => { const sourceIndex = items.findIndex((item) => String(item.id) === source); diff --git a/apps/admin/components/dashboard/revenue-statistics-card.tsx b/apps/admin/components/dashboard/revenue-statistics-card.tsx index 740cdbc..511ece7 100644 --- a/apps/admin/components/dashboard/revenue-statistics-card.tsx +++ b/apps/admin/components/dashboard/revenue-statistics-card.tsx @@ -36,6 +36,7 @@ import { Empty } from '../empty'; export function RevenueStatisticsCard() { const t = useTranslations('index'); + const locale = useLocale(); const IncomeStatisticsConfig = { new_purchase: { @@ -46,9 +47,12 @@ export function RevenueStatisticsCard() { label: t('repurchase'), color: 'hsl(var(--chart-2))', }, + total: { + label: t('totalIncome'), + color: 'hsl(var(--chart-3))', + }, }; - const locale = useLocale(); const { data: RevenueStatistics } = useQuery({ queryKey: ['queryRevenueStatistics'], queryFn: async () => { @@ -175,6 +179,10 @@ export function RevenueStatisticsCard() { date: item.date, new_purchase: unitConversion('centsToDollars', item.new_order_amount), repurchase: unitConversion('centsToDollars', item.renewal_order_amount), + total: unitConversion( + 'centsToDollars', + item.new_order_amount + item.renewal_order_amount, + ), })) || [] } > @@ -182,18 +190,60 @@ export function RevenueStatisticsCard() { { - return new Date(value).toLocaleDateString(locale, { + const [year, month, day] = value.split('-'); + return new Date(year, month - 1, day).toLocaleDateString(locale, { month: 'short', day: 'numeric', }); }} /> - - - } /> + + + ( + <> +
+ {IncomeStatisticsConfig[name as keyof typeof IncomeStatisticsConfig] + ?.label || name} +
+ {value} +
+ {index === 1 && ( +
+ {t('totalIncome')} +
+ {item.payload.total} +
+
+ )} + + )} + /> + } + cursor={false} + /> } /> @@ -247,6 +297,10 @@ export function RevenueStatisticsCard() { date: item.date, new_purchase: unitConversion('centsToDollars', item.new_order_amount), repurchase: unitConversion('centsToDollars', item.renewal_order_amount), + total: unitConversion( + 'centsToDollars', + item.new_order_amount + item.renewal_order_amount, + ), })) || [] } margin={{ @@ -259,14 +313,45 @@ export function RevenueStatisticsCard() { dataKey='date' tickLine={false} axisLine={false} - tickMargin={8} tickFormatter={(value) => { - return new Date(value).toLocaleDateString(locale, { + const [year, month] = value.split('-'); + return new Date(year, month - 1).toLocaleDateString(locale, { month: 'short', }); }} /> - } /> + ( + <> +
+ {IncomeStatisticsConfig[name as keyof typeof IncomeStatisticsConfig] + ?.label || name} +
+ {value} +
+ {index === 1 && ( +
+ {t('totalIncome')} +
+ {item.payload.total} +
+
+ )} + + )} + /> + } + /> { + // value format: "YYYY-MM-DD" return new Date(value).toLocaleDateString(locale, { month: 'short', day: 'numeric', }); }} /> - - - + + + } /> } /> @@ -267,9 +283,10 @@ export function UserStatisticsCard() { dataKey='date' tickLine={false} axisLine={false} - tickMargin={8} tickFormatter={(value) => { - return new Date(value).toLocaleDateString(locale, { + // value format: "YYYY-MM" + const [year, month] = value.split('-'); + return new Date(year, month - 1).toLocaleDateString(locale, { month: 'short', }); }}