-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[frontend] Handling notification (#243)
* Add handling of room enter/leave notifications * Separate logic and ui by cutting logic into custom hooks * Add handling of mute/updateRole notifications
- Loading branch information
Showing
10 changed files
with
425 additions
and
257 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
"use client"; | ||
|
||
import { blockUser, unblockUser } from "@/app/lib/actions"; | ||
import type { PublicUserEntity } from "@/app/lib/dtos"; | ||
import { toast } from "@/components/ui/use-toast"; | ||
import { useCallback, useState } from "react"; | ||
|
||
const showBlockErrorToast = () => { | ||
toast({ | ||
title: "Error", | ||
description: "failed to block user", | ||
}); | ||
}; | ||
|
||
const showUnblockErrorToast = () => { | ||
toast({ | ||
title: "Error", | ||
description: "failed to unblock user", | ||
}); | ||
}; | ||
|
||
export function useBlock(userId: number, blockingUsers: PublicUserEntity[]) { | ||
const [blockPending, setBlockPending] = useState(false); | ||
const [isBlocked, setIsBlocked] = useState( | ||
blockingUsers.some((u) => u.id === userId), | ||
); | ||
const block = useCallback(async () => { | ||
setBlockPending(true); | ||
const res = await blockUser(userId); | ||
if (res === "Success") { | ||
setIsBlocked(true); | ||
setBlockPending(false); | ||
} else { | ||
showBlockErrorToast(); | ||
setBlockPending(false); | ||
} | ||
}, [userId]); | ||
const unblock = useCallback(async () => { | ||
setBlockPending(true); | ||
const res = await unblockUser(userId); | ||
if (res === "Success") { | ||
setIsBlocked(false); | ||
setBlockPending(false); | ||
} else { | ||
showUnblockErrorToast(); | ||
setBlockPending(false); | ||
} | ||
}, [userId]); | ||
return { | ||
blockPending, | ||
isBlocked, | ||
block, | ||
unblock, | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
"use client"; | ||
|
||
import { useCallback, useState } from "react"; | ||
import { chatSocket as socket } from "@/socket"; | ||
|
||
export const useInviteToGame = (userId: number) => { | ||
const [isInvitingToGame, setIsInvitingToGame] = useState(false); | ||
const [invitePending, setInvitePending] = useState(false); | ||
|
||
const inviteToGame = useCallback(async () => { | ||
setInvitePending(true); | ||
await socket.emit("invite-pong", { userId: userId }); | ||
setIsInvitingToGame(true); | ||
setInvitePending(false); | ||
}, [userId]); | ||
const cancelInviteToGame = useCallback(async () => { | ||
setInvitePending(true); | ||
await socket.emit("invite-cancel-pong", { userId: userId }); | ||
setIsInvitingToGame(false); | ||
setInvitePending(false); | ||
}, [userId]); | ||
|
||
return { | ||
invitePending, | ||
isInvitingToGame, | ||
inviteToGame, | ||
cancelInviteToGame, | ||
}; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
"use client"; | ||
|
||
import { kickUserOnRoom } from "@/app/lib/actions"; | ||
import type { UserOnRoomEntity } from "@/app/lib/dtos"; | ||
import { toast } from "@/components/ui/use-toast"; | ||
import { useCallback, useState } from "react"; | ||
import { useRouter } from "next/navigation"; | ||
import { chatSocket as socket } from "@/socket"; | ||
|
||
const showKickErrorToast = () => { | ||
toast({ | ||
title: "Error", | ||
description: "failed to kick user", | ||
}); | ||
}; | ||
|
||
export function useKick(roomId: number, userId: number) { | ||
const router = useRouter(); | ||
const [kickPending, setKickPending] = useState(false); | ||
|
||
const kick = useCallback(async () => { | ||
setKickPending(true); | ||
const res = await kickUserOnRoom(roomId, userId); | ||
if (res === "Success") { | ||
setKickPending(false); | ||
} else { | ||
showKickErrorToast(); | ||
setKickPending(false); | ||
} | ||
}, [roomId, userId]); | ||
return { kickPending, kick }; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
"use client"; | ||
|
||
import { muteUser, unmuteUser } from "@/app/lib/actions"; | ||
import type { PublicUserEntity } from "@/app/lib/dtos"; | ||
import { toast } from "@/components/ui/use-toast"; | ||
import { useCallback, useEffect, useState } from "react"; | ||
import { chatSocket as socket } from "@/socket"; | ||
|
||
interface MuteEvent { | ||
userId: number; | ||
roomId: number; | ||
} | ||
|
||
const showMuteErrorToast = () => { | ||
toast({ | ||
title: "Error", | ||
description: "failed to mute user", | ||
}); | ||
}; | ||
|
||
const showUnmuteErrorToast = () => { | ||
toast({ | ||
title: "Error", | ||
description: "failed to unmute user", | ||
}); | ||
}; | ||
|
||
export function useMute( | ||
roomId: number, | ||
userId: number, | ||
mutedUsers: PublicUserEntity[], | ||
) { | ||
const [mutePending, setMutePending] = useState(false); | ||
const [isMuted, setIsMuted] = useState( | ||
mutedUsers.some((u: PublicUserEntity) => u.id === userId), | ||
); | ||
|
||
useEffect(() => { | ||
const handleMuteEvent = (data: MuteEvent) => { | ||
if (Number(data.userId) === userId && data.roomId === roomId) { | ||
setIsMuted(true); | ||
} | ||
}; | ||
const handleUnmuteEvent = (data: MuteEvent) => { | ||
if (Number(data.userId) === userId && data.roomId === roomId) { | ||
setIsMuted(false); | ||
} | ||
}; | ||
socket.on("mute", handleMuteEvent); | ||
socket.on("unmute", handleUnmuteEvent); | ||
|
||
return () => { | ||
socket.off("mute", handleMuteEvent); | ||
socket.off("unmute", handleUnmuteEvent); | ||
}; | ||
}, [roomId, userId]); | ||
|
||
const mute = useCallback( | ||
async (duration?: number) => { | ||
setMutePending(true); | ||
const res = await muteUser(roomId, userId, duration); | ||
if (res === "Success") { | ||
setIsMuted(true); | ||
setMutePending(false); | ||
} else { | ||
showMuteErrorToast(); | ||
setMutePending(false); | ||
} | ||
}, | ||
[roomId, userId], | ||
); | ||
const unmute = useCallback(async () => { | ||
setMutePending(true); | ||
const res = await unmuteUser(roomId, userId); | ||
if (res === "Success") { | ||
setIsMuted(false); | ||
setMutePending(false); | ||
} else { | ||
showUnmuteErrorToast(); | ||
setMutePending(false); | ||
} | ||
}, [roomId, userId]); | ||
return { mutePending, isMuted, mute, unmute }; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
"use client"; | ||
|
||
import { updateRoomUser } from "@/app/lib/actions"; | ||
import type { UserOnRoomEntity } from "@/app/lib/dtos"; | ||
import { toast } from "@/components/ui/use-toast"; | ||
import { useCallback, useEffect, useState } from "react"; | ||
import { chatSocket as socket } from "@/socket"; | ||
|
||
type Role = "ADMINISTRATOR" | "MEMBER"; | ||
|
||
interface UpdateRoleEvent { | ||
roomId: number; | ||
userId: number; | ||
role: Role; | ||
} | ||
|
||
const showUpdateRoleErrorToast = () => { | ||
toast({ | ||
title: "Error", | ||
description: "failed to update user role", | ||
}); | ||
}; | ||
|
||
export function useUpdateRole( | ||
roomId: number, | ||
me: UserOnRoomEntity, | ||
user: UserOnRoomEntity, | ||
) { | ||
const [updateRolePending, setUpdateRolePending] = useState(false); | ||
const [userRole, setUserRole] = useState(user.role); | ||
const [meRole, setMeRole] = useState(me.role); | ||
const isUserAdmin = userRole === "ADMINISTRATOR"; | ||
useEffect(() => { | ||
const handleUpdateRoleEvent = (data: UpdateRoleEvent) => { | ||
if (data.roomId === roomId && data.userId === user.userId) { | ||
setUserRole(data.role); | ||
} else if (data.roomId === roomId && data.userId === me.userId) { | ||
setMeRole(data.role); | ||
} | ||
}; | ||
socket.on("update-role", handleUpdateRoleEvent); | ||
|
||
return () => { | ||
socket.off("update-role", handleUpdateRoleEvent); | ||
}; | ||
}, [roomId, me.userId, user.userId]); | ||
|
||
const updateUserRole = useCallback(async () => { | ||
setUpdateRolePending(true); | ||
const res = await updateRoomUser( | ||
isUserAdmin ? "MEMBER" : "ADMINISTRATOR", | ||
roomId, | ||
user.userId, | ||
); | ||
if (res !== "Success") { | ||
showUpdateRoleErrorToast(); | ||
setUpdateRolePending(false); | ||
} else { | ||
setUserRole(isUserAdmin ? "MEMBER" : "ADMINISTRATOR"); | ||
setUpdateRolePending(false); | ||
} | ||
}, [roomId, user.userId, isUserAdmin]); | ||
return { | ||
updateRolePending, | ||
meRole, | ||
userRole, | ||
updateUserRole, | ||
}; | ||
} |
Oops, something went wrong.