import React from 'react';
import {
Alert,
Button,
FlatList,
Linking,
Platform,
Text,
TextInput,
TouchableOpacity,
View,
} from 'react-native';
import { openComposer } from 'react-native-email-link';
// Reduxs
import { connect } from 'react-redux';
import { deleteContact, setContact } from '../Store/Actions/contacts';
// Helpers
import Helpers from '../Lib/Helpers';
// Translations
import i18n from '../../I18n';
// Icons
import FontAwesome5 from 'react-native-vector-icons/FontAwesome5';
// Flash Messages
import { showMessage } from 'react-native-flash-message';
// Overlay
import { Overlay } from '@rneui/themed';
// Picker
import { Picker } from '@react-native-picker/picker';
// Style
import styles from '../../Resources/Styles/ContactStyle';
function mapStateToProps(state) {
return {
users: state.users.users,
contacts: state.contacts,
documents: state.documents,
currentUser: state.app.currentUser,
mainColor: state.app.mainColor,
};
}
/**
* @typedef {(user: import('./../Models/User').User, data: import('./../Models/Contact').Contact) => void} setContact
* @typedef {(user: import('./../Models/User').User, uuid: string ) => void} deleteContact
* @typedef {(email: string ) => void} sendBrochure
*/
const mapDispatchToProps = dispatch => {
return {
setContact: (user, data) => dispatch(setContact(user, data)),
deleteContact: (user, id) => dispatch(deleteContact(user, id)),
sendBrochure: email => dispatch({ type: 'SEND_BROCHURE', data: email }),
};
};
class ContactScreen extends React.Component {
state = {
contacts: [],
sortType: 'asc',
sortField: 'name',
searchTxt: '',
showSendBrochure: false,
selectedDocument: -1,
sendDocumentList: [],
selectedSendBrochureEmail: -1,
tmpSendBrochureEmail: '',
tmpSendBrochureSubject: '',
tmpSendBrochureMessage: '',
sortedDocuments: [],
sortedEmails: [],
/** @type {number} The user index selected for transfert */
selectedTransferUserIndex: 0,
/** @type {import('./../Models/Contact').Contact|null} The contact to transfert */
contactToTransfer: null,
/** @type {boolean} Is tranfert contact model display ? */
showTransferContact: false,
};
// * --- ACTIONS
sendBrochure() {
// FIXME: Si on n'a pas consulté les documents la liste des documents est vide apres initialisation
if (
this.state.tmpSendBrochureEmail !== '' &&
this.state.tmpSendBrochureSubject !== '' &&
this.state.tmpSendBrochureMessage !== '' &&
this.state.sendDocumentList.length > 0 &&
Helpers.isEmailValid(this.state.tmpSendBrochureEmail)
) {
/** @type {sendBrochure} */
const sendBrochure = this.props.sendBrochure;
const email = {
email: this.state.tmpSendBrochureEmail,
subject: this.state.tmpSendBrochureSubject,
message: this.state.tmpSendBrochureMessage,
documents: JSON.stringify(this.state.sendDocumentList),
app_user_id: this.props.currentUser.id,
};
sendBrochure(email);
this.setState({
showSendBrochure: false,
tmpSendBrochureEmail: '',
tmpSendBrochureSubject: '',
tmpSendBrochureMessage: '',
selectedSendBrochureEmail: -1,
selectedDocument: -1,
sendDocumentList: [],
});
showMessage({
message: i18n.t('global.message_sent') + '.',
description: i18n.t('global.message_will_be_sent_after_sync') + '.',
type: 'success',
duration: 1500,
});
} else {
Alert.alert(
i18n.t('error.incomplete_form'),
i18n.t('error.fill_all_fields_and_1_doc_min') + '.',
);
}
}
transferContact() {
/** @type {import('./../Models/User').User} */
const nextUser = this.props.users.filter(
user => user.id !== this.props.currentUser.id,
)[this.state.selectedTransferUserIndex];
/** @type {import('./../Models/Contact').ContactData} cloned contact */
const transferContact = this.state.contactToTransfer.toJSON();
if (transferContact === null) {
throw new Error('No selected contact to transfert');
}
// * Assign cloned contact to another user
transferContact.send_to_app_user_id = nextUser.id;
transferContact.timestamp = new Date();
transferContact.synced = false;
/** @type {setContact} */
const setContactHook = this.props.setContact;
setContactHook(this.props.currentUser, transferContact);
this.setState({ showTransferContact: false, contactToTransfer: null });
showMessage({
message: i18n.t('contact_s.contact_transferred') + '.',
description: i18n.t('contact_s.contact_will_be_sent_after_sync') + '.',
type: 'success',
duration: 1500,
});
}
/**
* Delete contact
* @param {import('../Models/Contact').Contact} contact
*/
deleteContactAction(contact) {
Alert.alert(
i18n.t('global.confirmation'),
i18n.t('contact_s.confirm_contact_delete'),
[
{
text: i18n.t('global.no'),
onPress: () => console.debug('Cancel Pressed'),
style: 'cancel',
},
{
text: i18n.t('global.yes'),
onPress: () => {
this.setState({ contacts: [], sortedEmails: [] });
/** @type {setContact} */
const setContactHook = this.props.setContact;
/** @type {import('./../Models/Contact').ContactData} */
const contactToDelete = contact.toJSON();
contactToDelete.to_delete = true;
setContactHook(this.props.currentUser, contactToDelete);
showMessage({
message: i18n.t('contact_s.contact_deleted') + '.',
type: 'success',
duration: 500,
});
},
},
],
{ cancelable: false },
);
}
/**
* Try to call the number
*
* @param {string} phone
*/
callNumberIfSupported(phone) {
let phoneNumber = phone;
if (Platform.OS !== 'android') {
phoneNumber = `telprompt:${phone}`;
} else {
phoneNumber = `tel:${phone}`;
}
Linking.canOpenURL(phoneNumber)
.then(supported => {
if (supported) {
return Linking.openURL(phoneNumber);
}
})
.catch(err => console.error(err));
}
/**
* Write a new email to
*
* @param {string} email
*/
composeNewEmailTo(email) {
openComposer({
to: email,
});
}
// * END --- ACTIONS
/**
* Render the table header
* @returns {JSX.Element}
*/
HeaderItem() {
return (
{
this.sortContacts('lastname');
}}>
{i18n.t('global.lastname')}
{
this.sortContacts('email');
}}>
{i18n.t('global.email')}
{
this.sortContacts('phone');
}}>
{i18n.t('global.phone')}
);
}
/**
* Render a line of contact
* @param {import('../Models/Contact').Contact} contact
* @returns
*/
Item(contact) {
const displayName =
String(contact.lastname ?? '').toUpperCase() +
' ' +
(contact.firstname ?? '');
return (
this.props.navigation.navigate('ContactDetailsScreen', {
action: 'edit',
contactId: contact.id,
})
}>
{contact.lastname || contact.firstname ? displayName : contact.id}
this.composeNewEmailTo(contact.email)}>
{contact.email}
contact.phone ? this.callNumberIfSupported(contact.phone) : false
}>
{contact.phone}
{
this.deleteContactAction(contact);
}}>
{
this.setState({
showTransferContact: true,
contactToTransfer: contact,
});
}}>
);
}
sortContacts(field) {
let sort;
if (field !== this.state.sortField) {
sort = 'asc';
} else {
if (this.state.sortType === 'asc') {
sort = 'desc';
} else {
sort = 'asc';
}
}
this.setState({
contacts: this.state.contacts.sort(Helpers.compareValues(field, sort)),
sortType: sort,
sortField: field,
});
}
handleSearchBtn() {
if (this.state.searchTxt.length > 0) {
let obj = this.props.contacts;
let array = Object.keys(obj).map(function (key) {
return obj[key];
});
this.setState({
contacts: array.sort(Helpers.compareValues('name', 'asc')),
sortType: 'asc',
searchTxt: '',
});
}
}
handleSearchTxt(text) {
this.setState({ searchTxt: text });
/** @type {Array} */
const contacts = this.props.contacts;
if (text.length > 0) {
const tmpContactsLastname = contacts.filter(
item => item.lastname?.toLowerCase()?.indexOf(text.toLowerCase()) >= 0,
);
const tmpContactsFirstname = contacts.filter(
item => item.firstname?.toLowerCase()?.indexOf(text.toLowerCase()) >= 0,
);
const tmpContactsEmail = contacts.filter(
item => item.email.toLowerCase().indexOf(text.toLowerCase()) >= 0,
);
const tmpContactsPhone = contacts.filter(
item => item.phone?.toLowerCase()?.indexOf(text.toLowerCase()) >= 0,
);
const resSearch = new Map();
tmpContactsLastname.forEach(contact =>
resSearch.set(contact.id, contact),
);
tmpContactsFirstname.forEach(contact =>
resSearch.set(contact.id, contact),
);
tmpContactsEmail.forEach(contact => resSearch.set(contact.id, contact));
tmpContactsPhone.forEach(contact => resSearch.set(contact.id, contact));
this.setState({
contacts: [...resSearch.values()].sort(
Helpers.compareValues('name', 'asc'),
),
sortType: 'asc',
});
} else {
let obj = this.props.contacts;
let array = Object.keys(obj).map(function (key) {
return obj[key];
});
this.setState({
contacts: array.sort(Helpers.compareValues('name', 'asc')),
sortType: 'asc',
});
}
}
componentDidMount() {
this.init();
}
componentDidUpdate(prevProps, prevState, snapshot) {
if (prevProps.contacts !== this.props.contacts) {
this.init();
}
}
init() {
let objContacts = this.props.contacts;
let objDocs = this.props.documents;
let arrayContacts = Object.keys(objContacts).map(function (key) {
return objContacts[key];
});
let arrayEmails = Object.keys(objContacts).map(function (key) {
return objContacts[key];
});
let arrayDocs = Object.keys(objDocs).map(function (key) {
return objDocs[key];
});
const { action } = this.props.route.params;
if (action === 'add') {
this.props.navigation.navigate('ContactDetailsScreen', {
action: 'add',
});
}
this.setState({
contacts: arrayContacts.sort(Helpers.compareValues('timestamp', 'desc')),
sortedDocuments: arrayDocs.sort(Helpers.compareValues('title', 'asc')),
sortedEmails: arrayEmails.sort(Helpers.compareValues('email', 'asc')),
sortType: 'asc',
sortField: 'name',
});
}
render() {
const { contactAdded } = this.props.route.params;
if (contactAdded === true) {
this.props.navigation.setParams({ contactAdded: false });
showMessage({
message: i18n.t('contact_s.contact_added') + '.',
type: 'success',
duration: 500,
});
}
return (
{/* ACTIONS */}
{/* TABLE view */}
this.Item(item)}
ListHeaderComponent={this.HeaderItem.bind(this)}
keyExtractor={item => item.id.toString()}
/>
{/* TRANSFERT CONTACT POPUP */}
{i18n.t('contact_s.select_contact')} :
{
this.setState({ selectedTransferUserIndex: itemIndex });
}}>
{this.props.users
.filter(user => user.id !== this.props.currentUser.id)
.sort(Helpers.compareValues('email', 'asc'))
.map((item, index) => {
return (
);
})}
this.setState({ showTransferContact: false })}
/>
this.transferContact()}
/>
{/* DELETE CONTACT POPUP */}
this.setState({ tmpSendBrochureEmail: text })
}
/>
{
if (itemValue !== '-1') {
this.setState({
tmpSendBrochureEmail:
this.state.sortedEmails[itemIndex - 1].email,
});
}
}}>
{this.state.sortedEmails.map((item, index) => {
return (
);
})}
this.setState({ tmpSendBrochureSubject: text })
}
/>
this.setState({ tmpSendBrochureMessage: text })
}
/>
{
if (
itemValue !== '-1' &&
this.state.sendDocumentList.length < 8
) {
const tmp = this.state.sendDocumentList;
const toPush = this.state.sortedDocuments[itemIndex - 1];
const test = this.state.sendDocumentList.filter(
item => item.id === toPush.id,
);
if (test.length === 0) {
tmp.push(toPush);
this.setState({
sendDocumentList: tmp,
});
}
}
}}>
{this.state.sortedDocuments.map((item, index) => {
return (
);
})}
{this.state.sendDocumentList.map((item, index) => {
return (
{
const tmp = this.state.sendDocumentList;
tmp.splice(this.props.documents[index], 1);
this.setState({
sendDocumentList: tmp,
});
}}>
{item.title} ({item.type.toUpperCase()}){' '}
);
})}
this.setState({
showSendBrochure: false,
tmpSendBrochureEmail: '',
tmpSendBrochureSubject: '',
tmpSendBrochureMessage: '',
selectedSendBrochureEmail: -1,
selectedDocument: -1,
sendDocumentList: [],
})
}
/>
this.sendBrochure()}
color={this.props.mainColor}
/>
);
}
}
export default connect(mapStateToProps, mapDispatchToProps)(ContactScreen);