mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-08-28 05:27:24 +00:00
Add a client component for post-auth routing (#37)
This commit is contained in:
parent
dfe41a5da6
commit
486b641381
11 changed files with 125 additions and 63 deletions
59
src/app/(centered)/authorized/[[...state]]/Authorized.tsx
Normal file
59
src/app/(centered)/authorized/[[...state]]/Authorized.tsx
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
'use client';
|
||||
|
||||
import { useState, useRef, useEffect } from 'react';
|
||||
import { useSessionStorage } from 'react-use';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import { useAuth } from '@clerk/nextjs';
|
||||
import { LoaderCircle, CircleCheck, CircleX } from 'lucide-react';
|
||||
|
||||
import { Card, CardContent } from '@/components/ui';
|
||||
|
||||
export const Authorized = () => {
|
||||
const { isSignedIn, orgId } = useAuth();
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const isLoadingRef = useRef(true);
|
||||
const router = useRouter();
|
||||
const [state, setState] = useSessionStorage<string | undefined>('state');
|
||||
|
||||
useEffect(() => {
|
||||
if (typeof isSignedIn !== 'undefined' && isLoadingRef.current) {
|
||||
isLoadingRef.current = false;
|
||||
setTimeout(() => setIsLoading(false), 250);
|
||||
}
|
||||
}, [isSignedIn]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isLoading) {
|
||||
let path;
|
||||
|
||||
if (!isSignedIn) {
|
||||
path = state ? `/sign-in?state=${state}` : '/sign-in';
|
||||
} else if (!orgId) {
|
||||
path = state ? `/select-org/${state}` : '/select-org';
|
||||
} else {
|
||||
path = state ? `/extension/sign-in?state=${state}` : '/dashboard';
|
||||
}
|
||||
|
||||
setTimeout(() => router.push(path), 1000);
|
||||
}
|
||||
}, [router, isLoading, isSignedIn, orgId, state, setState]);
|
||||
|
||||
return (
|
||||
<Card className="max-w-md mx-auto">
|
||||
<CardContent className="flex flex-col gap-4">
|
||||
<div className="flex flex-row items-center gap-2">
|
||||
<div className="font-medium text-sm text-muted-foreground">
|
||||
Authenticating
|
||||
</div>
|
||||
{isLoading ? (
|
||||
<LoaderCircle className="animate-spin" />
|
||||
) : isSignedIn ? (
|
||||
<CircleCheck className="text-lime-500" />
|
||||
) : (
|
||||
<CircleX className="text-rose-500" />
|
||||
)}
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
5
src/app/(centered)/authorized/[[...state]]/page.tsx
Normal file
5
src/app/(centered)/authorized/[[...state]]/page.tsx
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
import { Authorized } from './Authorized';
|
||||
|
||||
export default function Page() {
|
||||
return <Authorized />;
|
||||
}
|
||||
|
|
@ -18,14 +18,16 @@ export default async function Page(props: Props) {
|
|||
}
|
||||
|
||||
const { userId, orgId } = await auth();
|
||||
const code = userId ? await getSignInToken(userId) : undefined;
|
||||
const code = userId
|
||||
? await getSignInToken(userId).catch(() => undefined)
|
||||
: undefined;
|
||||
|
||||
if (!code) {
|
||||
redirect(`/sign-in?state=${state}`);
|
||||
}
|
||||
|
||||
if (!orgId) {
|
||||
redirect(`/select-org?state=${state}`);
|
||||
redirect(`/select-org/${state}`);
|
||||
}
|
||||
|
||||
const searchParams = new URLSearchParams({ state, code });
|
||||
|
|
|
|||
|
|
@ -1,22 +0,0 @@
|
|||
'use client';
|
||||
|
||||
import { useMemo } from 'react';
|
||||
import { useSearchParams } from 'next/navigation';
|
||||
import { OrganizationList } from '@clerk/nextjs';
|
||||
|
||||
export const SelectOrg = () => {
|
||||
const searchParams = useSearchParams();
|
||||
|
||||
const afterSelectOrganizationUrl = useMemo(() => {
|
||||
const state = searchParams.get('state');
|
||||
return state ? `/extension/sign-in?state=${state}` : '/dashboard';
|
||||
}, [searchParams]);
|
||||
|
||||
return (
|
||||
<OrganizationList
|
||||
afterSelectOrganizationUrl={afterSelectOrganizationUrl}
|
||||
afterCreateOrganizationUrl={afterSelectOrganizationUrl}
|
||||
hidePersonal
|
||||
/>
|
||||
);
|
||||
};
|
||||
15
src/app/(centered)/select-org/[[...state]]/SelectOrg.tsx
Normal file
15
src/app/(centered)/select-org/[[...state]]/SelectOrg.tsx
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
import { OrganizationList } from '@clerk/nextjs';
|
||||
|
||||
export const SelectOrg = ({ state }: { state?: string }) => {
|
||||
const redirectUrl = state
|
||||
? `/extension/sign-in?state=${state}`
|
||||
: '/dashboard';
|
||||
|
||||
return (
|
||||
<OrganizationList
|
||||
afterSelectOrganizationUrl={redirectUrl}
|
||||
afterCreateOrganizationUrl={redirectUrl}
|
||||
hidePersonal
|
||||
/>
|
||||
);
|
||||
};
|
||||
10
src/app/(centered)/select-org/[[...state]]/page.tsx
Normal file
10
src/app/(centered)/select-org/[[...state]]/page.tsx
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
import { SelectOrg } from './SelectOrg';
|
||||
|
||||
type Props = {
|
||||
params: Promise<{ state: string }>;
|
||||
};
|
||||
|
||||
export default async function Page({ params }: Props) {
|
||||
const { state } = await params;
|
||||
return <SelectOrg state={state} />;
|
||||
}
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
import { SelectOrg } from './SelectOrg';
|
||||
|
||||
export default async function Page() {
|
||||
return <SelectOrg />;
|
||||
}
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
'use client';
|
||||
|
||||
import { useMemo } from 'react';
|
||||
import { useSearchParams } from 'next/navigation';
|
||||
import { SignIn as ClerkSignIn } from '@clerk/nextjs';
|
||||
|
||||
export const SignIn = () => {
|
||||
const searchParams = useSearchParams();
|
||||
|
||||
const forceRedirectUrl = useMemo(() => {
|
||||
const state = searchParams.get('state');
|
||||
return state ? `/extension/sign-in?state=${state}` : undefined;
|
||||
}, [searchParams]);
|
||||
|
||||
return <ClerkSignIn forceRedirectUrl={forceRedirectUrl} />;
|
||||
};
|
||||
|
|
@ -1,5 +1,20 @@
|
|||
import { SignIn } from './SignIn';
|
||||
'use client';
|
||||
|
||||
import { useSessionStorage, useMount } from 'react-use';
|
||||
import { useSearchParams } from 'next/navigation';
|
||||
import { SignIn } from '@clerk/nextjs';
|
||||
|
||||
export default function Page() {
|
||||
const searchParams = useSearchParams();
|
||||
const [, setState] = useSessionStorage<string | undefined>('state');
|
||||
|
||||
useMount(() => {
|
||||
const state = searchParams.get('state');
|
||||
|
||||
if (state) {
|
||||
setState(state);
|
||||
}
|
||||
});
|
||||
|
||||
return <SignIn />;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,16 +0,0 @@
|
|||
'use client';
|
||||
|
||||
import { useMemo } from 'react';
|
||||
import { useSearchParams } from 'next/navigation';
|
||||
import { SignUp as ClerkSignUp } from '@clerk/nextjs';
|
||||
|
||||
export const SignUp = () => {
|
||||
const searchParams = useSearchParams();
|
||||
|
||||
const forceRedirectUrl = useMemo(() => {
|
||||
const state = searchParams.get('state');
|
||||
return state ? `/extension/sign-in?state=${state}` : undefined;
|
||||
}, [searchParams]);
|
||||
|
||||
return <ClerkSignUp forceRedirectUrl={forceRedirectUrl} />;
|
||||
};
|
||||
|
|
@ -1,5 +1,20 @@
|
|||
import { SignUp } from './SignUp';
|
||||
'use client';
|
||||
|
||||
import { useSessionStorage, useMount } from 'react-use';
|
||||
import { useSearchParams } from 'next/navigation';
|
||||
import { SignUp } from '@clerk/nextjs';
|
||||
|
||||
export default function Page() {
|
||||
const searchParams = useSearchParams();
|
||||
const [, setState] = useSessionStorage<string | undefined>('state');
|
||||
|
||||
useMount(() => {
|
||||
const state = searchParams.get('state');
|
||||
|
||||
if (state) {
|
||||
setState(state);
|
||||
}
|
||||
});
|
||||
|
||||
return <SignUp />;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue