0% found this document useful (0 votes)
28 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
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
28 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
We take content rights seriously. If you suspect this is your content, claim it here.
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