diff --git a/web/pages/stats.tsx b/web/pages/stats.tsx index 41d8f679..78abf76f 100644 --- a/web/pages/stats.tsx +++ b/web/pages/stats.tsx @@ -1,6 +1,23 @@ +import { + ArrowTrendingUpIcon, + BoltIcon, + BuildingLibraryIcon, + ChatBubbleLeftRightIcon, + ChatBubbleOvalLeftIcon, + CheckCircleIcon, + ClipboardDocumentListIcon, + EnvelopeIcon, + HandRaisedIcon, + PuzzlePieceIcon, + QuestionMarkCircleIcon, + ScaleIcon, + StarIcon, + UserIcon, + UsersIcon, +} from '@heroicons/react/24/outline' import clsx from 'clsx' import {type Stats} from 'common/stats' -import {ReactNode, useEffect, useState} from 'react' +import {ComponentType, ReactNode, SVGProps, useEffect, useState} from 'react' import {PageBase} from 'web/components/page-base' import {SEO} from 'web/components/SEO' import ChartMembers from 'web/components/widgets/charts' @@ -10,16 +27,18 @@ import {getCount} from 'web/lib/supabase/users' // ─── Types ──────────────────────────────────────────────────────────────────── +type IconType = ComponentType> + interface StatCardProps { value: string | number | null | undefined label: string - icon: string + icon: IconType accent?: 'amber' | 'sage' | 'muted' large?: boolean } interface StatGroupProps { - icon: string + icon: IconType title: string children: ReactNode } @@ -34,7 +53,7 @@ function formatNumber(n: number): string { // ─── Stat Card ──────────────────────────────────────────────────────────────── -function StatCard({value, label, icon, accent = 'amber', large}: StatCardProps) { +function StatCard({value, label, icon: Icon, accent = 'amber', large}: StatCardProps) { if (value === null || value === undefined || value === 0) return null const formatted = typeof value === 'number' ? formatNumber(value) : value @@ -56,8 +75,8 @@ function StatCard({value, label, icon, accent = 'amber', large}: StatCardProps) " >
-
- {icon} +
+
@@ -80,11 +99,11 @@ function StatCard({value, label, icon, accent = 'amber', large}: StatCardProps) // ─── Stat Group ─────────────────────────────────────────────────────────────── -function StatGroup({icon, title, children}: StatGroupProps) { +function StatGroup({icon: Icon, title, children}: StatGroupProps) { return (
- {icon} + {title} @@ -107,8 +126,8 @@ function ChartCard() { " >
-
- 📈 +
+

@@ -136,23 +155,28 @@ function HighlightRow({ messages: number | null | undefined }) { const t = useT() - const items = [ + const items: { + value: number | null | undefined + label: string + icon: IconType + accent: 'amber' | 'sage' + }[] = [ { value: members, label: t('stats.highlight.members', 'Total Members'), - icon: '👥', + icon: UsersIcon, accent: 'amber' as const, }, { value: active, label: t('stats.highlight.active', 'Active (last month)'), - icon: '⚡', + icon: BoltIcon, accent: 'sage' as const, }, { value: messages, label: t('stats.highlight.messages', 'Messages sent'), - icon: '✉️', + icon: EnvelopeIcon, accent: 'amber' as const, }, ].filter((i) => !!i.value) @@ -161,31 +185,34 @@ function HighlightRow({ return (
- {items.map((item) => ( -
-
- {item.icon} -
-
- {typeof item.value === 'number' ? formatNumber(item.value) : item.value} +
+ +
+
+ {typeof item.value === 'number' ? formatNumber(item.value) : item.value} +
+

+ {item.label} +

-

- {item.label} -

-
- ))} + ) + })}
) } @@ -294,77 +321,83 @@ export default function Stats() { {/* ── Community ── */} - + {/* ── Conversations ── */} - + {/* ── Compatibility ── */} - + {/* ── Democracy ── */} - + {/*