mirror of
https://github.com/chillpadclub/bedolaga-cabinet.git
synced 2026-07-30 02:23:47 +00:00
refactor(cabinet): unify all statistics onto the shared StatCard
Bring every stat strip across the admin panel and user cabinet onto the canonical StatCard (icon chip + label-on-top + tone-coloured value), matching the sales/Remnawave style the rest of the app already used. - Convert ~20 hand-rolled stat strips across 21 pages/components - Remove 4 divergent local StatCard components (Dashboard, Users, BanSystem, Payments) and migrate Remnawave's local StatCard (33 cards) - Extend StatCard with optional subValue, loading skeleton, trailing slot, and icon-size normalisation (all backward-compatible) - StatsGrid nav tiles now use StatCard while keeping link/chevron/loading - Preserve all data, i18n keys, conditionals and interactive filters; fix the dead 'info' colour by mapping it to accent
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { SendIcon } from '@/components/icons';
|
||||
import { GiftIcon, SendIcon } from '@/components/icons';
|
||||
import { StatCard } from '@/components/stats';
|
||||
import { useCurrency } from '../../../hooks/useCurrency';
|
||||
import type { AdminUserGiftItem, AdminUserGiftsResponse } from '../../../api/adminUsers';
|
||||
|
||||
@@ -208,18 +209,18 @@ export function GiftsTab({ giftsLoading, giftsData, locale, onNavigateToUser }:
|
||||
<div className="space-y-6">
|
||||
{/* Summary counters */}
|
||||
<div className="grid grid-cols-2 gap-3">
|
||||
<div className="rounded-xl bg-dark-800/50 p-4">
|
||||
<div className="mb-1 text-xs text-dark-500">
|
||||
{t('admin.users.detail.gifts.totalSent')}
|
||||
</div>
|
||||
<div className="text-2xl font-bold text-accent-400">{giftsData.sent_total}</div>
|
||||
</div>
|
||||
<div className="rounded-xl bg-dark-800/50 p-4">
|
||||
<div className="mb-1 text-xs text-dark-500">
|
||||
{t('admin.users.detail.gifts.totalReceived')}
|
||||
</div>
|
||||
<div className="text-2xl font-bold text-success-400">{giftsData.received_total}</div>
|
||||
</div>
|
||||
<StatCard
|
||||
label={t('admin.users.detail.gifts.totalSent')}
|
||||
value={giftsData.sent_total}
|
||||
icon={<GiftIcon className="h-5 w-5" />}
|
||||
tone="accent"
|
||||
/>
|
||||
<StatCard
|
||||
label={t('admin.users.detail.gifts.totalReceived')}
|
||||
value={giftsData.received_total}
|
||||
icon={<GiftIcon className="h-5 w-5" />}
|
||||
tone="success"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Sent Gifts */}
|
||||
|
||||
@@ -5,7 +5,8 @@ import { useNavigate } from 'react-router';
|
||||
import { useCurrency } from '../../../hooks/useCurrency';
|
||||
import { useNotify } from '../../../platform/hooks/useNotify';
|
||||
import { adminUsersApi, type UserDetailResponse, type UserListItem } from '../../../api/adminUsers';
|
||||
import { XIcon } from '@/components/icons';
|
||||
import { StatCard } from '@/components/stats';
|
||||
import { BanknotesIcon, PercentIcon, TagIcon, UsersIcon, XIcon } from '@/components/icons';
|
||||
|
||||
// ──────────────────────────────────────────────────────────────────
|
||||
// Referrals tab — top-of-graph referrer + stats + referrals list,
|
||||
@@ -327,40 +328,35 @@ export function ReferralsTab({ user, userId, onUserRefresh }: ReferralsTabProps)
|
||||
|
||||
{/* Section 2: Referral stats */}
|
||||
<div className="grid grid-cols-2 gap-3 lg:grid-cols-4">
|
||||
<div className="rounded-xl bg-dark-800/40 p-4">
|
||||
<div className="text-xs text-dark-500">
|
||||
{t('admin.users.detail.referrals.totalReferrals')}
|
||||
</div>
|
||||
<div className="mt-1 text-xl font-bold text-dark-100">
|
||||
{user.referral.referrals_count}
|
||||
</div>
|
||||
</div>
|
||||
<div className="rounded-xl bg-dark-800/40 p-4">
|
||||
<div className="text-xs text-dark-500">
|
||||
{t('admin.users.detail.referrals.totalEarnings')}
|
||||
</div>
|
||||
<div className="mt-1 text-xl font-bold text-dark-100">
|
||||
{formatWithCurrency(user.referral.total_earnings_kopeks / 100)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="rounded-xl bg-dark-800/40 p-4">
|
||||
<div className="text-xs text-dark-500">
|
||||
{t('admin.users.detail.referrals.commission')}
|
||||
</div>
|
||||
<div className="mt-1 text-xl font-bold text-dark-100">
|
||||
{user.referral.commission_percent != null
|
||||
<StatCard
|
||||
label={t('admin.users.detail.referrals.totalReferrals')}
|
||||
value={user.referral.referrals_count}
|
||||
icon={<UsersIcon className="h-5 w-5" />}
|
||||
tone="neutral"
|
||||
/>
|
||||
<StatCard
|
||||
label={t('admin.users.detail.referrals.totalEarnings')}
|
||||
value={formatWithCurrency(user.referral.total_earnings_kopeks / 100)}
|
||||
icon={<BanknotesIcon className="h-5 w-5" />}
|
||||
tone="neutral"
|
||||
/>
|
||||
<StatCard
|
||||
label={t('admin.users.detail.referrals.commission')}
|
||||
value={
|
||||
user.referral.commission_percent != null
|
||||
? `${user.referral.commission_percent}%`
|
||||
: t('admin.users.detail.referrals.default')}
|
||||
</div>
|
||||
</div>
|
||||
<div className="rounded-xl bg-dark-800/40 p-4">
|
||||
<div className="text-xs text-dark-500">
|
||||
{t('admin.users.detail.referrals.referralCode')}
|
||||
</div>
|
||||
<div className="mt-1 truncate font-mono text-sm text-dark-100">
|
||||
{user.referral.referral_code}
|
||||
</div>
|
||||
</div>
|
||||
: t('admin.users.detail.referrals.default')
|
||||
}
|
||||
icon={<PercentIcon className="h-5 w-5" />}
|
||||
tone="neutral"
|
||||
/>
|
||||
<StatCard
|
||||
label={t('admin.users.detail.referrals.referralCode')}
|
||||
value={user.referral.referral_code}
|
||||
icon={<TagIcon className="h-5 w-5" />}
|
||||
tone="neutral"
|
||||
valueClassName="font-mono"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Section 3: Referrals list */}
|
||||
|
||||
Reference in New Issue
Block a user