import { createSignal, createEffect, For, Show } from 'solid-js'; import { gql } from '@urql/core'; import { createQuery, createMutation, createSubscription } from '@urql/solid'; import { Message } from '../types'; const ROOM_QUERY = gql` query GetRoom($id: ID!) { room(id: $id) { id name description isPrivate owner { id username } members { id username } messages { id content createdAt user { id username } } } } `; const SEND_MESSAGE_MUTATION = gql` mutation SendMessage($content: String!, $roomId: ID!) { sendMessage(content: $content, roomId: $roomId) { id content createdAt user { id username } } } `; const MESSAGE_SUBSCRIPTION = gql` subscription OnMessageAdded($roomId: ID!) { messageAdded(roomId: $roomId) { id content createdAt user { id username } } } `; const LEAVE_ROOM_MUTATION = gql` mutation LeaveRoom($roomId: ID!) { leaveRoom(roomId: $roomId) } `; interface ChatRoomProps { roomId: string; userId: string; onLeaveRoom?: () => void; } export function ChatRoom(props: ChatRoomProps) { const [variables, setVariables] = createSignal({ id: props.roomId, roomId: props.roomId, }); const [message, setMessage] = createSignal(''); const [messages, setMessages] = createSignal([]); const [confirmLeave, setConfirmLeave] = createSignal(false); const [leaveError, setLeaveError] = createSignal(null); // Query room details const [roomQuery] = createQuery({ query: ROOM_QUERY, variables: variables, context: { requestPolicy: 'network-only', // Force refetch when variables change }, }); // Send message mutation const [, sendMessage] = createMutation(SEND_MESSAGE_MUTATION); // Subscribe to new messages const [messageSubscription] = createSubscription({ query: MESSAGE_SUBSCRIPTION, variables: variables, pause: false, // Ensure subscription is active }); // Leave room mutation const [leaveRoomResult, leaveRoom] = createMutation(LEAVE_ROOM_MUTATION); // Reset messages when room changes createEffect(() => { // Access props.roomId to create a dependency setVariables({ id: props.roomId, roomId: props.roomId }); // Reset messages when room changes // Clear any errors or confirmations setLeaveError(null); setConfirmLeave(false); }); // Load initial messages createEffect(() => { const result = roomQuery; if (result.data?.room) { setMessages(result.data.room.messages); } }); // Handle new messages from subscription createEffect(() => { const result = messageSubscription; if (result.data?.messageAdded) { const newMessage = result.data.messageAdded; setMessages((prev) => [...prev, newMessage]); } }); // Handle leave room error createEffect(() => { if (leaveRoomResult.error) { setLeaveError(leaveRoomResult.error.message); setConfirmLeave(false); } }); const handleSendMessage = async (e: Event) => { e.preventDefault(); if (!message().trim()) return; try { await sendMessage({ content: message(), roomId: props.roomId, }); setMessage(''); } catch (error) { console.error('Failed to send message:', error); } }; const handleLeaveRoom = async () => { if (!confirmLeave()) { setConfirmLeave(true); return; } setLeaveError(null); try { const result = await leaveRoom({ roomId: props.roomId }); if (result.data?.leaveRoom) { if (props.onLeaveRoom) { props.onLeaveRoom(); } } } catch (err) { console.error('Failed to leave room:', err); } }; const cancelLeave = () => { setConfirmLeave(false); setLeaveError(null); }; const formatTime = (dateString: string) => { const date = new Date(dateString); return date.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }); }; return (
Loading room...
}>

{roomQuery.data?.room.name}

{roomQuery.data?.room.description}

{leaveError()}
Are you sure you want to leave this room?
Loading messages...
} > {(message) => (
{message.user.username} {formatTime(message.createdAt)}
{message.content}
)}
setMessage(e.currentTarget.value)} placeholder='Type a message...' />
); }