Skip to content

Commit

Permalink
Fix/update states (#115)
Browse files Browse the repository at this point in the history
* feat: remove unecessary sidebar

* feat: move menus to top

* fix: update name on header after update

* style: better height disposal

* feat: update chat gateway to emit updated list of members

* refactor: update chat list to handle emit

* refactor: remove unecessary console log

* fix: set user not used anymore
  • Loading branch information
iaurg authored Nov 24, 2023
1 parent 05ca1d7 commit 5987a1a
Show file tree
Hide file tree
Showing 16 changed files with 176 additions and 133 deletions.
69 changes: 69 additions & 0 deletions backend/src/chat/chat.gateway.ts
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,7 @@ export class ChatGateway
if (you.role !== 'OWNER') {
return;
}

const members = await this.chatService.listMembersByChatId(chatId);
if (!members) {
client.emit('leaveChat', { error: 'Failed to list members' });
Expand Down Expand Up @@ -372,6 +373,50 @@ export class ChatGateway
}
}

async updateListMembers(chatId: number) {
const members = await this.chatService.listMembersByChatId(chatId);
if (!members) {
this.logger.error('Failed to list members');
return;
}

// order members by alphabetical order
members.sort((a, b) => {
if (a.userLogin < b.userLogin) {
return -1;
}
if (a.userLogin > b.userLogin) {
return 1;
}
return 0;
});

// order members by role
members.sort((a, b) => {
if (a.role === 'OWNER') {
return -1;
}
if (b.role === 'OWNER') {
return 1;
}
if (a.role === 'ADMIN') {
return -1;
}
if (b.role === 'ADMIN') {
return 1;
}
return 0;
});

// update list of members in chat and emit event to all members
for (const member of members) {
const socket = this.connectedUsers[member.userLogin];
if (socket) {
socket.emit('listMembers', members);
}
}
}

@SubscribeMessage('promoteToAdmin')
async promoteToAdmin(
@MessageBody('user') user: string,
Expand All @@ -390,6 +435,10 @@ export class ChatGateway
this.logger.error('Failed to promote user');
return;
}

// update list of members in chat and emit event to all members
await this.updateListMembers(chatId);

this.logger.log(`You promoted ${user} to admin of chat ${chatId}`);
}

Expand Down Expand Up @@ -420,6 +469,10 @@ export class ChatGateway
this.logger.error('Failed to demote user');
return;
}

// update list of members in chat and emit event to all members
await this.updateListMembers(chatId);

this.logger.log(`You demoted ${user} to member of chat ${chatId}`);
}

Expand Down Expand Up @@ -501,6 +554,10 @@ export class ChatGateway
message: `You have been kicked from chat ${chatId}`,
});
}

// update list of members in chat and emit event to all members
await this.updateListMembers(chatId);

client.emit('kickMember', {
message: `You kicked ${user} from chat ${chatId}`,
});
Expand Down Expand Up @@ -553,6 +610,10 @@ export class ChatGateway
message: `You have been banned from chat ${chatId}`,
});
}

// update list of members in chat and emit event to all members
await this.updateListMembers(chatId);

client.emit('banMember', {
message: `You banned ${user} from chat ${chatId}`,
});
Expand All @@ -574,6 +635,10 @@ export class ChatGateway
client.emit('muteMember', { error: 'Failed to mute user' });
return;
}

// update list of members in chat and emit event to all members
await this.updateListMembers(chatId);

client.emit('muteMember', {
message: `You muted ${user} from chat ${chatId}`,
});
Expand All @@ -597,6 +662,10 @@ export class ChatGateway
client.emit('unmuteMember', { error: 'Failed to unmute user' });
return;
}

// update list of members in chat and emit event to all members
await this.updateListMembers(chatId);

