Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
IT2810 H21
Team 05
prosjekt4
Commits
c449c05c
Commit
c449c05c
authored
Nov 17, 2021
by
ErlendHer
Browse files
#15
add more sound loading spinner logic and fix css errors.
parent
1afca964
Changes
4
Hide whitespace changes
Inline
Side-by-side
components/FilterPane.tsx
View file @
c449c05c
...
...
@@ -59,7 +59,7 @@ const FilterPane: React.FC<FilterPaneProps> = ({
const
styles
=
StyleSheet
.
create
({
container
:
{
marginTop
:
96
,
marginTop
:
8
,
marginHorizontal
:
16
,
width
:
'
95%
'
,
display
:
'
flex
'
,
...
...
components/MovieDetailScreen.tsx
View file @
c449c05c
import
{
StatusBar
}
from
'
expo-status-bar
'
;
import
*
as
React
from
'
react
'
;
import
{
Platform
,
StyleSheet
,
Image
,
useWindowDimensions
,
Button
,
ScrollView
}
from
'
react-native
'
;
import
{
Button
,
Image
,
ScrollView
,
StyleSheet
,
useWindowDimensions
,
}
from
'
react-native
'
;
import
Lord
from
'
../assets/images/lord.jpg
'
;
import
{
MovieDetail
}
from
'
../models/movieDetail.model
'
;
import
ProfileInfo
from
'
./ProfileInfo
'
;
import
{
Text
,
View
}
from
'
./Themed
'
;
import
Lord
from
"
../assets/images/lord.jpg
"
;
import
{
movies
}
from
'
../store/ducks/movies
'
;
import
KeyStatisticsItem
from
'
./KeyStatisticsItem
'
;
import
Seperator
from
'
./Seperator
'
;
import
Pill
from
'
./Pill
'
;
import
WrapperStatistic
from
'
antd/lib/statistic/Statistic
'
;
import
Seperator
from
'
./Seperator
'
;
import
{
Text
,
View
}
from
'
./Themed
'
;
interface
MovieDetailProps
{
movieDetail
:
MovieDetail
;
}
export
default
function
MovieDetailScreen
({
movieDetail
}:
MovieDetailProps
)
{
const
{
height
}
=
useWindowDimensions
();
export
default
function
MovieDetailScreen
({
movieDetail
}:
MovieDetailProps
)
{
const
{
height
}
=
useWindowDimensions
();
const
styles
=
StyleSheet
.
create
({
root
:
{
...
...
@@ -28,10 +30,10 @@ export default function MovieDetailScreen({movieDetail}: MovieDetailProps) {
height
:
350
,
},
container
:
{
width
:
"
100%
"
,
width
:
'
100%
'
,
padding
:
15
,
marginVertical
:
5
,
alignItems
:
"
center
"
,
alignItems
:
'
center
'
,
borderRadius
:
5
,
},
subText
:
{
...
...
@@ -45,98 +47,101 @@ export default function MovieDetailScreen({movieDetail}: MovieDetailProps) {
flex
:
1
,
flexDirection
:
'
row
'
,
flexWrap
:
'
wrap
'
,
alignItems
:
'
flex-start
'
alignItems
:
'
flex-start
'
,
},
genres
:
{
flex
:
1
,
flexWrap
:
"
wrap
"
,
flexDirection
:
"
row
"
,
flex
:
1
,
flexWrap
:
'
wrap
'
,
flexDirection
:
'
row
'
,
marginTop
:
15
,
paddingBottom
:
"
1rem
"
,
}
})
paddingBottom
:
'
1rem
'
,
},
});
return
(
<
ScrollView
style
=
{
styles
.
root
}
>
<
View
style
=
{
{
alignItems
:
"
center
"
}
}
>
<
Image
source
=
{
Lord
}
style
=
{
[
styles
.
logo
,
{
height
:
height
*
0.5
}]
}
resizeMode
=
"contain"
/>
</
View
>
<
View
style
=
{
{
alignItems
:
"
center
"
}
}
>
Stars -
{
'
>
'
}
To be implemented
</
View
>
<
View
>
<
Button
onPress
=
{
()
=>
console
.
log
(
"
To be implemented
"
)
}
title
=
{
"
Give a rating
"
}
/>
</
View
>
<
View
style
=
{
styles
.
key_number_container
}
>
<
KeyStatisticsItem
title
=
"RUNTIME"
statistics
=
{
String
(
movieDetail
.
runtime
)
}
/>
<
KeyStatisticsItem
title
=
"IMDG-RATING"
statistics
=
{
String
(
movieDetail
.
avgRating
)
}
/>
<
KeyStatisticsItem
title
=
"RATING"
statistics
=
{
String
(
movieDetail
.
avgRating
)
}
/>
<
KeyStatisticsItem
title
=
"PGA-RATING"
statistics
=
{
String
(
movieDetail
.
avgRating
)
}
/>
</
View
>
<
Seperator
/>
<
View
>
<
Text
style
=
{
{
fontSize
:
22
}
}
>
{
movieDetail
.
year
}
</
Text
>
<
Text
style
=
{
{
fontSize
:
18
}
}
>
{
movieDetail
.
title
}
</
Text
>
<
View
style
=
{
styles
.
genres
}
>
{
movieDetail
.
genres
.
map
((
genre
)
=>
<
Pill
text
=
{
genre
}
>
genre
</
Pill
>)
}
</
View
>
</
View
>
<
Seperator
/>
<
Text
>
{
movieDetail
.
plot
}
</
Text
>
<
Seperator
/>
{
LabelAndText
(
"
DIRECTORS
"
,
"
Joshua King
"
)
}
<
Seperator
/>
{
LabelAndText
(
"
PRODUCTION
"
,
"
Paramount Pictures, W365
"
)
}
<
Seperator
/>
{
LabelAndText
(
"
WRITERS
"
,
"
Phil Hay, Matt Manfredi, Peter Chung
"
)
}
<
Seperator
/>
{
LabelAndText
(
"
STARRING ACTORS
"
,
"
Charlize Theron, Frances McDormand, Sophie Okonedo
"
)
}
<
Seperator
/>
<
View
style
=
{
{
alignItems
:
'
center
'
}
}
>
<
Image
source
=
{
Lord
}
style
=
{
[
styles
.
logo
,
{
height
:
height
*
0.5
}]
}
resizeMode
=
"contain"
/>
</
View
>
<
View
style
=
{
{
alignItems
:
'
center
'
}
}
>
Stars -
{
'
>
'
}
To be implemented
</
View
>
<
View
>
<
Button
onPress
=
{
()
=>
console
.
log
(
'
To be implemented
'
)
}
title
=
{
'
Give a rating
'
}
/>
</
View
>
<
View
style
=
{
styles
.
key_number_container
}
>
<
KeyStatisticsItem
title
=
"RUNTIME"
statistics
=
{
String
(
movieDetail
.
runtime
)
}
/>
<
KeyStatisticsItem
title
=
"IMDG-RATING"
statistics
=
{
String
(
movieDetail
.
avgRating
)
}
/>
<
KeyStatisticsItem
title
=
"RATING"
statistics
=
{
String
(
movieDetail
.
avgRating
)
}
/>
<
KeyStatisticsItem
title
=
"PGA-RATING"
statistics
=
{
String
(
movieDetail
.
avgRating
)
}
/>
</
View
>
<
Seperator
/>
<
View
>
<
Text
style
=
{
{
fontSize
:
22
}
}
>
{
movieDetail
.
year
}
</
Text
>
<
Text
style
=
{
{
fontSize
:
18
}
}
>
{
movieDetail
.
title
}
</
Text
>
<
View
style
=
{
styles
.
genres
}
>
{
movieDetail
.
genres
.
map
((
genre
)
=>
(
<
Pill
text
=
{
genre
}
>
genre
</
Pill
>
))
}
</
View
>
</
View
>
<
Seperator
/>
<
Text
>
{
movieDetail
.
plot
}
</
Text
>
<
Seperator
/>
{
LabelAndText
(
'
DIRECTORS
'
,
'
Joshua King
'
)
}
<
Seperator
/>
{
LabelAndText
(
'
PRODUCTION
'
,
'
Paramount Pictures, W365
'
)
}
<
Seperator
/>
{
LabelAndText
(
'
WRITERS
'
,
'
Phil Hay, Matt Manfredi, Peter Chung
'
)
}
<
Seperator
/>
{
LabelAndText
(
'
STARRING ACTORS
'
,
'
Charlize Theron, Frances McDormand, Sophie Okonedo
'
)
}
<
Seperator
/>
<
View
>
Reviews -
{
'
>
'
}
To be implemented
</
View
>
<
View
>
Reviews -
{
'
>
'
}
To be implemented
</
View
>
</
ScrollView
>
);
}
function
LabelAndText
(
label
:
string
,
text
:
string
){
const
styles
=
StyleSheet
.
create
({
function
LabelAndText
(
label
:
string
,
text
:
string
)
{
const
styles
=
StyleSheet
.
create
({
label
:
{
textTransform
:
"
capitalize
"
,
fontWeight
:
"
bold
"
,
textTransform
:
'
capitalize
'
,
fontWeight
:
'
bold
'
,
marginRight
:
5
,
},
container
:
{
flex
:
1
,
flexWrap
:
"
wrap
"
,
flexDirection
:
"
row
"
,
}
})
flexWrap
:
'
wrap
'
,
flexDirection
:
'
row
'
,
}
,
})
;
return
(
return
(
<
View
style
=
{
styles
.
container
}
>
<
Text
style
=
{
styles
.
label
}
>
{
label
}
:
</
Text
>
<
Text
>
{
text
}
</
Text
>
<
Text
style
=
{
styles
.
label
}
>
{
label
}
:
</
Text
>
<
Text
>
{
text
}
</
Text
>
</
View
>
)
}
\ No newline at end of file
);
}
components/MovieTable.tsx
View file @
c449c05c
import
React
,
{
useEffect
,
useState
}
from
"
react
"
;
import
{
FlatList
,
StyleSheet
,
Text
,
View
}
from
"
react-native
"
;
import
{
SafeAreaView
}
from
"
react-native-safe-area-context
"
;
import
{
useSelector
}
from
"
react-redux
"
;
import
{
FetchMovieParams
,
MovieEntity
}
from
"
../store/ducks/movies/types
"
;
import
{
ApplicationState
}
from
"
../store/interface
"
;
import
MovieCard
from
"
./MovieCard
"
;
import
React
,
{
useEffect
,
useState
}
from
'
react
'
;
import
{
ActivityIndicator
,
FlatList
,
StyleSheet
,
Text
,
View
,
}
from
'
react-native
'
;
import
{
useSelector
}
from
'
react-redux
'
;
import
{
FetchMovieParams
,
MovieEntity
}
from
'
../store/ducks/movies/types
'
;
import
{
ApplicationState
}
from
'
../store/interface
'
;
import
MovieCard
from
'
./MovieCard
'
;
export
type
MovieTableProps
=
{
path
:
string
;
query
:
FetchMovieParams
;
movies
:
MovieEntity
[];
currentPage
:
number
;
moviesLoading
:
boolean
;
onPageScroll
:
()
=>
void
;
};
...
...
@@ -18,59 +24,95 @@ const MovieTable: React.FC<MovieTableProps> = ({
path
,
query
,
movies
,
moviesLoading
,
currentPage
,
onPageScroll
,
}:
MovieTableProps
)
=>
{
const
{
data
,
documentCount
,
loading
,
error
}
=
useSelector
(
const
{
documentCount
}
=
useSelector
(
({
movies
}:
ApplicationState
)
=>
movies
);
const
[
isFull
,
setIsfull
]
=
useState
(
false
);
useEffect
(()
=>
{
setIsfull
(
!
(
movies
.
length
<
documentCount
));
},
[
movies
]);
return
(
<
View
style
=
{
styles
.
movieList
}
>
<
FlatList
style
=
{
{
width
:
"
100%
"
,
height
:
"
100%
"
}
}
columnWrapperStyle
=
{
{
flex
:
1
,
justifyContent
:
"
space-around
"
}
}
contentContainerStyle
=
{
styles
.
movieItems
}
data
=
{
movies
}
numColumns
=
{
2
}
keyExtractor
=
{
(
movie
)
=>
movie
.
id
}
onEndReached
=
{
({
distanceFromEnd
})
=>
{
// Prevent bug where onEndReached is called multiple times
if
(
distanceFromEnd
<
0
)
return
;
// Prevent fetching if all movies are loaded
if
(
currentPage
>=
Math
.
ceil
(
documentCount
/
query
.
perPage
))
return
;
// Dispatch scroll event to parent component
onPageScroll
();
}
}
onEndReachedThreshold
=
{
1.5
}
initialNumToRender
=
{
query
.
perPage
}
showsVerticalScrollIndicator
=
{
false
}
renderItem
=
{
({
item
})
=>
<
MovieCard
movie
=
{
item
}
/>
}
ListFooterComponent
=
{
()
=>
(
<>
{
loading
&&
<
Text
style
=
{
styles
.
loading
}
>
Loading...
</
Text
>
}
</>
)
}
/>
{
movies
.
length
>
0
||
moviesLoading
?
(
<
FlatList
style
=
{
styles
.
movieFlatList
}
columnWrapperStyle
=
{
{
flex
:
1
,
justifyContent
:
'
space-around
'
}
}
contentContainerStyle
=
{
styles
.
movieItems
}
data
=
{
movies
}
numColumns
=
{
2
}
keyExtractor
=
{
(
movie
)
=>
movie
.
id
}
onEndReached
=
{
({
distanceFromEnd
})
=>
{
// Prevent bug where onEndReached is called multiple times
if
(
distanceFromEnd
<
0
)
return
;
// Prevent fetching if all movies are loaded
if
(
currentPage
>=
Math
.
ceil
(
documentCount
/
query
.
perPage
))
{
setIsfull
(
true
);
return
;
}
setIsfull
(
false
);
// Dispatch scroll event to parent component
onPageScroll
();
}
}
onEndReachedThreshold
=
{
1.5
}
initialNumToRender
=
{
query
.
perPage
}
showsVerticalScrollIndicator
=
{
false
}
renderItem
=
{
({
item
})
=>
<
MovieCard
movie
=
{
item
}
/>
}
ListFooterComponent
=
{
()
=>
(
<>
{
!
isFull
?
(
<>
<
Text
style
=
{
styles
.
loading
}
>
Loading...
</
Text
>
<
ActivityIndicator
size
=
"large"
color
=
"#00ff00"
/>
</>
)
:
(
<>
{
movies
.
length
>
4
&&
(
<
Text
style
=
{
styles
.
loading
}
>
--- No more movies ---
</
Text
>
)
}
</>
)
}
</>
)
}
/>
)
:
(
<
Text
style
=
{
styles
.
loading
}
>
No Movies Found
</
Text
>
)
}
</
View
>
);
};
const
styles
=
StyleSheet
.
create
({
movieItems
:
{
justifyContent
:
"
center
"
,
justifyContent
:
'
center
'
,
flexGrow
:
1
/
2
,
backgroundColor
:
"
white
"
,
backgroundColor
:
'
white
'
,
},
movieFlatList
:
{
width
:
'
100%
'
,
height
:
'
100%
'
,
marginBottom
:
4
,
},
movieList
:
{
marginTop
:
4
,
width
:
"
95%
"
,
height
:
"
95%
"
,
display
:
"
flex
"
,
alignItems
:
"
center
"
,
textAlign
:
"
center
"
,
width
:
'
95%
'
,
height
:
'
95%
'
,
alignItems
:
'
center
'
,
textAlign
:
'
center
'
,
flex
:
1
,
},
loading
:
{
fontWeight
:
"
bold
"
,
marginBottom
:
8
,
flex
:
1
,
fontSize
:
20
,
fontWeight
:
'
bold
'
,
marginBottom
:
16
,
textAlign
:
'
center
'
,
},
});
...
...
screens/MovieTableScreen.tsx
View file @
c449c05c
import
React
,
{
useState
,
useEffect
,
useCallback
}
from
"
react
"
;
import
{
StyleSheet
}
from
"
react-native
"
;
import
{
useDispatch
,
useSelector
}
from
"
react-redux
"
;
import
FilterPane
,
{
FilterPaneProps
}
from
"
../components/FilterPane
"
;
import
React
,
{
useState
,
useEffect
,
useCallback
}
from
'
react
'
;
import
{
StyleSheet
}
from
'
react-native
'
;
import
{
useDispatch
,
useSelector
}
from
'
react-redux
'
;
import
FilterPane
,
{
FilterPaneProps
}
from
'
../components/FilterPane
'
;
import
MovieTable
,
{
MovieTableProps
}
from
"
../components/MovieTable
"
;
import
{
View
}
from
"
../components/Themed
"
;
import
MovieTable
,
{
MovieTableProps
}
from
'
../components/MovieTable
'
;
import
{
View
}
from
'
../components/Themed
'
;
import
{
FilterKeys
,
FilterValues
,
SortDirection
,
SortKeys
,
}
from
"
../constants/filterOptions/interface
"
;
import
{
fetchMovies
}
from
"
../store/ducks/movies/actions
"
;
}
from
'
../constants/filterOptions/interface
'
;
import
{
fetchMovies
}
from
'
../store/ducks/movies/actions
'
;
import
{
FetchMovieParams
,
initialQuery
,
MovieEntity
,
}
from
"
../store/ducks/movies/types
"
;
import
{
ApplicationState
}
from
"
../store/interface
"
;
import
{
RootTabScreenProps
}
from
"
../types
"
;
}
from
'
../store/ducks/movies/types
'
;
import
{
ApplicationState
}
from
'
../store/interface
'
;
import
{
RootTabScreenProps
}
from
'
../types
'
;
export
default
function
MovieTableScreen
({
navigation
,
}:
RootTabScreenProps
<
"
Movies
"
>
)
{
}:
RootTabScreenProps
<
'
Movies
'
>
)
{
const
dispatch
=
useDispatch
();
const
[
currentPage
,
setCurrentPage
]
=
useState
<
number
>
(
1
);
const
[
movies
,
setMovies
]
=
useState
<
MovieEntity
[]
>
([]);
const
[
query
,
setQuery
]
=
useState
<
FetchMovieParams
>
(
initialQuery
);
const
[
moviesLoading
,
setMoviesLoading
]
=
useState
<
boolean
>
(
false
);
const
{
data
,
loading
,
error
}
=
useSelector
(
({
movies
}:
ApplicationState
)
=>
movies
...
...
@@ -50,6 +51,7 @@ export default function MovieTableScreen({
});
setMovies
([...
moviesToAdd
]);
}
setMoviesLoading
(
false
);
// Reset loaded content when component unmounts
return
()
=>
{
setMovies
([]);
...
...
@@ -60,6 +62,7 @@ export default function MovieTableScreen({
// Update the query state with new values
// Reset pagination increments and loaded movies, if reset is true
function
updateQuery
(
newQuery
:
FetchMovieParams
,
reset
=
true
)
{
setMoviesLoading
(
true
);
let
{
page
,
...
other
}
=
newQuery
;
if
(
reset
)
{
setMovies
([]);
...
...
@@ -117,10 +120,11 @@ export default function MovieTableScreen({
// Map properties to the movie table component
const
mapStateToMovieTableProps
:
MovieTableProps
=
{
path
:
"
/screens/TabOneScreen.tsx
"
,
path
:
'
/screens/TabOneScreen.tsx
'
,
query
,
movies
,
currentPage
,
moviesLoading
,
onPageScroll
:
useCallback
(()
=>
handlePageScroll
(),
[
query
]),
};
...
...
@@ -135,19 +139,18 @@ export default function MovieTableScreen({
const
styles
=
StyleSheet
.
create
({
container
:
{
flex
:
1
,
display
:
"
flex
"
,
flexDirection
:
"
column
"
,
alignItems
:
"
center
"
,
justifyContent
:
"
center
"
,
width
:
"
100%
"
,
flexDirection
:
'
column
'
,
alignItems
:
'
center
'
,
justifyContent
:
'
center
'
,
width
:
'
100%
'
,
},
title
:
{
fontSize
:
20
,
fontWeight
:
"
bold
"
,
fontWeight
:
'
bold
'
,
},
separator
:
{
marginVertical
:
30
,
height
:
1
,
width
:
"
90%
"
,
width
:
'
90%
'
,
},
});
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment