From c32160e0303fcce70a1f55bf7eafbe6247964b29 Mon Sep 17 00:00:00 2001 From: 0xFirekeeper <0xFirekeeper@gmail.com> Date: Tue, 22 Sep 2026 19:36:02 +0700 Subject: [PATCH 1/2] [Dashboard] Accept team invites for existing members Co-Authored-By: Claude Fable 5.1 --- apps/dashboard/src/@/api/team/team-invites.ts | 27 +++++++++++++++++++ .../team/[team_slug]/[invite_id]/page.tsx | 8 ++++-- 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/apps/dashboard/src/@/api/team/team-invites.ts b/apps/dashboard/src/@/api/team/team-invites.ts index cecb6fbbde5..a3b494221bd 100644 --- a/apps/dashboard/src/@/api/team/team-invites.ts +++ b/apps/dashboard/src/@/api/team/team-invites.ts @@ -44,3 +44,30 @@ export async function getTeamInvites( return json.result; } + +export async function getTeamInvite(teamId: string, inviteId: string) { + const authToken = await getAuthToken(); + + if (!authToken) { + return undefined; + } + + const res = await fetch( + `${NEXT_PUBLIC_THIRDWEB_API_HOST}/v1/teams/${teamId}/invites/${inviteId}`, + { + headers: { + Authorization: `Bearer ${authToken}`, + }, + }, + ); + + if (!res.ok) { + return undefined; + } + + const json = (await res.json()) as { + result: TeamInvite; + }; + + return json.result; +} diff --git a/apps/dashboard/src/app/(app)/join/team/[team_slug]/[invite_id]/page.tsx b/apps/dashboard/src/app/(app)/join/team/[team_slug]/[invite_id]/page.tsx index 40396784d1c..1db070b29eb 100644 --- a/apps/dashboard/src/app/(app)/join/team/[team_slug]/[invite_id]/page.tsx +++ b/apps/dashboard/src/app/(app)/join/team/[team_slug]/[invite_id]/page.tsx @@ -1,6 +1,7 @@ import { notFound, redirect } from "next/navigation"; import { getValidAccount } from "@/api/account/get-account"; import { getTeamBySlug, service_getTeamBySlug } from "@/api/team/get-team"; +import { getTeamInvite } from "@/api/team/team-invites"; import { JoinTeamPage } from "./JoinTeamPage"; export default async function Page(props: { @@ -16,9 +17,12 @@ export default async function Page(props: { service_getTeamBySlug(team_slug), ]); - // if the user is already a member of the team, redirect to the team + // a member can still hold a pending invite, e.g. for a different role if (userTeam) { - redirect(`/team/${team_slug}`); + const invite = await getTeamInvite(userTeam.id, invite_id); + if (invite?.status !== "pending") { + redirect(`/team/${team_slug}`); + } } if (!inviteTeam) { From cde5aee36fec2608b582e65df83d158bd4d22a0d Mon Sep 17 00:00:00 2001 From: 0xFirekeeper <0xFirekeeper@gmail.com> Date: Tue, 22 Sep 2026 19:43:56 +0700 Subject: [PATCH 2/2] [Dashboard] Accept team invites for existing members Co-Authored-By: Claude Fable 5.1 --- apps/dashboard/src/@/api/team/team-invites.ts | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/apps/dashboard/src/@/api/team/team-invites.ts b/apps/dashboard/src/@/api/team/team-invites.ts index a3b494221bd..1727839e70b 100644 --- a/apps/dashboard/src/@/api/team/team-invites.ts +++ b/apps/dashboard/src/@/api/team/team-invites.ts @@ -45,11 +45,14 @@ export async function getTeamInvites( return json.result; } -export async function getTeamInvite(teamId: string, inviteId: string) { +export async function getTeamInvite( + teamId: string, + inviteId: string, +): Promise { const authToken = await getAuthToken(); if (!authToken) { - return undefined; + throw new Error("Unauthorized"); } const res = await fetch( @@ -61,10 +64,15 @@ export async function getTeamInvite(teamId: string, inviteId: string) { }, ); - if (!res.ok) { + if (res.status === 404) { return undefined; } + if (!res.ok) { + const errorMessage = await res.text(); + throw new Error(errorMessage); + } + const json = (await res.json()) as { result: TeamInvite; };