+
}
tone="success"
/>
- }
- tone="neutral"
- />
diff --git a/src/locales/en.json b/src/locales/en.json
index eef7a36..41c7c93 100644
--- a/src/locales/en.json
+++ b/src/locales/en.json
@@ -1304,6 +1304,7 @@
"activeSubs": "Active Subs",
"activeTrials": "Active Trials",
"newTrials": "New Trials",
+ "newPaid": "New Paid Subscriptions",
"conversion": "Conversion",
"renewals": "Renewals",
"addonRevenue": "Add-on Revenue",
@@ -1314,7 +1315,6 @@
"totalRegistrations": "Registrations",
"trialsIssued": "Trials Issued",
"conversion": "Conversion Rate",
- "avgDuration": "Avg Duration",
"byProvider": "By Registration Source",
"dailyChart": "Daily Registrations & Trials",
"registrations": "Registrations"
diff --git a/src/locales/fa.json b/src/locales/fa.json
index 377d506..00ef8c1 100644
--- a/src/locales/fa.json
+++ b/src/locales/fa.json
@@ -1177,6 +1177,7 @@
"activeSubs": "اشتراک فعال",
"activeTrials": "آزمایشی فعال",
"newTrials": "آزمایشی جدید",
+ "newPaid": "اشتراکهای پولی جدید",
"conversion": "تبدیل",
"renewals": "تمدید",
"addonRevenue": "درآمد خدمات اضافی",
@@ -1187,7 +1188,6 @@
"totalRegistrations": "ثبتنامها",
"trialsIssued": "آزمایشی صادرشده",
"conversion": "نرخ تبدیل",
- "avgDuration": "میانگین مدت",
"byProvider": "بر اساس منبع",
"dailyChart": "ثبتنام و آزمایشی روزانه",
"registrations": "ثبتنام"
diff --git a/src/locales/ru.json b/src/locales/ru.json
index 3ad0fe5..d7bd867 100644
--- a/src/locales/ru.json
+++ b/src/locales/ru.json
@@ -1326,6 +1326,7 @@
"activeSubs": "Активные подписки",
"activeTrials": "Активные триалы",
"newTrials": "Новые триалы",
+ "newPaid": "Новые платные подписки",
"conversion": "Конверсия",
"renewals": "Продления",
"addonRevenue": "Доп. услуги",
@@ -1336,7 +1337,6 @@
"totalRegistrations": "Регистрации",
"trialsIssued": "Выданные триалы",
"conversion": "Конверсия",
- "avgDuration": "Средняя длит.",
"byProvider": "По источнику регистрации",
"dailyChart": "Регистрации и триалы по дням",
"registrations": "Регистрации"
diff --git a/src/locales/zh.json b/src/locales/zh.json
index 9a188d9..9143769 100644
--- a/src/locales/zh.json
+++ b/src/locales/zh.json
@@ -1177,6 +1177,7 @@
"activeSubs": "活跃订阅",
"activeTrials": "活跃试用",
"newTrials": "新试用",
+ "newPaid": "新增付费订阅",
"conversion": "转化率",
"renewals": "续订",
"addonRevenue": "附加服务收入",
@@ -1187,7 +1188,6 @@
"totalRegistrations": "注册数",
"trialsIssued": "已发放试用",
"conversion": "转化率",
- "avgDuration": "平均时长",
"byProvider": "按注册来源",
"dailyChart": "每日注册与试用",
"registrations": "注册"
diff --git a/src/pages/AdminSalesStats.tsx b/src/pages/AdminSalesStats.tsx
index 78a366e..ce59c47 100644
--- a/src/pages/AdminSalesStats.tsx
+++ b/src/pages/AdminSalesStats.tsx
@@ -12,6 +12,7 @@ import {
BanknotesIcon,
GiftIcon,
PercentIcon,
+ PlusIcon,
RepeatIcon,
RocketIcon,
SparklesIcon,
@@ -113,12 +114,26 @@ export default function AdminSalesStats() {
return {
revenue: computeDelta(summary.total_revenue_kopeks, prevSummary.total_revenue_kopeks),
newTrials: computeDelta(summary.new_trials, prevSummary.new_trials),
+ newPaid: computeDelta(summary.new_paid_subscriptions, prevSummary.new_paid_subscriptions),
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),
};
}, [summary, prevSummary]);
+ // Active-subscriptions trend = net change over the period (new paid − expired),
+ // shown relative to the count at the start of the period. The active count
+ // itself is a "right now" snapshot, so a plain period-over-period delta would
+ // always be zero — this shows real growth/shrinkage instead.
+ const activeDelta = useMemo(() => {
+ if (!summary) return null;
+ const net = summary.new_paid_subscriptions - summary.expired_subscriptions;
+ if (net === 0) return null;
+ const base = summary.active_subscriptions - net;
+ const percent = base > 0 ? Math.round((Math.abs(net) / base) * 1000) / 10 : 100;
+ return { percent, trend: net > 0 ? 'up' : 'down' };
+ }, [summary]);
+
const tabs: { id: TabId; label: string }[] = [
{ id: 'trials', label: t('admin.salesStats.tabs.trials') },
{ id: 'sales', label: t('admin.salesStats.tabs.sales') },
@@ -150,7 +165,7 @@ export default function AdminSalesStats() {
{t('admin.salesStats.loadError')}
)}
-
+
}
tone="accent"
+ delta={activeDelta}
+ />
+
}
+ tone="success"
+ delta={deltas?.newPaid}
/>
}
+ icon={
}
tone="accent"
delta={deltas?.addonRevenue}
/>