diff --git a/app.json b/app.json index 9fdf386..8c9fb46 100644 --- a/app.json +++ b/app.json @@ -18,7 +18,10 @@ ], "ios": { "supportsTablet": true, - "bundleIdentifier": "com.tsh22.gozerowaste" + "bundleIdentifier": "com.tsh22.gozerowaste", + "infoPlist": { + "NSCameraUsageDescription": "This app uses the camera to scan QR codes to allow users to borrow reusables and earn rewards from bringing their own reusables." + } }, "android": { "adaptiveIcon": { diff --git a/components/UnsuccessBox.js b/components/UnsuccessBox.js index e4f8f74..19061ac 100644 --- a/components/UnsuccessBox.js +++ b/components/UnsuccessBox.js @@ -10,48 +10,50 @@ export default function UnsuccessBox() { const navigation = useNavigation(); return ( - - - - Oops! - Oops, there seems to be an error! - - - - + + - + Oops! + + Oops, there seems to be an error! + - + + + + - - We apologise for the inconvenience! - + - { - navigation.dispatch(StackActions.popToTop()); - navigation.navigate("Home Screen"); - }} - > - Back - - + + We apologise for the inconvenience! + + + { + navigation.dispatch(StackActions.popToTop()); + navigation.navigate("Home Screen"); + }} + > + Back + + ); } @@ -71,6 +73,7 @@ const styles = StyleSheet.create({ paddingHorizontal: 20, paddingVertical: 20, justifyContent: "center", + marginBottom: 30, }, warningText: { fontSize: 18, diff --git a/package-lock.json b/package-lock.json index b2ec615..8c5b5c8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2492,6 +2492,11 @@ "invariant": "^2.2.4" } }, + "@react-native-community/hooks": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/@react-native-community/hooks/-/hooks-2.8.1.tgz", + "integrity": "sha512-DCmCIC0Gn9m6K0Mlg2MwNmTxMEpBu5lTLsI6b/XUAv/vLGa6o+X7RhCai4FWeqkjCU36+ZOwaLzDo4NBWMXaoQ==" + }, "@react-native-community/masked-view": { "version": "0.1.10", "resolved": "https://registry.npmjs.org/@react-native-community/masked-view/-/masked-view-0.1.10.tgz", diff --git a/package.json b/package.json index 1a77827..9433977 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,7 @@ }, "dependencies": { "@react-native-community/datetimepicker": "3.2.0", + "@react-native-community/hooks": "^2.8.1", "@react-native-community/masked-view": "0.1.10", "@react-navigation/bottom-tabs": "^5.11.11", "@react-navigation/native": "^5.9.4", diff --git a/screens/BasicApi.js b/screens/BasicApi.js index 750836a..5ca4c57 100644 --- a/screens/BasicApi.js +++ b/screens/BasicApi.js @@ -2,6 +2,7 @@ import React from "react"; import { View, Text } from "react-native"; import firebase from "../database/firebaseDB"; import moment from "moment"; +import { Alert, BackHandler } from "react-native"; // Get user's coins export function getCoins(uid, setCoins) { @@ -104,3 +105,14 @@ export function renderAllDates(dates) { ; } } + +export const backActionHandler = () => { + Alert.alert("Alert!", "Are you sure you want to exit app?", [ + { + text: "Cancel", + onPress: () => null, + }, + { text: "YES", onPress: () => BackHandler.exitApp() }, + ]); + return true; +}; diff --git a/screens/HomeStack.js b/screens/HomeStack.js index 235d3eb..e6792c9 100644 --- a/screens/HomeStack.js +++ b/screens/HomeStack.js @@ -11,7 +11,7 @@ const Stack = createStackNavigator(); export default function HomeStack() { return ( - + {/* { + setDisabled(false); + }, 10000); + } const validationSchema = yup.object().shape({ email: yup @@ -34,7 +42,7 @@ export default function ForgotPasswordScreen({ navigation }) { /(@u.nus.edu|@nus.edu.sg|@u.yale-nus.edu.sg|@u.duke.nus.edu)$/, "Please enter a valid NUS email" ) - .required("Please enter your email") + .required("Please enter your email"), }); return ( @@ -44,15 +52,7 @@ export default function ForgotPasswordScreen({ navigation }) { { - // navigation.navigate("Forgot Password Verification Screen"); - if(timeout) { - clearTimeout(timeout); - } - timeout = setTimeout(() => { - forgotPassword({ email, setStatusMsg, setErrorMsg }) - }, 10000); //timeout for 10 seconds - }} + onSubmit={handleButtonClicked} > {({ setFieldValue, handleSubmit, errors, isValid }) => ( @@ -75,7 +75,7 @@ export default function ForgotPasswordScreen({ navigation }) { Send password reset email @@ -132,7 +132,7 @@ const styles = StyleSheet.create({ color: colors.black, textAlign: "center", marginHorizontal: 30, - marginTop: 90, + marginTop: 60, fontSize: 18, }, errorMsg: { diff --git a/screens/borrow-screens/BorrowSelectionScreen.js b/screens/borrow-screens/BorrowSelectionScreen.js index 1faf2ba..f4c299d 100644 --- a/screens/borrow-screens/BorrowSelectionScreen.js +++ b/screens/borrow-screens/BorrowSelectionScreen.js @@ -16,6 +16,8 @@ import firebase from "../../database/firebaseDB"; import { setStallDetails, setQuotas, getBorrowedNum } from "./BorrowApi"; import { UserContext } from "../../assets/UserContext"; import Constants from "expo-constants"; +import { useBackHandler } from "@react-native-community/hooks"; +import { backActionHandler } from "../BasicApi"; export default function BorrowSelectionScreen({ navigation, route }) { // Stall name from scanning QR code @@ -41,6 +43,9 @@ export default function BorrowSelectionScreen({ navigation, route }) { const [numCups, setCupNum] = useState(0); const [numContainers, setContainerNum] = useState(0); + // Prevent back button action on Android + useBackHandler(backActionHandler); + // Set up stall details / quotas on intial render useEffect(() => { setQuotas(setCupQuota, setContainerQuota); @@ -142,6 +147,12 @@ export default function BorrowSelectionScreen({ navigation, route }) { setContainerNum={setContainerNum} /> {renderNextButton()} + navigation.popToTop()} + style={[globalStyles.button, { width: "90%" }]} + > + Cancel + diff --git a/screens/borrow-screens/BorrowStack.js b/screens/borrow-screens/BorrowStack.js index 4c5e589..7a48cf0 100644 --- a/screens/borrow-screens/BorrowStack.js +++ b/screens/borrow-screens/BorrowStack.js @@ -11,7 +11,7 @@ const Stack = createStackNavigator(); export default function BorrowStack() { return ( - + - + > */} { uploadBorrowData(userData.id, numCups, numContainers, setError); diff --git a/screens/borrow-screens/BorrowUnsuccessfulScreen.js b/screens/borrow-screens/BorrowUnsuccessfulScreen.js index 13424fa..0e306df 100644 --- a/screens/borrow-screens/BorrowUnsuccessfulScreen.js +++ b/screens/borrow-screens/BorrowUnsuccessfulScreen.js @@ -3,8 +3,12 @@ import { StyleSheet, Text, ScrollView, Image, Dimensions } from "react-native"; import UnsuccessBox from "../../components/UnsuccessBox"; import colors from "../../assets/colors"; import { globalStyles } from "../../assets/globalStyles"; +import { useBackHandler } from "@react-native-community/hooks"; +import { backActionHandler } from "../BasicApi"; export default function BorrowUnsuccessfulScreen() { + // Prevent back button action on Android + useBackHandler(backActionHandler); return ( @@ -21,4 +25,4 @@ const styles = StyleSheet.create({ container: { backgroundColor: colors.white, }, -}); \ No newline at end of file +}); diff --git a/screens/byo-screens/BYOScreen.js b/screens/byo-screens/BYOScreen.js index 13896d2..dcaf0df 100644 --- a/screens/byo-screens/BYOScreen.js +++ b/screens/byo-screens/BYOScreen.js @@ -95,24 +95,29 @@ export default function BYOScreen({ navigation }) { }} > - - navigation.navigate("BYO Unsuccessful Screen")} - style={styles.imagePlaceholder} - > - (Unsuccessful Screen) - - navigation.navigate("BYO Selection Screen")} - style={styles.imagePlaceholder} - > - (Selection screen) - + {/* navigation.navigate("BYO Unsuccessful Screen")} + style={styles.imagePlaceholder} + > + (Unsuccessful Screen) + + navigation.navigate("BYO Selection Screen")} + style={styles.imagePlaceholder} + > + (Selection screen) + */} Scan the QR code! + navigation.popToTop()} + style={[globalStyles.buttonTop, { marginTop: 30, width: "80%" }]} + > + Back to Home + diff --git a/screens/byo-screens/BYOSelectionScreen.js b/screens/byo-screens/BYOSelectionScreen.js index 4011df1..4a00cba 100644 --- a/screens/byo-screens/BYOSelectionScreen.js +++ b/screens/byo-screens/BYOSelectionScreen.js @@ -14,6 +14,8 @@ import SelectionComponent from "../../components/SelectionComponent"; import FooterText from "../../components/FooterText"; import Constants from "expo-constants"; import { setStallDetails, setQuotas } from "../borrow-screens/BorrowApi"; +import { useBackHandler } from "@react-native-community/hooks"; +import { backActionHandler } from "../BasicApi"; export default function BYOSelectionScreen({ navigation, route }) { //Based on this store name, grab data from firebase @@ -36,6 +38,9 @@ export default function BYOSelectionScreen({ navigation, route }) { const [numCups, setCupNum] = useState(0); const [numContainers, setContainerNum] = useState(0); + // Prevent back button action on Android + useBackHandler(backActionHandler); + useEffect(() => { setQuotas(setCupQuota, setContainerQuota); setStallDetails( @@ -136,6 +141,12 @@ export default function BYOSelectionScreen({ navigation, route }) { setContainerNum={setContainerNum} /> {renderNextButton()} + navigation.popToTop()} + style={[globalStyles.button, { width: "90%" }]} + > + Cancel + diff --git a/screens/byo-screens/BYOStack.js b/screens/byo-screens/BYOStack.js index a1f467f..ca4075a 100644 --- a/screens/byo-screens/BYOStack.js +++ b/screens/byo-screens/BYOStack.js @@ -9,26 +9,26 @@ const Stack = createStackNavigator(); export default function BYOStack() { return ( - + ); diff --git a/screens/byo-screens/BYOSuccessScreen.js b/screens/byo-screens/BYOSuccessScreen.js index 0d419b2..a13e315 100644 --- a/screens/byo-screens/BYOSuccessScreen.js +++ b/screens/byo-screens/BYOSuccessScreen.js @@ -6,6 +6,8 @@ import { globalStyles } from "../../assets/globalStyles"; import FooterText from "../../components/FooterText"; import { uploadByoData, updateCoins } from "./BYOApi"; import { UserContext } from "../../assets/UserContext"; +import { useBackHandler } from "@react-native-community/hooks"; +import { backActionHandler } from "../BasicApi"; export default function BYOSuccessScreen({ route }) { const { numCups, numContainers } = route.params; @@ -16,6 +18,9 @@ export default function BYOSuccessScreen({ route }) { // Can change the value of coins earned accordingly const coinsEarned = numCups + numContainers; + // Prevent back button action on Android + useBackHandler(backActionHandler); + useEffect(() => { uploadByoData(uid, numCups, numContainers, setError); updateCoins(uid, coinsEarned); diff --git a/screens/byo-screens/BYOUnsuccessfulScree.js b/screens/byo-screens/BYOUnsuccessfulScree.js index b5dda59..fb7a577 100644 --- a/screens/byo-screens/BYOUnsuccessfulScree.js +++ b/screens/byo-screens/BYOUnsuccessfulScree.js @@ -1,20 +1,32 @@ import React from "react"; -import { StyleSheet, Text, View, ScrollView, Image, Dimensions } from "react-native"; +import { + StyleSheet, + Text, + View, + ScrollView, + Image, + Dimensions, +} from "react-native"; import UnsuccessBox from "../../components/UnsuccessBox"; import colors from "../../assets/colors"; import { globalStyles } from "../../assets/globalStyles"; +import { useBackHandler } from "@react-native-community/hooks"; +import { backActionHandler } from "../BasicApi"; export default function BYOUnsuccessfulScreen() { + // Prevent back button action on Android + useBackHandler(backActionHandler); + return ( - +