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:
@@ -5,7 +5,16 @@ import { useTranslation } from 'react-i18next';
|
||||
import { promocodesApi, PromoGroup } from '../api/promocodes';
|
||||
import { usePlatform } from '../platform/hooks/usePlatform';
|
||||
import { useFocusTrap } from '../hooks/useFocusTrap';
|
||||
import { BackIcon, PlusIcon, EditIcon, TrashIcon, UsersIcon } from '@/components/icons';
|
||||
import {
|
||||
BackIcon,
|
||||
PlusIcon,
|
||||
EditIcon,
|
||||
TrashIcon,
|
||||
UsersIcon,
|
||||
TagIcon,
|
||||
BoltIcon,
|
||||
} from '@/components/icons';
|
||||
import { StatCard } from '@/components/stats';
|
||||
|
||||
export default function AdminPromoGroups() {
|
||||
const { t } = useTranslation();
|
||||
@@ -66,22 +75,24 @@ export default function AdminPromoGroups() {
|
||||
{/* Stats */}
|
||||
{groups.length > 0 && (
|
||||
<div className="mb-6 grid grid-cols-2 gap-3 sm:grid-cols-3">
|
||||
<div className="rounded-xl border border-dark-700 bg-dark-800 p-4">
|
||||
<div className="text-2xl font-bold text-dark-100">{groups.length}</div>
|
||||
<div className="text-xs text-dark-400">{t('admin.promoGroups.stats.total')}</div>
|
||||
</div>
|
||||
<div className="rounded-xl border border-dark-700 bg-dark-800 p-4">
|
||||
<div className="text-2xl font-bold text-accent-400">
|
||||
{groups.reduce((sum, g) => sum + g.members_count, 0)}
|
||||
</div>
|
||||
<div className="text-xs text-dark-400">{t('admin.promoGroups.stats.members')}</div>
|
||||
</div>
|
||||
<div className="rounded-xl border border-dark-700 bg-dark-800 p-4">
|
||||
<div className="text-2xl font-bold text-warning-400">
|
||||
{groups.filter((g) => g.auto_assign_total_spent_kopeks).length}
|
||||
</div>
|
||||
<div className="text-xs text-dark-400">{t('admin.promoGroups.stats.autoAssign')}</div>
|
||||
</div>
|
||||
<StatCard
|
||||
label={t('admin.promoGroups.stats.total')}
|
||||
value={groups.length}
|
||||
icon={<TagIcon className="h-5 w-5" />}
|
||||
tone="neutral"
|
||||
/>
|
||||
<StatCard
|
||||
label={t('admin.promoGroups.stats.members')}
|
||||
value={groups.reduce((sum, g) => sum + g.members_count, 0)}
|
||||
icon={<UsersIcon className="h-5 w-5" />}
|
||||
tone="accent"
|
||||
/>
|
||||
<StatCard
|
||||
label={t('admin.promoGroups.stats.autoAssign')}
|
||||
value={groups.filter((g) => g.auto_assign_total_spent_kopeks).length}
|
||||
icon={<BoltIcon className="h-5 w-5" />}
|
||||
tone="warning"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user