Untitled

mail@pastecode.io avatar
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: () => {},
};