Created
August 24, 2022 20:29
-
-
Save chamellion/5d424f89c6bf51ea61c01e4a5561f6d5 to your computer and use it in GitHub Desktop.
Chat on booklist
This file contains hidden or 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 React, {useEffect, useState} from 'react'; | |
import SafeAreaContainer from "../../components/SafeAreaContainer"; | |
import { | |
Alert, | |
FlatList, KeyboardAvoidingView, LayoutAnimation, | |
StyleSheet, | |
Text, | |
TextInput, | |
ToastAndroid, | |
TouchableOpacity, | |
View | |
} from "react-native"; | |
import Utils from "../Utils"; | |
import DefaultPreferences from "react-native-default-preference"; | |
import CustomSpinner from "../../components/CustomSpinner"; | |
import Ionicons from "react-native-vector-icons/Ionicons"; | |
const globalStyle = require('../GlobalStyleSheet') | |
const caretUp = <Ionicons name={'caret-up-sharp'} color={'black'} size={18}/> | |
const caretDown = <Ionicons name={'caret-down-sharp'} color={'black'} size={18}/> | |
const Chat = (props) => { | |
const resourceId = props.resourceId.id | |
const [chatResource, setChatResource] = useState([]) | |
const [loading, setLoading] = useState(true) | |
const [showReply, setShowReply] = useState(false) | |
const [showComment, setShowComment] = useState(false) | |
const [shouldReplyComment, setShouldReplyComment] = useState(false) | |
const [activeIndex, setActiveIndex] = useState(0) | |
const [userComment, setUserComment] = useState("") | |
const [replyComment, setReplyComment] = useState("") | |
const getAllBookChats = async () => { | |
try { | |
setLoading(true) | |
let token = await DefaultPreferences.get("TOKEN_PREF") | |
let BASE_URL = Utils.baseUrl | |
let bookList = "book list" | |
let response = await fetch(`${BASE_URL}/chat/resource/${bookList}/resourceId/${resourceId}`, { | |
method: 'GET', | |
headers: { | |
"Authorization": token | |
} | |
}) | |
let responseJson = await response.json() | |
if (response.status === 200) { | |
let chatData = responseJson.data.Chats | |
const rData = restructureData(chatData) | |
setChatResource(rData) | |
} else { | |
Alert.alert("Error", responseJson.messages[0]) | |
} | |
} catch (e) { | |
console.log(e); | |
Alert.alert("Error", "One or more error has occurred") | |
} finally { | |
setLoading(false) | |
} | |
} | |
const saveAComment = async () => { | |
try { | |
setLoading(true) | |
if (userComment.length <= 0) { | |
Alert.alert("Error", "Empty text, enter a valid message to continue") | |
} else { | |
let profileId = await DefaultPreferences.get("PROFILE_PREF") | |
let token = await DefaultPreferences.get("TOKEN_PREF") | |
const data = JSON.stringify({ | |
"profileId": profileId, | |
"resource": "book list", | |
"resourceId": resourceId, | |
"discussion": userComment, | |
"reply": null, | |
"attachment": null | |
}) | |
let BASE_URL = Utils.baseUrl | |
let response = await fetch(BASE_URL + "chat", { | |
method: 'POST', | |
headers: { | |
"Authorization": token, | |
'Content-type': 'application/json', | |
}, | |
body: data | |
}) | |
let responseJson = await response.json(); | |
if (response.status === 201) { | |
ToastAndroid.show("Post successful", ToastAndroid.SHORT) | |
await getAllBookChats() | |
} | |
} | |
} catch (e) { | |
console.log(e); | |
} finally { | |
setLoading(false) | |
} | |
} | |
const saveAReply = async (replyId) => { | |
try { | |
setLoading(true) | |
if (replyComment.length <= 0) { | |
Alert.alert("Error", "Empty text, enter a valid message to continue") | |
} else { | |
let profileId = await DefaultPreferences.get("PROFILE_PREF") | |
let token = await DefaultPreferences.get("TOKEN_PREF") | |
const data = JSON.stringify({ | |
"profileId": profileId, | |
"resource": "book list", | |
"resourceId": resourceId, | |
"discussion": replyComment, | |
"reply": replyId, | |
"attachment": null | |
}) | |
let BASE_URL = Utils.baseUrl | |
let response = await fetch(BASE_URL + "chat", { | |
method: 'POST', | |
headers: { | |
"Authorization": token, | |
'Content-type': 'application/json', | |
}, | |
body: data | |
}) | |
let responseJson = await response.json(); | |
if (response.status === 201) { | |
ToastAndroid.show("Post successful", ToastAndroid.SHORT) | |
await getAllBookChats() | |
} | |
} | |
} catch (e) { | |
console.log(e); | |
} finally { | |
setLoading(false) | |
} | |
} | |
useEffect(() => { | |
getAllBookChats().catch(e => console.log(e)) | |
}, []) | |
return ( | |
<SafeAreaContainer> | |
<View> | |
<View> | |
<CustomSpinner setVisibility={loading} spinnerStyle={Style.spinnerStyle}/> | |
<TouchableOpacity style={Style.buttonContainer} onPress={() => setShowComment(!showComment)}> | |
<Text style={Style.buttonText}>{showComment ? "Close Comment" : "Write Comment"}</Text> | |
</TouchableOpacity> | |
{ | |
showComment && <View> | |
<TextInput style={[globalStyle.textInputStyle, {alignSelf: "center", marginTop: 12}]} | |
placeholder={"Type your comment"} | |
multiline={true} | |
onChangeText={setUserComment} | |
value={userComment} | |
/> | |
<TouchableOpacity style={Style.sendButtonContainer} onPress={async () => { | |
if (userComment.length <= 0) { | |
Alert.alert("Error", "Empty text, enter a valid message to continue") | |
} else { | |
await saveAComment() | |
setUserComment("") | |
} | |
}}> | |
<Text style={Style.sendButtonText}>Send</Text> | |
</TouchableOpacity> | |
</View> | |
} | |
</View> | |
<FlatList | |
data={chatResource} | |
initialNumToRender={10} | |
keyExtractor={(item, index) => index} | |
showsVerticalScrollIndicator={false} | |
renderItem={({item, index}) => { | |
const data = item.cleanData ? item.cleanData : item; | |
let discussion = data.discussion | |
let fullName = data.profile_info.surname + " " + data.profile_info.firstname | |
if (data.replies.length > 0) { | |
return ( | |
<KeyboardAvoidingView> | |
<TouchableOpacity onPress={() => { | |
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut) | |
setShowReply(!showReply) | |
setActiveIndex(index) | |
setReplyComment("") | |
}}> | |
<View style={Style.chatContainer}> | |
<Text style={Style.chatName}>{fullName}</Text> | |
<Text style={Style.chatMessage}>{discussion}</Text> | |
<View style={{ | |
flexDirection: "row", | |
alignSelf: 'flex-end', | |
marginEnd: 12, | |
justifyContent: 'center' | |
}}> | |
<Text | |
style={Style.replyNumber}>{data.replies.length} {data.replies.length > 1 ? "Replies" : "Reply"}</Text> | |
<Text>{showReply ? caretDown : caretUp}</Text> | |
</View> | |
</View> | |
</TouchableOpacity> | |
{ | |
(activeIndex === index) && showReply && data.replies.map((item, index) => ( | |
<View style={Style.replyContainer} key={index}> | |
<Text | |
style={Style.chatName}>{item.profile_info.surname + " " + item.profile_info.firstname}</Text> | |
<Text style={Style.chatMessage}>{item.discussion}</Text> | |
</View> | |
)) | |
} | |
{ | |
(activeIndex === index) && showReply && | |
<View> | |
<TextInput style={[globalStyle.textInputStyle, { | |
alignSelf: "flex-end", | |
marginTop: 4, | |
padding: 8, | |
width: '80%' | |
}]} | |
placeholder={"Reply Comment"} | |
multiline={true} | |
onChangeText={setReplyComment} | |
value={replyComment} | |
/> | |
<TouchableOpacity style={[Style.sendButtonContainer, {padding: 2}]} | |
onPress={async () => { | |
if (replyComment.length <= 0) { | |
Alert.alert("Error", "Empty text, enter a valid message to continue") | |
} else { | |
await saveAReply(data.id) | |
setReplyComment("") | |
} | |
}}> | |
<Text style={Style.sendButtonText}>Reply</Text> | |
</TouchableOpacity> | |
</View> | |
} | |
</KeyboardAvoidingView> | |
) | |
} else { | |
return ( | |
<KeyboardAvoidingView> | |
<TouchableOpacity onPress={() => { | |
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut) | |
setShouldReplyComment(!shouldReplyComment) | |
setActiveIndex(index) | |
setReplyComment("") | |
}}> | |
<View> | |
<View style={Style.chatContainer}> | |
<Text style={Style.chatName}>{fullName}</Text> | |
<Text style={Style.chatMessage}>{discussion}</Text> | |
</View> | |
{ | |
(activeIndex === index) && shouldReplyComment && <View> | |
<TextInput style={[globalStyle.textInputStyle, { | |
alignSelf: "flex-end", | |
marginTop: 4, | |
padding: 8, | |
width: '80%' | |
}]} | |
placeholder={"Reply Comment"} | |
multiline={true} | |
onChangeText={setReplyComment} | |
value={replyComment} | |
/> | |
<TouchableOpacity style={[Style.sendButtonContainer, {padding: 2}]} | |
onPress={async () => { | |
if (replyComment.length <= 0) { | |
Alert.alert("Error", "Empty text, enter a valid message to continue") | |
} else { | |
await saveAReply(data.id) | |
setReplyComment("") | |
} | |
}}> | |
<Text style={Style.sendButtonText}>Reply</Text> | |
</TouchableOpacity> | |
</View> | |
} | |
</View> | |
</TouchableOpacity> | |
</KeyboardAvoidingView> | |
) | |
} | |
}} | |
/> | |
</View> | |
</SafeAreaContainer> | |
); | |
}; | |
const Style = StyleSheet.create({ | |
container: { | |
margin: 16, | |
}, | |
buttonContainer: { | |
backgroundColor: Utils.buttonColor, | |
paddingVertical: 12, | |
paddingHorizontal: 10, | |
borderRadius: 5, | |
alignSelf: 'flex-end', | |
marginTop: 6, | |
}, | |
buttonText: { | |
color: 'white', | |
fontFamily: 'NunitoSans-ExtraBold', | |
fontSize: 12, | |
textAlign: 'center', | |
textTransform: 'uppercase', | |
} | |
, | |
headerContainer: { | |
flexDirection: 'row', | |
alignItems: 'center', | |
margin: 8, | |
justifyContent: 'space-between' | |
} | |
, | |
vRatingText: { | |
fontFamily: 'NunitoSans-SemiBold', | |
fontSize: 16 | |
} | |
, | |
ratingNumber: { | |
fontFamily: 'NunitoSans-ExtraBold', | |
textAlign: 'center', | |
color: 'black' | |
} | |
, | |
chatName: { | |
fontFamily: 'NunitoSans-ExtraBold', | |
color: 'black' | |
} | |
, | |
chatMessage: { | |
fontFamily: 'NunitoSans-SemiBoldItalic', | |
} | |
, | |
chatContainer: { | |
backgroundColor: '#F2F3F7', | |
padding: 12, | |
marginTop: 16, | |
marginStart: 8, | |
borderRadius: 12, | |
}, | |
replyContainer: { | |
backgroundColor: '#F2F3F7', | |
padding: 12, | |
marginTop: 4, | |
marginStart: 50, | |
borderRadius: 12, | |
}, | |
createChatBox: { | |
borderWidth: 1 | |
}, | |
sendButtonContainer: { | |
paddingHorizontal: 16, | |
alignSelf: 'flex-end', | |
backgroundColor: | |
Utils.buttonColor, | |
borderRadius: 5, | |
paddingVertical: 6, | |
marginEnd: 24, | |
marginTop: 4, | |
marginBottom: 8, | |
justifyContent: 'flex-end' | |
}, | |
sendButtonText: { | |
textTransform: 'uppercase', | |
color: 'white', | |
fontFamily: 'NunitoSans-ExtraBold' | |
}, | |
spinnerStyle: { | |
position: "absolute", | |
alignSelf: "center", | |
top: 100, | |
zIndex: 3, | |
elevation: 3 | |
}, | |
replyNumber: { | |
fontFamily: 'NunitoSans-BoldItalic', | |
textAlign: 'right', | |
marginEnd: 16, | |
fontSize: 13 | |
} | |
} | |
) | |
export function restructureData(itemArray) { | |
let sanitizedData = [] | |
const messages = itemArray.filter(item => item.reply === null) | |
const replies = itemArray.filter(item => item.reply !== null) | |
for (const message of messages) { | |
let messageId = message.id | |
const replyArray = replies.filter(item => item.reply === messageId) | |
Object.assign(message, {"replies": replyArray}) | |
sanitizedData.push(message) | |
} | |
console.log("Sanitized array is ") | |
console.log(sanitizedData) | |
return sanitizedData | |
} | |
export default Chat; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment