Skip to content

Commit ab83052

Browse files
committed
Add remove participant from achievement
1 parent e1786e6 commit ab83052

File tree

4 files changed

+86
-8
lines changed

4 files changed

+86
-8
lines changed
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
"use client";
2+
3+
import { Trash } from "lucide-react";
4+
5+
interface RemoveUserProps {
6+
userName: string;
7+
userId: string;
8+
handleRemoveUser(userId: string): Promise<void>;
9+
}
10+
11+
export default function RemoveUser({
12+
userName,
13+
userId,
14+
handleRemoveUser,
15+
}: RemoveUserProps) {
16+
async function removeUser() {
17+
if (window.confirm(`Do you really want to remove ${userName}?`)) {
18+
await handleRemoveUser(userId);
19+
window.location.reload();
20+
}
21+
}
22+
23+
return (
24+
<button
25+
onClick={removeUser}
26+
className="size-8 flex items-center justify-center rounded-full shadow-md bg-red-800 text-white"
27+
>
28+
<Trash size={16} />
29+
</button>
30+
);
31+
}

src/app/(authenticated)/sessions/[id]/participants/page.tsx

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { AchievementService } from "@/services/AchievementService";
66
import { SessionService } from "@/services/SessionService";
77
import { UserService } from "@/services/UserService";
88
import { getServerSession } from "next-auth";
9+
import RemoveUser from "./RemoveUser";
910

1011
interface SessionParticipantsParams {
1112
id: string;
@@ -24,20 +25,38 @@ export default async function SessionParticipants({
2425
return <BlankPageWithMessage message="Session not found!" />;
2526
}
2627

27-
const session = await getServerSession(authOptions);
28+
const session = (await getServerSession(authOptions))!;
2829

2930
const sessionAchievement = await AchievementService.getAchievementBySession(
30-
session!.cannonToken,
31-
sessionID
31+
session.cannonToken,
32+
sessionID,
3233
);
3334
if (!sessionAchievement) {
3435
return <BlankPageWithMessage message="Sesssion Achievement not found!" />;
3536
}
3637

38+
async function removeUser(userId: string) {
39+
"use server";
40+
await AchievementService.removeUser(
41+
session.cannonToken,
42+
sessionAchievement!.id,
43+
userId,
44+
);
45+
}
46+
3747
async function getUserTile(userId: string) {
3848
const user = await UserService.getUser(session!.cannonToken, userId);
3949
if (!user) return undefined;
40-
return <UserTile key={user.id} user={user} />;
50+
return (
51+
<div className="flex items-center gap-x-2 w-full">
52+
<UserTile key={user.id} user={user} />
53+
<RemoveUser
54+
userId={user.id}
55+
userName={user.name}
56+
handleRemoveUser={removeUser}
57+
/>
58+
</div>
59+
);
4160
}
4261

4362
const unregisteredUsers = sessionAchievement.unregisteredUsers || 0;
@@ -52,7 +71,7 @@ export default async function SessionParticipants({
5271
>
5372
{sessionAchievement.users?.length ? (
5473
await Promise.all(
55-
sessionAchievement.users.map((id) => getUserTile(id))
74+
sessionAchievement.users.map((id) => getUserTile(id)),
5675
)
5776
) : (
5877
<div>There are no registered users at this session</div>

src/components/ListCard.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ interface ConditionalLinkProps extends Partial<LinkProps> {
2727
function ConditionalLink({ children, href, ...props }: ConditionalLinkProps) {
2828
if (!href) return children;
2929
return (
30-
<Link href={href} {...props}>
30+
<Link href={href} className="grow" {...props}>
3131
{children}
3232
</Link>
3333
);
@@ -52,7 +52,7 @@ export default function ListCard({
5252
return (
5353
<ConditionalLink href={link} {...linkProps}>
5454
<div
55-
className={`min-w-[340px] min-h-[74px] px-4 py-2 flex items-center justify-start gap-x-4 bg-white rounded-md shadow-md text-sm overflow-hidden hover:bg-slate-50 hover:shadow-sm active:bg-gray-200 active:shadow-none ${extraClassName || ""}`}
55+
className={`min-w-[300px] min-h-[74px] px-4 py-2 flex items-center justify-start gap-x-4 bg-white rounded-md shadow-md text-sm overflow-hidden hover:bg-slate-50 hover:shadow-sm active:bg-gray-200 active:shadow-none ${extraClassName || ""}`}
5656
>
5757
{img && (
5858
<Image

src/services/AchievementService.ts

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,5 +52,33 @@ export const AchievementService = (() => {
5252
return false;
5353
};
5454

55-
return { getAchievements, getAchievementBySession, redeemSecretAchievement };
55+
const removeUser = async (
56+
cannonToken: string,
57+
id: string,
58+
userId: string,
59+
): Promise<Achievement | null> => {
60+
try {
61+
const resp = await fetch(
62+
`${achievementsEndpoint}/${id}/users/${userId}`,
63+
{
64+
method: "DELETE",
65+
headers: {
66+
"Content-Type": "application/json",
67+
Authorization: `Bearer ${cannonToken}`,
68+
},
69+
},
70+
);
71+
if (resp.ok) return (await resp.json()) as Achievement;
72+
} catch (e) {
73+
console.error(e);
74+
}
75+
return null;
76+
};
77+
78+
return {
79+
getAchievements,
80+
getAchievementBySession,
81+
redeemSecretAchievement,
82+
removeUser,
83+
};
5684
})();

0 commit comments

Comments
 (0)