diff --git a/src/api/adminSalesStats.ts b/src/api/adminSalesStats.ts
index 7b5f261..8faabc8 100644
--- a/src/api/adminSalesStats.ts
+++ b/src/api/adminSalesStats.ts
@@ -19,6 +19,8 @@ export interface SalesSummary {
trial_to_paid_conversion: number;
renewals_count: number;
addon_revenue_kopeks: number;
+ refunds_count: number;
+ refunds_kopeks: number;
}
// ============ Trials ============
diff --git a/src/components/stats/StatCard.tsx b/src/components/stats/StatCard.tsx
index 79f2600..92189ae 100644
--- a/src/components/stats/StatCard.tsx
+++ b/src/components/stats/StatCard.tsx
@@ -26,6 +26,9 @@ interface StatCardProps {
valueClassName?: string;
/** Optional period-over-period change shown under the value. */
delta?: StatCardDelta | null;
+ /** For "lower is better" metrics (e.g. refunds): keep the real arrow but flip
+ * the colour, so a rise reads as bad (red) and a drop as good (green). */
+ invertDelta?: boolean;
}
export function StatCard({
@@ -35,10 +38,18 @@ export function StatCard({
tone = 'neutral',
valueClassName,
delta,
+ invertDelta = false,
}: StatCardProps) {
const toneStyle = TONE[tone];
const valueClass = valueClassName ?? toneStyle.value;
- const trendStyle = delta ? (TREND_STYLES[delta.trend] ?? TREND_STYLES.stable) : null;
+ const baseTrend = delta ? (TREND_STYLES[delta.trend] ?? TREND_STYLES.stable) : null;
+ const trendStyle =
+ baseTrend && invertDelta && delta && delta.trend !== 'stable'
+ ? {
+ arrow: baseTrend.arrow,
+ className: TREND_STYLES[delta.trend === 'up' ? 'down' : 'up'].className,
+ }
+ : baseTrend;
return (
diff --git a/src/locales/en.json b/src/locales/en.json
index 6a482c4..68bfaac 100644
--- a/src/locales/en.json
+++ b/src/locales/en.json
@@ -1306,7 +1306,9 @@
"conversion": "Conversion",
"renewals": "Renewals",
"addonRevenue": "Add-on Revenue",
- "manualTopup": "Manual Top-ups"
+ "manualTopup": "Manual Top-ups",
+ "refundsCount": "Refunds",
+ "refundsAmount": "Refunded amount"
},
"trials": {
"total": "Total Trials",
diff --git a/src/locales/fa.json b/src/locales/fa.json
index 26cde24..2c744e2 100644
--- a/src/locales/fa.json
+++ b/src/locales/fa.json
@@ -1179,7 +1179,9 @@
"conversion": "تبدیل",
"renewals": "تمدید",
"addonRevenue": "درآمد خدمات اضافی",
- "manualTopup": "شارژ دستی"
+ "manualTopup": "شارژ دستی",
+ "refundsCount": "بازپرداختها",
+ "refundsAmount": "مبلغ بازپرداخت"
},
"trials": {
"total": "کل آزمایشی",
diff --git a/src/locales/ru.json b/src/locales/ru.json
index 872bd7c..b77dbec 100644
--- a/src/locales/ru.json
+++ b/src/locales/ru.json
@@ -1328,7 +1328,9 @@
"conversion": "Конверсия",
"renewals": "Продления",
"addonRevenue": "Доп. услуги",
- "manualTopup": "Ручные пополнения"
+ "manualTopup": "Ручные пополнения",
+ "refundsCount": "Возвраты",
+ "refundsAmount": "Сумма возвратов"
},
"trials": {
"total": "Всего триалов",
diff --git a/src/locales/zh.json b/src/locales/zh.json
index dca06ba..6a9d6a1 100644
--- a/src/locales/zh.json
+++ b/src/locales/zh.json
@@ -1179,7 +1179,9 @@
"conversion": "转化率",
"renewals": "续订",
"addonRevenue": "附加服务收入",
- "manualTopup": "手动充值"
+ "manualTopup": "手动充值",
+ "refundsCount": "退款",
+ "refundsAmount": "退款金额"
},
"trials": {
"total": "试用总数",
diff --git a/src/pages/AdminSalesStats.tsx b/src/pages/AdminSalesStats.tsx
index 55cdb8d..bd044db 100644
--- a/src/pages/AdminSalesStats.tsx
+++ b/src/pages/AdminSalesStats.tsx
@@ -13,6 +13,7 @@ import {
GiftIcon,
PercentIcon,
RepeatIcon,
+ ResetIcon,
RocketIcon,
SparklesIcon,
TicketIcon,
@@ -115,6 +116,7 @@ export default function AdminSalesStats() {
renewals: computeDelta(summary.renewals_count, prevSummary.renewals_count),
addonRevenue: computeDelta(summary.addon_revenue_kopeks, prevSummary.addon_revenue_kopeks),
manualTopup: computeDelta(summary.manual_topup_kopeks, prevSummary.manual_topup_kopeks),
+ refunds: computeDelta(summary.refunds_kopeks, prevSummary.refunds_kopeks),
};
}, [summary, prevSummary]);
@@ -148,7 +150,7 @@ export default function AdminSalesStats() {
{t('admin.salesStats.loadError')}
)}
-
+
+ }
+ tone="error"
+ />
+ }
+ tone="error"
+ delta={deltas?.refunds}
+ invertDelta
+ />
{/* Tabs */}