-
Couldn't load subscription status.
- Fork 311
Week 16 - React Native App - Jessica Sandler #300
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
5f4b8c9
887c4da
1293489
93aee21
9f3ea62
c43f18e
2bf8336
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,25 +1,59 @@ | ||
| import React from 'react'; | ||
| import styled from 'styled-components/native'; | ||
| import React from 'react' | ||
| import { NavigationContainer } from '@react-navigation/native' | ||
| import { createBottomTabNavigator } from '@react-navigation/bottom-tabs' | ||
| import Ionicons from '@expo/vector-icons/Ionicons' | ||
| import { FontAwesome5 } from '@expo/vector-icons'; | ||
|
|
||
| const Container = styled.View` | ||
| flex: 1; | ||
| background-color: papayawhip; | ||
| justify-content: center; | ||
| align-items: center; | ||
| `; | ||
| import { Colors } from './assets/colors'; | ||
|
|
||
| const Title = styled.Text` | ||
| font-size: 24px; | ||
| color: palevioletred; | ||
| `; | ||
| import StartScreen from './screens/StartScreen' | ||
| import DogScreen from './screens/DogScreen' | ||
| import GameScreen from './screens/GameScreen' | ||
|
|
||
| const Tab = createBottomTabNavigator() | ||
|
|
||
| const App = () => { | ||
|
|
||
| return ( | ||
| <Container> | ||
| <Title>This is your cool app!</Title> | ||
| <Title>Go to App.js and start coding</Title> | ||
| <Title>💅💅💅</Title> | ||
| </Container> | ||
| <NavigationContainer> | ||
| <Tab.Navigator | ||
| screenOptions={({ route }) => ({ | ||
| tabBarIcon: ({ focused, color, size }) => { | ||
| if (route.name === 'Home') { | ||
|
Comment on lines
+18
to
+22
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I really like your tab navigation with the tab function in the bottom. |
||
| return ( | ||
| <Ionicons | ||
| name='home' | ||
| size={size} | ||
| color={color} | ||
| /> | ||
| ); | ||
| } else if (route.name === 'Game') { | ||
| return ( | ||
| <Ionicons | ||
| name='ios-game-controller' | ||
| size={size} | ||
| color={color} | ||
| /> | ||
| ); | ||
| } else if (route.name === 'Dogs') { | ||
| return ( | ||
| <FontAwesome5 | ||
| name='dog' | ||
| size={size} | ||
| color={color} | ||
| /> | ||
| ); | ||
| } | ||
| }, | ||
| tabBarInactiveTintColor: 'darkgrey', | ||
| tabBarActiveTintColor: 'black' | ||
| })} | ||
| > | ||
| <Tab.Screen name="Home" component={StartScreen} /> | ||
| <Tab.Screen name="Game" component={GameScreen} /> | ||
| <Tab.Screen name="Dogs" component={DogScreen} /> | ||
| </Tab.Navigator> | ||
| </NavigationContainer> | ||
| ); | ||
| }; | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,13 +1,7 @@ | ||
| # Project React Native App 📱 | ||
|
|
||
| Replace this readme with your own information about your project. | ||
|
|
||
| Start by briefly describing the assignment in a sentence or two. Keep it short and to the point. | ||
|
|
||
| ## The problem | ||
|
|
||
| Describe how you approached to problem, and what tools and techniques you used to solve it. How did you plan? What technologies did you use? If you had more time, what would be next? | ||
| This week's project was an introduction to React Native. I created a multiscreen app using React Navigation where you can either choose to play a version of the Labyrinth game (last week's project) or get random images from Dog API (https://dog.ceo/dog-api/). | ||
|
|
||
| ## View it live | ||
|
|
||
| Every project should be deployed somewhere. Be sure to include the link to the deployed project so that the viewer can click around and see what it's all about. | ||
| https://expo.dev/@jessand77/project-react-native-app?serviceType=classic&distribution=expo-go |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| export const Colors = { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Cool that you could store this in a separate file and then import it |
||
| white: '#fff', | ||
| black: '#000', | ||
| grain: '#D7CEC7', | ||
| blackboard: '#565656', | ||
| oxblood: '#76323F', | ||
| tan: '#C09F80' | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| import React from 'react' | ||
| import { Text, StyleSheet, TouchableOpacity } from 'react-native' | ||
| import { Colors } from '../assets/colors' | ||
|
|
||
| const DirectionButton = ({ title, onPress }) => { | ||
| return ( | ||
| <TouchableOpacity style={styles.button} onPress={onPress}> | ||
| <Text style={styles.text}>{title}</Text> | ||
| </TouchableOpacity> | ||
| ) | ||
| } | ||
|
|
||
| const styles = StyleSheet.create({ | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nice job with the stylesheet! :D |
||
| button: { | ||
| alignItems: 'center', | ||
| justifyContent: 'center', | ||
| marginVertical: 10, | ||
| paddingVertical: 12, | ||
| paddingHorizontal: 32, | ||
| borderRadius: 4, | ||
| elevation: 3, | ||
| backgroundColor: Colors.blackboard, | ||
| }, | ||
| text: { | ||
| fontSize: 16, | ||
| lineHeight: 21, | ||
| fontWeight: 'bold', | ||
| letterSpacing: 0.25, | ||
| color: Colors.white | ||
| }, | ||
| }); | ||
|
|
||
| export default DirectionButton | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| import React from 'react' | ||
| import { StyleSheet, View } from 'react-native'; | ||
| import { useSelector } from 'react-redux'; | ||
|
|
||
| import Loader from './Loader'; | ||
| import StartGame from './StartGame'; | ||
| import PlayGame from './PlayGame'; | ||
| import { Colors } from '../assets/colors'; | ||
|
|
||
| const Game = () => { | ||
|
|
||
| const username = useSelector(store => store.game.username) | ||
| const isLoading = useSelector(store => store.game.loading) | ||
|
|
||
| if (isLoading) { | ||
| return <Loader /> | ||
| } | ||
|
|
||
| return ( | ||
| <View style={styles.screenContainer}> | ||
| {!username ? <StartGame /> : <PlayGame />} | ||
| </View> | ||
| ); | ||
| } | ||
|
|
||
| const styles = StyleSheet.create({ | ||
| screenContainer: { | ||
| flex: 1, | ||
| backgroundColor: Colors.grain, | ||
| alignItems: 'center', | ||
| justifyContent: 'center', | ||
| }, | ||
| }); | ||
|
|
||
| export default Game |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| import React from 'react' | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good with a loader so the user can see something when there is waiting time :D |
||
| import { StyleSheet, View, ActivityIndicator } from 'react-native'; | ||
| import { useSelector } from 'react-redux'; | ||
| import { Colors } from '../assets/colors'; | ||
|
|
||
| const Loader = () => { | ||
|
|
||
| const isLoading = useSelector(store => store.game.loading) | ||
|
|
||
| return ( | ||
| isLoading && ( | ||
| <View style={styles.container}> | ||
| <ActivityIndicator size="large" color={Colors.oxblood} /> | ||
| </View> | ||
| ) | ||
| ) | ||
| } | ||
|
|
||
| const styles = StyleSheet.create({ | ||
| container: { | ||
| flex: 1, | ||
| backgroundColor: Colors.grain, | ||
| alignItems: 'center', | ||
| justifyContent: 'center', | ||
| }, | ||
| }); | ||
|
|
||
| export default Loader | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,78 @@ | ||
| import React from 'react' | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Really nice that you implemented an old project as the game :D |
||
| import { StyleSheet, Text, View, TouchableOpacity, Button } from 'react-native' | ||
| import ScalableText from 'react-native-text' | ||
| import { useSelector, useDispatch } from 'react-redux' | ||
|
|
||
| import StyledButton from './StyledButton' | ||
| import DirectionButton from './DirectionButton' | ||
|
|
||
| import game, { getNextPosition } from '../reducers/game' | ||
| import { Colors } from '../assets/colors' | ||
|
|
||
| const PlayGame = () => { | ||
|
|
||
| const currentPosition = useSelector((state) => state.game.currentPosition) | ||
| const username = useSelector((state) => state.game.username) | ||
|
|
||
| const dispatch = useDispatch() | ||
|
|
||
| const handleAction = (actionDirection) => { | ||
| dispatch(getNextPosition(actionDirection, username)) | ||
| } | ||
|
|
||
| const handleRestart = () => dispatch(game.actions.restartGame()) | ||
|
|
||
| return ( | ||
| <> | ||
| <ScalableText style={styles.currentText}>{currentPosition.description}</ScalableText> | ||
|
|
||
| {currentPosition.actions.map((action, index) => { | ||
| return ( | ||
| <View style={styles.actionsContainer} key={index}> | ||
| <ScalableText style={styles.actionText}>{action.description}</ScalableText> | ||
| <View style={styles.buttonContainer}> | ||
| <DirectionButton | ||
| title={`Go ${action.direction.toLowerCase()}`} | ||
| onPress={() => handleAction(action.direction)} | ||
| /> | ||
| </View> | ||
| </View> | ||
| ) | ||
| })} | ||
|
|
||
| <StyledButton | ||
| title="Restart" | ||
| onPress={handleRestart} | ||
| /> | ||
| </> | ||
| ) | ||
| } | ||
|
|
||
|
|
||
| const styles = StyleSheet.create({ | ||
| currentText: { | ||
| marginHorizontal: 20, | ||
| marginBottom: 10, | ||
| fontSize: 22, | ||
| fontWeight: 'bold', | ||
| color: Colors.oxblood | ||
| }, | ||
| actionsContainer: { | ||
| backgroundColor: Colors.tan, | ||
| marginHorizontal: 20, | ||
| marginVertical: 10, | ||
| padding: 10, | ||
| borderRadius: 30 | ||
| }, | ||
| actionText: { | ||
| marginHorizontal: 20, | ||
| marginVertical: 10, | ||
| fontSize: 16, | ||
| color: Colors.black, | ||
| }, | ||
| buttonContainer: { | ||
| alignItems: 'center' | ||
| }, | ||
| }); | ||
|
|
||
| export default PlayGame | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,78 @@ | ||
| import React, { useState } from 'react' | ||
| import { StyleSheet, View, Text, TextInput, TouchableOpacity } from 'react-native' | ||
| import ScalableText from 'react-native-text' | ||
| import { useDispatch } from 'react-redux' | ||
|
|
||
| import StyledButton from './StyledButton' | ||
|
|
||
| import game, { startGame } from '../reducers/game' | ||
| import { Colors } from '../assets/colors' | ||
|
|
||
|
|
||
| const StartGame = () => { | ||
|
|
||
| const [inputName, setInputName] = useState('') | ||
|
|
||
| const dispatch = useDispatch() | ||
|
|
||
| const handleSubmit = (event) => { | ||
| event.preventDefault() | ||
| dispatch(game.actions.setUsername(inputName)) | ||
| dispatch(startGame()) | ||
| setInputName('') | ||
| } | ||
|
|
||
| return ( | ||
| <View style={styles.container}> | ||
| <ScalableText style={styles.welcomeText}>The Labyrinth</ScalableText> | ||
| <ScalableText style={styles.label}>What's your name?</ScalableText> | ||
| <TextInput | ||
| style={styles.input} | ||
| maxLength={25} | ||
| value={inputName} | ||
| onChangeText={newNameInput => setInputName(newNameInput)} | ||
| /> | ||
| <StyledButton | ||
| onPress={handleSubmit} | ||
| title="Start the game" | ||
| > | ||
| </StyledButton> | ||
| </View> | ||
| ) | ||
| } | ||
|
|
||
| const styles = StyleSheet.create({ | ||
| container: { | ||
| flex: 1, | ||
| marginHorizontal: 20, | ||
| backgroundColor: Colors.grain, | ||
| alignItems: 'center', | ||
| justifyContent: 'center', | ||
| }, | ||
| welcomeText: { | ||
| fontSize: 30, | ||
| fontWeight: 'bold', | ||
| color: Colors.blackboard, | ||
| textAlign: 'center', | ||
| marginBottom: 10 | ||
| }, | ||
| label: { | ||
| fontSize: 15, | ||
| fontWeight: 'bold', | ||
| textAlign: 'center', | ||
| color: Colors.oxblood, | ||
| marginBottom: 5 | ||
| }, | ||
| input: { | ||
| height: 35, | ||
| backgroundColor: Colors.white, | ||
| marginHorizontal: 30, | ||
| marginVertical: 15, | ||
| borderWidth: 1, | ||
| borderRadius: 10, | ||
| padding: 10, | ||
| minWidth: 150 | ||
| }, | ||
| }); | ||
|
|
||
| export default StartGame |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| import React from 'react' | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Great that you created a separate component for the button |
||
| import { Text, StyleSheet, TouchableOpacity } from 'react-native' | ||
| import { Colors } from '../assets/colors' | ||
|
|
||
| const StyledButton = ({ title, onPress }) => { | ||
| return ( | ||
| <TouchableOpacity style={styles.button} onPress={onPress}> | ||
| <Text style={styles.text}>{title}</Text> | ||
| </TouchableOpacity> | ||
| ) | ||
| } | ||
|
|
||
| const styles = StyleSheet.create({ | ||
| button: { | ||
| alignItems: 'center', | ||
| justifyContent: 'center', | ||
| marginVertical: 10, | ||
| paddingVertical: 12, | ||
| paddingHorizontal: 32, | ||
| borderRadius: 4, | ||
| elevation: 3, | ||
| backgroundColor: Colors.oxblood | ||
| }, | ||
| text: { | ||
| fontSize: 16, | ||
| lineHeight: 21, | ||
| fontWeight: 'bold', | ||
| letterSpacing: 0.25, | ||
| color: Colors.white | ||
| }, | ||
| }); | ||
|
|
||
| export default StyledButton | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Really nice with different pages in your app! :D