Skip to content

Commit 2810957

Browse files
committed
[TOOL-4292] Dashboard: Show Team selector page for '~' team slug
1 parent c803893 commit 2810957

File tree

2 files changed

+122
-13
lines changed

2 files changed

+122
-13
lines changed
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
import { type Team, getTeams } from "@/api/team";
2+
import { GradientAvatar } from "@/components/blocks/Avatars/GradientAvatar";
3+
import { AppFooter } from "@/components/blocks/app-footer";
4+
import { DotsBackgroundPattern } from "@/components/ui/background-patterns";
5+
import { getThirdwebClient } from "@/constants/thirdweb.server";
6+
import { ChevronRightIcon, UsersIcon } from "lucide-react";
7+
import Link from "next/link";
8+
import { notFound, redirect } from "next/navigation";
9+
import { getAuthToken } from "../../../api/lib/getAuthToken";
10+
import { TeamPlanBadge } from "../../../components/TeamPlanBadge";
11+
import { TeamHeader } from "../../components/TeamHeader/team-header";
12+
13+
export default async function Page(props: {
14+
params: Promise<{
15+
paths?: string[];
16+
}>;
17+
searchParams: Promise<Record<string, string | undefined | string[]>>;
18+
}) {
19+
const params = await props.params;
20+
const searchParams = await props.searchParams;
21+
22+
const teams = await getTeams();
23+
const authToken = await getAuthToken();
24+
25+
if (!teams || !authToken) {
26+
notFound();
27+
}
28+
29+
const searchParamsString = Object.entries(searchParams)
30+
.map(([key, value]) => {
31+
if (Array.isArray(value)) {
32+
return value.map((v) => `${key}=${v}`).join("&");
33+
}
34+
return `${key}=${value}`;
35+
})
36+
.join("&");
37+
38+
// if there is a single team, redirect to the team page directly
39+
if (teams.length === 1 && teams[0]) {
40+
redirect(
41+
createTeamLink({
42+
team: teams[0],
43+
paths: params.paths,
44+
searchParams: searchParamsString,
45+
}),
46+
);
47+
}
48+
49+
const client = getThirdwebClient({
50+
jwt: authToken,
51+
teamId: undefined,
52+
});
53+
54+
return (
55+
<div className="relative flex min-h-dvh flex-col ">
56+
<div className="border-b bg-card">
57+
<TeamHeader />
58+
</div>
59+
60+
<div className="relative flex grow flex-col overflow-hidden">
61+
<DotsBackgroundPattern />
62+
<div className="container z-10 flex grow flex-col items-center justify-center py-20">
63+
<div className="w-full max-w-lg rounded-xl border bg-card shadow-2xl">
64+
<div className="flex flex-col border-b p-4 lg:p-6">
65+
<div className="mb-2 self-start rounded-full border p-2">
66+
<UsersIcon className="size-5 text-muted-foreground" />
67+
</div>
68+
<h1 className="mb-0.5 font-semibold text-xl tracking-tight">
69+
Select a team
70+
</h1>
71+
<p className="text-muted-foreground text-sm">
72+
You are currently a member of multiple teams
73+
<br />
74+
Select a team to view this page
75+
</p>
76+
</div>
77+
78+
<div className="flex flex-col [&>*:not(:last-child)]:border-b">
79+
{teams.map((team) => {
80+
return (
81+
<div
82+
key={team.id}
83+
className="group relative flex items-center gap-3 px-4 py-4 hover:bg-accent/50 lg:px-6"
84+
>
85+
<GradientAvatar
86+
src={team.image || ""}
87+
id={team.id}
88+
className="size-8 rounded-full border"
89+
client={client}
90+
/>
91+
<Link
92+
href={createTeamLink({
93+
team,
94+
paths: params.paths,
95+
searchParams: searchParamsString,
96+
})}
97+
className="before:absolute before:inset-0"
98+
>
99+
{team.name}
100+
</Link>
101+
<TeamPlanBadge plan={team.billingPlan} />
102+
<ChevronRightIcon className="ml-auto size-4 text-muted-foreground group-hover:text-foreground" />
103+
</div>
104+
);
105+
})}
106+
</div>
107+
</div>
108+
</div>
109+
</div>
110+
111+
<AppFooter className="relative z-10" />
112+
</div>
113+
);
114+
}
115+
116+
function createTeamLink(params: {
117+
team: Team;
118+
paths: string[] | undefined;
119+
searchParams: string | undefined;
120+
}) {
121+
return `/team/${params.team.slug}/${(params.paths || [])?.join("/") || ""}${params.searchParams ? `?${params.searchParams}` : ""}`;
122+
}

apps/dashboard/src/middleware.ts

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { getDefaultTeam } from "@/api/team";
21
import { isLoginRequired } from "@/constants/auth";
32
import { COOKIE_ACTIVE_ACCOUNT, COOKIE_PREFIX_TOKEN } from "@/constants/cookie";
43
import { type NextRequest, NextResponse } from "next/server";
@@ -188,18 +187,6 @@ export async function middleware(request: NextRequest) {
188187
}
189188
}
190189

191-
// redirect /team/~/... to /team/<first_team_slug>/...
192-
if (paths[0] === "team" && paths[1] === "~") {
193-
const firstTeam = await getDefaultTeam();
194-
if (firstTeam) {
195-
const modifiedPaths = [...paths];
196-
modifiedPaths[1] = firstTeam.slug;
197-
return redirect(request, `/${modifiedPaths.join("/")}`, {
198-
searchParams: request.nextUrl.searchParams.toString(),
199-
cookiesToSet,
200-
});
201-
}
202-
}
203190
// END /<address>/... case
204191
// all other cases are handled by the file system router so we just fall through
205192
if (cookiesToSet) {

0 commit comments

Comments
 (0)