-
Notifications
You must be signed in to change notification settings - Fork 0
feat(Onboarding) UI update and basic text input verification #24
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: main
Are you sure you want to change the base?
Changes from all commits
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 |
---|---|---|
@@ -0,0 +1,197 @@ | ||
import React, { useState, useRef } from 'react'; | ||
import { View, Text, TouchableOpacity, TextInput, StyleSheet, ScrollView, Dimensions, Animated } from 'react-native'; | ||
import { createNativeStackNavigator } from '@react-navigation/native-stack'; | ||
import AsyncStorage from '@react-native-async-storage/async-storage'; | ||
import { useUserContext } from '@app/utils/UserContext'; | ||
|
||
const Stack = createNativeStackNavigator(); | ||
|
||
function OnboardingScreen({ navigation }) { | ||
const [school, setSchool] = useState(''); | ||
const [birthday, setBirthday] = useState(''); | ||
const [interests, setInterests] = useState(''); | ||
const [error1, setError1 ] = useState(false); | ||
const [error2, setError2 ] = useState(false); | ||
const [error3, setError3 ] = useState(false); | ||
const [error4, setError4 ] = useState(false); | ||
|
||
const { onboardingCompleted } = useUserContext(); | ||
|
||
const handleSubmit = async () => { | ||
await AsyncStorage.setItem('isFirstTime', JSON.stringify(false)); | ||
onboardingCompleted(); | ||
|
||
if (!school.trim()) | ||
{ | ||
setError1(true); | ||
} | ||
if (!birthday.trim()) | ||
{ | ||
setError2(true); | ||
} | ||
if (!interests.trim()) | ||
{ | ||
setError3(true); | ||
} | ||
if (!school.trim() || !birthday.trim() || !interests.trim()) | ||
{ | ||
setError4(true); | ||
} | ||
else | ||
{ | ||
navigation.navigate('TabNavigation'); | ||
} | ||
}; | ||
|
||
const handleSkip = async () => { | ||
navigation.navigate('TabNavigation'); | ||
}; | ||
|
||
return ( | ||
<View> | ||
<ScrollView | ||
pagingEnabled={true} | ||
horizontal={true} | ||
showsHorizontalScrollIndicator={false}> | ||
<View style={styles.slide}> | ||
<Text>Where do you go to school?</Text> | ||
<TextInput | ||
style={styles.input} | ||
placeholder= "Your School" | ||
onChangeText={setSchool} | ||
value={school} | ||
/> | ||
{error2 ? ( | ||
<Text style={styles.error}>*Your School is Required</Text> | ||
) : null | ||
} | ||
</View> | ||
Comment on lines
+56
to
+68
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. This is more optional, but I've seen other websites recommend a list of schools as you type. |
||
|
||
<View style={styles.slide}> | ||
<Text>When's your birthday?</Text> | ||
<TextInput | ||
style={styles.input} | ||
placeholder= "MM/DD/YYYY" | ||
onChangeText={setBirthday} | ||
value={birthday} | ||
/> | ||
{error2 ? ( | ||
<Text style={styles.error}>*Your Birthday is Required</Text> | ||
) : null | ||
} | ||
</View> | ||
Comment on lines
+70
to
+82
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. There should be input validation checking if the correct values are typed in for Birthday (maybe School too?). A date picker would also be a good choice for the Birthday. |
||
|
||
<View style={styles.slide}> | ||
<Text>List some of your interest:</Text> | ||
<TextInput | ||
style={styles.input} | ||
placeholder= "Your Interests" | ||
onChangeText={setInterests} | ||
value={interests} | ||
/> | ||
{error3 ? ( | ||
<Text style={styles.error}>*Your Interests are Required</Text> | ||
) : null | ||
} | ||
<TouchableOpacity style={styles.button} onPress={handleSubmit}> | ||
<Text style={styles.buttonText}>Submit</Text> | ||
</TouchableOpacity> | ||
{error4 ? ( | ||
<Text style={styles.error}>*Missing Required Responses</Text> | ||
) : null | ||
} | ||
</View> | ||
Comment on lines
+84
to
+103
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. For the interests, the Twitter reference you posted in the RFC looks good. You can try implementing selecting interests like that with mock data. |
||
</ScrollView> | ||
<View style={styles.indicatorContainer}> | ||
<TouchableOpacity style={styles.skipBtn} onPress={handleSkip}> | ||
<Text>SKIP</Text> | ||
</TouchableOpacity> | ||
<View style={styles.indicator}></View> | ||
<View style={styles.indicator}></View> | ||
<View style={styles.indicator}></View> | ||
Comment on lines
+109
to
+111
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. The page indicators on the bottom should show you what page you're on (maybe with a change of color or size). |
||
<TouchableOpacity style={styles.nextBtn}> | ||
<Text>NEXT</Text> | ||
</TouchableOpacity> | ||
Comment on lines
+112
to
+114
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. Next button doesn't work yet. |
||
</View> | ||
</View> | ||
); | ||
} | ||
|
||
const {width, height} = Dimensions.get('window'); | ||
|
||
function OnboardingStack() { | ||
return ( | ||
<Stack.Navigator screenOptions={{ headerShown: false }}> | ||
<Stack.Screen name="onboardingscreeen" component={OnboardingScreen} /> | ||
</Stack.Navigator> | ||
); | ||
} | ||
|
||
const styles = StyleSheet.create({ | ||
container: { | ||
flex: 1, | ||
justifyContent: 'center', | ||
alignItems: 'center', | ||
}, | ||
error: { | ||
color: 'red', | ||
}, | ||
slide: { | ||
width: width, | ||
height: height, | ||
justifyContent: 'center', | ||
alignItems: 'center', | ||
}, | ||
title: { | ||
fontSize: 24, | ||
marginBottom: 20, | ||
fontWeight: 'bold', | ||
}, | ||
input: { | ||
borderWidth: 1, | ||
borderColor: '#ccc', | ||
borderRadius: 4, | ||
width: 270, | ||
height: 45, | ||
margin: 12, | ||
padding: 10, | ||
}, | ||
button: { | ||
backgroundColor: '#007AFF', | ||
padding: 10, | ||
borderRadius: 4, | ||
}, | ||
buttonText: { | ||
color: '#fff', | ||
textAlign: 'center', | ||
fontWeight: 'bold', | ||
}, | ||
skipText: { | ||
textAlign: 'center', | ||
marginTop: 10, | ||
textDecorationLine: 'underline', | ||
}, | ||
indicatorContainer: { | ||
position: 'absolute', | ||
width: width, | ||
bottom: 0, | ||
height: 60, | ||
flexDirection: 'row', | ||
justifyContent: 'center', | ||
}, | ||
indicator: { | ||
width: 10, | ||
height: 10, | ||
backgroundColor: 'gray', | ||
borderRadius: 5, | ||
marginHorizontal: 10, | ||
}, | ||
skipBtn: { | ||
marginRight: 65, | ||
}, | ||
nextBtn: { | ||
marginLeft: 65, | ||
}, | ||
}); | ||
|
||
export default OnboardingStack; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,3 @@ | ||
const URL = "https://e924-24-205-170-250.ngrok-free.app"; | ||
const URL = "https://edbe-2603-8000-4507-f23e-4988-bbd6-d792-84bd.ngrok.io"; | ||
|
||
export const ENDPOINT = `${URL}/api`; |
Uh oh!
There was an error while loading. Please reload this page.
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.
Should isFirstTime be stored in AsyncStorage? I'm guessing it should be stored on a database somewhere so that the user only needs to do onboarding once. With AsyncStorage, if the user were to log on in another device, they would see the onboarding screen again.
You can remove the AsyncStorage code for now. Luke will add a isNewUser boolean property to google and local login routes.