@@ -12,7 +12,7 @@ import type {Moment} from 'moment-timezone'
1212import { toLaxTitleCase as titleCase } from '@frogpond/titlecase'
1313import type { StreamType } from './types'
1414import { API } from '@frogpond/api'
15- import { fetch } from '@frogpond/fetch '
15+ import { useFetch } from 'react-async '
1616
1717const styles = StyleSheet . create ( {
1818 listContainer : {
@@ -23,52 +23,32 @@ const styles = StyleSheet.create({
2323 } ,
2424} )
2525
26- export const StreamListView = ( ) : JSX . Element => {
27- let [ error , setError ] = React . useState < Error | null > ( null )
28- let [ loading , setLoading ] = React . useState ( true )
29- let [ refreshing , setRefreshing ] = React . useState ( false )
30- let [ streams , setStreams ] = React . useState <
31- Array < { title : string ; data : StreamType [ ] } >
32- > ( [ ] )
33-
34- React . useEffect ( ( ) => {
35- try {
36- getStreams ( ) . then ( ( ) => {
37- setLoading ( false )
38- } )
39- } catch ( error ) {
40- if ( error instanceof Error ) {
41- setError ( error )
42- } else {
43- setError ( new Error ( 'unknown error - not an Error' ) )
44- }
45- return
46- }
47- } , [ ] )
48-
49- let refresh = async ( ) : Promise < void > => {
50- setRefreshing ( true )
51- await getStreams ( true )
52- setRefreshing ( false )
53- }
26+ const groupStreams = ( entries : StreamType [ ] ) => {
27+ let grouped = groupBy ( entries , ( j ) => j . $groupBy )
28+ return toPairs ( grouped ) . map ( ( [ title , data ] ) => ( { title, data} ) )
29+ }
5430
55- let getStreams = async (
56- reload ?: boolean ,
57- date : Moment = moment . tz ( timezone ( ) ) ,
58- ) => {
59- let dateFrom = date . format ( 'YYYY-MM-DD' )
60- let dateTo = date . clone ( ) . add ( 2 , 'month' ) . format ( 'YYYY-MM-DD' )
31+ const useStreams = ( date : Moment = moment . tz ( timezone ( ) ) ) => {
32+ let dateFrom = date . format ( 'YYYY-MM-DD' )
33+ let dateTo = date . clone ( ) . add ( 2 , 'month' ) . format ( 'YYYY-MM-DD' )
34+
35+ return useFetch < StreamType [ ] > (
36+ API ( '/streams/upcoming' , {
37+ sort : 'ascending' ,
38+ dateFrom,
39+ dateTo,
40+ } ) ,
41+ {
42+ headers : { accept : 'application/json' } ,
43+ } ,
44+ )
45+ }
6146
62- let data = await fetch ( API ( '/streams/upcoming' ) , {
63- searchParams : {
64- sort : 'ascending' ,
65- dateFrom,
66- dateTo,
67- } ,
68- delay : reload ? 500 : 0 ,
69- } ) . json < Array < StreamType > > ( )
47+ export const StreamListView = ( ) : JSX . Element => {
48+ let { data = [ ] , error, reload, isPending, isInitial, isLoading} = useStreams ( )
7049
71- data = data
50+ let entries = React . useMemo ( ( ) => {
51+ return data
7252 . filter ( ( stream ) => stream . category !== 'athletics' )
7353 . map ( ( stream ) => {
7454 let date : Moment = moment ( stream . starttime )
@@ -84,38 +64,33 @@ export const StreamListView = (): JSX.Element => {
8464 $groupBy : group ,
8565 }
8666 } )
87-
88- let grouped = groupBy ( data , ( j ) => j . $groupBy )
89- let mapped = toPairs ( grouped ) . map ( ( [ title , data ] ) => ( { title, data} ) )
90-
91- setStreams ( mapped )
92- }
93-
94- let keyExtractor = ( item : StreamType ) => item . eid
95-
96- let renderItem = ( { item} : { item : StreamType } ) => < StreamRow stream = { item } />
97-
98- if ( loading ) {
99- return < LoadingView />
100- }
67+ } , [ data ] )
10168
10269 if ( error ) {
103- return < NoticeView text = { `Error: ${ error . message } ` } />
70+ return (
71+ < NoticeView
72+ buttonText = "Try Again"
73+ onPress = { reload }
74+ text = { `A problem occured while loading the streams. ${ error . message } ` }
75+ />
76+ )
10477 }
10578
10679 return (
10780 < SectionList
10881 ItemSeparatorComponent = { ListSeparator }
109- ListEmptyComponent = { < NoticeView text = "No Streams" /> }
82+ ListEmptyComponent = {
83+ isLoading ? < LoadingView /> : < NoticeView text = "No streams." />
84+ }
11085 contentContainerStyle = { styles . contentContainer }
111- keyExtractor = { keyExtractor }
112- onRefresh = { refresh }
113- refreshing = { refreshing }
114- renderItem = { renderItem }
86+ keyExtractor = { ( item : StreamType ) => item . eid }
87+ onRefresh = { reload }
88+ refreshing = { isPending && ! isInitial }
89+ renderItem = { ( { item } : { item : StreamType } ) => < StreamRow stream = { item } /> }
11590 renderSectionHeader = { ( { section : { title} } ) => (
11691 < ListSectionHeader title = { title } />
11792 ) }
118- sections = { streams }
93+ sections = { groupStreams ( entries ) }
11994 style = { styles . listContainer }
12095 />
12196 )
0 commit comments