/* * This file is part of OrangeHRM * * Copyright (C) 2020 onwards OrangeHRM (https://www.orangehrm.com/) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * */ import React from 'react'; import { FlatList, View, StyleSheet, TouchableOpacity, TextInput as RNTextInput, RefreshControl, Platform, } from 'react-native'; import {connect, ConnectedProps} from 'react-redux'; import {RootState} from 'store'; import SafeAreaLayout from 'layouts/SafeAreaLayout'; import withTheme, {WithTheme} from 'lib/hoc/withTheme'; import Text from 'components/DefaultText'; import Divider from 'components/DefaultDivider'; import FlatButton from 'components/FlatButton'; import Avatar from 'components/DefaultAvatar'; import TextInput, {TextInputProps} from 'components/DefaultTextInput'; import { PickEmployeeRouteParams, PickEmployeeNavigationProp, } from 'screens/leave/navigators'; import {Employee} from 'screens/leave/navigators'; import {getFirstAndLastNames} from 'lib/helpers/name'; import {selectSubordinates} from 'store/leave/assign-leave/selectors'; class PickEmployee extends React.Component<PickEmployeeProps> { inputRef: RNTextInput | null; constructor(props: PickEmployeeProps) { super(props); this.inputRef = null; } filterFunction = (text: string) => (item: Employee) => { const fullName = item.firstName + ' ' + item.lastName; const regex = new RegExp(text, 'i'); return item.employeeId.includes(text) || regex.test(fullName); }; pickEmployee = (employee: Employee) => () => { const {route, navigation} = this.props; const {pickEmployee} = route.params; pickEmployee(employee); navigation.goBack(); }; onPressEmployeePicker = () => { if (this.inputRef?.isFocused()) { this.inputRef?.blur(); } else { this.inputRef?.focus(); } }; render() { const {theme, route, navigation, employees} = this.props; const {textValue, setTextValue, onRefresh} = route.params; let filteredData; if (textValue !== '') { const filterFn = this.filterFunction(textValue); filteredData = employees?.filter(filterFn); } else { filteredData = employees; } const paddingRight = theme.spacing * 6; return ( <SafeAreaLayout> <View style={[ styles.flex, {backgroundColor: theme.palette.backgroundSecondary}, ]}> <View style={[styles.row, styles.inflex]}> <FlatButton text={'Employee'} icon={'account'} rightIcon={false} elevation onPress={this.onPressEmployeePicker} /> </View> <View style={styles.inflex}> <PickEmployeeTextInput ref={(input) => { this.inputRef = input; }} autoFocus value={textValue} onChangeText={(text) => { navigation.setParams({textValue: text}); setTextValue(text); }} style={[ { paddingRight, paddingLeft: theme.spacing * 12, backgroundColor: theme.palette.background, ...Platform.select({ ios: { paddingVertical: theme.spacing * 4, }, }), }, styles.textInputView, ]} /> </View> <View style={[styles.row, styles.flex]}> {filteredData === undefined || filteredData.length === 0 ? ( <View style={[styles.row, styles.flex, styles.center]}> <Text style={{ padding: theme.spacing * 4, }}> {'No matching records found'} </Text> </View> ) : ( <FlatList ItemSeparatorComponent={() => { return <Divider />; }} ListHeaderComponent={<Divider />} ListFooterComponent={ <View style={{ paddingBottom: theme.spacing * 2, }} /> } data={filteredData} renderItem={({item}) => { const fullName = getFirstAndLastNames(item); return ( <TouchableOpacity onPress={this.pickEmployee(item)}> <View style={[ styles.row, styles.flex, { paddingVertical: theme.spacing * 3, paddingRight, paddingLeft: theme.spacing * 4, backgroundColor: theme.palette.background, }, ]}> <Avatar name={fullName} small /> <View style={[ styles.row, styles.flex, styles.listItemView, { paddingTop: theme.spacing * 2, paddingLeft: theme.spacing * 4, }, ]}> <Text style={styles.fullName}>{fullName}</Text> <Text style={styles.employeeId}> {item.employeeId} </Text> </View> </View> </TouchableOpacity> ); }} keyExtractor={(item) => item.empNumber} keyboardShouldPersistTaps="handled" refreshControl={ <RefreshControl refreshing={false} onRefresh={onRefresh} /> } /> )} </View> </View> </SafeAreaLayout> ); } } interface PickEmployeeProps extends WithTheme, ConnectedProps<typeof connector> { navigation: PickEmployeeNavigationProp; route: PickEmployeeRouteParams; } const styles = StyleSheet.create({ flex: { flex: 1, }, inflex: { flex: 0, }, row: { flexDirection: 'row', }, listItemView: { justifyContent: 'space-between', }, textInputView: { shadowOpacity: 0.5, shadowRadius: 1, shadowOffset: {height: 0.5, width: 0}, elevation: 1, }, center: { justifyContent: 'center', }, fullName: { flex: 5, }, employeeId: { flex: 1, textAlign: 'right', }, }); const mapStateToProps = (state: RootState) => ({ employees: selectSubordinates(state), }); const connector = connect(mapStateToProps); const PickEmployeeWithTheme = withTheme<PickEmployeeProps>()(PickEmployee); export default connector(PickEmployeeWithTheme); export const PickEmployeeTextInput = React.forwardRef< RNTextInput, TextInputProps >((props, ref) => { return ( <TextInput ref={ref} placeholder={'Type for hints...'} maxLength={100} {...props} /> ); });