added React Native Dropdown Picker and wrapper component

This commit is contained in:
Andrew14o
2021-11-23 12:25:57 -08:00
parent 0a2b3f7987
commit 4e451e0b6c
5 changed files with 105 additions and 33 deletions

View File

@@ -1,6 +1,6 @@
module.exports = { module.exports = {
root: true, root: true,
extends: '@react-native-community', extends: ['@react-native-community', 'prettier'],
rules: { rules: {
'react-native/no-inline-styles': 'off', 'react-native/no-inline-styles': 'off',
}, },

1
.gitignore vendored
View File

@@ -35,6 +35,7 @@ local.properties
node_modules/ node_modules/
npm-debug.log npm-debug.log
yarn-error.log yarn-error.log
.yarn
# BUCK # BUCK
buck-out/ buck-out/

View File

@@ -21,6 +21,7 @@
"axios": "^0.23.0", "axios": "^0.23.0",
"react": "17.0.2", "react": "17.0.2",
"react-native": "0.66.1", "react-native": "0.66.1",
"react-native-dropdown-picker": "^5.2.3",
"react-native-fs": "^2.18.0", "react-native-fs": "^2.18.0",
"react-native-keychain": "^8.0.0", "react-native-keychain": "^8.0.0",
"react-native-localization": "^2.1.7", "react-native-localization": "^2.1.7",
@@ -41,6 +42,7 @@
"eslint": "7.14.0", "eslint": "7.14.0",
"jest": "^26.6.3", "jest": "^26.6.3",
"metro-react-native-babel-preset": "^0.66.2", "metro-react-native-babel-preset": "^0.66.2",
"prettier": "^2.4.1",
"react-test-renderer": "17.0.2" "react-test-renderer": "17.0.2"
}, },
"jest": { "jest": {

View File

@@ -0,0 +1,70 @@
import React, { useState } from 'react';
import { StyleSheet, Text, View } from 'react-native';
import { grayColor, paddingHorizontalDefault, primaryColor, whiteColor } from '../AppStyle';
import DropDownPicker from 'react-native-dropdown-picker';
export default function ItemPickerWithLabel(props) {
const [open, setOpen] = useState(false);
const [items, setItems] = useState(props.items ?? []);
const placeholder = props.placeholder ?? 'Select an item';
const label = props.label ?? '';
const onChangeValue = value => {
if (props.onChangeValue) {
props.onChangeValue(value);
}
};
const componentStyles = StyleSheet.create({
container: {
width: '100%',
// Layout
flexDirection: 'column',
flexWrap: 'nowrap',
flex: 1,
justifyContent: 'space-evenly',
// Visual
paddingHorizontal: paddingHorizontalDefault,
},
textLabel: {
fontSize: 11,
color: primaryColor,
},
picker: {
borderWidth: 0,
borderRadius: 0,
},
pickerContainer: {
paddingVertical: 5,
},
dropDownContainer: {
borderWidth: 1,
borderRadius: 0,
backgroundColor: whiteColor,
borderColor: grayColor,
},
});
return (
<View style={componentStyles.container}>
<Text style={componentStyles.textLabel} numberOfLines={1}>
{label}
</Text>
<DropDownPicker
listMode={'SCROLLVIEW'}
loading={props.loading ?? false}
placeholder={placeholder}
open={open}
value={props.value}
items={items}
setOpen={setOpen}
setValue={props.setValue}
setItems={setItems}
style={componentStyles.picker}
containerStyle={componentStyles.pickerContainer}
dropDownContainerStyle={componentStyles.dropDownContainer}
onChangeValue={value => onChangeValue(value)}
/>
</View>
);
}

View File

@@ -1,4 +1,4 @@
import React, { useCallback, useState } from 'react'; import React, { useCallback, useEffect, useState } from 'react';
import { strings } from '../localization/LocalizationStrings'; import { strings } from '../localization/LocalizationStrings';
import { import {
marginTopDefault, marginTopDefault,
@@ -9,7 +9,7 @@ import {
pageItemStyle, pageItemStyle,
paddingVerticalDefault, paddingVerticalDefault,
} from '../AppStyle'; } from '../AppStyle';
import { StyleSheet, SafeAreaView, View, Text, ScrollView } from 'react-native'; import { StyleSheet, SafeAreaView, View, ScrollView } from 'react-native';
import { logStringifyPretty, showGeneralMessage, signOut } from '../Utils'; import { logStringifyPretty, showGeneralMessage, signOut } from '../Utils';
import { emailApi, getCredentials, handleApiError, userManagementApi } from '../api/apiHandler'; import { emailApi, getCredentials, handleApiError, userManagementApi } from '../api/apiHandler';
import { MfaAuthInfoMethodEnum } from '../api/generated/owSecurityApi'; import { MfaAuthInfoMethodEnum } from '../api/generated/owSecurityApi';
@@ -20,13 +20,14 @@ import ButtonStyled from '../components/ButtonStyled';
import ItemTextWithIcon from '../components/ItemTextWithIcon'; import ItemTextWithIcon from '../components/ItemTextWithIcon';
import ItemTextWithLabel from '../components/ItemTextWithLabel'; import ItemTextWithLabel from '../components/ItemTextWithLabel';
import ItemTextWithLabelEditable from '../components/ItemTextWithLabelEditable'; import ItemTextWithLabelEditable from '../components/ItemTextWithLabelEditable';
import RadioCheckbox from '../components/RadioCheckbox'; import ItemPickerWithLabel from '../components/ItemPickerWithLabel';
const Profile = props => { const Profile = props => {
const state = store.getState(); const state = store.getState();
const session = state.session.value; const session = state.session.value;
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [profile, setProfile] = useState(); const [profile, setProfile] = useState();
const [mfaValue, setMfaValue] = useState('off');
// Refresh the getProfile only anytime there is a navigation change and this has come into focus // Refresh the getProfile only anytime there is a navigation change and this has come into focus
// Need to becareful here as useFocusEffect is also called during re-render so it can result in // Need to becareful here as useFocusEffect is also called during re-render so it can result in
@@ -132,6 +133,14 @@ const Profile = props => {
updateProfile({ userTypeProprietaryInfo: proprietaryInfo }); updateProfile({ userTypeProprietaryInfo: proprietaryInfo });
}; };
useEffect(() => {
if (profile) {
let mfa = profile.userTypeProprietaryInfo.mfa;
let val = mfa.enabled ? mfa.method : 'off';
setMfaValue(val);
}
}, [profile]);
// Phone Numbers // Phone Numbers
const renderPhoneNumberFields = () => { const renderPhoneNumberFields = () => {
let views = []; let views = [];
@@ -201,6 +210,10 @@ const Profile = props => {
section: { section: {
marginTop: marginTopDefault, marginTop: marginTopDefault,
}, },
accountSection: {
marginTop: marginTopDefault,
zIndex: 1,
},
item: { item: {
paddingVertical: paddingVerticalDefault, paddingVertical: paddingVerticalDefault,
paddingHorizontal: paddingHorizontalDefault, paddingHorizontal: paddingHorizontalDefault,
@@ -234,7 +247,7 @@ const Profile = props => {
/> />
) : ( ) : (
<AccordionSection <AccordionSection
style={styles.section} style={styles.accountSection}
title={strings.profile.accountInfo} title={strings.profile.accountInfo}
isLoading={loading} isLoading={loading}
disableAccordion={true}> disableAccordion={true}>
@@ -249,34 +262,20 @@ const Profile = props => {
{renderPhoneNumberFields()} {renderPhoneNumberFields()}
{/* MFA */} {/* MFA */}
<View key="mfa" style={styles.item}> {profile.userTypeProprietaryInfo.mfa && (
<Text style={styles.label}>{strings.profile.mfa}</Text> <ItemPickerWithLabel
{profile.userTypeProprietaryInfo.mfa && ( label={strings.profile.mfa}
<View> loading={loading}
<RadioCheckbox value={mfaValue}
label={strings.profile.off} setValue={setMfaValue}
checked={!profile.userTypeProprietaryInfo.mfa.enabled} items={[
onChange={() => onMfaChange()} { label: strings.profile.off, value: 'off' },
/> { label: strings.profile.email, value: MfaAuthInfoMethodEnum.Email },
<RadioCheckbox { label: strings.profile.sms, value: MfaAuthInfoMethodEnum.Sms },
label={strings.profile.sms} ]}
checked={ onChangeValue={onMfaChange}
profile.userTypeProprietaryInfo.mfa.enabled && />
profile.userTypeProprietaryInfo.mfa.method === MfaAuthInfoMethodEnum.Sms )}
}
onChange={() => onMfaChange(MfaAuthInfoMethodEnum.Sms)}
/>
<RadioCheckbox
label={strings.profile.email}
checked={
profile.userTypeProprietaryInfo.mfa.enabled &&
profile.userTypeProprietaryInfo.mfa.method === MfaAuthInfoMethodEnum.Email
}
onChange={() => onMfaChange(MfaAuthInfoMethodEnum.Email)}
/>
</View>
)}
</View>
</AccordionSection> </AccordionSection>
)} )}