feat: initial scaffolding, client can connect with a user name

This commit is contained in:
Alexander Daichendt 2025-02-11 18:29:57 +01:00
commit b0ce2fe0af
31 changed files with 3342 additions and 0 deletions

69
client/src/pages/Home.tsx Normal file
View file

@ -0,0 +1,69 @@
import { useState } from "react";
import { useNavigate } from "react-router-dom";
import Layout from "../components/Layout";
function Home() {
const [roomId, setRoomId] = useState("");
const navigate = useNavigate();
function onClickCreateRoom() {
const roomId = Math.random().toString(36).substring(7);
navigate(`/room/${roomId}`);
}
function onClickJoinRoom() {
if (!roomId) {
return;
}
navigate(`/room/${roomId}`);
}
return (
<Layout>
<section className="max-w-md mx-auto">
<div className="space-y-4">
<h2 className="text-2xl font-semibold text-gray-800">
Create a new Room
</h2>
<button
type="button"
onClick={onClickCreateRoom}
className="w-full py-2 px-4 bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors duration-200 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2"
>
Create
</button>
</div>
<div className="space-y-4 mt-16">
<h2 className="text-2xl font-semibold text-gray-800">
Join Existing Room
</h2>
<label
htmlFor="roomId"
className="block text-sm font-medium text-gray-700"
>
Room ID:
</label>
<input
id="roomId"
type="text"
placeholder="Room ID"
value={roomId}
onChange={(e) => setRoomId(e.target.value)}
className="w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
/>
<button
type="button"
onClick={onClickJoinRoom}
disabled={!roomId}
className="w-full py-2 px-4 bg-green-600 text-white rounded-md hover:bg-green-700 transition-colors duration-200 focus:outline-none focus:ring-2 focus:ring-green-500 focus:ring-offset-2 disabled:opacity-50 disabled:cursor-not-allowed"
>
Join
</button>
</div>
</section>
</Layout>
);
}
export default Home;

32
client/src/pages/Room.tsx Normal file
View file

@ -0,0 +1,32 @@
import { useParams } from "react-router-dom";
import Layout from "../components/Layout";
import Connect from "../components/Connect";
import { useWebSocket } from "../hooks/useWebSocket";
function Room() {
const { roomId } = useParams();
const { isConnected, connect } = useWebSocket(roomId ?? "");
return (
<Layout>
<section className="w-full">
<h2 className="text-xl bg-gray-100 p-4 flex justify-between items-center rounded-md shadow-sm">
<span className="font-medium">Room ID: {roomId}</span>
<span
className={`px-3 py-1 rounded-full text-sm font-medium ${
isConnected
? "bg-green-100 text-green-800"
: "bg-red-100 text-red-800"
}`}
>
{isConnected ? "Connected" : "Not Connected"}
</span>
</h2>
{!isConnected && <Connect onConnect={connect} />}
</section>
</Layout>
);
}
export default Room;