import { createSignal, createEffect, For, Show } from 'solid-js'; import { gql } from '@urql/core'; import { createQuery, createSubscription, createMutation } from '@urql/solid'; import { Room } from '../types'; const ROOMS_QUERY = gql` query GetRooms { rooms { id name description isPrivate createdAt members { id } } } `; const ROOM_ADDED_SUBSCRIPTION = gql` subscription OnRoomAdded { roomAdded { id name description isPrivate createdAt members { id } } } `; const ROOM_UPDATED_SUBSCRIPTION = gql` subscription OnRoomUpdated { roomUpdated { id name description isPrivate createdAt members { id } } } `; const JOIN_ROOM_MUTATION = gql` mutation JoinRoom($roomId: ID!) { joinRoom(roomId: $roomId) { id name members { id } } } `; interface RoomListProps { onSelectRoom: (roomId: string) => void; selectedRoomId?: string; } export function RoomList(props: RoomListProps) { const [rooms, setRooms] = createSignal([]); const [error, setError] = createSignal(null); const [isJoining, setIsJoining] = createSignal(false); // Query rooms const [roomsQuery] = createQuery({ query: ROOMS_QUERY, context: { requestPolicy: 'network-only', }, }); // Subscribe to new rooms const [roomAddedSubscription] = createSubscription<{ roomAdded: Room; }>({ query: ROOM_ADDED_SUBSCRIPTION, }); // Subscribe to room updates (when members change) const [roomUpdatedSubscription] = createSubscription<{ roomUpdated: Room; }>({ query: ROOM_UPDATED_SUBSCRIPTION, }); // Join room mutation const [joinRoomResult, joinRoom] = createMutation<{ joinRoom: Room; }>(JOIN_ROOM_MUTATION); // Load initial rooms createEffect(() => { const result = roomsQuery; if (result.data?.rooms) { setRooms(result.data.rooms); } }); // Handle new rooms from subscription createEffect(() => { const result = roomAddedSubscription; if (result.data?.roomAdded) { const newRoom = result.data.roomAdded; setRooms((prev) => { // Check if room already exists if (prev.some((room) => room.id === newRoom.id)) { return prev; } return [...prev, newRoom]; }); } }); // Handle room updates from subscription createEffect(() => { const result = roomUpdatedSubscription; if (result.data?.roomUpdated) { const updatedRoom = result.data.roomUpdated; setRooms((prev) => { return prev.map((room) => { if (room.id === updatedRoom.id) { return { ...room, ...updatedRoom }; } return room; }); }); } }); // Handle join room error createEffect(() => { if (joinRoomResult.error) { setError(joinRoomResult.error.message); setIsJoining(false); } }); const handleJoinRoom = async (roomId: string, event: MouseEvent) => { event.stopPropagation(); setError(null); setIsJoining(true); try { const result = await joinRoom({ roomId }); if (result.data?.joinRoom) { // Update the local room data with the joined room setRooms((prev) => prev.map((room) => room.id === roomId ? { ...room, members: result.data!.joinRoom.members } : room ) ); // Select the room after joining props.onSelectRoom(roomId); } } catch (err) { console.error('Failed to join room:', err); } finally { setIsJoining(false); } }; // Check if the current user is a member of a room const isMember = (room: Room) => { const userId = window.localStorage.getItem('userId'); return room.members?.some((member) => member.id === userId); }; return (

Chat Rooms

{error()}
Loading rooms...
}> {(room) => (
isMember(room) ? props.onSelectRoom(room.id) : null } >
{room.name} {isMember(room) && Member}
{room.description}
)}
); }