Skip to content

Instantly share code, notes, and snippets.

@harsh661
Created September 14, 2024 08:46
Show Gist options
  • Save harsh661/c807023c24340bd00098f868fa98bec2 to your computer and use it in GitHub Desktop.
Save harsh661/c807023c24340bd00098f868fa98bec2 to your computer and use it in GitHub Desktop.
import Image from 'next/image'
import React, { useEffect, useRef, useState } from 'react'
import MessagesBody from './messageBody'
import MessageForm from './messageForm'
import useChatStore from '@/stores/chatStore'
import { useGetBusinesses } from '@/hooks/useGetBusinesses'
export type MessageType = {
From: string,
Type: string,
body: string,
contacts_id: string,
id: string,
status: string,
timestamp: string,
type: string
}
const ChatScreen = () => {
const [messages, setMessages] = useState<MessageType[]>([]);
const connection = useRef<WebSocket | null>(null);
const { activeChat, activeNumber, activeChatRecipient } = useChatStore();
const { token } = useGetBusinesses();
// WebSocket URL
const websocketURL = process.env.NEXT_PUBLIC_SOCKET_URL as string;
useEffect(() => {
if (activeChatRecipient) {
handleShowCurrentChats();
}
return () => {
if (connection.current) {
connection.current.close();
}
};
}, [activeChatRecipient]);
// Function to initialize WebSocket connection
const handleShowCurrentChats = () => {
// Create WebSocket connection if it doesn't exist or is closed
if (!connection.current || connection.current.readyState !== WebSocket.OPEN) {
connection.current = new WebSocket(websocketURL);
// On open WebSocket connection
connection.current.onopen = () => {
console.log('WebSocket connection opened');
subscribeToMessages(); // Subscribe to chat messages
};
// Handle incoming messages
connection.current.onmessage = (event) => {
const data = JSON.parse(event.data);
handleReceiveMessage(data);
};
// Handle WebSocket close and attempt reconnection
connection.current.onclose = () => {
console.log('WebSocket connection closed');
};
// Handle WebSocket error
connection.current.onerror = (error) => {
console.error('WebSocket error', error);
};
}
};
const subscribeToMessages = () => {
if (connection.current?.readyState === WebSocket.OPEN && activeNumber && activeChatRecipient?.id) {
connection.current?.send(
JSON.stringify({
type: 'subscribe',
collection: 'Message',
query: {
filter: {
_or: [
{
_and: [
{ From: { _eq: activeNumber } },
{ contacts_id: { _eq: activeChatRecipient?.id } },
],
},
{
_and: [
{ From: { _eq: activeChatRecipient?.id } },
{ contacts_id: { _eq: activeNumber } },
],
},
],
},
fields: ['*'],
},
})
);
}
};
// Function to handle incoming messages
const handleReceiveMessage = (data: any) => {
console.log('message', data)
if (data.type === 'subscription' && data.event === 'init') {
const sortedMessages = data.data.sort(
(a: MessageType, b: MessageType) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime()
);
setMessages(sortedMessages);
} else if (data.type === 'subscription' && data.event === 'create') {
setMessages((prevMessages) => [...prevMessages, data.data[0]]);
}
// Respond to ping to keep WebSocket alive
if (data.type === 'ping') {
connection.current?.send(JSON.stringify({ type: 'pong' }));
}
};
const sendMessage = async ({ message }: { message: any }) => {
try {
const sendMsgResponse = await fetch(
`https://graph.facebook.com/v20.0/${activeNumber}/messages`,
{
method: 'POST',
headers: {
Authorization: `Bearer ${token}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
messaging_product: 'whatsapp',
recipient_type: 'individual',
to: `${activeChatRecipient?.number}`,
type: 'text',
text: {
preview_url: false,
body: `${message}`,
},
}),
}
);
if (!sendMsgResponse.ok) {
throw new Error('Failed to send message to WhatsApp API');
}
const sendMsgData = await sendMsgResponse.json();
// Save the message to Directus database using fetch
const saveToDirectusResponse = await fetch(
`${process.env.NEXT_PUBLIC_BASE_URL}/items/Message`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
credentials: 'include',
body: JSON.stringify({
id: sendMsgData.messages[0].id,
From: activeNumber,
timestamp: new Date().toISOString(),
body: `${message}`,
type: 'text',
status: 'sent',
contacts_id: Number(activeChatRecipient?.id),
}),
}
);
if (!saveToDirectusResponse.ok) {
throw new Error('Failed to save message to Directus');
}
} catch (error) {
console.error('Error sending message:', error);
}
};
return (
<div className='h-full grid grid-rows-[auto_1fr_auto]'>
{/* Header */}
<div className='py-3 border-b border-b-black/30'>
<div className='flex flex-col items-center gap-3'>
<Image
src={'/assets/user.png'}
alt='user'
width={48}
height={48}
className='w-12 h-12 object-cover rounded-full'
/>
<p className='font-medium lg:text-lg'>{activeChatRecipient?.number}</p>
</div>
</div>
<MessagesBody messages={messages} />
<MessageForm onSend={sendMessage} />
</div>
)
}
export default ChatScreen;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment