|
1 | | -import { createResource, Suspense } from 'solid-js' |
| 1 | +import { createResource } from 'solid-js' |
2 | 2 | import type { VoidComponent } from 'solid-js' |
3 | | -import clsx from 'clsx' |
4 | 3 |
|
5 | 4 | import { TimelineStatistics, getTimelineStatistics } from '~/api/derived' |
6 | 5 | import type { Route } from '~/types' |
7 | 6 | import { formatDistance, formatRouteDuration } from '~/utils/format' |
| 7 | +import StatisticBar from './StatisticBar' |
8 | 8 |
|
9 | | -const formatEngagement = (timeline?: TimelineStatistics): string => { |
10 | | - if (!timeline) return '' |
| 9 | +const formatEngagement = (timeline?: TimelineStatistics): string | undefined => { |
| 10 | + if (!timeline) return undefined |
11 | 11 | const { engagedDuration, duration } = timeline |
12 | 12 | return `${(100 * (engagedDuration / duration)).toFixed(0)}%` |
13 | 13 | } |
14 | 14 |
|
15 | | -const formatUserFlags = (timeline?: TimelineStatistics): string => { |
16 | | - return timeline?.userFlags.toString() ?? '' |
17 | | -} |
18 | | - |
19 | | -type RouteStatisticsProps = { |
20 | | - class?: string |
21 | | - route?: Route |
22 | | -} |
23 | | - |
24 | | -const RouteStatistics: VoidComponent<RouteStatisticsProps> = (props) => { |
| 15 | +const RouteStatistics: VoidComponent<{ class?: string; route: Route }> = (props) => { |
25 | 16 | const [timeline] = createResource(() => props.route, getTimelineStatistics) |
26 | 17 |
|
27 | 18 | return ( |
28 | | - <div class={clsx('flex size-full items-stretch gap-8', props.class)}> |
29 | | - <div class="flex grow flex-col justify-between"> |
30 | | - <span class="text-body-sm text-on-surface-variant">Distance</span> |
31 | | - <span class="font-mono text-label-lg uppercase">{formatDistance(props.route?.length)}</span> |
32 | | - </div> |
33 | | - |
34 | | - <div class="flex grow flex-col justify-between"> |
35 | | - <span class="text-body-sm text-on-surface-variant">Duration</span> |
36 | | - <span class="font-mono text-label-lg uppercase">{formatRouteDuration(props.route)}</span> |
37 | | - </div> |
38 | | - |
39 | | - <div class="hidden grow flex-col justify-between xs:flex"> |
40 | | - <span class="text-body-sm text-on-surface-variant">Engaged</span> |
41 | | - <Suspense> |
42 | | - <span class="font-mono text-label-lg uppercase">{formatEngagement(timeline())}</span> |
43 | | - </Suspense> |
44 | | - </div> |
45 | | - |
46 | | - <div class="flex grow flex-col justify-between"> |
47 | | - <span class="text-body-sm text-on-surface-variant">User flags</span> |
48 | | - <Suspense> |
49 | | - <span class="font-mono text-label-lg uppercase">{formatUserFlags(timeline())}</span> |
50 | | - </Suspense> |
51 | | - </div> |
52 | | - </div> |
| 19 | + <StatisticBar |
| 20 | + class={props.class} |
| 21 | + statistics={[ |
| 22 | + { label: 'Distance', value: formatDistance(props.route?.length) }, |
| 23 | + { label: 'Duration', value: formatRouteDuration(props.route) }, |
| 24 | + { label: 'Engaged', value: formatEngagement(timeline()) }, |
| 25 | + { label: 'User flags', value: timeline()?.userFlags.toString() }, |
| 26 | + ]} |
| 27 | + /> |
53 | 28 | ) |
54 | 29 | } |
55 | 30 |
|
|
0 commit comments