Untitled
unknown
plain_text
a year ago
11 kB
4
Indexable
Never
import React, { Component } from 'react'; import { View, Modal, TouchableOpacity, FlatList, Dimensions, Text, ActivityIndicator, TextInput, } from 'react-native'; import PropTypes from 'prop-types'; import { getStatusBarHeight } from 'react-native-status-bar-height'; import Icon from 'react-native-vector-icons/AntDesign'; import ButtonOutline from './button-outline'; import TextField from './text-field'; import LocalizedString from '../localization'; import { COLOR_BLACK_INACTIVE, COLOR_BODY_TEXT, COLOR_PRIMARY, } from '../constant'; import { Body, H4 } from './labels'; const getScreenDimension = () => { const statusBarHeight = getStatusBarHeight(); const { height, width } = Dimensions.get('window'); return { height: height - statusBarHeight, width }; }; const { width, height } = getScreenDimension(); const styles = { modalContainer: { flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: 'rgba(0, 0, 0, 0.5)', }, modalInnerContainer: { alignItems: 'center', backgroundColor: '#fff', width: width - 30, borderRadius: 10, paddingTop: 20, paddingHorizontal: 10, }, headerSectionIos: { height: 50, alignSelf: 'stretch', flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', paddingHorizontal: 20, backgroundColor: '#fff', }, iosModalButton: { color: 'black', }, bodySectionIos: { alignSelf: 'stretch', paddingVertical: 20, paddingHorizontal: 10, }, pickerItemAndroid: { borderBottomWidth: 1, paddingVertical: 15, alignItems: 'center', }, flatListAndroid: { height: (height * 30) / 100, alignSelf: 'stretch', }, footerAndroid: { marginVertical: 20, alignItems: 'center', alignSelf: 'stretch', }, clearButton: { paddingVertical: 10, paddingHorizontal: 10, marginTop: 10, }, simplePickerButton: { flexDirection: 'row', alignItems: 'flex-end', // width: '100%', }, noItemContainer: { height: 50, width, alignItems: 'center', alignSelf: 'center', }, }; export default class SimplePicker extends Component { constructor(props) { super(props); this.state = { showModal: false, selectedValue: props.selectedValue, searchQuery: '', }; } componentDidUpdate() { if (this.props.selectedValue !== this.state.selectedValue) { // eslint-disable-next-line react/no-did-update-set-state this.setState({ selectedValue: this.props.selectedValue }); } } onSearchQueryChange = query => { this.setState({ searchQuery: query }); }; onClearButtonPressed = () => { this.setState({ showModal: false }); this.props.onClearPressed(); }; onTextFieldPressed = () => { if (this.props.validationButtonPress) { this.props.onPressButton(); } else { if (!this.props.disabled) { this.setState({ showModal: true }); } } }; onValueSelect = item => { const selectedItem = item || this.props.data[0]; this.props.onValueSelected(selectedItem); this.setState({ showModal: false, searchQuery: '', }); }; onPickerValueChanged = value => { const { data } = this.props; const realValue = data.find(x => x.label || x.value ? x.value === value : x === value, ); this.props.onValueSelected(realValue); this.setState({ selectedValue: realValue }); }; onCancelPicker = () => { this.setState({ showModal: false, searchQuery: '' }); }; // renderPicker = () => { // const { selectedValue } = this.props; // const displayedSelectedValue = selectedValue && (selectedValue.label || selectedValue.value) // ? selectedValue.value // : selectedValue; // return ( // <Fragment> // { // this.props.data.length > 0 ? // <Picker // mode="dropdown" // selectedValue={displayedSelectedValue} // onValueChange={this.onPickerValueChanged} // style={{ paddingHorizontal: 10 }} // > // { // this.props.data.map((item) => { // const label = item.label || item; // const value = item.value || item; // return ( // <Picker.Item label={label} value={value} key={value} /> // ); // }) // } // </Picker> : // <View style={styles.noItemContainer}> // <H4 > // {LocalizedString.common.errMsgNoResultFound} // </H4> // </View> // } // </Fragment> // ); // }; renderTextField = () => { const { selectedValue, loading } = this.props; const displayedSelectedValue = typeof selectedValue === 'object' ? selectedValue.label : selectedValue || ''; return ( <TouchableOpacity style={styles.simplePickerButton} disabled={this.props.disabled || loading} onPress={this.onTextFieldPressed}> <TextField label={this.props.label} required={this.props.required} error={this.props.error} value={displayedSelectedValue} editable={false} containerStyle={{ flex: 1 }} dow {...this.props} /> {loading ? ( <View style={{ alignSelf: 'center' }}> <ActivityIndicator size="small" color={COLOR_PRIMARY} /> </View> ) : ( <Icon name="caretdown" size={10} style={{ marginBottom: 23 }} color={COLOR_BLACK_INACTIVE} /> )} </TouchableOpacity> ); }; onPickerItemAndroidPressed = item => { this.setState({ selectedValue: item }); this.onValueSelect(item); }; renderPickerItemAndroid = ({ item }) => ( <TouchableOpacity style={[ styles.pickerItemAndroid, { borderColor: this.props.separatorColor }, ]} onPress={() => this.onPickerItemAndroidPressed(item)}> <Text style={this.props.itemTextStyle} allowFontScaling={false} adjustsFontSizeToFit> {item.label || item.value ? item.label : item} </Text> </TouchableOpacity> ); renderAndroidPicker = () => { const { data, cancelCaption, isSearch } = this.props; const { searchQuery } = this.state; const flatListHeight = data && data.length > 3 ? {} : { height: undefined }; const filteredData = data.filter(item => { if (isSearch === true) { return item.label.toLowerCase().includes(searchQuery.toLowerCase()); } }); return ( <View> {this.renderTextField()} <Modal animationType={this.props.animationType} transparent visible={this.state.showModal} onRequestClose={() => {}}> <View style={[styles.modalContainer]}> <View style={[styles.modalInnerContainer]}> {isSearch && ( <TextInput style={{ height: 45, width: '100%', color: COLOR_BODY_TEXT, borderWidth: 1, borderColor: COLOR_BLACK_INACTIVE, borderRadius: 8, paddingHorizontal: 10, }} placeholder="Search..." onChangeText={this.onSearchQueryChange} /> )} <FlatList data={isSearch === true ? filteredData : data} ListEmptyComponent={ <View style={styles.noItemContainer}> <H4>{LocalizedString.common.errMsgNoResultFound}</H4> </View> } renderItem={this.renderPickerItemAndroid} keyExtractor={item => item.value || item} style={[styles.flatListAndroid, flatListHeight]} /> {this.props.showClearButton ? ( <View style={styles.footerAndroid}> <ButtonOutline caption={cancelCaption} onPress={this.onCancelPicker} /> <TouchableOpacity onPress={this.onClearButtonPressed} style={styles.clearButton}> <Body bold style={{ color: COLOR_PRIMARY }}> {'Clear'} </Body> </TouchableOpacity> </View> ) : ( <View style={styles.footerAndroid}> <TouchableOpacity onPress={this.onCancelPicker}> <Body bold style={{ color: COLOR_PRIMARY }}> {cancelCaption} </Body> </TouchableOpacity> </View> )} </View> </View> </Modal> </View> ); }; render() { // return ios // ? this.renderIosPicker() // : this.renderAndroidPicker(); return this.renderAndroidPicker(); } } const pickerItemShape = PropTypes.shape({ value: PropTypes.string, label: PropTypes.string, }); const arrayShape = PropTypes.arrayOf(pickerItemShape); SimplePicker.propTypes = { loading: PropTypes.bool, showClearButton: PropTypes.bool, onClearPressed: PropTypes.func, animationType: PropTypes.string, label: PropTypes.string, error: PropTypes.string, separatorColor: PropTypes.string, cancelCaption: PropTypes.string, okCaption: PropTypes.string, disabled: PropTypes.bool, required: PropTypes.bool, itemTextStyle: PropTypes.objectOf( PropTypes.oneOfType([PropTypes.string, PropTypes.number]), ), selectedValue: PropTypes.oneOfType([pickerItemShape, PropTypes.string]), onValueSelected: PropTypes.func, data: PropTypes.oneOfType([arrayShape, PropTypes.arrayOf(PropTypes.string)]) .isRequired, }; SimplePicker.defaultProps = { loading: false, showClearButton: false, animationType: 'fade', cancelCaption: 'Cancel', okCaption: 'OK', label: '', error: '', separatorColor: '#EEEEEE', disabled: false, required: false, selectedValue: undefined, itemTextStyle: { fontSize: 14 }, onValueSelected: () => {}, onClearPressed: () => {}, };