import { useCallback, useEffect, useState } from "react"; import socket from "@/lib/socket.io"; type RoomUpdatePayload = { roomId: string; payloads: T[]; }; type RoomErrorPayload = { roomId?: string; message?: string; }; type UpdateMode = "append" | "replace"; export function useSocketRoom( roomId: string, getKey?: (item: T) => string | number, updateMode: UpdateMode = "append", ) { const [data, setData] = useState([]); const [info, setInfo] = useState( "No data yet — join the room to start receiving", ); const clearRoom = useCallback( (id?: string | number) => { if (id !== undefined && getKey) { setData((prev) => prev.filter((item) => getKey(item) !== id)); setInfo(`Removed item ${id}`); return; } console.log("cleared data from the room"); setData([]); setInfo("Room data cleared"); }, [getKey], ); useEffect(() => { function handleConnect() { socket.emit("join-room", roomId); setInfo(`Joined room: ${roomId}`); } function handleUpdate(payload: RoomUpdatePayload) { // protects against other room updates hitting this hook if (payload.roomId !== roomId) return; // resetting room data for rooms that just need updated data. if (updateMode === "replace") { setData(payload.payloads); } else { setData((prev) => [...payload.payloads, ...prev]); } setInfo(""); } function handleError(err: RoomErrorPayload) { if (err.roomId && err.roomId !== roomId) return; setInfo(err.message ?? "Room error"); } socket.on("connect", handleConnect); socket.on("room-update", handleUpdate); socket.on("room-error", handleError); if (!socket.connected && socket.disconnected) { socket.connect(); } // If already connected, join immediately if (socket.connected) { socket.emit("join-room", roomId); setInfo(`Joined room: ${roomId}`); } return () => { socket.emit("leave-room", roomId); socket.off("connect", handleConnect); socket.off("room-update", handleUpdate); socket.off("room-error", handleError); }; }, [roomId, updateMode]); return { data, info, clearRoom }; } /* const isDockDoorPage = location.pathname.startsWith("/dockdoor"); useSocketRoom( dockId ? `dockdoor:${dockId}` : null, isDockDoorPage, ); */