From 138dc7084d9d30bc4a35e2ed94aed90e4c82dccc Mon Sep 17 00:00:00 2001 From: Andrej Date: Tue, 11 Feb 2025 20:57:02 +0100 Subject: [PATCH] feat: adding pending invited users screen --- .../get-pending-workspace-users.ts | 29 +++++ apps/api/src/workspace-user/index.ts | 9 +- .../team/invite-team-member-modal.tsx | 43 +------ .../get-pending-workspace-users.ts | 17 +++ .../use-get-pending-workspace-users.ts | 11 ++ apps/web/src/routeTree.gen.ts | 113 +++++++++++++++++- .../dashboard/workspace/$workspaceId/team.tsx | 104 ++++++++-------- .../$workspaceId/team/invitations.tsx | 107 +++++++++++++++++ .../workspace/$workspaceId/team/members.tsx | 27 +++++ .../workspace/$workspaceId/team/roles.tsx | 11 ++ biome.json | 3 +- 11 files changed, 377 insertions(+), 97 deletions(-) create mode 100644 apps/api/src/workspace-user/controllers/get-pending-workspace-users.ts create mode 100644 apps/web/src/fetchers/workspace-user/get-pending-workspace-users.ts create mode 100644 apps/web/src/hooks/queries/workspace-users/use-get-pending-workspace-users.ts create mode 100644 apps/web/src/routes/dashboard/workspace/$workspaceId/team/invitations.tsx create mode 100644 apps/web/src/routes/dashboard/workspace/$workspaceId/team/members.tsx create mode 100644 apps/web/src/routes/dashboard/workspace/$workspaceId/team/roles.tsx diff --git a/apps/api/src/workspace-user/controllers/get-pending-workspace-users.ts b/apps/api/src/workspace-user/controllers/get-pending-workspace-users.ts new file mode 100644 index 0000000..7ec4e04 --- /dev/null +++ b/apps/api/src/workspace-user/controllers/get-pending-workspace-users.ts @@ -0,0 +1,29 @@ +import { and, eq, isNull } from "drizzle-orm"; +import db from "../../database"; +import { userTable, workspaceUserTable } from "../../database/schema"; + +async function getPendingWorkspaceUsers({ + workspaceId, +}: { + workspaceId: string; +}) { + const pendingInvites = await db + .select({ + id: workspaceUserTable.id, + email: workspaceUserTable.userEmail, + role: workspaceUserTable.role, + invitedAt: workspaceUserTable.joinedAt, + }) + .from(workspaceUserTable) + .leftJoin(userTable, eq(workspaceUserTable.userEmail, userTable.email)) + .where( + and( + eq(workspaceUserTable.workspaceId, workspaceId), + isNull(userTable.email), + ), + ); + + return pendingInvites; +} + +export default getPendingWorkspaceUsers; diff --git a/apps/api/src/workspace-user/index.ts b/apps/api/src/workspace-user/index.ts index 5fedb6e..3fe7623 100644 --- a/apps/api/src/workspace-user/index.ts +++ b/apps/api/src/workspace-user/index.ts @@ -1,14 +1,21 @@ import Elysia, { t } from "elysia"; +import getPendingWorkspaceUsers from "./controllers/get-pending-workspace-users"; import getWorkspaceUsers from "./controllers/get-workspace-users"; import inviteWorkspaceUser from "./controllers/invite-workspace-user"; const workspaceUser = new Elysia({ prefix: "/workspace-user" }) .get("/list/:workspaceId", async ({ params: { workspaceId } }) => { const workspaceUsersInWorkspace = await getWorkspaceUsers({ workspaceId }); - console.log({ workspaceUsersInWorkspace }); return workspaceUsersInWorkspace; }) + .get("/pending/list/:workspaceId", async ({ params: { workspaceId } }) => { + const pendingWorkspaceUsersInWorkspace = await getPendingWorkspaceUsers({ + workspaceId, + }); + + return pendingWorkspaceUsersInWorkspace; + }) .post( "/:workspaceId/invite", async ({ body }) => { diff --git a/apps/web/src/components/team/invite-team-member-modal.tsx b/apps/web/src/components/team/invite-team-member-modal.tsx index f7f0479..a29d6ce 100644 --- a/apps/web/src/components/team/invite-team-member-modal.tsx +++ b/apps/web/src/components/team/invite-team-member-modal.tsx @@ -1,8 +1,8 @@ import useInviteWorkspaceUser from "@/hooks/mutations/workspace-user/use-invite-workspace-user"; -import useGetWorkspaces from "@/hooks/queries/workspace/use-get-workspaces"; +import { Route } from "@/routes/dashboard/workspace/$workspaceId/team"; import { zodResolver } from "@hookform/resolvers/zod"; import * as Dialog from "@radix-ui/react-dialog"; -import { Building2, X } from "lucide-react"; +import { X } from "lucide-react"; import { useForm } from "react-hook-form"; import { z } from "zod"; import { Button } from "../ui/button"; @@ -15,7 +15,6 @@ import { FormMessage, } from "../ui/form"; import { Input } from "../ui/input"; -import { Select } from "../ui/select"; type Props = { open: boolean; @@ -24,24 +23,22 @@ type Props = { const teamMemberSchema = z.object({ userEmail: z.string().email(), - workspaceId: z.string(), }); type TeamMemberFormValues = z.infer; function InviteTeamMemberModal({ open, onClose }: Props) { - const { data: workspaces } = useGetWorkspaces(); const { mutateAsync } = useInviteWorkspaceUser(); + const { workspaceId } = Route.useParams(); const form = useForm({ resolver: zodResolver(teamMemberSchema), defaultValues: { userEmail: "", - workspaceId: "", }, }); - const onSubmit = async ({ userEmail, workspaceId }: TeamMemberFormValues) => { + const onSubmit = async ({ userEmail }: TeamMemberFormValues) => { await mutateAsync({ userEmail, workspaceId }); form.reset(); @@ -87,38 +84,6 @@ function InviteTeamMemberModal({ open, onClose }: Props) { )} /> - - ( - - - Workspace - - -