0% found this document useful (0 votes)
25 views

Previous Code

This document defines a MessageInput component in React that allows sending and receiving messages in a chat. It imports necessary libraries and defines states and functions related to messages, files, and websockets. On component mount, it connects to a websocket to subscribe to new messages and display them. It also defines logic for handling multipart messages and merging message parts on receipt.

Uploaded by

sm zubayer
Copyright
© © All Rights Reserved
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
25 views

Previous Code

This document defines a MessageInput component in React that allows sending and receiving messages in a chat. It imports necessary libraries and defines states and functions related to messages, files, and websockets. On component mount, it connects to a websocket to subscribe to new messages and display them. It also defines logic for handling multipart messages and merging message parts on receipt.

Uploaded by

sm zubayer
Copyright
© © All Rights Reserved
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 14

import React, { useContext, useEffect, useState } from 'react';

import { FaFileImage } from 'react-icons/fa';


import { AiOutlineSend } from 'react-icons/ai';
import { MdOndemandVideo } from 'react-icons/md';
import { AiOutlineFileAdd } from 'react-icons/ai';
import axios from 'axios';
import toast from 'react-hot-toast';
import { AuthContext } from '../../../context/UserContext';
import { Client } from '@stomp/stompjs';
import { sendChatMessage } from './SendMessageFunction';

