feat(editor): ✨ Team workspaces
This commit is contained in:
3
apps/builder/services/workspace/index.ts
Normal file
3
apps/builder/services/workspace/index.ts
Normal file
@ -0,0 +1,3 @@
|
||||
export * from './workspace'
|
||||
export * from './member'
|
||||
export * from './invitation'
|
28
apps/builder/services/workspace/invitation.ts
Normal file
28
apps/builder/services/workspace/invitation.ts
Normal file
@ -0,0 +1,28 @@
|
||||
import { WorkspaceInvitation } from 'db'
|
||||
import { sendRequest } from 'utils'
|
||||
import { Member } from './member'
|
||||
|
||||
export const sendInvitation = (
|
||||
invitation: Omit<WorkspaceInvitation, 'id' | 'createdAt'>
|
||||
) =>
|
||||
sendRequest<{ invitation?: WorkspaceInvitation; member?: Member }>({
|
||||
url: `/api/workspaces/${invitation.workspaceId}/invitations`,
|
||||
method: 'POST',
|
||||
body: invitation,
|
||||
})
|
||||
|
||||
export const updateInvitation = (invitation: Partial<WorkspaceInvitation>) =>
|
||||
sendRequest({
|
||||
url: `/api/workspaces/${invitation.workspaceId}/invitations/${invitation.id}`,
|
||||
method: 'PATCH',
|
||||
body: invitation,
|
||||
})
|
||||
|
||||
export const deleteInvitation = (invitation: {
|
||||
workspaceId: string
|
||||
id: string
|
||||
}) =>
|
||||
sendRequest({
|
||||
url: `/api/workspaces/${invitation.workspaceId}/invitations/${invitation.id}`,
|
||||
method: 'DELETE',
|
||||
})
|
41
apps/builder/services/workspace/member.ts
Normal file
41
apps/builder/services/workspace/member.ts
Normal file
@ -0,0 +1,41 @@
|
||||
import { MemberInWorkspace, WorkspaceInvitation } from 'db'
|
||||
import { fetcher } from 'services/utils'
|
||||
import useSWR from 'swr'
|
||||
import { sendRequest } from 'utils'
|
||||
|
||||
export type Member = MemberInWorkspace & {
|
||||
name: string | null
|
||||
image: string | null
|
||||
email: string | null
|
||||
}
|
||||
|
||||
export const useMembers = ({ workspaceId }: { workspaceId?: string }) => {
|
||||
const { data, error, mutate } = useSWR<
|
||||
{ members: Member[]; invitations: WorkspaceInvitation[] },
|
||||
Error
|
||||
>(workspaceId ? `/api/workspaces/${workspaceId}/members` : null, fetcher, {
|
||||
dedupingInterval: process.env.NEXT_PUBLIC_E2E_TEST ? 0 : undefined,
|
||||
})
|
||||
return {
|
||||
members: data?.members,
|
||||
invitations: data?.invitations,
|
||||
isLoading: !error && !data,
|
||||
mutate,
|
||||
}
|
||||
}
|
||||
|
||||
export const updateMember = (
|
||||
workspaceId: string,
|
||||
member: Partial<MemberInWorkspace>
|
||||
) =>
|
||||
sendRequest({
|
||||
method: 'PATCH',
|
||||
url: `/api/workspaces/${workspaceId}/members/${member.userId}`,
|
||||
body: member,
|
||||
})
|
||||
|
||||
export const deleteMember = (workspaceId: string, userId: string) =>
|
||||
sendRequest({
|
||||
method: 'DELETE',
|
||||
url: `/api/workspaces/${workspaceId}/members/${userId}`,
|
||||
})
|
58
apps/builder/services/workspace/workspace.ts
Normal file
58
apps/builder/services/workspace/workspace.ts
Normal file
@ -0,0 +1,58 @@
|
||||
import { WorkspaceWithMembers } from 'contexts/WorkspaceContext'
|
||||
import { Plan, Workspace } from 'db'
|
||||
import useSWR from 'swr'
|
||||
import { isNotDefined, sendRequest } from 'utils'
|
||||
import { fetcher } from '../utils'
|
||||
|
||||
export const useWorkspaces = ({ userId }: { userId?: string }) => {
|
||||
const { data, error, mutate } = useSWR<
|
||||
{
|
||||
workspaces: WorkspaceWithMembers[]
|
||||
},
|
||||
Error
|
||||
>(userId ? `/api/workspaces` : null, fetcher)
|
||||
return {
|
||||
workspaces: data?.workspaces,
|
||||
isLoading: !error && !data,
|
||||
mutate,
|
||||
}
|
||||
}
|
||||
|
||||
export const createNewWorkspace = async (
|
||||
body: Omit<Workspace, 'id' | 'icon' | 'createdAt' | 'stripeId'>
|
||||
) =>
|
||||
sendRequest<{
|
||||
workspace: Workspace
|
||||
}>({
|
||||
url: `/api/workspaces`,
|
||||
method: 'POST',
|
||||
body,
|
||||
})
|
||||
|
||||
export const updateWorkspace = async (updates: Partial<Workspace>) =>
|
||||
sendRequest<{
|
||||
workspace: Workspace
|
||||
}>({
|
||||
url: `/api/workspaces/${updates.id}`,
|
||||
method: 'PATCH',
|
||||
body: updates,
|
||||
})
|
||||
|
||||
export const planToReadable = (plan?: Plan) => {
|
||||
if (!plan) return
|
||||
switch (plan) {
|
||||
case Plan.FREE:
|
||||
return 'Free'
|
||||
case Plan.LIFETIME:
|
||||
return 'Lifetime'
|
||||
case Plan.OFFERED:
|
||||
return 'Offered'
|
||||
case Plan.PRO:
|
||||
return 'Pro'
|
||||
case Plan.TEAM:
|
||||
return 'Team'
|
||||
}
|
||||
}
|
||||
|
||||
export const isFreePlan = (workspace?: Pick<Workspace, 'plan'>) =>
|
||||
isNotDefined(workspace) || workspace?.plan === Plan.FREE
|
Reference in New Issue
Block a user