This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import _ from "lodash"; | |
import React from 'react'; | |
import moment from 'moment'; | |
import { connect } from 'react-redux'; | |
import API from '@Services/Api/profile'; | |
import { ApiManager } from "../../api/apiManager"; | |
import ParsedText from 'react-native-parsed-text'; | |
import { NavigationEvents } from "react-navigation"; | |
import { DateToWordsFromNow } from '../../helpers/helper'; | |
import { ACTIVITY_NOTIFICATION } from "../../api/constants"; | |
import EmptyState from "../../components/empty_state/emptyState"; | |
import { Feather, MaterialCommunityIcons, AntDesign, Entypo } from '@expo/vector-icons'; | |
import { scale, blumerMainColor, blumerSixthColor, MAIN_FONT_FAMILY, blumerSecondaryColor} from "@Styles/style"; | |
import { | |
Text, | |
View, | |
Alert, | |
Image, | |
FlatList, | |
Dimensions, | |
TouchableOpacity, | |
ActivityIndicator, | |
DeviceEventEmitter, | |
} from 'react-native'; | |
import { notification } from "expo-haptics"; | |
const { height, width } = Dimensions.get('window'); | |
function firstCap(string) { | |
return string.charAt(0).toUpperCase() + string.slice(1); | |
} | |
const Thumbnail = ({ onLoad, notification, icon }) => ( | |
<View style={{ | |
borderWidth: .5, | |
width: scale(60), | |
height: scale(60), | |
alignItems: 'center', | |
borderColor: '#CDCDCD', | |
borderRadius: scale(30), | |
justifyContent: 'center', | |
marginRight: 10, | |
}}> | |
<View style={{ | |
width: scale(55), | |
height: scale(55), | |
borderRadius: scale(55 / 2), | |
}}> | |
<Image | |
onLoad={onLoad} | |
source={{ uri: notification.photo }} | |
style={{ | |
width: '100%', | |
height: '100%', | |
borderRadius: scale(55 / 2), | |
}} | |
/> | |
</View> | |
<View style={{ | |
right: 2.5, | |
bottom: -5, | |
width: scale(25), | |
height: scale(25), | |
position: 'absolute', | |
alignItems: 'center', | |
justifyContent: 'center', | |
borderRadius: scale(25 / 2), | |
backgroundColor: blumerSecondaryColor | |
}}> | |
{icon} | |
</View> | |
</View> | |
); | |
const NoNotifications = () => { | |
return ( | |
<View style={{ | |
flex: 1, | |
height: height - scale(150) | |
}}> | |
<View style={{ | |
marginTop: 8, | |
flexDirection: 'row', | |
marginHorizontal: 70, | |
}}> | |
<View style={{ | |
flex: 1, | |
width: scale(240), | |
alignItems: 'center', | |
justifyContent: 'center', | |
}}> | |
<Text style={{ | |
color: '#a9c4fc', | |
textAlign: 'center', | |
fontSize: scale(15), | |
}}> | |
Agrega amigos para que comiences a interactuar | |
</Text> | |
</View> | |
<Image | |
style={{ width: scale(43), height: scale(43) }} | |
source={require('@Assets/images/arrow-up.png')} | |
/> | |
</View> | |
<View style={{ | |
flex: 1, | |
alignItems: 'center', | |
justifyContent: 'center', | |
}}> | |
<Image | |
style={{ width: width * .9, height: width * .9 }} | |
source={require('@Assets/images/notifications.png')} | |
/> | |
<Text style={{ | |
marginTop: 15, | |
color: '#a9c4fc', | |
fontSize: scale(22), | |
}}> | |
… Aún no tienes notificaciones … | |
</Text> | |
</View> | |
</View> | |
) | |
} | |
const FRIEND_RELATIONSHIP_STATUS = { | |
IS_FRIEND: 1, | |
IN_PROCESS: 2, | |
BLOCKED_USER: 4, | |
IS_NOT_FRIEND: 0, | |
FRIENDSHIP_REQUESTED: 3, | |
}; | |
const FRIENDSHIP_STATUS = { | |
DENY: 3, // Reject/Cancel friendship request | |
DELETE: 4, // Delete friend | |
UNBLOCK: 6, // Unblock friend | |
BLOCKED: 5, // Block friend | |
ACCEPTED: 2, // <= Acept friend request | |
REQUESTED: 1, // <= Friendship request | |
}; | |
class ProfileNotifications extends React.Component { | |
constructor(props) { | |
super(props); | |
this.state = { | |
loading: false, | |
refreshing: false, | |
notifications: [], | |
loadingFriendshipProcess: false, | |
friendshipStatus: FRIEND_RELATIONSHIP_STATUS.IS_NOT_FRIEND, | |
} | |
this.page = 0; | |
this.lastPage = -1; | |
} | |
async componentDidMount() { | |
await this.getNotifications(); | |
} | |
async getNotifications() { | |
this.setState({ loading: true }); | |
const res = await ApiManager.getNotifications(this.props.token, this.page); | |
this.setState({ loading: false }); | |
console.log('NOTIFICACIONES:', res) | |
this.lastPage = this.page; | |
if (!res.error) { | |
const _notifications = this.page == 0 ? res.message.data : [...this.state.notifications, ...res.message.data] | |
let notifications = []; | |
for (let i = 0; i < _notifications.length; i++) { | |
const notification = _notifications[i]; | |
if (_.findIndex(notifications, { id: notification.id, type_notification: notification.type_notification }) == -1) { | |
notifications.push(notification); | |
} | |
} | |
this.setState({ notifications }) | |
if (res.message.data.length > 0) { | |
this.page++; | |
} | |
} | |
else { | |
Alert.alert('Atención', 'No se pudo obtener el listado de notificaciones.'); | |
} | |
} | |
async setNotificationAsRead(postId, typeOfNotification, typeOfNotificationId, ownerProfileId = '', ...props) { | |
DeviceEventEmitter.emit('onLoadingEvent', { loading: true }) | |
let notificationAsReadBody = { | |
friendShipId: typeOfNotificationId, | |
notificationId: typeOfNotificationId, | |
typeOfNotification: typeOfNotification | |
} | |
if (typeOfNotification == ACTIVITY_NOTIFICATION.FRIENDSHIP) { | |
delete notificationAsReadBody.notificationId; | |
} | |
else { | |
delete notificationAsReadBody.friendShipId; | |
} | |
let res = await ApiManager.sendReadStatus(this.props.token, notificationAsReadBody); | |
DeviceEventEmitter.emit('onLoadingEvent', { loading: false }) | |
if (!res.error) { | |
if (typeOfNotification == ACTIVITY_NOTIFICATION.FRIENDSHIP) { | |
this.props.navigation.navigate('PersonProfile', { token: this.props.token, userId: ownerProfileId }) | |
} else { | |
this.props.navigation.navigate('PostDetails', { token: this.props.token, postId: postId }) | |
} | |
} | |
else { | |
Alert.alert('Atención', 'Se ha producido un error, por favor vuelve a intentarlo.'); | |
} | |
} | |
onFriendRequestAction = (allow = true, notification_id) => { | |
this.setState({ loadingFriendshipProcess: true }); | |
const { userId } = this.props; | |
return API.cancelFriendRequest({ | |
notification: 1, | |
follow_id: userId, | |
status_id: allow ? FRIENDSHIP_STATUS.ACCEPTED : FRIENDSHIP_STATUS.DENY, | |
}).then(({ response, rawResponse, error }) => { | |
if (!error && !response.error && [200, 201].indexOf(rawResponse.status) !== -1) { | |
return API.notificationFriendRequest({ | |
notification_id | |
}).then(({ error: error2, rawResponse: rawResponse2, }) => { | |
if (!error2 && [200, 201].indexOf(rawResponse2.status) !== -1) { | |
if (allow) { | |
const notifications = _.cloneDeep(this.state.notifications); | |
const _notification = _.find(notifications, { id: notification_id }); | |
if (!!_notification) { | |
_notification.by_read = true; | |
} | |
this.setState({ notifications }); | |
} else { | |
this.setState({ | |
notifications: _.filter(({ id }) => id !== notification_id) | |
}); | |
} | |
} else { | |
console.log('Error Al leer la notificacion') | |
} | |
}) | |
} else { | |
this.setState({ loadingFriendshipProcess: false }); | |
Alert.alert('Lo sentimos', 'Ha ocurrido un error intentando procesar su solicitud'); | |
} | |
}); | |
} | |
renderFriendRequestNotification(notificationElement) { | |
return ( | |
<TouchableOpacity | |
style={{ | |
flex: 1, | |
// width: width - 20, | |
padding: 10, | |
marginVertical: 1, | |
alignItems: 'center', | |
flexDirection: 'row', | |
backgroundColor: '#FFF', | |
justifyContent: 'space-between', | |
paddingHorizontal: 20, | |
}} | |
onPress={() => { | |
this.setNotificationAsRead( | |
notificationElement.post_id, | |
notificationElement.type_notification, | |
notificationElement.id, | |
notificationElement.id_profile_owner, | |
notificationElement.by_read | |
) | |
}} | |
activeOpacity={.9} | |
> | |
<View style={{ | |
flexDirection: 'row', | |
backgroundColor: '#FFF', | |
}}> | |
<Thumbnail | |
onLoad={() => { }} | |
notification={notificationElement} | |
icon={( | |
<Feather name="user-plus" size={14} color="#FFF" /> | |
)} | |
/> | |
<View style={{ flex: 1 }}> | |
{ | |
this.state.friendshipStatus === FRIEND_RELATIONSHIP_STATUS.IS_FRIEND ? | |
<View style={{}}> | |
<Text style={{ | |
color: '#000000', | |
fontSize: scale(13), | |
fontFamily: MAIN_FONT_FAMILY, | |
}}> | |
{ `${_.startCase(_.lowerCase(notificationElement.first_name))} ${_.startCase(_.lowerCase(notificationElement.last_name))} y tu` } | |
</Text> | |
<Text style={{ | |
marginTop: 2.5, | |
color: '#808080', | |
fontSize: scale(12), | |
fontFamily: MAIN_FONT_FAMILY, | |
}}> | |
Ahora son amigos en Blumer! | |
</Text> | |
</View> | |
: <View> | |
<Text style={{ | |
color: '#000000', | |
fontSize: scale(13), | |
fontFamily: MAIN_FONT_FAMILY, | |
}}> | |
{ _.startCase(_.lowerCase(`${notificationElement.first_name} ${notificationElement.last_name}`)) } | |
</Text> | |
<Text style={{ | |
marginTop: 2.5, | |
color: '#808080', | |
fontSize: scale(12), | |
fontFamily: MAIN_FONT_FAMILY, | |
}}> | |
Te ha enviado una solicitud de amistad. | |
</Text> | |
<View style={{ | |
marginTop: 10, | |
flexDirection: 'row', | |
}}> | |
<TouchableOpacity | |
activeOpacity={.9} | |
onPress={() => this.onFriendRequestAction(true, notification_id = notificationElement.by_read)} | |
disabled={this.state.loadingFriendshipProcess} | |
style={{ | |
flex: 1, | |
marginRight: 5, | |
borderRadius: 8, | |
height: scale(25), | |
flexDirection: 'row', | |
alignItems: 'center', | |
borderColor: '#D1D1D1', | |
justifyContent: 'center', | |
backgroundColor: blumerSecondaryColor, | |
}} | |
> | |
<Text style={{ | |
color: '#FFF', | |
fontSize: scale(12), | |
textAlign: 'center', | |
fontFamily: MAIN_FONT_FAMILY, | |
}}> | |
Confirmar | |
</Text> | |
{ | |
this.state.loadingFriendshipProcess && <View style={{ | |
marginLeft: 10 | |
}}> | |
<ActivityIndicator color="#FFF" /> | |
</View> | |
} | |
</TouchableOpacity> | |
<TouchableOpacity | |
activeOpacity={.9} | |
onPress={() => this.onFriendRequestAction(false, notification_id = notificationElement.by_read)} | |
disabled={this.state.loadingFriendshipProcess} | |
style={{ | |
flex: 1, | |
marginRight: 5, | |
borderRadius: 8, | |
height: scale(25), | |
flexDirection: 'row', | |
alignItems: 'center', | |
justifyContent: 'center', | |
backgroundColor: '#E3E3E3', | |
}} | |
> | |
<Text style={{ | |
color: '#979797', | |
fontSize: scale(12), | |
textAlign: 'center', | |
fontFamily: MAIN_FONT_FAMILY, | |
}}> | |
Eliminar | |
</Text> | |
{ | |
this.state.loadingFriendshipProcess && <View style={{ | |
marginLeft: 10 | |
}}> | |
<ActivityIndicator color="red" /> | |
</View> | |
} | |
</TouchableOpacity> | |
</View> | |
</View> | |
} | |
<Text style={{ | |
marginTop: 10, | |
color: '#808080', | |
fontSize: scale(12), | |
fontFamily: MAIN_FONT_FAMILY | |
}}> | |
{ firstCap(moment(notificationElement.date).startOf('hour').fromNow()) } | |
</Text> | |
</View> | |
{ | |
this.state.friendshipStatus === FRIEND_RELATIONSHIP_STATUS.IS_FRIEND ? | |
<View style={{ | |
borderRadius: 8, | |
width: scale(65), | |
height: scale(65), | |
}}> | |
<Image | |
resizeMode="cover" | |
source={require('@Assets/images/friend-blumer.png')} | |
style={{ width: '100%', height: '100%', alignSelf: "center", borderRadius: 8 }} | |
/> | |
</View> : null | |
} | |
</View> | |
</TouchableOpacity> | |
) | |
} | |
renderActivityNotification(notificationElement) { | |
// let message = `${notificationElement.first_name}`; | |
let message = `__name__`; | |
if ('listado_actores' in notificationElement) { | |
if (notificationElement.listado_actores.length > 0) { | |
for (let index = 0; index < notificationElement.listado_actores.length; index++) { | |
const actor = notificationElement.listado_actores[index]; | |
if (index == notificationElement.listado_actores.length - 1) { | |
if (notificationElement.count > 0) { | |
message += `, ${actor} y ${(notificationElement.count > 1 ? `otras ${notificationElement.count} personas` : `una persona más`)}`; | |
} | |
else { | |
message += ` y ${actor}`; | |
} | |
} | |
else { | |
message += `, ${actor}`; | |
} | |
} | |
} | |
} | |
switch (notificationElement.type_notification) { | |
case ACTIVITY_NOTIFICATION.LIKE: | |
notificationIcon = <AntDesign name="like2" size={15} color="#FFF" />; | |
message += (`${notificationElement.listado_actores} Le gusta tu publicación`); | |
break; | |
case ACTIVITY_NOTIFICATION.COMMENT: | |
notificationIcon = <MaterialCommunityIcons name="comment-multiple-outline" size={15} color="#FFF" />; | |
message += (`${notificationElement.listado_actores} Comentó en tu publicación`); | |
break; | |
case ACTIVITY_NOTIFICATION.SHARED: | |
notificationIcon = <Entypo name="share" size={15} color="#FFF" />; | |
message += (`${notificationElement.listado_actores} Compartió tu publicación`); | |
break; | |
case ACTIVITY_NOTIFICATION.MENTION: | |
notificationIcon = null; | |
message += " te ha mencionado en una publicación." | |
break; | |
} | |
return ( | |
<TouchableOpacity | |
style={{ | |
padding: 10, | |
marginVertical: 1, | |
flexDirection: 'row', | |
backgroundColor: '#FFF', | |
paddingHorizontal: 20, | |
}} | |
onPress={() => { | |
this.setNotificationAsRead( | |
notificationElement.post_id, | |
notificationElement.type_notification, | |
notificationElement.id | |
) | |
}} | |
activeOpacity={.9} | |
> | |
<Thumbnail | |
onLoad={() => { }} | |
icon={notificationIcon} | |
notification={notificationElement} | |
/> | |
<View style={{ flex: 1 }}> | |
<ParsedText | |
style={{ | |
color: '#808080', | |
fontSize: scale(12), | |
fontFamily: MAIN_FONT_FAMILY | |
}} | |
parse={[ | |
{ | |
pattern: /__name__/, | |
onPress: (name) => { }, | |
renderText: (string) => `${notificationElement.first_name} ${notificationElement.last_name}`, | |
style: { | |
color: '#000', | |
fontSize: scale(13), | |
fontFamily: MAIN_FONT_FAMILY, | |
}, | |
}, | |
]} | |
> | |
{message} | |
</ParsedText> | |
<Text style={{ | |
marginTop: 10, | |
color: '#808080', | |
fontSize: scale(12), | |
fontFamily: MAIN_FONT_FAMILY | |
}}> | |
{ firstCap(moment(notificationElement.date).startOf('hour').fromNow()) } | |
</Text> | |
</View> | |
<View style={{ | |
width: scale(65), | |
height: scale(65), | |
backgroundColor: '#F4F4F4F4', | |
borderRadius: 8, | |
}}> | |
<Image | |
resizeMode="cover" | |
source={{ uri: notificationElement.cover }} | |
style={{ width: '100%', height: '100%', alignSelf: "center", borderRadius: 8 }} | |
onLoad={() => this.setState({ ['loadingImage' + notificationElement.id]: true })} | |
/> | |
</View> | |
</TouchableOpacity> | |
); | |
} | |
_onRefresh = async () => { | |
this.setState({ refreshing: true }); | |
this.page = 0; | |
await this.getNotifications(); | |
this.setState({ refreshing: false }); | |
} | |
_handleLoadMore = async () => { | |
if (!this.state.loading && this.lastPage !== this.page) | |
await this.getNotifications(); | |
} | |
_renderFooter = () => { | |
if (!this.state.loading || this.lastPage === this.page) return null; | |
return ( | |
<View style={{ width: '100%', alignItems: 'center', padding: 15 }}> | |
<ActivityIndicator size="large" color={blumerMainColor} /> | |
</View> | |
) | |
} | |
render() { | |
return ( | |
<View style={{ flex: 1, backgroundColor: blumerSixthColor, }}> | |
{/* <NavigationEvents onDidFocus={payload => this._onNavigationDidFocus(payload)}/> */} | |
<View style={{ flex: 1, }}> | |
<FlatList | |
keyExtractor={(item, index) => index.toString()} | |
ListEmptyComponent={( | |
this.state.notifications.length == 0 && !this.state.loading && | |
<NoNotifications /> | |
)} | |
data={this.state.notifications} | |
onRefresh={this._onRefresh} | |
refreshing={this.state.refreshing} | |
onEndReached={this._handleLoadMore} | |
onEndReachedThreshold={0.8} | |
extraData={this.state} | |
ListFooterComponent={this._renderFooter} | |
renderItem={({ item, index }) => ( | |
<View key={index}> | |
{ | |
item.type_notification == ACTIVITY_NOTIFICATION.FRIENDSHIP && | |
this.renderFriendRequestNotification(item) | |
} | |
{ | |
item.type_notification != ACTIVITY_NOTIFICATION.FRIENDSHIP && | |
this.renderActivityNotification(item) | |
} | |
</View> | |
)} | |
/> | |
</View> | |
</View> | |
) | |
} | |
} | |
/** | |
* Function to map the global state into component props | |
* | |
* @param {Object} param0 The object global state | |
*/ | |
const mapStateToProps = ({ session }) => ({ | |
token: session.token, | |
userId: session.userId, | |
}); | |
export default connect(mapStateToProps)(ProfileNotifications); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment