Skip to content

Commit 9317fad

Browse files
committed
Format session duration as human-readable time on analytics chart (#25)
1 parent da25d61 commit 9317fad

3 files changed

Lines changed: 25 additions & 5 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
- Fix ASC rate limit errors when saving many locales at once
99
- Only save changed locales instead of all locales on store listing and app details
1010
- Fix control characters from AI models causing ASC save failures on name and subtitle
11+
- Fix session duration chart showing raw seconds instead of human-readable durations
1112
- Fix all linting and React compiler errors, make lint failures block CI
1213

1314
## 1.6.1

src/app/dashboard/apps/[appId]/analytics/usage/page.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import {
2222
ChartLegendContent,
2323
type ChartConfig,
2424
} from "@/components/ui/chart";
25-
import { formatDateShort } from "@/lib/format";
25+
import { formatDateShort, formatDuration } from "@/lib/format";
2626
import { useAnalytics } from "@/lib/analytics-context";
2727
import { parseRange, filterByDateRange, getStoredRange } from "@/lib/analytics-range";
2828
import { AnalyticsStateGuard } from "@/components/analytics-state-guard";
@@ -35,7 +35,7 @@ const sessionsConfig = {
3535
} satisfies ChartConfig;
3636

3737
const durationConfig = {
38-
avgDuration: { label: "Avg duration (s)", color: "var(--color-chart-3)" },
38+
avgDuration: { label: "Avg duration", color: "var(--color-chart-3)" },
3939
} satisfies ChartConfig;
4040

4141
const installDeleteConfig = {
@@ -193,16 +193,16 @@ export default function UsagePage() {
193193
<YAxis
194194
tickLine={false}
195195
axisLine={false}
196-
width={35}
197-
tickFormatter={(v) => `${v}s`}
196+
width={45}
197+
tickFormatter={(v) => formatDuration(v as number, true)}
198198
/>
199199
<ChartTooltip
200200
content={
201201
<ChartTooltipContent
202202
labelFormatter={(v) => formatDateShort(v as string)}
203203
formatter={(value) => (
204204
<span className="font-mono font-medium tabular-nums">
205-
{value}s
205+
{formatDuration(value as number)}
206206
</span>
207207
)}
208208
/>

src/lib/format.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,22 @@ export function formatDateTimeLong(iso: string): string {
3636
minute: "2-digit",
3737
});
3838
}
39+
40+
/**
41+
* Format a duration in seconds to a human-readable string.
42+
* Compact form for axis ticks: "45s", "12m", "2.5h"
43+
* Long form for tooltips: "45s", "12m 30s", "2h 15m"
44+
*/
45+
export function formatDuration(seconds: number, compact = false): string {
46+
if (seconds < 60) return `${Math.round(seconds)}s`;
47+
if (seconds < 3600) {
48+
const m = Math.floor(seconds / 60);
49+
const s = Math.round(seconds % 60);
50+
if (compact) return s === 0 ? `${m}m` : `${m}m`;
51+
return s > 0 ? `${m}m ${s}s` : `${m}m`;
52+
}
53+
const h = Math.floor(seconds / 3600);
54+
const m = Math.round((seconds % 3600) / 60);
55+
if (compact) return m === 0 ? `${h}h` : `${h}h`;
56+
return m > 0 ? `${h}h ${m}m` : `${h}h`;
57+
}

0 commit comments

Comments
 (0)