feat: enhance UI and functionality in various components

This commit is contained in:
CaIon
2026-04-28 18:38:02 +08:00
parent fc377dae3e
commit 28f7e9eb2e
40 changed files with 1567 additions and 470 deletions
@@ -24,10 +24,8 @@ let themeManagerPromise: Promise<
(typeof import('@visactor/vchart'))['ThemeManager']
> | null = null
type UserChartTab = 'rank' | 'trend'
const CHART_TABS: {
value: UserChartTab
const USER_CHARTS: {
value: string
labelKey: string
specKey: keyof ProcessedUserChartData
}[] = [
@@ -46,7 +44,6 @@ const CHART_TABS: {
export function UserCharts() {
const { t } = useTranslation()
const { resolvedTheme } = useTheme()
const [activeTab, setActiveTab] = useState<UserChartTab>('rank')
const [themeReady, setThemeReady] = useState(false)
const themeManagerRef = useRef<
(typeof import('@visactor/vchart'))['ThemeManager'] | null
@@ -121,9 +118,6 @@ export function UserCharts() {
[userData, isLoading, timeGranularity, t]
)
const activeSpec = CHART_TABS.find((tab) => tab.value === activeTab)
const spec = activeSpec ? chartData[activeSpec.specKey] : null
return (
<div className='space-y-4'>
{/* Toolbar: time range presets + granularity */}
@@ -169,50 +163,41 @@ export function UserCharts() {
)}
</div>
{/* Chart card */}
<div className='overflow-hidden rounded-lg border'>
<div className='flex w-full flex-col gap-3 border-b px-4 py-3 sm:px-5 lg:flex-row lg:items-center lg:justify-between'>
<div className='flex items-center gap-2'>
<Users className='text-muted-foreground/60 size-4' />
<div className='text-sm font-semibold'>{t('User Analytics')}</div>
</div>
<div className='grid gap-4'>
{USER_CHARTS.map((chart) => {
const spec = chartData[chart.specKey]
<div className='bg-muted/60 inline-flex h-8 rounded-md border p-0.5'>
{CHART_TABS.map((tab) => (
<button
key={tab.value}
type='button'
onClick={() => setActiveTab(tab.value)}
className={`rounded-[5px] px-3 text-xs font-medium transition-colors ${
activeTab === tab.value
? 'bg-background text-foreground shadow-sm'
: 'text-muted-foreground hover:text-foreground'
}`}
>
{t(tab.labelKey)}
</button>
))}
</div>
</div>
return (
<div
key={chart.value}
className='overflow-hidden rounded-lg border'
>
<div className='flex w-full items-center gap-2 border-b px-4 py-3 sm:px-5'>
<Users className='text-muted-foreground/60 size-4' />
<div className='text-sm font-semibold'>{t(chart.labelKey)}</div>
</div>
<div className='h-96 p-2'>
{isLoading ? (
<Skeleton className='h-full w-full' />
) : (
themeReady &&
spec && (
<VChart
key={`user-${activeTab}-${resolvedTheme}`}
spec={{
...spec,
theme: resolvedTheme === 'dark' ? 'dark' : 'light',
background: 'transparent',
}}
option={VCHART_OPTION}
/>
)
)}
</div>
<div className='h-96 p-2'>
{isLoading ? (
<Skeleton className='h-full w-full' />
) : (
themeReady &&
spec && (
<VChart
key={`user-${chart.value}-${resolvedTheme}`}
spec={{
...spec,
theme: resolvedTheme === 'dark' ? 'dark' : 'light',
background: 'transparent',
}}
option={VCHART_OPTION}
/>
)
)}
</div>
</div>
)
})}
</div>
</div>
)