From 8f097a40168f379ba4274aa65e0049d0f1866cbd Mon Sep 17 00:00:00 2001 From: Giancarlo Buomprisco Date: Fri, 5 Jul 2024 00:28:06 +0800 Subject: [PATCH] Add workspace context and custom hooks for user and team accounts (#41) * Add workspace context and custom hooks for user and team accounts The commit introduces a new workspace context for both user and team accounts. New custom hooks, useUserWorkspace and useAccountWorkspace, were created to access this context data. These changes allow for more streamlined data access and manipulation, enabling features that depend on account context information to function more efficiently. * Upgrade pnpm action-setup to version 4 The commit updates the version of pnpm action-setup used in GitHub workflows from v2 to v4. This upgrade can provide enhancements and improved features offered by the newer version. * Update pnpm/action-setup version in workflow The commit removes the explicit "version: 8" specifier in the Github Action workflow for "pnpm/action-setup". The updated workflow now points to "pnpm/action-setup@v4" instead of "pnpm/action-setup@v2", aligning it with usage elsewhere in the workflow. * Refactor magic link auth container for URL handling The magic link auth container has been updated to use a standard URL interface for managing URL and query parameters. This improves readability and error handling in the code.URL-related operations are now conducted via the URL object. --- .github/workflows/workflow.yml | 8 +--- apps/web/app/home/(user)/layout.tsx | 5 ++- apps/web/app/home/[account]/layout.tsx | 5 ++- packages/features/accounts/package.json | 1 + .../features/accounts/src/components/index.ts | 1 + .../src/components/user-workspace-context.tsx | 40 +++++++++++++++++++ .../accounts/src/hooks/use-user-workspace.ts | 17 ++++++++ .../components/magic-link-auth-container.tsx | 9 ++++- packages/features/team-accounts/package.json | 1 + .../team-accounts/src/components/index.ts | 1 + .../team-account-workspace-context.tsx | 27 +++++++++++++ .../src/hooks/use-team-account-workspace.ts | 22 ++++++++++ 12 files changed, 127 insertions(+), 10 deletions(-) create mode 100644 packages/features/accounts/src/components/index.ts create mode 100644 packages/features/accounts/src/components/user-workspace-context.tsx create mode 100644 packages/features/accounts/src/hooks/use-user-workspace.ts create mode 100644 packages/features/team-accounts/src/components/team-account-workspace-context.tsx create mode 100644 packages/features/team-accounts/src/hooks/use-team-account-workspace.ts diff --git a/.github/workflows/workflow.yml b/.github/workflows/workflow.yml index 0de266fa2..b7043778e 100644 --- a/.github/workflows/workflow.yml +++ b/.github/workflows/workflow.yml @@ -20,9 +20,7 @@ jobs: with: fetch-depth: 2 - - uses: pnpm/action-setup@v2 - with: - version: 8 + - uses: pnpm/action-setup@v4 - uses: actions/setup-node@v4 with: @@ -62,9 +60,7 @@ jobs: with: fetch-depth: 2 - - uses: pnpm/action-setup@v2 - with: - version: 8 + - uses: pnpm/action-setup@v4 - uses: actions/cache@v4 with: diff --git a/apps/web/app/home/(user)/layout.tsx b/apps/web/app/home/(user)/layout.tsx index 228ea90c2..0e6684940 100644 --- a/apps/web/app/home/(user)/layout.tsx +++ b/apps/web/app/home/(user)/layout.tsx @@ -2,6 +2,7 @@ import { use } from 'react'; import { cookies } from 'next/headers'; +import { UserWorkspaceContextProvider } from '@kit/accounts/components'; import { If } from '@kit/ui/if'; import { Page, @@ -41,7 +42,9 @@ function UserHomeLayout({ children }: React.PropsWithChildren) { - {children} + + {children} + ); } diff --git a/apps/web/app/home/[account]/layout.tsx b/apps/web/app/home/[account]/layout.tsx index 7be08f0ad..8bf2ee4a5 100644 --- a/apps/web/app/home/[account]/layout.tsx +++ b/apps/web/app/home/[account]/layout.tsx @@ -2,6 +2,7 @@ import { use } from 'react'; import { cookies } from 'next/headers'; +import { TeamAccountWorkspaceContextProvider } from '@kit/team-accounts/components'; import { If } from '@kit/ui/if'; import { Page, @@ -69,7 +70,9 @@ function TeamWorkspaceLayout({ - {children} + + {children} + ); } diff --git a/packages/features/accounts/package.json b/packages/features/accounts/package.json index a5ca9b7b5..a0276e631 100644 --- a/packages/features/accounts/package.json +++ b/packages/features/accounts/package.json @@ -12,6 +12,7 @@ "./personal-account-dropdown": "./src/components/personal-account-dropdown.tsx", "./account-selector": "./src/components/account-selector.tsx", "./personal-account-settings": "./src/components/personal-account-settings/index.ts", + "./components": "./src/components/index.ts", "./hooks/*": "./src/hooks/*.ts", "./api": "./src/server/api.ts" }, diff --git a/packages/features/accounts/src/components/index.ts b/packages/features/accounts/src/components/index.ts new file mode 100644 index 000000000..a5795bec0 --- /dev/null +++ b/packages/features/accounts/src/components/index.ts @@ -0,0 +1 @@ +export * from './user-workspace-context'; \ No newline at end of file diff --git a/packages/features/accounts/src/components/user-workspace-context.tsx b/packages/features/accounts/src/components/user-workspace-context.tsx new file mode 100644 index 000000000..aced8d41c --- /dev/null +++ b/packages/features/accounts/src/components/user-workspace-context.tsx @@ -0,0 +1,40 @@ +'use client'; + +import { createContext } from 'react'; + +import { User } from '@supabase/supabase-js'; + +import { Tables } from '@kit/supabase/database'; + +interface UserWorkspace { + accounts: Array<{ + label: string | null; + value: string | null; + image: string | null; + }>; + + workspace: { + id: string | null; + name: string | null; + picture_url: string | null; + subscription_status: Tables<'subscriptions'>['status'] | null; + }; + + user: User; +} + +export const UserWorkspaceContext = createContext( + {} as UserWorkspace, +); + +export function UserWorkspaceContextProvider( + props: React.PropsWithChildren<{ + value: UserWorkspace; + }>, +) { + return ( + + {props.children} + + ); +} diff --git a/packages/features/accounts/src/hooks/use-user-workspace.ts b/packages/features/accounts/src/hooks/use-user-workspace.ts new file mode 100644 index 000000000..d8793d4f1 --- /dev/null +++ b/packages/features/accounts/src/hooks/use-user-workspace.ts @@ -0,0 +1,17 @@ +'use client'; + +import { useContext } from 'react'; + +import { UserWorkspaceContext } from '../components'; + +export function useUserWorkspace() { + const ctx = useContext(UserWorkspaceContext); + + if (!ctx) { + throw new Error( + 'useUserWorkspace must be used within a UserWorkspaceProvider. This is only provided within the user workspace /home', + ); + } + + return ctx; +} diff --git a/packages/features/auth/src/components/magic-link-auth-container.tsx b/packages/features/auth/src/components/magic-link-auth-container.tsx index 3b5b1f8dc..bb48bc910 100644 --- a/packages/features/auth/src/components/magic-link-auth-container.tsx +++ b/packages/features/auth/src/components/magic-link-auth-container.tsx @@ -49,8 +49,13 @@ export function MagicLinkAuthContainer({ }); const onSubmit = ({ email }: { email: string }) => { - const queryParams = inviteToken ? `?invite_token=${inviteToken}` : ''; - const emailRedirectTo = [redirectUrl, queryParams].join(''); + const url = new URL(redirectUrl); + + if (inviteToken) { + url.searchParams.set('invite_token', inviteToken); + } + + const emailRedirectTo = url.href; const promise = () => signInWithOtpMutation.mutateAsync({ diff --git a/packages/features/team-accounts/package.json b/packages/features/team-accounts/package.json index 72582e3fd..e187dcf93 100644 --- a/packages/features/team-accounts/package.json +++ b/packages/features/team-accounts/package.json @@ -11,6 +11,7 @@ "exports": { "./api": "./src/server/api.ts", "./components": "./src/components/index.ts", + "./hooks/*": "./src/hooks/*.ts", "./webhooks": "./src/server/services/webhooks/index.ts" }, "dependencies": { diff --git a/packages/features/team-accounts/src/components/index.ts b/packages/features/team-accounts/src/components/index.ts index 3ed2dd258..afa8a53b9 100644 --- a/packages/features/team-accounts/src/components/index.ts +++ b/packages/features/team-accounts/src/components/index.ts @@ -5,3 +5,4 @@ export * from './invitations/account-invitations-table'; export * from './settings/team-account-settings-container'; export * from './invitations/accept-invitation-container'; export * from './create-team-account-dialog'; +export * from './team-account-workspace-context'; \ No newline at end of file diff --git a/packages/features/team-accounts/src/components/team-account-workspace-context.tsx b/packages/features/team-accounts/src/components/team-account-workspace-context.tsx new file mode 100644 index 000000000..c3fa685d9 --- /dev/null +++ b/packages/features/team-accounts/src/components/team-account-workspace-context.tsx @@ -0,0 +1,27 @@ +'use client'; + +import { createContext } from 'react'; + +import { User } from '@supabase/supabase-js'; + +import { Database } from '@kit/supabase/database'; + +interface AccountWorkspace { + accounts: Database['public']['Views']['user_accounts']['Row'][]; + account: Database['public']['Functions']['team_account_workspace']['Returns'][0]; + user: User; +} + +export const TeamAccountWorkspaceContext = createContext( + {} as AccountWorkspace, +); + +export function TeamAccountWorkspaceContextProvider( + props: React.PropsWithChildren<{ value: AccountWorkspace }>, +) { + return ( + + {props.children} + + ); +} diff --git a/packages/features/team-accounts/src/hooks/use-team-account-workspace.ts b/packages/features/team-accounts/src/hooks/use-team-account-workspace.ts new file mode 100644 index 000000000..ec29b899a --- /dev/null +++ b/packages/features/team-accounts/src/hooks/use-team-account-workspace.ts @@ -0,0 +1,22 @@ +'use client'; + +import { useContext } from 'react'; + +import { TeamAccountWorkspaceContext } from '../components'; + +/** + * @name useAccountWorkspace + * @description A hook to access the account workspace data. + * @returns The account workspace data. + */ +export function useAccountWorkspace() { + const ctx = useContext(TeamAccountWorkspaceContext); + + if (!ctx) { + throw new Error( + 'useAccountWorkspace must be used within a TeamAccountWorkspaceContext.Provider. This is only provided within the account workspace /home/[account]', + ); + } + + return ctx; +}