feat: initial scaffolding, client can connect with a user name
This commit is contained in:
commit
b0ce2fe0af
31 changed files with 3342 additions and 0 deletions
69
client/src/pages/Home.tsx
Normal file
69
client/src/pages/Home.tsx
Normal 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
32
client/src/pages/Room.tsx
Normal 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;
|
||||
Loading…
Add table
Add a link
Reference in a new issue