const MessageInput = ({
setAllChat,
selectedCustomerChat,
allChat,

}) => {

const [message, setMessage] = useState('');


const [selectedFiles, setSelectedFiles] = useState([]);
const [fileType, setFileType] = useState(null); // Default to 'image'
const [allPart, setAllPart] = useState([]);
const { chattingUser } = useContext(AuthContext);
const [newOne, setNewOne] = useState({});
const MAX_WAIT_TIME = 60000;
const [response, setResponse] = useState({});

function getCurrentTimestampInSeconds() {
const currentDate = new Date();
const timestampInSeconds = Math.floor(currentDate.getTime() / 1000);
return timestampInSeconds;
}
// <---------------------------Final Web
Socket------------------------------------>

const [connected, setConnected] = useState(false);


const [parts, setParts] = useState("");

const stompClient = new Client({


brokerURL: 'wss://grozziie.zjweiting.com:3091/CustomerService-Chat/websocket',
// brokerURL: 'ws://web-api-tht-env.eba-kcaa52ff.us-east-
1.elasticbeanstalk.com/websocket',
});

useEffect(() => {

const connect = () => {


stompClient.onConnect = (frame) => {
setConnected(true);
console.log('Connected: ' + frame);
stompClient.subscribe(`/topic/${chattingUser?.userId}`, (message) => {

console.log(message?.body, "coming sms")


const newSMS = JSON.parse(message.body);

showGreeting(message.body, newSMS)
// console.log(newSMS, "newSMS")
toast.success(`Sms send from Name:${chattingUser?.userName} Id:$
{chattingUser?.userId}`, {
position: "top-right"
})

});
};

stompClient.onWebSocketError = (error) => {


console.error('Error with websocket', error);
// Handle error here, you can update state or show an error message to the
user.
};

stompClient.activate();
};

// Try to connect
connect();

// Retry every 5 seconds if not connected


const retryInterval = setInterval(() => {
if (!connected) {
console.log('Reconnecting to WebSocket...');
connect();
} else {
clearInterval(retryInterval);
}
}, 5000);

// Cleanup on unmount
return () => {
clearInterval(retryInterval);
stompClient.deactivate();
};
}, [connected]);

// function after getting every sms


//public =========================
let myArraySentId = [];
let myArryPartTotal = [];
let myArryPartNumberCount = [];
let myArryGetFlag = [false];
let myArryGetString = [];
const [newChat, setNewChat] = useState([]);

let id = 0;
let flag = false;
//===========================

const showGreeting = async (message, sms) => {

if (sms.msgType === "ans") {


//setResponse(sms);
getAnswer(sms);
return;
}

console.log(sms, "checking response sms")


//Add New response
const textMessage = {
chatId: sms?.chatId,
sentBy: sms?.sentTo,
sentTo: sms?.sentBy,
sentId: sms?.sentId,
message: sms?.msgType,
msgType: "ans",
totalPart: sms?.totalPart,
partNo: sms?.partNo,
timestamp: getCurrentTime(),
};
//one user
const getAnswer=()=>{
if(sms.totalPart==1)
{
//show your message/video/file/image

}
else
{
if(sms.partNo==sms.totalPart)
{
//show your message/video/file/image
}
else
{
//getmap [10] totalpart=10; getpartnumber=1
//sent next part
sendChatMessage(1);

}
}
};
sendChatMessage(textMessage);

// try {
// const response = await axios.post(
// 'https://grozziie.zjweiting.com:3091/CustomerService-Chat/api/dev/
messages',
// sms
// );
// console.log(response, "response")
// if (response.status === 201) {
// sendChatMessage(sms);
// }

// return sms; // Return the message if sent successfully


// } catch (error) {
// // Handle errors from the API request
// console.error('Error sending message(s):', error);
// throw error;
// }
//finish in here

//console.log(sms,"intial value")
// setComingSMS(sms);
// setAllChat((prevChat) => [...prevChat, sms]);
//==============================================

console.log(sms.totalPart);
console.log(sms.message);
/*
if(id==0)
{

myArraySentId.push(sms.sentId);//4
myArryPartTotal.push(sms.totalPart);//1
myArryGetString.push(sms.message);//hello
//mytype:text

//let partNumber=sms.partNo;
if(sms.totalPart==1)
{
myArryPartNumberCount.push(sms.partNo)//2
myArryGetFlag.push(true);//can show
console.log("======================")
console.log(myArryGetString[0])
console.log("======================")

//setAllChat((prevChat) => [...prevChat, sms]);


}
else
{
myArryGetFlag.push(false);
myArryPartNumberCount.push(1)//2
}

id++;
}
else
{
console.log("totalpart")
console.log(sms.totalPart)

for(let i=0;i<id;i++)
{

console.log("0000000")
console.log(sms.sentId)
console.log(myArraySentId[i])

if(myArraySentId[i]==sms.sentId)
{

myArryPartNumberCount[i]=myArryPartNumberCount[i]+1; //2 1

console.log("------------------------2")
console.log(myArryPartNumberCount[i])
myArryGetString[i]=myArryPartTotal[i]+sms.message;

if(myArryPartNumberCount[i]==myArryPartTotal[i])
{
myArryGetFlag[i]=true;//can show
console.log("======================")
console.log(myArryGetString[i])
console.log("======================")
flag=true;
}
else
{

}
break;
}

if(!flag)
{
flag=false;
myArraySentId.push(sms.sentId);//4
myArryPartTotal.push(sms.totalPart);//1
myArryGetString.push(sms.message);//hello
//mytype:text

//let partNumber=sms.partNo;
if(sms.totalPart==1)
{
myArryGetFlag.push(true);//can show
myArryPartNumberCount.push(sms.partNo)//2

//setAllChat((prevChat) => [...prevChat, sms]);


}
else
{
myArryGetFlag.push(false);
console.log("ssssss")
myArryPartNumberCount.push(1)//2
console.log(myArryPartNumberCount)
console.log(myArraySentId)
}

id++;

}
*/

//==============================================

// const newSMS = mergeMessagesBySentId(sms)


// if (sms?.totalPart > 1) {
// if (sms?.partNo === 1) {
// console.log(sms?.partNo, "check the part no to send")
// setNewOne(sms);
// }
// else if (sms?.partNo === sms?.totalPart && sms?.sentId === newOne?.sentId)
{
// console.log(sms?.partNo, "check the part no to send")

// setAllChat((prevChat) => [...prevChat, {


// chatId: newOne?.chatId,
// sentBy: newOne?.sentBy,
// sentTo: newOne?.sentTo,
// sentId: newOne?.sentId,
// message: newOne?.message + sms?.message,
// msgType: newOne?.msgType,
// totalPart: newOne?.totalPart,
// partNo: newOne?.partNo,
// timestamp: getCurrentTime(),

// }]);
// setNewOne({});

// }
// else if (sms?.partNo > 1 && sms?.partNo < sms?.totalPart && sms?.sentId
=== newOne?.sentId) {
// console.log(sms?.partNo, "check the part no to send")
// setNewOne({
// chatId: newOne?.chatId,
// sentBy: newOne?.sentBy,
// sentTo: newOne?.sentTo,
// sentId: newOne?.sentId,
// message: newOne?.message + sms?.message,
// msgType: newOne?.msgType,
// totalPart: newOne?.totalPart,
// partNo: newOne?.partNo,
// timestamp: getCurrentTime(),

// })
// }
// }
setAllChat((prevChat) => [...prevChat, sms]);

};

// console.log(allChat, "show after marge")

// <---------------------------Final Web
Socket------------------------------------>

const handleFileChange = (e) => {


const files = e.target.files;
const fileArray = Array.from(files);
setSelectedFiles(fileArray);
};

function getCurrentTime() {
const now = new Date();
const hours = now.getHours();
const minutes = now.getMinutes();

// Determine AM or PM
const ampm = hours >= 12 ? 'PM' : 'AM';

// Convert hours to 12-hour format


const formattedHours = hours % 12 || 12;

// Add leading zeros to minutes if needed


const formattedMinutes = minutes < 10 ? `0${minutes}` : minutes;

return `${formattedHours}:${formattedMinutes} ${ampm}`;


}

const handleRemoveFile = (fileIndex) => {


const updatedFiles = selectedFiles.filter((_, index) => index !== fileIndex);
setSelectedFiles(updatedFiles);
};

// Function to read a file as base64


const readAsBase64 = (file) => {
return new Promise((resolve) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => {
resolve(reader.result.split(',')[1]); // Remove the
"data:image/jpeg;base64," part
};
});
};

function splitBase64String(base64Data, maxSizeInBytes) {


const base64Parts = [];
let currentPart = '';

for (let i = 0; i < base64Data.length; i++) {


currentPart += base64Data.charAt(i);

if (currentPart.length * 0.75 >= maxSizeInBytes) {


// If the current part exceeds the specified size, push it to the array
base64Parts.push(currentPart);
currentPart = '';
}
}

if (currentPart.length > 0) {
// Push any remaining data as a part
base64Parts.push(currentPart);
}

return base64Parts;
}

const handleFileIconClick = (type) => {


// Programmatically trigger the input file dialog when the icon is clicked
document.getElementById('fileInput').click();
setFileType(type);
};

const handleKeyDown = (e) => {


// Check if the Enter key is pressed (key code 13)
if (e.keyCode === 13 && !e.shiftKey) {
e.preventDefault();
handleSubmit(e);
}
};

// function to send the sms part by part

const handleSubmit = async (e) => {


e.preventDefault();

if (message.trim() !== '' || selectedFiles.length > 0) {


const allMessages = [];

if (message.trim() !== '') {


const textMessage = {
chatId: selectedCustomerChat?.chatId,
sentBy: selectedCustomerChat?.customerServiceId,
sentTo: selectedCustomerChat?.userId,
sentId: getCurrentTimestampInSeconds(),
message: message,
msgType: "text",
totalPart: 1,
partNo: 1,
timestamp: getCurrentTime(),
};
allMessages.push(textMessage);

setAllChat([...allChat, ...allMessages]);
setResponse({});
sendChatMessage(textMessage);

if (selectedFiles.length > 0) {
// Use Promise.all to read and convert selected files to base64
Promise.all(
selectedFiles.map(async (file) => {
const base64Data = await readAsBase64(file);
const stringParts = splitBase64String(base64Data, 45000);

setAllChat((prevChat) => [...prevChat, {


chatId: selectedCustomerChat?.chatId,
sentBy: selectedCustomerChat?.customerServiceId,
sentTo: selectedCustomerChat?.userId,
sentId: getCurrentTimestampInSeconds(),
message: fileType === 'video' ? `${base64Data}` : `${base64Data}`,
msgType: fileType === "video" ? "video" : "image",
from: true,
totalPart: stringParts?.length,
timestamp: getCurrentTime(),
}]);

return stringParts.map((part, index) => {


if (fileType === "video" || fileType === "image") {
return {
chatId: selectedCustomerChat?.chatId,
sentBy: selectedCustomerChat?.customerServiceId,
sentTo: selectedCustomerChat?.userId,
sentId: getCurrentTimestampInSeconds(),
message: fileType === 'video' ? `${part}` : `${part}`,
msgType: fileType === "video" ? "video" : "image",
totalPart: stringParts?.length,
partNo: index + 1,
timestamp: getCurrentTime(),
}
} else {
return {
chatId: selectedCustomerChat?.chatId,
sentBy: selectedCustomerChat?.customerServiceId,
sentTo: selectedCustomerChat?.userId,
sentId: getCurrentTimestampInSeconds(),
message: fileType === 'file' ? `${part}` : `${part}`,
msgType: fileType === "file" ? "file" : "text", // Adjusted this
line
totalPart: stringParts?.length,
partNo: index + 1,
timestamp: getCurrentTime(),
}
};
});
})
).then(async (filesMessages) => {
// Flatten the array of arrays into a single array
// do get message public map part
// list[0]="a"
//list[1]="b"
//list[2]="c"

// allMessages.map
sendChatMessage(allMessages[0]);

send(list[0])
const allMessages = [].concat(...filesMessages);
let sendPromises;
// Check if there are messages to send
if (allMessages && allMessages.length > 0) {

if (allMessages?.length === 1) {
sendPromises = allMessages.map(async (sms, index) => {

await sendChatMessage(allMessages[0])
})
}

else {
sendChatMessage(sms[0]);// send first part
const waitForResponse = async () => {
console.log("partNo",response.partNo+1 , sms.partNo)
if (response && response.msgType === "ans" ) {
console.log(response, "into the more than 2 part");
setResponse({});
await sendChatMessage(sms);
sent = true;
resolve(sms); // Resolve the promise when the message is sent
} else {
// Wait for a short delay (e.g., 3000 milliseconds) before checking
the condition again
//setTimeout(waitForResponse, 3000);
}
};

sendPromises = allMessages.map(async (sms, index) => {

console.log(sms, response, "1st line");

async function sendPart(sms) {


if (sms.partNo === 1) {
await sendChatMessage(sms);
} else if (sms.partNo > 1) {
return new Promise(async (resolve, reject) => {
let sent = false;

const waitForResponse = async () => {


console.log("partNo",response.partNo+1 , sms.partNo)
if (response && response.msgType === "ans" ) {
console.log(response, "into the more than 2 part");
setResponse({});
await sendChatMessage(sms);
sent = true;
resolve(sms); // Resolve the promise when the message is
sent
} else {
// Wait for a short delay (e.g., 3000 milliseconds)
before checking the condition again
setTimeout(waitForResponse, 3000);
}
};

// Start waiting for the response


await waitForResponse();

// Set a timeout to handle cases where the condition is never


met
const timeout = setTimeout(() => {
if (!sent) {
reject("Message sending timeout"); // Reject the promise
on timeout
}
}, MAX_WAIT_TIME);
});
}
}
// Call the function to send the part
return sendPart(sms);
});
}

// Use Promise.all to wait for all sendPromises to complete


Promise.all(sendPromises)
.then((sentMessages) => {
// Update the chat state with all sent messages
setAllChat((prevChat) => [...prevChat, ...sentMessages]);
toast.success("All messages sent successfully");
})
.catch((error) => {
toast.error("Error sending messages: " + error);
});
}
});
}

else {
// Clear the 'text' variable if needed
setMessage('');

// Update the chat state with only text messages


setAllChat([...allChat, ...allMessages]);
}
}
};

return (
<div className=" absolute rounded-b-lg z-40 bg-white pt-1 w-full bottom-0 ">
<div className="flex justify-around text-sm">
<button className="bg-[#004368] text-white ml-8 hover:bg-blue-700 px-2 py-1
rounded-md mr-3">
Auto Reply
</button>
<button className="">
Select & Reply
</button>
<button className="mr-10">
Typically
</button>
</div>
<form onSubmit={handleSubmit} className="p-4">
<div className="flex gap-2 w-full items-center px-3 my-2 bg-white z-40">
<button
onClick={() => handleFileIconClick('image')}
className={` ${fileType === 'image' ? 'selected' : ''}`}
>
<FaFileImage className="mr-2 text-gray-400
cursor-pointer"></FaFileImage>
</button>
<button
onClick={() => handleFileIconClick('video')}
className={` ${fileType === 'video' ? 'selected' : 'image'}`}
>
<MdOndemandVideo className="mr-2 text-gray-400 text-xl cursor-
pointer"></MdOndemandVideo>
</button>

<input
id="fileInput"
type="file"
accept={fileType === 'image' ? 'image/*' : 'video/*'}
onChange={handleFileChange}
className="hidden"
/>

<div>
<button
onClick={() => handleFileIconClick('file')}
className={` ${fileType === 'file'}`}
>
<AiOutlineFileAdd className="mr-2 text-gray-400 text-xl cursor-
pointer"></AiOutlineFileAdd>
</button>

<input
id="fileInput"
type="file"
accept=".pdf, .doc, .docx, .txt, .xls, .xlsx, .ppt, .pptx, .csv"
onChange={handleFileChange}
className="hidden"
/>
</div>

<textarea
value={message}
onChange={(e) => setMessage(e.target.value)}
onKeyDown={handleKeyDown}
placeholder="Type your message..."
className=" relative w-9/12 md:w-8/12 lg:9/12 py-1 px-2 rounded-md bg-
cyan-200"
/>
<button className="flex items-center absolute right-[55px] lg:right-
[95px] " type="submit">
<AiOutlineSend className=" cursor-pointer"></AiOutlineSend>
</button>
</div>

<div className="mt-2">
{selectedFiles.map((file, index) => (
<div key={index} className="flex items-center bg-gray-300 p-2 w-10/12">
<span className="mr-2">{file.name}</span>
<button
type="button"
onClick={() => handleRemoveFile(index)}
className="text-red-600 font-bold cursor-pointer"
>
X
</button>
</div>
))}
</div>
</form>
</div>
);
};

export default MessageInput;

You might also like