Created
September 14, 2024 08:46
-
-
Save harsh661/c807023c24340bd00098f868fa98bec2 to your computer and use it in GitHub Desktop.
This file contains 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 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