diff --git a/components/t/CreateNewTeamModal.tsx b/components/t/CreateNewTeamModal.tsx index db388c6c7..3683c204e 100644 --- a/components/t/CreateNewTeamModal.tsx +++ b/components/t/CreateNewTeamModal.tsx @@ -11,14 +11,15 @@ import { ModalFooter, ModalHeader, ModalOverlay, - useToast, } from "@chakra-ui/react"; import { t, Trans } from "@lingui/macro"; +import { makeNameUrlFriendly } from "lib/makeNameUrlFriendly"; import { sendData } from "lib/postData"; +import { useRouter } from "next/router"; import { useState } from "react"; const CreateNewTeamModal = () => { - const toast = useToast(); + const router = useRouter(); const [isOpen, setIsOpen] = useState(false); const [sending, setSending] = useState(false); @@ -37,10 +38,10 @@ const CreateNewTeamModal = () => { setSending(true); const success = await sendData("POST", "/api/teams", { name }); - setSending(false); - if (!success) return; - setIsOpen(false); + if (!success) return setSending(false); + + router.push(`/t/${makeNameUrlFriendly(name)}`); }; return ( diff --git a/components/t/TeamManagementModal.tsx b/components/t/TeamManagementModal.tsx index c2a8382cb..0529db52d 100644 --- a/components/t/TeamManagementModal.tsx +++ b/components/t/TeamManagementModal.tsx @@ -14,6 +14,7 @@ import { t, Trans } from "@lingui/macro"; import UserAvatar from "components/common/UserAvatar"; import { getToastOptions } from "lib/getToastOptions"; import { sendData } from "lib/postData"; +import { useRouter } from "next/router"; import { GetTeamData } from "prisma/queries/getTeam"; import { useState } from "react"; import { FiTrash, FiUsers } from "react-icons/fi"; @@ -25,12 +26,23 @@ interface Props { } const TeamManagementModal: React.FC = ({ roster, teamId }) => { + const router = useRouter(); const toast = useToast(); const [isOpen, setIsOpen] = useState(false); const [sending, setSending] = useState(false); - const onDelete = async () => { - console.log("bye"); + const deleteTeam = async () => { + if (!window.confirm(t`Delete the team? DELETING IS PERMANENT.`)) return; + + setSending(true); + + const success = await sendData("DELETE", "/api/teams"); + setSending(false); + if (!success) return; + + toast(getToastOptions(t`Team deleted`, "success")); + + router.push("/t"); }; const kickTeamMember = async (id: number, name: string) => { @@ -49,6 +61,27 @@ const TeamManagementModal: React.FC = ({ roster, teamId }) => { setIsOpen(false); }; + const makeOwner = async (id: number, name: string) => { + if ( + !window.confirm( + `Transfer the ownership to ${name}? YOU WILL LOSE ACCESS TO FEATURES RELATING TO MANAGING THE TEAM.` + ) + ) + return; + + setSending(true); + + const success = await sendData("POST", "/api/teams/owner", { id }); + setSending(false); + if (!success) return; + + mutate(`/api/teams/${teamId}`); + + toast(getToastOptions(t`Switched owners`, "success")); + + setIsOpen(false); + }; + return ( <> @@ -104,6 +135,12 @@ const TeamManagementModal: React.FC = ({ roster, teamId }) => { colorScheme="red" variant="outline" isDisabled={sending} + onClick={() => + makeOwner( + user.id, + `${user.username}#${user.discriminator}` + ) + } > Make owner diff --git a/lib/makeNameUrlFriendly.ts b/lib/makeNameUrlFriendly.ts new file mode 100644 index 000000000..e5c6d1753 --- /dev/null +++ b/lib/makeNameUrlFriendly.ts @@ -0,0 +1,3 @@ +export function makeNameUrlFriendly(name: string) { + return name.trim().replace(/\s\s+/g, " ").toLowerCase().replace(/ /g, "-"); +} diff --git a/pages/api/teams/index.ts b/pages/api/teams/index.ts index e581bfcf6..5ad6bfc54 100644 --- a/pages/api/teams/index.ts +++ b/pages/api/teams/index.ts @@ -1,4 +1,5 @@ import { getMySession } from "lib/getMySession"; +import { makeNameUrlFriendly } from "lib/makeNameUrlFriendly"; import { NextApiRequest, NextApiResponse } from "next"; import prisma from "prisma/client"; import { v4 as uuidv4 } from "uuid"; @@ -8,6 +9,9 @@ const teamsHandler = async (req: NextApiRequest, res: NextApiResponse) => { case "POST": await postHandler(req, res); break; + case "DELETE": + await deleteHandler(req, res); + break; default: res.status(405).end(); } @@ -41,7 +45,7 @@ async function postHandler(req: NextApiRequest, res: NextApiResponse) { return res.status(400).end(); } - const nameForUrl = normalizedTeamName.toLowerCase().replace(/ /g, "-"); + const nameForUrl = makeNameUrlFriendly(teamName); const existingTeam = await prisma.team.findUnique({ where: { nameForUrl } }); if (existingTeam) { @@ -61,4 +65,16 @@ async function postHandler(req: NextApiRequest, res: NextApiResponse) { res.status(200).end(); } +async function deleteHandler(req: NextApiRequest, res: NextApiResponse) { + const user = await getMySession(req); + if (!user) return res.status(401).end(); + + const team = await prisma.team.findUnique({ where: { captainId: user.id } }); + if (!team) return res.status(400).end(); + + await prisma.team.delete({ where: { id: team.id } }); + + res.status(200).end(); +} + export default teamsHandler; diff --git a/pages/api/teams/owner.ts b/pages/api/teams/owner.ts new file mode 100644 index 000000000..2eef0178b --- /dev/null +++ b/pages/api/teams/owner.ts @@ -0,0 +1,41 @@ +import { getMySession } from "lib/getMySession"; +import { NextApiRequest, NextApiResponse } from "next"; +import prisma from "prisma/client"; + +const ownerHandler = 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 userToMakeOwner = await prisma.user.findUnique({ + where: { id: req.body.id }, + include: { team: true }, + }); + if ( + !userToMakeOwner || + !userToMakeOwner.team || + userToMakeOwner.team.captainId !== user.id + ) { + return res.status(400).end(); + } + + await prisma.team.update({ + where: { id: userToMakeOwner.team.id }, + data: { captain: { connect: { id: req.body.id } } }, + }); + + res.status(200).end(); +} + +export default ownerHandler;