Skip to content

Commit 2254e92

Browse files
authored
Merge pull request #61 from ADARSHsri2004/main
feat: connected frontend and backend for rooms
2 parents c9e4dd4 + 379d20c commit 2254e92

11 files changed

Lines changed: 320 additions & 49 deletions

File tree

backend/package-lock.json

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

backend/src/controllers/roomController.ts

Lines changed: 30 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import type { Request, Response } from "express";
2+
import mongoose from "mongoose";
23
import Room from "../models/roomModel.js";
34
import type { IRoom } from "../models/roomModel.js";
4-
import mongoose from "mongoose";
55
import { io } from "../server.js";
66

7-
7+
// Extend Express Request with userId
88
declare global {
99
namespace Express {
1010
interface Request {
@@ -17,17 +17,25 @@ declare global {
1717
export const createRoom = async (req: Request, res: Response) => {
1818
try {
1919
const { name } = req.body;
20+
const userId = req.userId;
21+
2022
if (!name) return res.status(400).json({ message: "Room name is required" });
21-
if (!req.userId) return res.status(401).json({ message: "Unauthorized" });
23+
if (!userId) return res.status(401).json({ message: "Unauthorized" });
2224

2325
const existingRoom = await Room.findOne({ name });
2426
if (existingRoom)
2527
return res.status(400).json({ message: "Room with this name already exists" });
2628

27-
const room: IRoom = new Room({ name, members: [req.userId] });
29+
const room: IRoom = new Room({
30+
name,
31+
members: [userId],
32+
host: userId,
33+
isActive: true,
34+
});
35+
2836
await room.save();
2937

30-
io.emit("room-created", { roomId: room._id, name: room.name });
38+
io.emit("room-created", { roomId: room._id.toString(), name: room.name });
3139
res.status(201).json(room);
3240
} catch (error: any) {
3341
console.error("Create room error:", error.message);
@@ -38,7 +46,7 @@ export const createRoom = async (req: Request, res: Response) => {
3846
// ---------------------- List Rooms ----------------------
3947
export const listRooms = async (_req: Request, res: Response) => {
4048
try {
41-
const rooms = await Room.find().populate("members", "username email");
49+
const rooms = await Room.find({ isActive: true }).populate("members", "username email");
4250
res.json(rooms);
4351
} catch (error: any) {
4452
console.error("List rooms error:", error.message);
@@ -52,18 +60,16 @@ export const joinRoom = async (req: Request, res: Response) => {
5260
const roomIdOrName = req.params.roomIdOrName;
5361
const userId = req.userId;
5462

55-
if (!roomIdOrName) return res.status(400).json({ message: "Room name or ID is required" });
63+
if (!roomIdOrName)
64+
return res.status(400).json({ message: "Room name or ID is required" });
5665
if (!userId) return res.status(401).json({ message: "Unauthorized - Missing userId" });
5766

5867
let room = await Room.findOne({ name: roomIdOrName });
5968
if (!room && mongoose.Types.ObjectId.isValid(roomIdOrName)) {
6069
room = await Room.findById(roomIdOrName);
6170
}
6271

63-
if (!room) {
64-
console.error("Join room error: Room not found for", roomIdOrName);
65-
return res.status(404).json({ message: "Room not found" });
66-
}
72+
if (!room) return res.status(404).json({ message: "Room not found" });
6773

6874
const userObjId = new mongoose.Types.ObjectId(userId);
6975
if (!room.members.some(m => m.equals(userObjId))) {
@@ -72,12 +78,14 @@ export const joinRoom = async (req: Request, res: Response) => {
7278
}
7379

7480
const updatedRoom = await Room.findById(room._id).populate("members", "username email");
75-
io.to(room._id.toString()).emit("user-joined", { userId, roomId: room._id });
76-
io.to(room._id.toString()).emit("update-members", updatedRoom?.members || []);
81+
82+
const roomIdStr = room._id.toString();
83+
io.to(roomIdStr).emit("user-joined", { userId, roomId: roomIdStr });
84+
io.to(roomIdStr).emit("update-members", updatedRoom?.members || []);
7785

7886
res.json(updatedRoom);
7987
} catch (error: any) {
80-
console.error("Join room error:", error.message, error.stack);
88+
console.error("Join room error:", error.message);
8189
res.status(500).json({ message: "Server error", error: error.message });
8290
}
8391
};
@@ -87,6 +95,8 @@ export const leaveRoom = async (req: Request, res: Response) => {
8795
try {
8896
const { roomId } = req.params;
8997
const userId = req.userId;
98+
99+
if (!roomId) return res.status(400).json({ message: "Missing room ID" });
90100
if (!userId) return res.status(401).json({ message: "Unauthorized" });
91101

92102
const room = await Room.findById(roomId);
@@ -104,7 +114,8 @@ export const leaveRoom = async (req: Request, res: Response) => {
104114
io.to(roomId).emit("update-members", updatedRoom?.members || []);
105115

106116
if (room.members.length === 0) {
107-
await Room.findByIdAndDelete(roomId);
117+
room.isActive = false;
118+
await room.save();
108119
io.to(roomId).emit("room-ended", { roomId, reason: "empty" });
109120
io.socketsLeave(roomId);
110121
}
@@ -128,11 +139,12 @@ export const endRoom = async (req: Request, res: Response) => {
128139
const room = await Room.findById(roomId);
129140
if (!room) return res.status(404).json({ message: "Room not found" });
130141

131-
const hostId = room.members[0]?.toString();
132-
if (hostId !== userId)
142+
if (room.host.toString() !== userId)
133143
return res.status(403).json({ message: "Only the host can end the room" });
134144

135-
await Room.findByIdAndDelete(roomId);
145+
room.isActive = false;
146+
await room.save();
147+
136148
io.to(roomId).emit("room-ended", { roomId, endedBy: userId });
137149
io.socketsLeave(roomId);
138150

backend/src/models/roomModel.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import mongoose, { Schema, Document } from "mongoose";
22

33
export interface IRoom extends Document {
4+
_id: mongoose.Types.ObjectId;
45
name: string;
56
members: mongoose.Types.ObjectId[];
67
host: mongoose.Types.ObjectId; // 👈 identifies who created/owns the room

frontend/package-lock.json

Lines changed: 53 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

frontend/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
"axios": "^1.12.2",
2323
"class-variance-authority": "^0.7.1",
2424
"clsx": "^2.1.1",
25+
"framer-motion": "^12.23.24",
2526
"lucide-react": "^0.545.0",
2627
"next-themes": "^0.4.6",
2728
"react": "^19.2.0",

frontend/src/App.tsx

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -10,30 +10,34 @@ import OAuthSuccess from "./pages/OAuthSuccess.js";
1010
import RoomActions from "./pages/RoomActions.js";
1111
import ErrorBoundary from "./components/ErrorBoundary.js";
1212
import "./index.css"
13-
import CreateRoom from "./pages/CreateRoom.js";
1413
import JoinRoom from "./pages/JoinRoom.js";
14+
import InRoom from "./pages/InRoom.js";
15+
import CreateRoomLobby from "./pages/CreateRoomLobby.js";
16+
import CreateRoom from "./pages/CreateRoom.js";
1517
const queryClient = new QueryClient();
1618

1719
const App = () => (
1820
<ErrorBoundary>
19-
<QueryClientProvider client={queryClient}>
20-
<TooltipProvider>
21-
<Toaster />
22-
<Sonner />
23-
<BrowserRouter>
24-
<Routes>
25-
<Route path="/" element={<Index />} />
26-
<Route path="/signup" element={<SignUp />} />
27-
<Route path="/signin" element={<SignIn />} />
28-
<Route path="/room-actions" element={<RoomActions />} />
29-
<Route path="/oauth-success" element={<OAuthSuccess />} />
30-
<Route path="/create-room" element={<CreateRoom/>} /> {/* ✅ */}
31-
<Route path="/join-room" element={<JoinRoom />} /> {/* ✅ */}
32-
</Routes>
33-
</BrowserRouter>
34-
</TooltipProvider>
35-
</QueryClientProvider>
36-
</ErrorBoundary>
21+
<QueryClientProvider client={queryClient}>
22+
<TooltipProvider>
23+
<Toaster />
24+
<Sonner />
25+
<BrowserRouter>
26+
<Routes>
27+
<Route path="/" element={<Index />} />
28+
<Route path="/signup" element={<SignUp />} />
29+
<Route path="/signin" element={<SignIn />} />
30+
<Route path="/room-actions" element={<RoomActions />} />
31+
<Route path="/oauth-success" element={<OAuthSuccess />} />
32+
<Route path="/create-room" element={<CreateRoom />} /> {/* ✅ */}
33+
<Route path="/join-room" element={<JoinRoom />} /> {/* ✅ */}
34+
<Route path="/room/:roomName" element={<InRoom />} />
35+
<Route path="/lobby/:roomId" element={<CreateRoomLobby />} />
36+
</Routes>
37+
</BrowserRouter>
38+
</TooltipProvider>
39+
</QueryClientProvider>
40+
</ErrorBoundary>
3741
);
3842

3943
export default App;

0 commit comments

Comments
 (0)