Skip to content

Commit af9d3aa

Browse files
authored
Merge pull request #814 from trycompai/patch/stuck-in-onboarding
fix: fix issue with redirect to onboarding
2 parents 1dfdd48 + f9d3e4d commit af9d3aa

3 files changed

Lines changed: 55 additions & 64 deletions

File tree

apps/app/src/app/(app)/(dashboard)/[orgId]/layout.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ export default async function Layout({
5757
{onboarding?.triggerJobId && (
5858
<OnboardingTracker
5959
onboarding={onboarding}
60-
publicAccessToken={publicAccessToken!}
60+
publicAccessToken={publicAccessToken ?? ""}
6161
/>
6262
)}
6363
<Header />

apps/app/src/components/organization-switcher.tsx

Lines changed: 11 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -156,12 +156,14 @@ export function OrganizationSwitcher({
156156
const [showCreateOrg, setShowCreateOrg] = useState(false);
157157
const [pendingOrgId, setPendingOrgId] = useState<string | null>(null);
158158

159-
const [showOrganizationSwitcher, setShowOrganizationSwitcher] =
160-
useQueryState("showOrganizationSwitcher", {
159+
const [showOrganizationSwitcher, setShowOrganizationSwitcher] = useQueryState(
160+
"showOrganizationSwitcher",
161+
{
161162
history: "push",
162163
parse: (value) => value === "true",
163164
serialize: (value) => value.toString(),
164-
});
165+
},
166+
);
165167

166168
const { execute, status } = useAction(changeOrganizationAction, {
167169
onSuccess: (result) => {
@@ -218,14 +220,13 @@ export function OrganizationSwitcher({
218220
<DialogTrigger asChild>
219221
<Button
220222
variant="outline"
223+
// biome-ignore lint/a11y/useSemanticElements: <explanation>
221224
role="combobox"
222225
aria-label={"Select Organization"}
223226
className={cn(
224227
"flex justify-between mx-auto rounded-md",
225228
isCollapsed ? "h-min w-min p-0" : "h-10 w-full p-0",
226-
status === "executing"
227-
? "opacity-50 cursor-not-allowed"
228-
: "",
229+
status === "executing" ? "opacity-50 cursor-not-allowed" : "",
229230
)}
230231
disabled={status === "executing"}
231232
>
@@ -245,9 +246,7 @@ export function OrganizationSwitcher({
245246
</Button>
246247
</DialogTrigger>
247248
<DialogContent className="p-0 sm:max-w-[400px]">
248-
<DialogTitle className="sr-only">
249-
{"Select Organization"}
250-
</DialogTitle>
249+
<DialogTitle className="sr-only">{"Select Organization"}</DialogTitle>
251250
<Command>
252251
<div className="flex items-center border-b px-3">
253252
<Search className="mr-2 h-4 w-4 shrink-0 opacity-50" />
@@ -257,9 +256,7 @@ export function OrganizationSwitcher({
257256
/>
258257
</div>
259258
<CommandList>
260-
<CommandEmpty>
261-
{"No results found"}
262-
</CommandEmpty>
259+
<CommandEmpty>{"No results found"}</CommandEmpty>
263260
<CommandGroup className="max-h-[300px] overflow-y-auto">
264261
{organizations.map((org) => (
265262
<CommandItem
@@ -274,8 +271,7 @@ export function OrganizationSwitcher({
274271
}}
275272
disabled={status === "executing"}
276273
>
277-
{status === "executing" &&
278-
pendingOrgId === org.id ? (
274+
{status === "executing" && pendingOrgId === org.id ? (
279275
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
280276
) : currentOrganization?.id === org.id ? (
281277
<Check className="mr-2 h-4 w-4" />
@@ -287,9 +283,7 @@ export function OrganizationSwitcher({
287283
isCollapsed={false}
288284
className="mr-2 h-6 w-6"
289285
/>
290-
<span className="truncate">
291-
{getDisplayName(org)}
292-
</span>
286+
<span className="truncate">{getDisplayName(org)}</span>
293287
</CommandItem>
294288
))}
295289
</CommandGroup>

apps/app/src/middleware.ts

Lines changed: 43 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -4,53 +4,50 @@ import { headers } from "next/headers";
44
import { NextRequest, NextResponse } from "next/server";
55

66
export const config = {
7-
runtime: "nodejs",
8-
matcher: [
9-
// Skip auth-related routes
10-
"/((?!api|_next/static|_next/image|favicon.ico|monitoring|ingest|onboarding|research).*)",
11-
],
7+
runtime: "nodejs",
8+
matcher: [
9+
// Skip auth-related routes
10+
"/((?!api|_next/static|_next/image|favicon.ico|monitoring|ingest|onboarding|research).*)",
11+
],
1212
};
1313

1414
export async function middleware(request: NextRequest) {
15-
const session = await auth.api.getSession({
16-
headers: await headers(),
17-
});
18-
19-
const response = NextResponse.next();
20-
const nextUrl = request.nextUrl;
21-
22-
// Add x-path-name
23-
response.headers.set("x-pathname", nextUrl.pathname);
24-
25-
// 1. Not authenticated
26-
if (!session && nextUrl.pathname !== "/auth") {
27-
const url = new URL("/auth", request.url);
28-
29-
return NextResponse.redirect(url);
30-
}
31-
32-
// 2. Authenticated; redirect to onboarding if not completed
33-
if (session) {
34-
// 2.1. If the user has an active organization, redirect to implementation
35-
if (
36-
session.session.activeOrganizationId &&
37-
nextUrl.pathname !== "/auth" &&
38-
!nextUrl.pathname.startsWith("/setup/onboarding")
39-
) {
40-
const onboarding = await db.onboarding.findFirst({
41-
where: {
42-
organizationId: session.session
43-
.activeOrganizationId as string,
44-
},
45-
});
46-
47-
if (!onboarding?.completed && !onboarding?.triggerJobId) {
48-
return NextResponse.redirect(
49-
new URL("/setup/onboarding", request.url),
50-
);
51-
}
52-
}
53-
}
54-
55-
return response;
15+
const session = await auth.api.getSession({
16+
headers: await headers(),
17+
});
18+
19+
const response = NextResponse.next();
20+
const nextUrl = request.nextUrl;
21+
22+
// Add x-path-name
23+
response.headers.set("x-pathname", nextUrl.pathname);
24+
25+
// 1. Not authenticated
26+
if (!session && nextUrl.pathname !== "/auth") {
27+
const url = new URL("/auth", request.url);
28+
29+
return NextResponse.redirect(url);
30+
}
31+
32+
// 2. Authenticated; redirect to onboarding if not completed
33+
if (session) {
34+
// 2.1. If the user has an active organization, redirect to implementation
35+
if (
36+
session.session.activeOrganizationId &&
37+
nextUrl.pathname !== "/auth" &&
38+
!nextUrl.pathname.startsWith("/setup/onboarding")
39+
) {
40+
const onboarding = await db.onboarding.findFirst({
41+
where: {
42+
organizationId: session.session.activeOrganizationId as string,
43+
},
44+
});
45+
46+
if (onboarding && !onboarding.completed && !onboarding.triggerJobId) {
47+
return NextResponse.redirect(new URL("/setup/onboarding", request.url));
48+
}
49+
}
50+
}
51+
52+
return response;
5653
}

0 commit comments

Comments
 (0)