diff options
author | Leon Jiang <35908040+leonyjiang@users.noreply.github.com> | 2020-07-08 09:56:17 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-07-08 12:56:17 -0400 |
commit | e32241734c8cc258812ac12c7727aaa7f947eed5 (patch) | |
tree | 8ef1ab3a5203496641be721a9567173b87c4f551 /src/components/onboarding | |
parent | ff358c8927086a69f6732b6e7e1abb85a9e3cc84 (diff) |
[TMA-60] Registration Page UI & Field Validation (#13)
* remove unused image
* refactor LoginInput component to be more generic
* configure bare registration screen
* create index files for exports
* add yarn typing script
* refactor and re-style LoginInput component
* re-style login screen according to designs
* make LoginInput name more generic, give TaggInput dirty & width props
* add disabled feature to login screen submit button, finalized styles
* add arrow images and create ArrowButton component
* create RegistrationWizard component and move files around
* added disabled & enabled buttons to ArrowButton component
* create dummy terms and conditions text
* create common CenteredView component for re-use
* create custom RadioCheckbox for registration screen
* create TermsConditions & OverlayView components
* update index.ts export files
* build registration page UI with basic validation
* yarn lint/type & add platform-specific styling
* add yarn type item to PR checklist
* add react-native-animatable dependency to project
* add regex variables to constants file
* Add width prop for more flexible styling
* Add types and disable auto-capitalization
* Update email validation regex
* Create linear-gradient background component
* Update password regex and add inline docs
* Refactor code to be more readable
* Add warning prop and animation to TaggInput
* Add wrapper View for vertical margins
* Make JSX more readable & add TaggInput components
* Integrate refactored code into registration page
* Merge in login screen changes
* Lint and fix file syntax
* Fix function docs
* Add ViewProps to CenterView props
* Add KeyboardAvoidingView to Background component
* Add blurOnSubmit for inputs, restore deleted handleLogin code
* Create Verification screen and add it to routes
* Add routing to Verification page upon success
* Add API request upon registration submit
* Trigger warning shaking animation on submit
* Make disabled arrow touchable, tap triggers submit
Diffstat (limited to 'src/components/onboarding')
-rw-r--r-- | src/components/onboarding/ArrowButton.tsx | 23 | ||||
-rw-r--r-- | src/components/onboarding/Background.tsx | 44 | ||||
-rw-r--r-- | src/components/onboarding/RegistrationWizard.tsx | 47 | ||||
-rw-r--r-- | src/components/onboarding/TermsConditions.tsx | 140 | ||||
-rw-r--r-- | src/components/onboarding/index.ts | 4 |
5 files changed, 258 insertions, 0 deletions
diff --git a/src/components/onboarding/ArrowButton.tsx b/src/components/onboarding/ArrowButton.tsx new file mode 100644 index 00000000..bf07c6ac --- /dev/null +++ b/src/components/onboarding/ArrowButton.tsx @@ -0,0 +1,23 @@ +import React from 'react'; +import {Image, TouchableOpacity, TouchableOpacityProps} from 'react-native'; + +interface ArrowButtonProps extends TouchableOpacityProps { + direction: 'forward' | 'backward'; + disabled?: boolean; +} +const ArrowButton: React.FC<ArrowButtonProps> = (props: ArrowButtonProps) => { + const arrow = + props.direction === 'forward' + ? props.disabled + ? require('../../assets/images/arrow-forward-disabled.png') + : require('../../assets/images/arrow-forward-enabled.png') + : require('../../assets/images/arrow-backward.png'); + + return ( + <TouchableOpacity {...props}> + <Image source={arrow} /> + </TouchableOpacity> + ); +}; + +export default ArrowButton; diff --git a/src/components/onboarding/Background.tsx b/src/components/onboarding/Background.tsx new file mode 100644 index 00000000..98082022 --- /dev/null +++ b/src/components/onboarding/Background.tsx @@ -0,0 +1,44 @@ +import React from 'react'; +import LinearGradient from 'react-native-linear-gradient'; +import { + StyleSheet, + TouchableWithoutFeedback, + Keyboard, + ViewProps, + KeyboardAvoidingView, + View, + Platform, +} from 'react-native'; + +interface BackgroundProps extends ViewProps {} +const Background: React.FC<BackgroundProps> = (props) => { + return ( + <LinearGradient + colors={['#9F00FF', '#27EAE9']} + useAngle={true} + angle={154.72} + angleCenter={{x: 0.5, y: 0.5}} + style={styles.container}> + <KeyboardAvoidingView + behavior={Platform.OS === 'ios' ? 'padding' : 'height'} + style={styles.container}> + <TouchableWithoutFeedback accessible={false} onPress={Keyboard.dismiss}> + <View style={[styles.container, styles.view]} {...props}> + {props.children} + </View> + </TouchableWithoutFeedback> + </KeyboardAvoidingView> + </LinearGradient> + ); +}; + +const styles = StyleSheet.create({ + container: { + flex: 1, + }, + view: { + alignItems: 'center', + }, +}); + +export default Background; diff --git a/src/components/onboarding/RegistrationWizard.tsx b/src/components/onboarding/RegistrationWizard.tsx new file mode 100644 index 00000000..5d7e6ee2 --- /dev/null +++ b/src/components/onboarding/RegistrationWizard.tsx @@ -0,0 +1,47 @@ +import React from 'react'; +import {View, StyleSheet, ViewProps} from 'react-native'; + +interface RegistrationWizardProps extends ViewProps { + step: 'one' | 'two' | 'three'; +} + +const RegistrationWizard = (props: RegistrationWizardProps) => { + const stepStyle = styles.step; + const stepActiveStyle = [styles.step, styles.stepActive]; + return ( + <View {...props}> + <View style={styles.container}> + <View style={props.step === 'one' ? stepActiveStyle : stepStyle} /> + <View style={styles.progress} /> + <View style={props.step === 'two' ? stepActiveStyle : stepStyle} /> + <View style={styles.progress} /> + <View style={props.step === 'three' ? stepActiveStyle : stepStyle} /> + </View> + </View> + ); +}; + +const styles = StyleSheet.create({ + container: { + flexDirection: 'row', + justifyContent: 'center', + alignItems: 'center', + }, + step: { + height: 18, + width: 18, + borderRadius: 9, + borderWidth: 2, + borderColor: '#e1f0ff', + }, + stepActive: { + backgroundColor: '#e1f0ff', + }, + progress: { + width: '30%', + height: 2, + backgroundColor: '#e1f0ff', + }, +}); + +export default RegistrationWizard; diff --git a/src/components/onboarding/TermsConditions.tsx b/src/components/onboarding/TermsConditions.tsx new file mode 100644 index 00000000..5af1b972 --- /dev/null +++ b/src/components/onboarding/TermsConditions.tsx @@ -0,0 +1,140 @@ +import React, {useState} from 'react'; +import { + Modal, + StyleSheet, + View, + Text, + Button, + TouchableOpacity, + ScrollView, + ViewProps, +} from 'react-native'; + +import {RadioCheckbox, CenteredView, OverlayView} from '../common'; +import {dummyTermsConditions} from '../../constants'; + +interface TermsConditionsProps extends ViewProps { + accepted: boolean; + onChange: (accepted: boolean) => void; +} +const TermsConditions: React.FC<TermsConditionsProps> = (props) => { + // boolean representing if modal is visible + const [modalVisible, setModalVisible] = useState(false); + // destructure props + const {accepted, onChange} = props; + /** + * Hides the modal. + */ + const hideModal = (): void => { + if (modalVisible) { + setModalVisible(false); + } + }; + /** + * Sets `accepted` to `true` and hides the modal. + */ + const handleAccept = (): void => { + onChange(true); + hideModal(); + }; + /** + * Toggles the value of `accepted`. + */ + const toggleAccepted = (): void => { + onChange(!accepted); + }; + + return ( + <View {...props}> + <View style={styles.body}> + <RadioCheckbox checked={accepted} onPress={toggleAccepted} /> + <View style={styles.bodyPrompt}> + <Text style={styles.bodyPromptText}>I accept the </Text> + <TouchableOpacity onPress={() => setModalVisible(true)}> + <Text + style={[styles.bodyPromptText, styles.bodyPromptTextUnderline]}> + terms and conditions. + </Text> + </TouchableOpacity> + </View> + </View> + <Modal visible={modalVisible} transparent={true} animationType="fade"> + <OverlayView> + <CenteredView> + <View style={styles.modalView}> + <ScrollView + style={styles.modalScrollView} + contentContainerStyle={styles.modalScrollViewContent}> + <Text style={styles.tcHeader}>Terms and Conditions</Text> + <Text>{dummyTermsConditions}</Text> + </ScrollView> + <View style={styles.modalActions}> + <Button title="Accept" onPress={handleAccept} /> + <View style={styles.modalActionsDivider} /> + <Button title="Close" onPress={hideModal} /> + </View> + </View> + </CenteredView> + </OverlayView> + </Modal> + </View> + ); +}; + +const styles = StyleSheet.create({ + body: { + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'center', + }, + bodyPrompt: { + flexDirection: 'row', + marginLeft: 10, + }, + bodyPromptText: { + fontSize: 16, + color: '#fff', + }, + bodyPromptTextUnderline: { + textDecorationLine: 'underline', + }, + modalView: { + width: '85%', + height: '55%', + backgroundColor: '#fff', + shadowColor: '#000', + shadowOpacity: 30, + shadowOffset: {width: 0, height: 2}, + shadowRadius: 5, + borderRadius: 8, + paddingTop: 30, + paddingBottom: 15, + paddingHorizontal: 20, + alignItems: 'center', + justifyContent: 'space-between', + }, + modalScrollViewContent: { + justifyContent: 'center', + alignItems: 'center', + }, + modalScrollView: { + marginBottom: 10, + }, + tcHeader: { + fontSize: 18, + fontWeight: 'bold', + }, + modalActions: { + flexDirection: 'row', + justifyContent: 'space-evenly', + alignItems: 'center', + width: '100%', + }, + modalActionsDivider: { + height: '60%', + backgroundColor: '#0160Ca', + width: 1, + }, +}); + +export default TermsConditions; diff --git a/src/components/onboarding/index.ts b/src/components/onboarding/index.ts new file mode 100644 index 00000000..01255c01 --- /dev/null +++ b/src/components/onboarding/index.ts @@ -0,0 +1,4 @@ +export {default as ArrowButton} from './ArrowButton'; +export {default as Background} from './Background'; +export {default as RegistrationWizard} from './RegistrationWizard'; +export {default as TermsConditions} from './TermsConditions'; |