Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 34 additions & 2 deletions client/src/pages/AnalyticsPage.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useState } from 'react'
import { useEffect, useState } from 'react'
import { useQuery } from '@tanstack/react-query'
import {
BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer,
Expand All @@ -14,6 +14,26 @@ import { useI18n } from '@/i18n'

type TimeRange = '24h' | '7d' | '30d'

const TIME_RANGES: readonly TimeRange[] = ['24h', '7d', '30d']
const STORAGE_KEY = 'freellmapi.analytics.range'
const DEFAULT_RANGE: TimeRange = '7d'

// Read the previously-selected range from localStorage. Invalid or missing
// values fall back to the 7d default so a corrupted entry never bricks the
// page; SSR-safety follows the same try/catch shape as `lib/api.ts`.
function loadStoredRange(): TimeRange {
if (typeof window === 'undefined') return DEFAULT_RANGE
try {
const stored = window.localStorage.getItem(STORAGE_KEY)
if (stored && (TIME_RANGES as readonly string[]).includes(stored)) {
return stored as TimeRange
}
} catch {
/* localStorage unavailable (private mode, etc.) — use default */
}
return DEFAULT_RANGE
}

function formatTokens(n?: number): string {
if (!n) return '0'
if (n >= 1_000_000) return `${(n / 1_000_000).toFixed(1)}M`
Expand Down Expand Up @@ -50,7 +70,19 @@ const primaryFill = 'var(--foreground)'

export default function AnalyticsPage() {
const { t } = useI18n()
const [range, setRange] = useState<TimeRange>('7d')
const [range, setRange] = useState<TimeRange>(loadStoredRange)

// Remember the last-selected range across page reloads / new sessions so
// the user lands back on the window they were inspecting. Same
// localStorage shape as `theme` and `freellmapi.locale`.
useEffect(() => {
if (typeof window === 'undefined') return
try {
window.localStorage.setItem(STORAGE_KEY, range)
} catch {
/* ignore — storage quota / private mode */
}
}, [range])

const { data: summary } = useQuery({
queryKey: ['analytics', 'summary', range],
Expand Down
Loading