Skip to content

Commit 81e6b61

Browse files
committed
get invite link in server
1 parent 96c5fc2 commit 81e6b61

File tree

5 files changed

+42
-9
lines changed

5 files changed

+42
-9
lines changed

packages/web/src/app/[domain]/settings/members/page.tsx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ import { getSeats, SOURCEBOT_UNLIMITED_SEATS } from "@sourcebot/shared";
1313
import { RequestsList } from "./components/requestsList";
1414
import { OrgRole } from "@prisma/client";
1515
import { MemberApprovalRequiredToggle } from "@/app/onboard/components/memberApprovalRequiredToggle";
16+
import { headers } from "next/headers";
17+
import { getBaseUrl, createInviteLink } from "@/lib/utils";
1618

1719
interface MembersSettingsPageProps {
1820
params: {
@@ -60,6 +62,11 @@ export default async function MembersSettingsPage({ params: { domain }, searchPa
6062
const usedSeats = members.length
6163
const seatsAvailable = seats === SOURCEBOT_UNLIMITED_SEATS || usedSeats < seats;
6264

65+
// Get the current URL to construct the full invite link
66+
const headersList = headers();
67+
const baseUrl = getBaseUrl(headersList);
68+
const inviteLink = createInviteLink(baseUrl, org.inviteLinkId);
69+
6370
return (
6471
<div className="flex flex-col gap-6">
6572
<div className="flex items-start justify-between">
@@ -80,7 +87,7 @@ export default async function MembersSettingsPage({ params: { domain }, searchPa
8087
</div>
8188

8289
{userRoleInOrg === OrgRole.OWNER && (
83-
<MemberApprovalRequiredToggle memberApprovalRequired={org.memberApprovalRequired} inviteLinkEnabled={org.inviteLinkEnabled} inviteLinkId={org.inviteLinkId} />
90+
<MemberApprovalRequiredToggle memberApprovalRequired={org.memberApprovalRequired} inviteLinkEnabled={org.inviteLinkEnabled} inviteLink={inviteLink} />
8491
)}
8592

8693
<InviteMemberCard

packages/web/src/app/components/inviteLinkToggle.tsx

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,15 @@ import { isServiceError } from "@/lib/utils"
1212

1313
interface InviteLinkToggleProps {
1414
inviteLinkEnabled: boolean
15-
inviteLinkId?: string
15+
inviteLink: string | null
1616
}
1717

18-
export function InviteLinkToggle({ inviteLinkEnabled, inviteLinkId }: InviteLinkToggleProps) {
18+
export function InviteLinkToggle({ inviteLinkEnabled, inviteLink }: InviteLinkToggleProps) {
1919
const [enabled, setEnabled] = useState(inviteLinkEnabled)
2020
const [isLoading, setIsLoading] = useState(false)
2121
const [copied, setCopied] = useState(false)
2222
const { toast } = useToast()
2323

24-
const inviteLink = inviteLinkId ? `${window.location.origin}/invite?id=${inviteLinkId}` : null
25-
2624

2725
const handleToggle = async (checked: boolean) => {
2826
setIsLoading(true)

packages/web/src/app/onboard/components/memberApprovalRequiredToggle.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,10 @@ import { InviteLinkToggle } from "@/app/components/inviteLinkToggle"
1111
interface MemberApprovalRequiredToggleProps {
1212
memberApprovalRequired: boolean
1313
inviteLinkEnabled: boolean
14-
inviteLinkId?: string
14+
inviteLink: string | null
1515
}
1616

17-
export function MemberApprovalRequiredToggle({ memberApprovalRequired, inviteLinkEnabled, inviteLinkId }: MemberApprovalRequiredToggleProps) {
17+
export function MemberApprovalRequiredToggle({ memberApprovalRequired, inviteLinkEnabled, inviteLink }: MemberApprovalRequiredToggleProps) {
1818
const [enabled, setEnabled] = useState(memberApprovalRequired)
1919
const [isLoading, setIsLoading] = useState(false)
2020
const { toast } = useToast()
@@ -83,7 +83,7 @@ export function MemberApprovalRequiredToggle({ memberApprovalRequired, inviteLin
8383
? 'max-h-96 opacity-100'
8484
: 'max-h-0 opacity-0 pointer-events-none'
8585
}`}>
86-
<InviteLinkToggle inviteLinkEnabled={inviteLinkEnabled} inviteLinkId={inviteLinkId} />
86+
<InviteLinkToggle inviteLinkEnabled={inviteLinkEnabled} inviteLink={inviteLink} />
8787
</div>
8888
</div>
8989
)

packages/web/src/app/onboard/page.tsx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ import { BetweenHorizonalStart, GitBranchIcon, LockIcon } from "lucide-react";
1818
import { hasEntitlement } from "@sourcebot/shared";
1919
import { env } from "@/env.mjs";
2020
import { GcpIapAuth } from "@/app/[domain]/components/gcpIapAuth";
21+
import { headers } from "next/headers";
22+
import { getBaseUrl, createInviteLink } from "@/lib/utils";
2123

2224
interface OnboardingProps {
2325
searchParams?: { step?: string };
@@ -47,6 +49,11 @@ export default async function Onboarding({ searchParams }: OnboardingProps) {
4749
return <div>Error loading organization</div>;
4850
}
4951

52+
// Get the current URL to construct the full invite link
53+
const headersList = headers();
54+
const baseUrl = getBaseUrl(headersList);
55+
const inviteLink = createInviteLink(baseUrl, org.inviteLinkId);
56+
5057
if (org && org.isOnboarded) {
5158
redirect('/');
5259
}
@@ -149,7 +156,7 @@ export default async function Onboarding({ searchParams }: OnboardingProps) {
149156
subtitle: "Set up your organization's security settings.",
150157
component: (
151158
<div className="space-y-6">
152-
<MemberApprovalRequiredToggle memberApprovalRequired={org.memberApprovalRequired} inviteLinkEnabled={org.inviteLinkEnabled} inviteLinkId={org.inviteLinkId} />
159+
<MemberApprovalRequiredToggle memberApprovalRequired={org.memberApprovalRequired} inviteLinkEnabled={org.inviteLinkEnabled} inviteLink={inviteLink} />
153160
<Button asChild className="w-full h-11 bg-primary hover:bg-primary/90 text-primary-foreground transition-all duration-200 font-medium">
154161
<a href="/onboard?step=3">Continue →</a>
155162
</Button>

packages/web/src/lib/utils.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,27 @@ export function cn(...inputs: ClassValue[]) {
1919
return twMerge(clsx(inputs))
2020
}
2121

22+
/**
23+
* Gets the base URL from Next.js headers
24+
* @param headersList The headers from Next.js headers() function
25+
* @returns The base URL (e.g., "https://example.com")
26+
*/
27+
export const getBaseUrl = (headersList: Headers): string => {
28+
const host = headersList.get('host') || 'localhost:3000';
29+
const protocol = headersList.get('x-forwarded-proto') || 'http';
30+
return `${protocol}://${host}`;
31+
}
32+
33+
/**
34+
* Creates an invite link URL from the base URL and invite ID
35+
* @param baseUrl The base URL of the application
36+
* @param inviteLinkId The invite link ID
37+
* @returns The complete invite link URL or null if no inviteLinkId
38+
*/
39+
export const createInviteLink = (baseUrl: string, inviteLinkId?: string | null): string | null => {
40+
return inviteLinkId ? `${baseUrl}/invite?id=${inviteLinkId}` : null;
41+
}
42+
2243
/**
2344
* Adds a list of (potentially undefined) query parameters to a path.
2445
*

0 commit comments

Comments
 (0)