client.emit('unmuteMember', {
message: `You unmuted ${user} from chat ${chatId}`,
});
Expand Down
6 changes: 5 additions & 1 deletion frontend/src/app/(private)/game/play/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ export default function PlayPage() {
justify-center
items-center
py-6
h-[calc(100vh-130px)]
"
>
<div className="animate-spin rounded-full h-24 w-24 border-t-2 border-b-2 border-purple42-200"></div>
Expand All @@ -58,6 +59,7 @@ export default function PlayPage() {
justify-center
items-center
py-6
h-[calc(100vh-130px)]
"
>
<div className="text-white text-3xl text-center">Game finished</div>
Expand All @@ -84,6 +86,7 @@ export default function PlayPage() {
justify-center
items-center
py-6
h-[calc(100vh-130px)]
"
>
<div className="text-white text-3xl text-center">Game abandoned</div>
Expand All @@ -100,6 +103,7 @@ export default function PlayPage() {
rounded-lg
w-full
mt-4
h-[calc(100vh-130px)]
"
>
<div
Expand Down Expand Up @@ -140,7 +144,7 @@ export default function PlayPage() {
onClick={() => setGameLayout("dark")}
>
Dark
</button>
</button>
</div>
<div
className="
Expand Down
4 changes: 0 additions & 4 deletions frontend/src/app/(private)/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import type { Metadata } from "next";

// These styles apply to every route in the application
import "../../styles/globals.css";
import Sidebar from "@/components/Sidebar";
import Chat from "@/components/Chat";
import Header from "@/components/Header";
import Providers from "../auth/providers";
Expand All @@ -23,9 +22,6 @@ export default function RootPrivateLayout({
<html lang="en">
<body className="bg-black42-100 flex">
<Providers>
<div className="flex flex-col md:flex-row">
<Sidebar />
</div>
<div className="flex flex-col flex-1 py-4 mx-4">
<Header />
{children}
Expand Down
7 changes: 4 additions & 3 deletions frontend/src/app/auth/redirect/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,21 @@ import { useContext, useEffect } from "react";
import nookies from "nookies";
import jwt_decode from "jwt-decode";
import { useRouter } from "next/navigation";
import { queryClient } from "@/services/queryClient";

export default function RootLoginRedirectPage() {
const { payload: user, setPayload: setUser } = useContext(AuthContext);
const { payload: user } = useContext(AuthContext);
const router = useRouter();

useEffect(() => {
const { accessToken } = nookies.get(null, "accesssToken");
if (accessToken) {
const payload: TokenPayload = jwt_decode(accessToken);
if (payload) setUser(payload);
if (payload) queryClient.invalidateQueries(["me"]);
} else {
router.push("/login");
}
}, [setUser, router]);
}, [router]);

useEffect(() => {
if (user.sub) {
Expand Down
11 changes: 3 additions & 8 deletions frontend/src/components/Chat/ChatUsersChannelPopOver.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,9 @@ export default function ChatUsersChannelPopOver({
modifiers: [{ name: "arrow", options: { element: arrowElement } }],
placement: "left",
});

// import user from useContext but rename it as currentUser
const { user: currentUser, setUpdate } = useContext(ChatContext);
const { user: currentUser } = useContext(ChatContext);

const otherUsers = users.filter(
(user) => user.userLogin !== currentUser.login
Expand All @@ -68,7 +68,6 @@ export default function ChatUsersChannelPopOver({
promoteToAdminMutation.mutate(user);
// refresh the page to see the changes
toast.success(`${user.userLogin} is now an admin`);
setUpdate(true);
};

const muteUserMutation = useMutation({
Expand All @@ -85,7 +84,6 @@ export default function ChatUsersChannelPopOver({
const handleMuteUser = (user: ChatMember) => {
muteUserMutation.mutate(user);
toast.success(`${user.userLogin} is now muted`);
setUpdate(true);
};

const unmuteUserMutation = useMutation({
Expand All @@ -98,10 +96,10 @@ export default function ChatUsersChannelPopOver({
return user;
},
});

const handleUnmuteUser = (user: ChatMember) => {
unmuteUserMutation.mutate(user);
toast.success(`${user.userLogin} is now unmuted`);
setUpdate(true);
};

const banUserMutation = useMutation({
Expand All @@ -118,7 +116,6 @@ export default function ChatUsersChannelPopOver({
const handleBanUser = (user: ChatMember) => {
banUserMutation.mutate(user);
toast.success(`${user.userLogin} is now banned from the chat`);
setUpdate(true);
};

const kickUserMutation = useMutation({
Expand All @@ -135,7 +132,6 @@ export default function ChatUsersChannelPopOver({
const handleKickUser = (user: ChatMember) => {
kickUserMutation.mutate(user);
toast.success(`${user.userLogin} was kicked from the chat`);
setUpdate(true);
};

const demoteToMemberMutation = useMutation({
Expand All @@ -152,7 +148,6 @@ export default function ChatUsersChannelPopOver({
const handleDemoteToMember = (user: ChatMember) => {
demoteToMemberMutation.mutate(user);
toast.success(`${user.userLogin} is now a user`);
setUpdate(true);
};

return (
Expand Down
49 changes: 31 additions & 18 deletions frontend/src/components/Chat/OpenChannel.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import { ChatContext } from "@/contexts/ChatContext";
import { PaperPlaneTilt, PencilSimpleSlash, UsersThree, XCircle } from "@phosphor-icons/react";
import {
PaperPlaneTilt,
PencilSimpleSlash,
UsersThree,
XCircle,
} from "@phosphor-icons/react";
import { useContext, useEffect, useState } from "react";
import ChatUsersChannelPopOver, { ChatMember } from "./ChatUsersChannelPopOver";
import chatService from "@/services/chatClient";
Expand All @@ -20,16 +25,14 @@ export function OpenChannel() {
validationRequired,
setValidationRequired,
user,
update,
setUpdate,
} = useContext(ChatContext);
// List messages from the websocket
const [message, setMessage] = useState("");
const [messages, setMessages] = useState<Message[]>([]);
const [numberOfUsersInChat, setNumberOfUsersInChat] = useState<number>(0);
const [users, setUsers] = useState<ChatMember[]>([]);
const [isLoading, setIsLoading] = useState(true);
const myUserList = users.filter(usr => usr.userLogin === user.login);
const myUserList = users.filter((usr) => usr.userLogin === user.login);
const myUser = myUserList[0] || null;

chatService.socket?.on("listMessages", (messages: Message[]) => {
Expand All @@ -42,13 +45,15 @@ export function OpenChannel() {

useEffect(() => {
chatService.socket?.on("listMembers", (members: ChatMember[]) => {
const currentMembers = members.filter((member) => member.status !== "BANNED");
const currentMembers = members.filter(
(member) => member.status !== "BANNED"
);
setNumberOfUsersInChat(currentMembers.length);
setUsers(currentMembers);
console.log("listMembers", currentMembers);
setIsLoading(false);
setUpdate(false);
});
}, [update]);
}, []);

chatService.socket?.on("verifyPassword", (response: any) => {
if (response.error) {
Expand All @@ -62,8 +67,7 @@ export function OpenChannel() {
});

const handleSendMessage = () => {
if (myUser && myUser.status === 'MUTED')
return;
if (myUser && myUser.status === "MUTED") return;
chatService.socket?.emit("message", {
chatId: selectedChat.id,
content: message,
Expand Down Expand Up @@ -95,6 +99,7 @@ export function OpenChannel() {
chatId: selectedChat.id,
password: data.password,
});

chatService.socket?.emit("joinChat", {
chatId: selectedChat.id,
password: data.password,
Expand Down Expand Up @@ -141,13 +146,14 @@ export function OpenChannel() {
</div>
);
}

if (isLoading)
return (
<div className="flex flex-col flex-1 justify-center items-center">
<div className="animate-spin rounded-full h-24 w-24 border-t-2 border-b-2 border-purple42-200"></div>
<span className="text-white text-lg mt-4">Carregando...</span>
</div>
)
);

return (
<div className="flex flex-col flex-1 justify-between">
Expand Down Expand Up @@ -178,10 +184,11 @@ export function OpenChannel() {
<div
key={message.id}
// TODO: Implement user context to compare user login with message user
className={`${message.userLogin === user.login
? "text-white bg-purple42-200 self-end"
: "text-white bg-black42-300 self-start"
} py-2 px-4 w-3/4 rounded-lg mx-2 my-2 break-words`}
className={`${
message.userLogin === user.login
? "text-white bg-purple42-200 self-end"
: "text-white bg-black42-300 self-start"
} py-2 px-4 w-3/4 rounded-lg mx-2 my-2 break-words`}
>
<span className="font-semibold">
<Link href={`/game/history/${message.userId}`}>
Expand All @@ -207,13 +214,19 @@ export function OpenChannel() {
}
}}
/>
< button
<button
className="bg-purple42-200 text-white rounded-lg p-3 placeholder-gray-700 absolute z-10 right-4"
onClick={() => handleSendMessage()} /*TODO: Check if other users are receiving the message */
onClick={() =>
handleSendMessage()
} /*TODO: Check if other users are receiving the message */
>
{myUser && myUser.status !== 'MUTED' ? <PaperPlaneTilt size={20} color="white" /> : <PencilSimpleSlash alt="Muted user" size={20} color="gray" />}
{myUser && myUser.status !== "MUTED" ? (
<PaperPlaneTilt size={20} color="white" />
) : (
<PencilSimpleSlash alt="Muted user" size={20} color="gray" />
)}
</button>
</div>
</div >
</div>
);
}
Loading

0 comments on commit 5987a1a

Please sign in to comment.