feat(sales-stats): иконки на карточках во всех вкладках

Доделал душевный вид: карточки внутри вкладок (Триалы/Продажи/Продления/Допы/
Депозиты) тоже получили иконки в цветных чипах с тонами — единый стиль со сводкой
(регистрации/триалы/конверсия/длительность, продажи/выручка/чек/топ-тариф,
продления/%, допы/GB/устройства, пополнения/сумма/средний). Крупные суммы — без
копеек.
This commit is contained in:
c0mrade
2026-06-02 15:45:40 +03:00
parent 622ec318da
commit 80ac63102b
5 changed files with 70 additions and 17 deletions

View File

@@ -6,6 +6,13 @@ import type { SalesStatsParams } from '../../api/adminSalesStats';
import { salesStatsApi } from '../../api/adminSalesStats';
import { SALES_STATS } from '../../constants/salesStats';
import { useCurrency } from '../../hooks/useCurrency';
import {
BanknotesIcon,
CardIcon,
DevicesIcon,
PlusIcon,
TrafficIcon,
} from '../../components/icons';
import { StatCard } from '../stats';
import { BreakdownList } from './BreakdownList';
@@ -64,24 +71,32 @@ export function AddonsTab({ params }: AddonsTabProps) {
<StatCard
label={t('admin.salesStats.addons.totalPurchases')}
value={data.total_purchases}
icon={<PlusIcon className="h-5 w-5" />}
tone="accent"
/>
<StatCard
label={t('admin.salesStats.addons.totalGb')}
value={`${data.total_gb_purchased} GB`}
icon={<TrafficIcon className="h-5 w-5" />}
tone="neutral"
/>
<StatCard
label={t('admin.salesStats.addons.revenue')}
value={formatWithCurrency(data.addon_revenue_kopeks / SALES_STATS.KOPEKS_DIVISOR)}
valueClassName="text-success-400"
value={formatWithCurrency(data.addon_revenue_kopeks / SALES_STATS.KOPEKS_DIVISOR, 0)}
icon={<BanknotesIcon className="h-5 w-5" />}
tone="success"
/>
<StatCard
label={t('admin.salesStats.addons.devicePurchases')}
value={data.device_purchases}
icon={<DevicesIcon className="h-5 w-5" />}
tone="accent"
/>
<StatCard
label={t('admin.salesStats.addons.deviceRevenue')}
value={formatWithCurrency(data.device_revenue_kopeks / SALES_STATS.KOPEKS_DIVISOR)}
valueClassName="text-success-400"
value={formatWithCurrency(data.device_revenue_kopeks / SALES_STATS.KOPEKS_DIVISOR, 0)}
icon={<CardIcon className="h-5 w-5" />}
tone="success"
/>
</div>

View File

@@ -7,6 +7,7 @@ import { salesStatsApi } from '../../api/adminSalesStats';
import { METHOD_LABELS } from '../../constants/paymentMethods';
import { SALES_STATS } from '../../constants/salesStats';
import { useCurrency } from '../../hooks/useCurrency';
import { BanknotesIcon, CardIcon, WalletIcon } from '../../components/icons';
import { StatCard } from '../stats';
import PaymentMethodIcon from '../PaymentMethodIcon';
@@ -82,15 +83,20 @@ export function DepositsTab({ params }: DepositsTabProps) {
<StatCard
label={t('admin.salesStats.deposits.totalDeposits')}
value={data.total_deposits}
icon={<WalletIcon className="h-5 w-5" />}
tone="accent"
/>
<StatCard
label={t('admin.salesStats.deposits.totalAmount')}
value={formatWithCurrency(data.total_amount_kopeks / SALES_STATS.KOPEKS_DIVISOR)}
valueClassName="text-success-400"
value={formatWithCurrency(data.total_amount_kopeks / SALES_STATS.KOPEKS_DIVISOR, 0)}
icon={<BanknotesIcon className="h-5 w-5" />}
tone="success"
/>
<StatCard
label={t('admin.salesStats.deposits.avgDeposit')}
value={formatWithCurrency(data.avg_deposit_kopeks / SALES_STATS.KOPEKS_DIVISOR)}
icon={<CardIcon className="h-5 w-5" />}
tone="neutral"
/>
</div>

View File

@@ -5,6 +5,7 @@ import type { SalesStatsParams } from '../../api/adminSalesStats';
import { salesStatsApi } from '../../api/adminSalesStats';
import { SALES_STATS } from '../../constants/salesStats';
import { useCurrency } from '../../hooks/useCurrency';
import { BanknotesIcon, PercentIcon, RepeatIcon } from '../../components/icons';
import { StatCard } from '../stats';
import { TREND_STYLES } from '../stats/constants';
@@ -49,16 +50,23 @@ export function RenewalsTab({ params }: RenewalsTabProps) {
return (
<div className="space-y-4">
<div className="grid grid-cols-1 gap-3 sm:grid-cols-3">
<StatCard label={t('admin.salesStats.renewals.total')} value={data.total_renewals} />
<StatCard
label={t('admin.salesStats.renewals.total')}
value={data.total_renewals}
icon={<RepeatIcon className="h-5 w-5" />}
tone="success"
/>
<StatCard
label={t('admin.salesStats.renewals.rate')}
value={`${data.renewal_rate}%`}
valueClassName="text-success-400"
icon={<PercentIcon className="h-5 w-5" />}
tone="accent"
/>
<StatCard
label={t('admin.salesStats.renewals.revenue')}
value={formatWithCurrency(data.total_revenue_kopeks / SALES_STATS.KOPEKS_DIVISOR)}
valueClassName="text-success-400"
value={formatWithCurrency(data.total_revenue_kopeks / SALES_STATS.KOPEKS_DIVISOR, 0)}
icon={<BanknotesIcon className="h-5 w-5" />}
tone="success"
/>
</div>

View File

@@ -6,6 +6,7 @@ import type { SalesStatsParams } from '../../api/adminSalesStats';
import { salesStatsApi } from '../../api/adminSalesStats';
import { SALES_STATS } from '../../constants/salesStats';
import { useCurrency } from '../../hooks/useCurrency';
import { BanknotesIcon, CardIcon, TicketIcon, TrophyIcon } from '../../components/icons';
import { StatCard } from '../stats';
import { BreakdownList } from './BreakdownList';
@@ -68,18 +69,30 @@ export function SalesTab({ params }: SalesTabProps) {
return (
<div className="space-y-4">
<div className="grid grid-cols-2 gap-3 sm:grid-cols-4">
<StatCard label={t('admin.salesStats.sales.totalSales')} value={data.total_sales} />
<StatCard
label={t('admin.salesStats.sales.totalSales')}
value={data.total_sales}
icon={<TicketIcon className="h-5 w-5" />}
tone="accent"
/>
<StatCard
label={t('admin.salesStats.sales.totalRevenue')}
value={formatWithCurrency(data.total_revenue_kopeks / SALES_STATS.KOPEKS_DIVISOR)}
valueClassName="text-success-400"
value={formatWithCurrency(data.total_revenue_kopeks / SALES_STATS.KOPEKS_DIVISOR, 0)}
icon={<BanknotesIcon className="h-5 w-5" />}
tone="success"
/>
<StatCard
label={t('admin.salesStats.sales.avgOrder')}
value={formatWithCurrency(data.avg_order_kopeks / SALES_STATS.KOPEKS_DIVISOR)}
valueClassName="text-success-400"
icon={<CardIcon className="h-5 w-5" />}
tone="success"
/>
<StatCard
label={t('admin.salesStats.sales.topTariff')}
value={data.top_tariff_name}
icon={<TrophyIcon className="h-5 w-5" />}
tone="warning"
/>
<StatCard label={t('admin.salesStats.sales.topTariff')} value={data.top_tariff_name} />
</div>
<div className="grid grid-cols-1 gap-4 lg:grid-cols-2">

View File

@@ -4,6 +4,7 @@ import { useTranslation } from 'react-i18next';
import type { SalesStatsParams } from '../../api/adminSalesStats';
import { salesStatsApi } from '../../api/adminSalesStats';
import { SALES_STATS } from '../../constants/salesStats';
import { ClockIcon, GiftIcon, PercentIcon, UserPlusIcon } from '../../components/icons';
import { StatCard } from '../stats';
import { DonutChart } from './DonutChart';
@@ -64,16 +65,26 @@ export function TrialsTab({ params }: TrialsTabProps) {
<StatCard
label={t('admin.salesStats.trials.totalRegistrations')}
value={data.total_registrations}
icon={<UserPlusIcon className="h-5 w-5" />}
tone="accent"
/>
<StatCard
label={t('admin.salesStats.trials.total')}
value={data.total_trials}
icon={<GiftIcon className="h-5 w-5" />}
tone="neutral"
/>
<StatCard label={t('admin.salesStats.trials.total')} value={data.total_trials} />
<StatCard
label={t('admin.salesStats.trials.conversion')}
value={`${data.conversion_rate}%`}
valueClassName="text-success-400"
icon={<PercentIcon className="h-5 w-5" />}
tone="success"
/>
<StatCard
label={t('admin.salesStats.trials.avgDuration')}
value={`${data.avg_trial_duration_days} ${t('admin.trafficUsage.days')}`}
icon={<ClockIcon className="h-5 w-5" />}
tone="neutral"
/>
</div>