From bccfbffc399aad2b06a8fd2cb1f4ef9de2c60de0 Mon Sep 17 00:00:00 2001 From: lim Date: Tue, 30 Jan 2024 19:51:57 +0900 Subject: [PATCH 1/2] [frontend] Add user notifications for chat channel action errors --- frontend/app/lib/actions.ts | 4 +- frontend/app/room/[id]/sidebar-item.tsx | 51 +++++++++++++++++++++++++ frontend/app/ui/room/ban-item.tsx | 9 +++++ frontend/app/ui/room/invite-item.tsx | 9 +++++ frontend/app/ui/room/unban-item.tsx | 9 +++++ 5 files changed, 80 insertions(+), 2 deletions(-) diff --git a/frontend/app/lib/actions.ts b/frontend/app/lib/actions.ts index f7b4fb69..86b47e3c 100644 --- a/frontend/app/lib/actions.ts +++ b/frontend/app/lib/actions.ts @@ -337,7 +337,7 @@ export async function updateRoomUser( console.log(res.status); if (!res.ok) { console.error("updateRoomUser error: ", await res.json()); - throw new Error("updateRoomUser error"); + return "Error"; } else { const update = await res.json(); console.log(update); @@ -357,7 +357,7 @@ export async function kickUserOnRoom(roomId: number, userId: number) { ); if (!res.ok) { console.error("kickUserOnRoom error: ", await res.json()); - throw new Error("kickUserOnRoom error"); + return "Error"; } else { revalidatePath(`/room/${roomId}`); return "Success"; diff --git a/frontend/app/room/[id]/sidebar-item.tsx b/frontend/app/room/[id]/sidebar-item.tsx index fcc817c6..31224825 100644 --- a/frontend/app/room/[id]/sidebar-item.tsx +++ b/frontend/app/room/[id]/sidebar-item.tsx @@ -24,11 +24,54 @@ import { ContextMenuSubContent, ContextMenuSubTrigger, } from "@/components/ui/context-menu"; +import { toast } from "@/components/ui/use-toast"; import { chatSocket as socket } from "@/socket"; import { useRouter } from "next/navigation"; import { useEffect, useState, useTransition } from "react"; import MuteMenu from "./mute-menu"; +const showKickErrorToast = () => { + toast({ + title: "Error", + description: "failed to kick user", + }); +}; + +const showMuteErrorToast = () => { + toast({ + title: "Error", + description: "failed to mute user", + }); +}; + +const showUnmuteErrorToast = () => { + toast({ + title: "Error", + description: "failed to unmute user", + }); +}; + +const showBlockErrorToast = () => { + toast({ + title: "Error", + description: "failed to block user", + }); +}; + +const showUnblockErrorToast = () => { + toast({ + title: "Error", + description: "failed to unblock user", + }); +}; + +const showUpdateRoleErrorToast = () => { + toast({ + title: "Error", + description: "failed to update user role", + }); +}; + function truncateString(str: string | undefined, num: number): string { if (!str) { return ""; @@ -111,6 +154,7 @@ export default function SidebarItem({ if (res === "Success") { setBlockState({ isBlocked: true, isClicked: false }); } else { + showBlockErrorToast(); setBlockState({ ...blockState, isClicked: false }); } }; @@ -120,6 +164,7 @@ export default function SidebarItem({ if (res === "Success") { setBlockState({ isBlocked: false, isClicked: false }); } else { + showUnblockErrorToast(); setBlockState({ ...blockState, isClicked: false }); } }; @@ -139,6 +184,7 @@ export default function SidebarItem({ if (res === "Success") { setMuteState({ isMuted: true, isClicked: false }); } else { + showMuteErrorToast(); setMuteState({ ...muteState, isClicked: false }); } }; @@ -148,6 +194,7 @@ export default function SidebarItem({ if (res === "Success") { setMuteState({ isMuted: false, isClicked: false }); } else { + showUnmuteErrorToast(); setMuteState({ ...muteState, isClicked: false }); } }; @@ -157,6 +204,7 @@ export default function SidebarItem({ if (res === "Success") { setKickState({ isKicked: true, isClicked: false }); } else { + showKickErrorToast(); setKickState({ ...kickState, isClicked: false }); } }; @@ -167,6 +215,9 @@ export default function SidebarItem({ room.id, user.userId, ); + if (res !== "Success") { + showUpdateRoleErrorToast(); + } setIsUpdateRoleClicked(false); }; return ( diff --git a/frontend/app/ui/room/ban-item.tsx b/frontend/app/ui/room/ban-item.tsx index 2f11d2cb..d001fc96 100644 --- a/frontend/app/ui/room/ban-item.tsx +++ b/frontend/app/ui/room/ban-item.tsx @@ -5,9 +5,17 @@ import { PublicUserEntity } from "@/app/lib/dtos"; import { Avatar } from "@/app/ui/user/avatar"; import Loader from "@/components/ui/loader"; import { Ban } from "lucide-react"; +import { toast } from "@/components/ui/use-toast"; import { useRouter } from "next/navigation"; import { useState } from "react"; +const showBanErrorToast = () => { + toast({ + title: "Error", + description: "failed to ban user", + }); +}; + export default function BanItem({ roomId, user, @@ -24,6 +32,7 @@ export default function BanItem({ if (result === "Success") { router.refresh(); } else { + showBanErrorToast(); setIsClicked(false); } }; diff --git a/frontend/app/ui/room/invite-item.tsx b/frontend/app/ui/room/invite-item.tsx index 80b38275..8cf10a85 100644 --- a/frontend/app/ui/room/invite-item.tsx +++ b/frontend/app/ui/room/invite-item.tsx @@ -5,9 +5,17 @@ import { PublicUserEntity } from "@/app/lib/dtos"; import { Avatar } from "@/app/ui/user/avatar"; import Loader from "@/components/ui/loader"; import { LogIn } from "lucide-react"; +import { toast } from "@/components/ui/use-toast"; import { useRouter } from "next/navigation"; import { useState } from "react"; +const showInviteErrorToast = () => { + toast({ + title: "Error", + description: "failed to add user", + }); +}; + export default function InviteItem({ roomId, user, @@ -24,6 +32,7 @@ export default function InviteItem({ if (res === "Success") { router.refresh(); } else { + showInviteErrorToast(); setIsClicked(false); } }; diff --git a/frontend/app/ui/room/unban-item.tsx b/frontend/app/ui/room/unban-item.tsx index f8bd1871..550ce76c 100644 --- a/frontend/app/ui/room/unban-item.tsx +++ b/frontend/app/ui/room/unban-item.tsx @@ -5,9 +5,17 @@ import { PublicUserEntity } from "@/app/lib/dtos"; import { Avatar } from "@/app/ui/user/avatar"; import Loader from "@/components/ui/loader"; import { CheckCircle2 } from "lucide-react"; +import { toast } from "@/components/ui/use-toast"; import { useRouter } from "next/navigation"; import { useState } from "react"; +const showUnbanErrorToast = () => { + toast({ + title: "Error", + description: "failed to unban user", + }); +}; + export default function UnbanItem({ roomId, user, @@ -24,6 +32,7 @@ export default function UnbanItem({ if (result === "Success") { router.refresh(); } else { + showUnbanErrorToast(); setIsClicked(false); } }; From 2ab01c472fb4dc62d6f9cac92095e9094962dcad Mon Sep 17 00:00:00 2001 From: lim Date: Tue, 30 Jan 2024 23:13:28 +0900 Subject: [PATCH 2/2] [frontend] Exclude owner from user list on ban admin screen --- frontend/app/room/[id]/sidebar-menu.tsx | 5 ++--- frontend/app/ui/room/ban-modal.tsx | 6 +++++- frontend/app/ui/room/invite-modal.tsx | 6 ++++-- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/frontend/app/room/[id]/sidebar-menu.tsx b/frontend/app/room/[id]/sidebar-menu.tsx index f371c6c6..1481d597 100644 --- a/frontend/app/room/[id]/sidebar-menu.tsx +++ b/frontend/app/room/[id]/sidebar-menu.tsx @@ -69,8 +69,6 @@ export const SidebarMenu = ({ setIsBanOpen(true); }; - const members = usersOnRoom.map((member) => member.user); - return ( <> {isAdmin && ( @@ -85,6 +83,7 @@ export const SidebarMenu = ({ setOpen={setIsBanOpen} roomId={room.id} me={me} + usersOnRoom={usersOnRoom} allUsers={allUsers} bannedUsers={bannedUsers} /> @@ -93,7 +92,7 @@ export const SidebarMenu = ({ setOpen={setIsInviteOpen} room={room} me={me} - members={members} + usersOnRoom={usersOnRoom} allUsers={allUsers} bannedUsers={bannedUsers} /> diff --git a/frontend/app/ui/room/ban-modal.tsx b/frontend/app/ui/room/ban-modal.tsx index 02e23fce..191f0767 100644 --- a/frontend/app/ui/room/ban-modal.tsx +++ b/frontend/app/ui/room/ban-modal.tsx @@ -17,6 +17,7 @@ interface Props { setOpen: (open: boolean) => void; roomId: number; me: UserOnRoomEntity; + usersOnRoom: UserOnRoomEntity[]; allUsers: PublicUserEntity[]; bannedUsers: PublicUserEntity[]; } @@ -25,13 +26,16 @@ export default function BanModal({ setOpen, roomId, me, + usersOnRoom, allUsers, bannedUsers, }: Props) { + const owner = usersOnRoom.find((user) => user.role === "OWNER"); const UnbannedUsers = allUsers?.filter( (user) => !bannedUsers?.some((bannedUser) => bannedUser.id === user.id) && - user.id !== me?.userId, + user.id !== me?.userId && + user.id !== owner?.userId, ); return ( diff --git a/frontend/app/ui/room/invite-modal.tsx b/frontend/app/ui/room/invite-modal.tsx index eb2abacd..76993a63 100644 --- a/frontend/app/ui/room/invite-modal.tsx +++ b/frontend/app/ui/room/invite-modal.tsx @@ -17,7 +17,8 @@ interface Props { setOpen: (open: boolean) => void; room: RoomEntity; me: UserOnRoomEntity; - members: PublicUserEntity[]; + usersOnRoom: UserOnRoomEntity[]; + allUsers: PublicUserEntity[]; bannedUsers: PublicUserEntity[]; } @@ -27,7 +28,7 @@ export default function InviteModal({ setOpen, room, me, - members, + usersOnRoom, allUsers, bannedUsers, }: Props) { @@ -37,6 +38,7 @@ export default function InviteModal({ user.id !== me?.userId, ); + const members = usersOnRoom.map((member) => member.user); const OtherThanMembers = UnbannedUsers?.filter( (user) => !members?.some((member) => member.id === user.id), );