Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/lobby UI #71

Merged
merged 9 commits into from
Apr 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/components/routing/routeProtectors/LobbyGuard.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export const LobbyGuard = () => {
return <Outlet />;
}
// Debugging

return <Outlet />;
//return <Navigate to="/login" replace />;
};
Expand Down
148 changes: 120 additions & 28 deletions src/components/views/Lobby.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,15 @@ import "styles/views/Lobby.scss";
import { User, Room } from "types";
import Popup from "components/ui/Popup";
import { Dropdown } from "components/ui/Dropdown";


type PlayerProps = {
user: User;
};
type RoomComponentProps = {
room: Room;
};

type RoomListProps = {
rooms: Room[];
};
Expand Down Expand Up @@ -128,12 +131,14 @@ const Lobby = () => {
const roomCreationPopRef = useRef<HTMLDialogElement>(null);
const profilePopRef = useRef<HTMLDialogElement>(null);
const changeAvatarPopRef = useRef<HTMLDialogElement>(null);
const infoPopRef = useRef<HTMLDialogElement>(null);
const [rooms, setRooms] = useState<Room[]>(mockRooms);
const [user, setUser] = useState<User[]>(mockRoomPlayers[0]);
const [username, setUsername] = useState<string | null>(null);
const [avatar, setAvatar] = useState<string | null>(null);
const [avatarToBeChanged, setAvatarToBeChanged] = useState<string | null>(null);
const [avatarOrigin, setAvatarOrigin] = useState<string | null>(null);
const [roomName, setRoomName] = useState("");
const [numRounds, setNumRounds] = useState(0);
const [roomTheme, setRoomTheme] = useState("");
const logout = async () => {
const id = sessionStorage.getItem("id");
sessionStorage.removeItem("token");
Expand Down Expand Up @@ -190,12 +195,34 @@ const Lobby = () => {
if (error.response && error.response.data) {
alert(error.response.data.message);
} else {
console.error('Error:', error.message);
alert('An unexpected error occurred.');
console.error("Error:", error.message);
alert("An unexpected error occurred.");
}
}
};

const createRoom = async () => {
try {
const ownerId = sessionStorage.getItem("id"); // 假设ownerId存储在sessionStorage中
const requestBody = JSON.stringify({
name: roomName,
num: numRounds,
ownerId: ownerId,
theme: roomTheme
});

const response = await api.post("/games", requestBody);
console.log("Room created successfully:", response);
const roomId = response.roomId;
navigate(`/room=${roomId}`);
//toggleRoomCreationPop(); // 关闭创建房间的弹窗
} catch (error) {
console.error("Error creating room:", handleError(error));
alert(`Error creating room: ${handleError(error)}`);
}
};


const toggleRoomCreationPop = () => {
// if the ref is not set, do nothing
if (!roomCreationPopRef.current) {
Expand All @@ -218,6 +245,15 @@ const Lobby = () => {
: profilePopRef.current.showModal();
};

async function enterRoom(roomId, userId) {
try {
const requestBody = JSON.stringify({ userId, roomId });
await api.put("/games", requestBody);
} catch (error) {
console.error(`Something went wrong during the enterRoom: \n${handleError(error)}`);
}
}

const toggleAvatarPop = () => {
// if the ref is not set, do nothing
if (!changeAvatarPopRef.current) {
Expand All @@ -229,10 +265,40 @@ const Lobby = () => {
: changeAvatarPopRef.current.showModal();
};

const changeAvatar = (avatar) =>{
setAvatarToBeChanged(avatar);
updateAvatar(avatar);
toggleAvatarPop();
const toggleInfoPop = () => {
// if the ref is not set, do nothing
if (!infoPopRef.current) {
return;
}
// if the dialog is open, close it. Otherwise, open it.
infoPopRef.current.hasAttribute("open")
? infoPopRef.current.close()
: infoPopRef.current.showModal();
};

const changeAvatar = async (newAvatar) =>{
try {
// 更新本地状态
setAvatar(newAvatar);

// 构造请求体,只包含 avatar 更改
const requestBody = JSON.stringify({ username, avatar: newAvatar });
const id = sessionStorage.getItem("id");
console.log("Request body:", requestBody);
// 执行更新请求
await api.put(`/users/${id}`, requestBody);

// 可能需要关闭弹窗或执行其他 UI 反馈

console.log("Avatar changed successfully");
} catch (error) {
if (error.response && error.response.data) {
alert(error.response.data.message);
} else {
console.error("Error:", error.message);
alert("An unexpected error occurred.");
}
}
}

const updateAvatar = (newAvatar) => {
Expand All @@ -245,9 +311,23 @@ const Lobby = () => {
const userinfo = () => {
return;
};


const renderRoomLists = () => {
return mockRooms.map((Room) => (
<div className="room-container" key={Room.id}>
<div className="room-container" key={Room.id} onClick={(e) => {
e.preventDefault();
const currentId = sessionStorage.getItem("id");
// const isPlayerInRoom = Room.roomPlayersList.join().includes(currentId);
enterRoom(Room.id, currentId)
.then(() => {
navigate(`/room=${Room.id}`);
})
.catch(error => {
console.error(`Something went wrong during the enterRoom: \n${handleError(error)}`);
alert(`Something went wrong during the enterRoom: \n${handleError(error)}`);
});
}}>
<div className="room-players">
{Room.roomPlayersList?.map((user, index) => (
<div className="player" key={index}>
Expand All @@ -271,14 +351,15 @@ const Lobby = () => {
));
};


return (
<BaseContainer>
<div className="user-container" onClick={toggleProfilePop}>
<i className={"twa twa-" + user.avatar} style={{fontSize: "3.8rem", marginTop:"0.8rem"}}/>
<div className="name">{user.username}</div>
</div>
<div className="big-title">Kaeps</div>
<div className="information"> i </div>
<div className="information" onClick={toggleInfoPop}> i </div>
<div className="lobby room-list-wrapper">
{/* for clip the scrollbar inside the border */}
<div className="lobby room-list">
Expand All @@ -296,19 +377,21 @@ const Lobby = () => {
<BaseContainer className="profile-popup content">
<div className="avatar-container" onClick={() => {
toggleAvatarPop();
toggleProfilePop();
setAvatarOrigin(user.avatar);
// toggleProfilePop();
}}>
<i className={"twa twa-" + user.avatar} style={{fontSize: "10rem", marginTop:"0.8rem", textAlign:"center"}}/>
</div>
<FormField
label="Username:"
<div className="profile-popup field">
<label className="profile-popup label">
Username:
</label>
<input
// className="profile-popup input"
//value={user.username}
type="text"
placeholder="Username..."
value={user.username}
onChange={un => setUsername(un)}
disabled={false}
onChange={e => setUsername(e)}
/>
</div>

<div>Name: {user.name}</div>
<div>Status: {user.status}</div>
Expand All @@ -319,7 +402,6 @@ const Lobby = () => {
<div className="profile-popup btn-container">
<Button className="cancel" onClick={() => {
toggleProfilePop();
updateAvatar(avatarOrigin);
}}>
Cancel
</Button>
Expand All @@ -340,8 +422,8 @@ const Lobby = () => {
{avatarList?.map((avatar,index) => (
<div className="player" key={index} >
<i className={"twa twa-" + avatar} style={{fontSize: "3.8rem"}} onClick={() => {
changeAvatar(avatar);
toggleProfilePop();
changeAvatar(avatar).then(r => toggleProfilePop());

}}/>
</div>
))}
Expand All @@ -355,23 +437,33 @@ const Lobby = () => {
>
<BaseContainer className="room-creation-popup content">
<div className="title">Create Room</div>
<input type="text" placeholder="Room Name" />
<input type="number" placeholder="Round" />
<input type="text" placeholder="Room Name" value={roomName} onChange={e => setRoomName(e.target.value)} />
<input type="number" placeholder="Number of Players" value={numRounds} onChange={e => setNumRounds(parseInt(e.target.value, 10))} />
<Dropdown
className="theme-dropdown"
prompt="Select Theme"
value={roomTheme}
options={[
{ value: "Beginner", label: "Beginner"},
{ value: "Food", label: "Food" },
{ value: "Food", label: "Food" }
]}
onChange={(selectedOption) => setRoomTheme(selectedOption.value)}
/>
<div className="room-creation-popup btn-container">
<Button className="create-room">Create Room</Button>
<Button className="cancel" onClick={toggleRoomCreationPop}>
Cancel
</Button>
<Button className="create-room" onClick={createRoom}>Create Room</Button>
<Button className="cancel" onClick={toggleRoomCreationPop}>Cancel</Button>
</div>
</BaseContainer>

</Popup>

<Popup ref={infoPopRef} toggleDialog={toggleInfoPop} className="profile-popup">
<div>Here is some Guidelines....</div>
<div className="profile-popup btn-container">
<Button className="cancel" onClick={toggleInfoPop}>
Close
</Button>
</div>
</Popup>
</BaseContainer>
);
Expand Down
2 changes: 1 addition & 1 deletion src/styles/ui/Popup.scss
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
}
}
.popup-content {
height: 100%; // fill the height of the popup
height: 100%;
padding: 20px;
display: flex;
flex-direction: column;
Expand Down
6 changes: 3 additions & 3 deletions src/styles/views/Lobby.scss
Original file line number Diff line number Diff line change
Expand Up @@ -341,11 +341,11 @@
&.input {
height: 35px;
padding-left: 15px;
margin-left: -4px;
margin-left: 4px;
border: none;
border-radius: 0.75em;
//margin-top: 20px;
background: transparentize(white, 0.85);
margin-top: 5px;
background: #FFF3CF;
color: $textColor;
}

Expand Down
Loading