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;