From 5cb6863c14a8b05a7ec71c0535392d3332ca24dd Mon Sep 17 00:00:00 2001 From: devleejb Date: Tue, 23 Jan 2024 14:53:15 +0900 Subject: [PATCH] Add join workspace --- backend/src/workspaces/workspaces.service.ts | 4 +-- frontend/src/hooks/api/types/workspace.d.ts | 6 +++++ frontend/src/hooks/api/workspace.ts | 12 +++++++++ frontend/src/pages/workspace/join/Index.tsx | 26 ++++++++++++++++++++ frontend/src/routes.tsx | 6 +++++ 5 files changed, 52 insertions(+), 2 deletions(-) create mode 100644 frontend/src/pages/workspace/join/Index.tsx diff --git a/backend/src/workspaces/workspaces.service.ts b/backend/src/workspaces/workspaces.service.ts index a4ee8c5c..ff379b7a 100644 --- a/backend/src/workspaces/workspaces.service.ts +++ b/backend/src/workspaces/workspaces.service.ts @@ -6,7 +6,7 @@ import { CreateInvitationTokenResponse } from "./types/create-inviation-token-re import { WorkspaceRoleConstants } from "src/utils/constants/auth-role"; import slugify from "slugify"; import { generateRandomKey } from "src/utils/functions/random-string"; -import moment from "moment"; +import * as moment from "moment"; @Injectable() export class WorkspacesService { @@ -174,7 +174,7 @@ export class WorkspacesService { }, }); - if (!userWorkspace) { + if (userWorkspace) { return userWorkspace.workspace; } diff --git a/frontend/src/hooks/api/types/workspace.d.ts b/frontend/src/hooks/api/types/workspace.d.ts index b5d5d563..4762d457 100644 --- a/frontend/src/hooks/api/types/workspace.d.ts +++ b/frontend/src/hooks/api/types/workspace.d.ts @@ -26,3 +26,9 @@ export class CreateWorkspaceInviteTokenRequest { export class CreateWorkspaceInviteTokenResponse { invitationToken: string; } + +export class JoinWorkspaceRequest { + invitationToken: string; +} + +export class JoinWorkspaceResponse extends Workspace {} diff --git a/frontend/src/hooks/api/workspace.ts b/frontend/src/hooks/api/workspace.ts index b2dbd29c..1279f534 100644 --- a/frontend/src/hooks/api/workspace.ts +++ b/frontend/src/hooks/api/workspace.ts @@ -7,6 +7,8 @@ import { CreateWorkspaceResponse, GetWorkspaceListResponse, GetWorkspaceResponse, + JoinWorkspaceRequest, + JoinWorkspaceResponse, } from "./types/workspace"; export const generateGetWorkspaceQueryKey = (workspaceSlug: string) => { @@ -74,3 +76,13 @@ export const useCreateWorkspaceInvitationTokenMutation = (workspaceId: string) = }, }); }; + +export const useJoinWorkspaceMutation = () => { + return useMutation({ + mutationFn: async (data: JoinWorkspaceRequest) => { + const res = await axios.post("/workspaces/join", data); + + return res.data; + }, + }); +}; diff --git a/frontend/src/pages/workspace/join/Index.tsx b/frontend/src/pages/workspace/join/Index.tsx new file mode 100644 index 00000000..bc43af69 --- /dev/null +++ b/frontend/src/pages/workspace/join/Index.tsx @@ -0,0 +1,26 @@ +import { Backdrop, CircularProgress } from "@mui/material"; +import { useNavigate, useParams } from "react-router"; +import { useJoinWorkspaceMutation } from "../../../hooks/api/workspace"; +import { useEffect } from "react"; + +function JoinIndex() { + const params = useParams(); + const navigate = useNavigate(); + const { mutateAsync: joinWorkspace } = useJoinWorkspaceMutation(); + + useEffect(() => { + if (!params.invitationToken) return; + + joinWorkspace({ invitationToken: params.invitationToken }).then((data) => { + navigate(`/workspace/${data.slug}`); + }); + }, [joinWorkspace, navigate, params.invitationToken]); + + return ( + + + + ); +} + +export default JoinIndex; diff --git a/frontend/src/routes.tsx b/frontend/src/routes.tsx index 9d7ce6ac..de28305a 100644 --- a/frontend/src/routes.tsx +++ b/frontend/src/routes.tsx @@ -8,6 +8,7 @@ import GuestRoute from "./components/common/GuestRoute"; import PrivateRoute from "./components/common/PrivateRoute"; import WorkspaceIndex from "./pages/workspace/Index"; import CodePairError from "./components/common/CodePairError"; +import JoinIndex from "./pages/workspace/join/Index"; interface CodePairRoute { path: string; @@ -65,6 +66,11 @@ const codePairRoutes: Array = [ accessType: AccessType.GUEST, element: , }, + { + path: "join/:invitationToken", + accessType: AccessType.PRIVATE, + element: , + }, ]; const injectProtectedRoute = (routes: typeof codePairRoutes) => {