6
6
Index ,
7
7
onCleanup ,
8
8
onMount ,
9
+ Show ,
9
10
Suspense ,
10
11
type VoidComponent ,
11
12
} from 'solid-js'
@@ -15,19 +16,15 @@ import { getTimelineStatistics, TimelineStatistics } from '~/api/derived'
15
16
import Card , { CardContent , CardHeader } from '~/components/material/Card'
16
17
import Icon from '~/components/material/Icon'
17
18
import type { RouteSegments } from '~/types'
18
- import { formatRouteDistance , formatRouteDuration } from '~/utils/date'
19
+ import { formatDateRange , formatRouteDistance , formatRouteDuration , formatTimeRange } from '~/utils/date'
19
20
import { useDimensions } from '~/utils/window'
20
21
21
22
22
- const formatEngagement = ( timeline ?: TimelineStatistics ) : string => {
23
- if ( ! timeline ) return ''
23
+ const getEngagement = ( timeline ?: TimelineStatistics ) : string | null => {
24
+ if ( ! timeline ) return null
24
25
const { engagedDuration, duration } = timeline
25
- return `Engaged Time: ${ ( 100 * ( engagedDuration / duration ) ) . toFixed ( 0 ) } %`
26
- }
27
-
28
-
29
- const formatUserFlags = ( timeline ?: TimelineStatistics ) : string => {
30
- return timeline ?. userFlags !== undefined ? `${ timeline . userFlags } user flags` : ''
26
+ if ( ! duration ) return null
27
+ return `${ ( 100 * ( engagedDuration / duration ) ) . toFixed ( 0 ) } %`
31
28
}
32
29
33
30
@@ -36,17 +33,8 @@ interface RouteCardProps {
36
33
}
37
34
38
35
const RouteCard : VoidComponent < RouteCardProps > = ( props ) => {
39
- // TODO: move to date utils
40
- const dateRange = ( ) => new Intl . DateTimeFormat ( 'en' , {
41
- weekday : 'long' ,
42
- day : 'numeric' ,
43
- month : 'long' ,
44
- year : 'numeric' ,
45
- } ) . formatRange ( props . route . start_time_utc_millis , props . route . end_time_utc_millis )
46
- const timeRange = ( ) => new Intl . DateTimeFormat ( 'en' , {
47
- hour : 'numeric' ,
48
- minute : 'numeric' ,
49
- } ) . formatRange ( props . route . start_time_utc_millis , props . route . end_time_utc_millis )
36
+ const dateRange = ( ) => formatDateRange ( props . route . start_time_utc_millis , props . route . end_time_utc_millis )
37
+ const timeRange = ( ) => formatTimeRange ( props . route . start_time_utc_millis , props . route . end_time_utc_millis )
50
38
const [ timeline ] = createResource ( ( ) => props . route , getTimelineStatistics )
51
39
52
40
return (
@@ -55,29 +43,36 @@ const RouteCard: VoidComponent<RouteCardProps> = (props) => {
55
43
href = { `/${ props . route . dongle_id } /${ props . route . fullname . slice ( 17 ) } ` }
56
44
activeClass = "md:before:bg-primary"
57
45
>
58
- < CardHeader headline = { dateRange ( ) } subhead = { timeRange ( ) } />
46
+ < CardHeader
47
+ headline = { dateRange ( ) }
48
+ subhead = { timeRange ( ) }
49
+ trailing = { < div class = "flex flex-row gap-2" >
50
+ < Icon size = "24" > route</ Icon >
51
+ { formatRouteDistance ( props . route ) }
52
+ </ div > }
53
+ />
59
54
60
55
< CardContent >
61
- < div class = "grid size-full grid-cols-2 gap-4 " >
56
+ < div class = "grid gap-2 grid-cols-3 whitespace-nowrap " >
62
57
< div class = "flex items-center gap-2" >
63
58
< Icon size = "20" > schedule</ Icon >
64
59
{ formatRouteDuration ( props . route ) }
65
60
</ div >
66
- < div class = "flex items-center gap-2" >
67
- < Icon size = "20" > route</ Icon >
68
- { formatRouteDistance ( props . route ) }
69
- </ div >
70
- < Suspense fallback = { < div class = "skeleton-loader h-6" /> } >
71
- < div class = "hidden items-center gap-2 xs:flex" >
72
- < Icon size = "20" > speed</ Icon >
73
- { formatEngagement ( timeline ( ) ) }
74
- </ div >
61
+ < Suspense fallback = { < div class = "flex h-6" > < div class = "skeleton-loader size-full" /> </ div > } >
62
+ < Show when = { getEngagement ( timeline ( ) ) } > { ( engagement ) => (
63
+ < div class = "hidden items-center gap-2 xs:flex" >
64
+ < Icon size = "20" > speed</ Icon >
65
+ < span > Engaged: { engagement ( ) } </ span >
66
+ </ div >
67
+ ) } </ Show >
75
68
</ Suspense >
76
- < Suspense fallback = { < div class = "skeleton-loader h-6" /> } >
77
- < div class = "flex items-center gap-2" >
78
- < Icon size = "20" > flag</ Icon >
79
- { formatUserFlags ( timeline ( ) ) }
80
- </ div >
69
+ < Suspense fallback = { < div class = "flex h-6" > < div class = "skeleton-loader size-full" /> </ div > } >
70
+ < Show when = { timeline ( ) } > { ( timeline ) => (
71
+ < div class = "flex items-center gap-2 justify-self-end ps-2" >
72
+ < Icon size = "20" > flag</ Icon >
73
+ < span > { timeline ( ) ?. userFlags } < span class = "hidden xs:inline" > user</ span > flags</ span >
74
+ </ div >
75
+ ) } </ Show >
81
76
</ Suspense >
82
77
</ div >
83
78
</ CardContent >
0 commit comments