Not able to socketio custom handler

Tired with both realtime/hander.js and public/js
// bench/apps/chat/realtime/chat_handlers.js

function getIndividualRoomName(user1, user2) {
const sorted = [user1, user2].sort(); // Ensure consistency
return individual:${sorted[0]}-${sorted[1]};
}

function chat_handlers(socket) {
socket.on(“join_room”, (data) => {
try {
const { chat_type, person_email, channel_name, user_email } = data;

		if (!chat_type || (!person_email && !channel_name)) return;

		const room =
			chat_type === "Individual"
				? getIndividualRoomName(user_email, person_email)
				: `group:${channel_name}`;

		socket.join(room);
		console.log(`Joined room: ${room}`);
	} catch (err) {
		console.error("Failed to handle join_room:", err);
	}
});

socket.on("leave_room", (data) => {
	try {
		const { chat_type, person_email, channel_name, user_email } = data;

		if (!chat_type || (!person_email && !channel_name)) return;

		const room =
			chat_type === "Individual"
				? getIndividualRoomName(user_email, person_email)
				: `group:${channel_name}`;

		socket.leave(room);
		console.log(`Left room: ${room}`);
	} catch (err) {
		console.error("Failed to handle leave_room:", err);
	}
});

socket.on("send_message", (data) => {
	const { chat_type, sender, person_email, channel_name, content } = data;

	if (!content || !chat_type) return;

	let message = {
		doctype: "Chat Message VM",
		chat_type,
		sender,
		content,
	};

	let room;

	if (chat_type === "Individual") {
		message.receiver = person_email;
		room = getIndividualRoomName(sender, person_email);
	} else {
		message.channel_name = channel_name;
		room = `group:${channel_name}`;
	}

	frappe.db.insert(message)
		.then((doc) => {
			socket.to(room).emit("new_message", doc);
			socket.emit("new_message", doc);
		})
		.catch((err) => {
			console.error("Failed to handle send_message:", err);
		});
});

}

module.exports = chat_handlers;
index.js
// bench/apps/your_app/realtime/index.js

const chat_handlers = require(“./handler”);

frappe.socketio.on(“connection”, (socket) => {
chat_handlers(socket);
});

public/js
function getIndividualRoomName(user1, user2) {
const sorted = [user1, user2].sort(); // Ensure consistency
return individual:${sorted[0]}-${sorted[1]};
}

frappe.socketio.on(“join_room”, async function (socket, data) {
try {
const { chat_type, person_email, channel_name, user_email } = data;

	if (!chat_type || (!person_email && !channel_name)) return;

	const room =
		chat_type === "Individual"
			? getIndividualRoomName(user_email, person_email)
			: `group:${channel_name}`;

	socket.join(room);
    console.log(room)
} catch (err) {
	console.error("Failed to handle join_room:", err);
}

});

frappe.socketio.on(“leave_room”, async function (socket, data) {
try {
const { chat_type, person_email, channel_name, user_email } = data;

	if (!chat_type || (!person_email && !channel_name)) return;

	const room =
		chat_type === "Individual"
			? getIndividualRoomName(user_email, person_email)
			: `group:${channel_name}`;

	socket.leave(room);
} catch (err) {
	console.error("Failed to handle leave_room:", err);
}

});

frappe.socketio.on(“send_message”, function (socket, data) {
const { chat_type, sender, person_email, channel_name, content } = data;

if (!content || !chat_type) return;

let message = {
	doctype: "Chat Message VM",
	chat_type,
	sender,
	content,
};

let room;

if (chat_type === "Individual") {
	message.receiver = person_email;
	room = getIndividualRoomName(sender, person_email);
} else {
	message.channel_name = channel_name;
	room = `group:${channel_name}`;
}

frappe.db.insert(message)
	.then((doc) => {
		socket.to(room).emit("new_message", doc);
		socket.emit("new_message", doc); // emit to sender too
	})
	.catch((err) => {
		console.error("Failed to handle send_message:", err);
	});

});
please help me to setup socketio
frontend
import { useEffect, useState } from “react”;
import { io, Socket } from “socket.io-client”;

type ChatType = “Individual” | “Group”;

interface ChatMessage {
sender: string;
content: string;
[key: string]: any;
}

// Connect to Frappe’s WebSocket server
const socket: Socket = io(“http://test.localhost:9000”); // change if needed

function App() {
const [chatType, setChatType] = useState(“Individual”);
const [userEmail, setUserEmail] = useState(“user1@example.com”);
const [personEmail, setPersonEmail] = useState(“user2@example.com”);
const [channelName, setChannelName] = useState(“general”);
const [message, setMessage] = useState(“”);
const [messages, setMessages] = useState<ChatMessage>();

useEffect(() => {
socket.on(“connect”, () => {
console.log(“Connected to server:”, socket.id);
});

socket.on("new_message", (msg: ChatMessage) => {
  console.log("Received:", msg);
  setMessages((prev) => [...prev, msg]);
});

return () => {
  socket.off("new_message");
};

}, );

const joinRoom = () => {
socket.emit(“join_room”, {
chat_type: chatType,
user_email: userEmail,
person_email: personEmail,
channel_name: channelName,
});
};

const leaveRoom = () => {
socket.emit(“leave_room”, {
chat_type: chatType,
user_email: userEmail,
person_email: personEmail,
channel_name: channelName,
});
};

const sendMessage = () => {
if (!message.trim()) return;
console.log(“Sending”)

socket.emit("send_message", {
  chat_type: chatType,
  sender: userEmail,
  person_email: personEmail,
  channel_name: channelName,
  content: message,
});

setMessage("");

};

return (
<div style={{ padding: “2rem”, fontFamily: “Arial” }}>

:test_tube: Frappe Socket.IO Chat Test (TS)

  <div style={{ marginBottom: "1rem" }}>
    <label>
      Chat Type:{" "}
      <select
        value={chatType}
        onChange={(e) => setChatType(e.target.value as ChatType)}
      >
        <option value="Individual">Individual</option>
        <option value="Group">Group</option>
      </select>
    </label>
  </div>

  <div>
    <label>
      Your Email:{" "}
      <input
        value={userEmail}
        onChange={(e) => setUserEmail(e.target.value)}
      />
    </label>
  </div>

  {chatType === "Individual" ? (
    <div>
      <label>
        Receiver Email:{" "}
        <input
          value={personEmail}
          onChange={(e) => setPersonEmail(e.target.value)}
        />
      </label>
    </div>
  ) : (
    <div>
      <label>
        Channel Name:{" "}
        <input
          value={channelName}
          onChange={(e) => setChannelName(e.target.value)}
        />
      </label>
    </div>
  )}

  <div style={{ marginTop: "1rem" }}>
    <button onClick={joinRoom}>Join Room</button>
    <button onClick={leaveRoom} style={{ marginLeft: "0.5rem" }}>
      Leave Room
    </button>
  </div>

  <div style={{ marginTop: "1rem" }}>
    <input
      value={message}
      onChange={(e) => setMessage(e.target.value)}
      placeholder="Enter message..."
      style={{ width: "60%" }}
    />
    <button onClick={sendMessage} style={{ marginLeft: "0.5rem" }}>
      Send
    </button>
  </div>

  <div style={{ marginTop: "2rem" }}>
    <h3>💬 Messages</h3>
    <ul>
      {messages.map((msg, idx) => (
        <li key={idx}>
          <strong>{msg.sender}</strong>: {msg.content}
        </li>
      ))}
    </ul>
  </div>
</div>

);
}

export default App;