From e67ac39139ec50e2fb095a3ed7293c58733254ad Mon Sep 17 00:00:00 2001 From: "Kalle (Sendou)" <38327916+Sendouc@users.noreply.github.com> Date: Thu, 14 Jan 2021 20:09:03 +0200 Subject: [PATCH] kick team members --- components/t/TeamManagementModal.tsx | 100 +++++++++++++++++++++++---- pages/api/teams/[id].ts | 32 +++++++++ pages/api/teams/kick.ts | 41 +++++++++++ pages/t/[team].tsx | 19 +++-- prisma/queries/getTeam.ts | 5 +- 5 files changed, 176 insertions(+), 21 deletions(-) create mode 100644 pages/api/teams/[id].ts create mode 100644 pages/api/teams/kick.ts diff --git a/components/t/TeamManagementModal.tsx b/components/t/TeamManagementModal.tsx index c9d083813..c2a8382cb 100644 --- a/components/t/TeamManagementModal.tsx +++ b/components/t/TeamManagementModal.tsx @@ -1,18 +1,54 @@ import { + Box, Button, + Grid, Modal, ModalBody, ModalCloseButton, ModalContent, ModalHeader, ModalOverlay, + useToast, } from "@chakra-ui/react"; -import { Trans } from "@lingui/macro"; +import { t, Trans } from "@lingui/macro"; +import UserAvatar from "components/common/UserAvatar"; +import { getToastOptions } from "lib/getToastOptions"; +import { sendData } from "lib/postData"; +import { GetTeamData } from "prisma/queries/getTeam"; import { useState } from "react"; -import { FiUsers } from "react-icons/fi"; +import { FiTrash, FiUsers } from "react-icons/fi"; +import { mutate } from "swr"; -const TeamManagementModal = ({}) => { +interface Props { + roster: NonNullable["roster"]; + teamId: number; +} + +const TeamManagementModal: React.FC = ({ roster, teamId }) => { + const toast = useToast(); const [isOpen, setIsOpen] = useState(false); + const [sending, setSending] = useState(false); + + const onDelete = async () => { + console.log("bye"); + }; + + const kickTeamMember = async (id: number, name: string) => { + if (!window.confirm(`Kick ${name}?`)) return; + + setSending(true); + + const success = await sendData("POST", "/api/teams/kick", { id }); + setSending(false); + if (!success) return; + + mutate(`/api/teams/${teamId}`); + + toast(getToastOptions(t`User kicked`, "success")); + + setIsOpen(false); + }; + return ( <> + + {roster.map((user) => ( + <> + + + {user.username}#{user.discriminator} + + + + + ))} + diff --git a/pages/api/teams/[id].ts b/pages/api/teams/[id].ts new file mode 100644 index 000000000..9e0b98785 --- /dev/null +++ b/pages/api/teams/[id].ts @@ -0,0 +1,32 @@ +import { NextApiRequest, NextApiResponse } from "next"; +import { getTeam, GetTeamData } from "prisma/queries/getTeam"; + +const teamByIdHandler = async ( + req: NextApiRequest, + res: NextApiResponse +) => { + switch (req.method) { + case "GET": + await getHandler(req, res); + break; + default: + res.status(405).end(); + } +}; + +async function getHandler( + req: NextApiRequest, + res: NextApiResponse +) { + if (typeof req.query.id !== "string") return res.status(400).end(); + const id = parseInt(req.query.id); + + if (Number.isNaN(id)) return res.status(400).end(); + + const team = await getTeam({ id }); + if (!team) return res.status(400).end(); + + res.status(200).json(team); +} + +export default teamByIdHandler; diff --git a/pages/api/teams/kick.ts b/pages/api/teams/kick.ts new file mode 100644 index 000000000..440eda199 --- /dev/null +++ b/pages/api/teams/kick.ts @@ -0,0 +1,41 @@ +import { getMySession } from "lib/getMySession"; +import { NextApiRequest, NextApiResponse } from "next"; +import prisma from "prisma/client"; + +const kickHandler = async (req: NextApiRequest, res: NextApiResponse) => { + switch (req.method) { + case "POST": + await postHandler(req, res); + break; + default: + res.status(405).end(); + } +}; + +async function postHandler(req: NextApiRequest, res: NextApiResponse) { + const user = await getMySession(req); + if (!user) return res.status(401).end(); + + if (typeof req.body.id !== "number") return res.status(400).end(); + + const userToKick = await prisma.user.findUnique({ + where: { id: req.body.id }, + include: { team: true }, + }); + if ( + !userToKick || + !userToKick.team || + userToKick.team.captainId !== user.id + ) { + return res.status(400).end(); + } + + await prisma.user.update({ + where: { id: req.body.id }, + data: { team: { disconnect: true } }, + }); + + res.status(200).end(); +} + +export default kickHandler; diff --git a/pages/t/[team].tsx b/pages/t/[team].tsx index 2ccf99b64..a85675808 100644 --- a/pages/t/[team].tsx +++ b/pages/t/[team].tsx @@ -10,18 +10,22 @@ import { GetStaticPaths, GetStaticProps } from "next"; import { getTeam, GetTeamData } from "prisma/queries/getTeam"; import { useState } from "react"; import { FiTrash } from "react-icons/fi"; +import useSWR, { mutate } from "swr"; interface Props { team: GetTeamData; } const TeamPage: React.FC = (props) => { + const { data } = useSWR(`/api/teams/${props.team!.id}`, { + initialData: props.team!, + }); + const team = data!; + const [sending, setSending] = useState(false); const [user] = useUser(); const toast = useToast(); - const team = props.team!; - const leaveTeam = async () => { if (!window.confirm(t`Leave the team?`)) { return; @@ -33,7 +37,7 @@ const TeamPage: React.FC = (props) => { setSending(false); if (!success) return; - //mutate("/api/freeagents"); + mutate(`/api/teams/${props.team!.id}`); toast(getToastOptions(t`Left the team`, "success")); }; @@ -59,7 +63,12 @@ const TeamPage: React.FC = (props) => { .sort((a, b) => b[1] - a[1]) .map(([country]) => getEmojiFlag(country))} - {user?.id === team.captainId && } + {user?.id === team.captainId && ( + teamMember.id !== user.id)} + teamId={team.id} + /> + )} {user && user.id !== team.captainId && team.roster.some((teamMember) => user.id === teamMember.id) && ( @@ -85,7 +94,7 @@ export const getStaticPaths: GetStaticPaths = async () => { }; export const getStaticProps: GetStaticProps = async ({ params }) => { - const team = await getTeam(params!.team as string); + const team = await getTeam({ nameForUrl: params!.team as string }); if (!team) return { notFound: true }; diff --git a/prisma/queries/getTeam.ts b/prisma/queries/getTeam.ts index f32c2d0ad..5db099f33 100644 --- a/prisma/queries/getTeam.ts +++ b/prisma/queries/getTeam.ts @@ -3,10 +3,11 @@ import prisma from "prisma/client"; export type GetTeamData = Prisma.PromiseReturnType; -export const getTeam = async (nameForUrl: string) => +export const getTeam = async (where: { nameForUrl: string } | { id: number }) => prisma.team.findUnique({ - where: { nameForUrl }, + where, select: { + id: true, bio: true, recruitingPost: true, twitterName: true,