Showing
12 changed files
with
254 additions
and
0 deletions
App.js
0 → 100644
| 1 | +import { useState } from "react"; | ||
| 2 | +import { StyleSheet, View, FlatList, Button } from "react-native"; | ||
| 3 | +import { StatusBar } from "expo-status-bar"; | ||
| 4 | + | ||
| 5 | +import GoalItem from "./components/GoalItem"; | ||
| 6 | +import GoalInput from "./components/GoalInput"; | ||
| 7 | + | ||
| 8 | +export default function App() { | ||
| 9 | + const [modalIsVisible, setModalIsVisible] = useState(false); | ||
| 10 | + const [goals, setGoals] = useState([]); | ||
| 11 | + | ||
| 12 | + function startAddGoalHandler() { | ||
| 13 | + setModalIsVisible(true); | ||
| 14 | + } | ||
| 15 | + | ||
| 16 | + function endAddGoalHandler() { | ||
| 17 | + setModalIsVisible(false); | ||
| 18 | + } | ||
| 19 | + | ||
| 20 | + function addGoalHandler(enteredGoalText) { | ||
| 21 | + setGoals((currentGoals) => [ | ||
| 22 | + ...currentGoals, | ||
| 23 | + { text: enteredGoalText, id: Math.random().toString() }, | ||
| 24 | + ]); | ||
| 25 | + endAddGoalHandler(); | ||
| 26 | + } | ||
| 27 | + | ||
| 28 | + function deleteGoalHandler(id) { | ||
| 29 | + setGoals((currentGoals) => { | ||
| 30 | + return currentGoals.filter((goal) => goal.id !== id); | ||
| 31 | + }); | ||
| 32 | + } | ||
| 33 | + | ||
| 34 | + return ( | ||
| 35 | + <> | ||
| 36 | + <StatusBar style="light" /> | ||
| 37 | + <View style={styles.appContainer}> | ||
| 38 | + <Button | ||
| 39 | + title="Add New Goal" | ||
| 40 | + color="#a065ec" | ||
| 41 | + onPress={startAddGoalHandler} | ||
| 42 | + /> | ||
| 43 | + <GoalInput | ||
| 44 | + visible={modalIsVisible} | ||
| 45 | + onAddGoal={addGoalHandler} | ||
| 46 | + onCancel={endAddGoalHandler} | ||
| 47 | + /> | ||
| 48 | + <View style={styles.goalsContainer}> | ||
| 49 | + <FlatList | ||
| 50 | + data={goals} | ||
| 51 | + renderItem={(itemData) => { | ||
| 52 | + return ( | ||
| 53 | + <GoalItem | ||
| 54 | + text={itemData.item.text} | ||
| 55 | + id={itemData.item.id} | ||
| 56 | + onDeleteItem={deleteGoalHandler} | ||
| 57 | + /> | ||
| 58 | + ); | ||
| 59 | + }} | ||
| 60 | + keyExtractor={(item, index) => { | ||
| 61 | + return item.id; | ||
| 62 | + }} | ||
| 63 | + alwaysBounceVertical={false} | ||
| 64 | + /> | ||
| 65 | + </View> | ||
| 66 | + </View> | ||
| 67 | + </> | ||
| 68 | + ); | ||
| 69 | +} | ||
| 70 | + | ||
| 71 | +const styles = StyleSheet.create({ | ||
| 72 | + appContainer: { | ||
| 73 | + flex: 1, | ||
| 74 | + paddingTop: 50, | ||
| 75 | + paddingHorizontal: 16, | ||
| 76 | + }, | ||
| 77 | + goalsContainer: { | ||
| 78 | + flex: 6, | ||
| 79 | + }, | ||
| 80 | +}); |
app.json
0 → 100644
| 1 | +{ | ||
| 2 | + "expo": { | ||
| 3 | + "name": "RNC", | ||
| 4 | + "slug": "RNC", | ||
| 5 | + "version": "1.0.0", | ||
| 6 | + "orientation": "portrait", | ||
| 7 | + "icon": "./assets/icon.png", | ||
| 8 | + "backgroundColor": "#1e085a", | ||
| 9 | + "splash": { | ||
| 10 | + "image": "./assets/splash.png", | ||
| 11 | + "resizeMode": "contain", | ||
| 12 | + "backgroundColor": "#ffffff" | ||
| 13 | + }, | ||
| 14 | + "updates": { | ||
| 15 | + "fallbackToCacheTimeout": 0 | ||
| 16 | + }, | ||
| 17 | + "assetBundlePatterns": ["**/*"], | ||
| 18 | + "ios": { | ||
| 19 | + "supportsTablet": true | ||
| 20 | + }, | ||
| 21 | + "android": { | ||
| 22 | + "adaptiveIcon": { | ||
| 23 | + "foregroundImage": "./assets/adaptive-icon.png", | ||
| 24 | + "backgroundColor": "#FFFFFF" | ||
| 25 | + } | ||
| 26 | + }, | ||
| 27 | + "web": { | ||
| 28 | + "favicon": "./assets/favicon.png" | ||
| 29 | + } | ||
| 30 | + } | ||
| 31 | +} |
assets/adaptive-icon.png
0 → 100644
17.1 KB
assets/favicon.png
0 → 100644
1.43 KB
assets/icon.png
0 → 100644
21.9 KB
assets/images/goal.png
0 → 100644
18.7 KB
assets/splash.png
0 → 100644
46.2 KB
babel.config.js
0 → 100644
components/GoalInput.js
0 → 100644
| 1 | +import { useState } from "react"; | ||
| 2 | +import { | ||
| 3 | + View, | ||
| 4 | + TextInput, | ||
| 5 | + Button, | ||
| 6 | + StyleSheet, | ||
| 7 | + Modal, | ||
| 8 | + Image, | ||
| 9 | +} from "react-native"; | ||
| 10 | + | ||
| 11 | +function GoalInput(props) { | ||
| 12 | + const [enteredGoalText, setEnteredGoalText] = useState(""); | ||
| 13 | + | ||
| 14 | + function goalInputHandler(enteredText) { | ||
| 15 | + setEnteredGoalText(enteredText); | ||
| 16 | + } | ||
| 17 | + | ||
| 18 | + function addGoalHandler() { | ||
| 19 | + props.onAddGoal(enteredGoalText); | ||
| 20 | + setEnteredGoalText(""); | ||
| 21 | + } | ||
| 22 | + | ||
| 23 | + return ( | ||
| 24 | + <Modal visible={props.visible} animationType="slide"> | ||
| 25 | + <View style={styles.inputContainer}> | ||
| 26 | + <Image | ||
| 27 | + style={styles.image} | ||
| 28 | + source={require("../assets/images/goal.png")} | ||
| 29 | + /> | ||
| 30 | + <TextInput | ||
| 31 | + style={styles.textInput} | ||
| 32 | + placeholder="Your goal" | ||
| 33 | + onChangeText={goalInputHandler} | ||
| 34 | + value={enteredGoalText} | ||
| 35 | + /> | ||
| 36 | + <View style={styles.buttonContainer}> | ||
| 37 | + <View style={styles.button}> | ||
| 38 | + <Button title="Cancel" onPress={props.onCancel} color="#f31282" /> | ||
| 39 | + </View> | ||
| 40 | + <View style={styles.button}> | ||
| 41 | + <Button title="Add Goal" onPress={addGoalHandler} color="#b180f0" /> | ||
| 42 | + </View> | ||
| 43 | + </View> | ||
| 44 | + </View> | ||
| 45 | + </Modal> | ||
| 46 | + ); | ||
| 47 | +} | ||
| 48 | + | ||
| 49 | +export default GoalInput; | ||
| 50 | + | ||
| 51 | +const styles = StyleSheet.create({ | ||
| 52 | + inputContainer: { | ||
| 53 | + flex: 1, | ||
| 54 | + justifyContent: "center", | ||
| 55 | + alignItems: "center", | ||
| 56 | + padding: 16, | ||
| 57 | + backgroundColor: "#311b6b", | ||
| 58 | + }, | ||
| 59 | + image: { | ||
| 60 | + width: 100, | ||
| 61 | + height: 100, | ||
| 62 | + margin: 20, | ||
| 63 | + }, | ||
| 64 | + textInput: { | ||
| 65 | + borderWidth: 1, | ||
| 66 | + borderColor: "#e4d0ff", | ||
| 67 | + backgroundColor: "#e4d0ff", | ||
| 68 | + color: "#120438", | ||
| 69 | + borderRadius: 6, | ||
| 70 | + width: "100%", | ||
| 71 | + padding: 8, | ||
| 72 | + }, | ||
| 73 | + buttonContainer: { | ||
| 74 | + marginTop: 16, | ||
| 75 | + flexDirection: "row", | ||
| 76 | + }, | ||
| 77 | + button: { | ||
| 78 | + width: 100, | ||
| 79 | + marginHorizontal: 8, | ||
| 80 | + }, | ||
| 81 | +}); |
components/GoalItem.js
0 → 100644
| 1 | +import { StyleSheet, View, Text, Pressable } from "react-native"; | ||
| 2 | + | ||
| 3 | +function GoalItem(props) { | ||
| 4 | + return ( | ||
| 5 | + <View style={styles.goalItem}> | ||
| 6 | + <Pressable | ||
| 7 | + android_ripple={{ color: "#ddddd" }} | ||
| 8 | + onPress={props.onDeleteItem.bind(this, props.id)} | ||
| 9 | + style={({ pressed }) => pressed && styles.pressedItem} | ||
| 10 | + > | ||
| 11 | + <Text style={styles.goalText}>{props.text}</Text> | ||
| 12 | + </Pressable> | ||
| 13 | + </View> | ||
| 14 | + ); | ||
| 15 | +} | ||
| 16 | + | ||
| 17 | +export default GoalItem; | ||
| 18 | + | ||
| 19 | +const styles = StyleSheet.create({ | ||
| 20 | + goalItem: { | ||
| 21 | + margin: 8, | ||
| 22 | + borderRadius: 6, | ||
| 23 | + backgroundColor: "#5e0acc", | ||
| 24 | + }, | ||
| 25 | + pressedItem: { | ||
| 26 | + opacity: 0.5, | ||
| 27 | + }, | ||
| 28 | + goalText: { | ||
| 29 | + color: "white", | ||
| 30 | + padding: 8, | ||
| 31 | + }, | ||
| 32 | +}); |
package.json
0 → 100644
| 1 | +{ | ||
| 2 | + "name": "rnc", | ||
| 3 | + "version": "1.0.0", | ||
| 4 | + "main": "node_modules/expo/AppEntry.js", | ||
| 5 | + "scripts": { | ||
| 6 | + "start": "expo start", | ||
| 7 | + "android": "expo start --android", | ||
| 8 | + "ios": "expo start --ios", | ||
| 9 | + "web": "expo start --web", | ||
| 10 | + "eject": "expo eject" | ||
| 11 | + }, | ||
| 12 | + "dependencies": { | ||
| 13 | + "expo": "~45.0.0", | ||
| 14 | + "expo-status-bar": "~1.3.0", | ||
| 15 | + "react": "17.0.2", | ||
| 16 | + "react-dom": "17.0.2", | ||
| 17 | + "react-native": "0.68.2", | ||
| 18 | + "react-native-web": "0.17.7" | ||
| 19 | + }, | ||
| 20 | + "devDependencies": { | ||
| 21 | + "@babel/core": "^7.12.9" | ||
| 22 | + }, | ||
| 23 | + "private": true | ||
| 24 | +} |
yarn.lock
0 → 100644
This diff could not be displayed because it is too large.
-
Please register or login to post a comment