refactor(onboarding): restructure onboarding routes and components
- Removed obsolete onboarding routes: complete, create-complex, index, verify-email, and verify. - Introduced new setup stepper page for onboarding process. - Created a multi-step setup component to handle complex creation with validation. - Added new schemas for complex creation and plan features. - Implemented detailed steps for complex name, location, plan selection, and court setup. - Enhanced error handling and user feedback during the onboarding process.
This commit is contained in:
@@ -17,23 +17,9 @@ function AuthCallbackPage() {
|
||||
|
||||
try {
|
||||
await acceptStoredPendingInvite(apiClient.complexes.acceptPendingInvitations);
|
||||
const complexes = await apiClient.complexes.listMine();
|
||||
|
||||
if (complexes.length === 1) {
|
||||
await apiClient.complexes.select({ complexId: complexes[0].id });
|
||||
navigate({ to: '/' });
|
||||
} else if (complexes.length > 1) {
|
||||
const current = await apiClient.complexes.getCurrent();
|
||||
if (current) {
|
||||
navigate({ to: '/' });
|
||||
} else {
|
||||
navigate({ to: '/select-complex' });
|
||||
}
|
||||
} else {
|
||||
navigate({ to: '/onboard/create-complex' });
|
||||
}
|
||||
navigate({ to: '/' });
|
||||
} catch {
|
||||
navigate({ to: '/onboard' });
|
||||
navigate({ to: '/login' });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { OnboardLoginPage } from '@/features/onboard/onboard-login-page';
|
||||
import { apiClient } from '@/lib/api-client';
|
||||
import { useAuth } from '@/lib/auth';
|
||||
import { acceptStoredPendingInvite, setPendingInvite } from '@/lib/invitations';
|
||||
@@ -25,6 +24,7 @@ function InvitePage() {
|
||||
|
||||
useEffect(() => {
|
||||
if (!isAuthenticated) {
|
||||
navigate({ to: '/login' });
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -34,15 +34,11 @@ function InvitePage() {
|
||||
})();
|
||||
}, [isAuthenticated, navigate]);
|
||||
|
||||
if (isAuthenticated) {
|
||||
return (
|
||||
<main className="flex min-h-screen w-full items-center justify-center px-3 sm:px-6">
|
||||
<p className="text-sm text-muted-foreground">Aceptando invitación...</p>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
||||
return <OnboardLoginPage variant="invite" inviteEmail={search.email ?? null} />;
|
||||
return (
|
||||
<main className="flex min-h-screen w-full items-center justify-center px-3 sm:px-6">
|
||||
<p className="text-sm text-muted-foreground">Aceptando invitación...</p>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
||||
export const Route = createFileRoute('/invite')({
|
||||
|
||||
@@ -1,22 +1,11 @@
|
||||
import { LoginPage } from '@/features/login/login-page';
|
||||
import { createFileRoute, redirect } from '@tanstack/react-router';
|
||||
import { z } from 'zod';
|
||||
|
||||
const loginSearchSchema = z.object({
|
||||
redirect: z.string().optional(),
|
||||
});
|
||||
|
||||
export const Route = createFileRoute('/login')({
|
||||
validateSearch: loginSearchSchema,
|
||||
beforeLoad: ({ context }) => {
|
||||
if (context.auth.isAuthenticated) {
|
||||
throw redirect({ to: '/' });
|
||||
}
|
||||
},
|
||||
component: LoginRouteComponent,
|
||||
component: LoginPage,
|
||||
});
|
||||
|
||||
function LoginRouteComponent() {
|
||||
const search = Route.useSearch();
|
||||
return <LoginPage redirectTo={search.redirect} />;
|
||||
}
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
import { OnboardCompletePage } from '@/features/onboard/onboard-complete-page';
|
||||
import { createFileRoute } from '@tanstack/react-router';
|
||||
|
||||
export const Route = createFileRoute('/onboard/complete')({
|
||||
component: OnboardCompletePage,
|
||||
});
|
||||
@@ -1,11 +0,0 @@
|
||||
import { OnboardLoginPage } from '@/features/onboard/onboard-login-page';
|
||||
import { createFileRoute, redirect } from '@tanstack/react-router';
|
||||
|
||||
export const Route = createFileRoute('/onboard/')({
|
||||
beforeLoad: ({ context }) => {
|
||||
if (!context.auth.isAuthenticated) {
|
||||
throw redirect({ to: '/login', search: { redirect: '/onboard/create-complex' } });
|
||||
}
|
||||
},
|
||||
component: OnboardLoginPage,
|
||||
});
|
||||
@@ -1,14 +1,14 @@
|
||||
import { CreateComplexPage } from '@/features/onboard/create-complex-page';
|
||||
import { SetupStepperPage } from '@/features/onboard/setup-stepper-page';
|
||||
import { createFileRoute, redirect } from '@tanstack/react-router';
|
||||
|
||||
export const Route = createFileRoute('/onboard/create-complex')({
|
||||
export const Route = createFileRoute('/onboard/setup')({
|
||||
beforeLoad: ({ context }) => {
|
||||
const hasSession = context.auth.isAuthenticated;
|
||||
const hasPendingSignup = Boolean(sessionStorage.getItem('pending-signup-email'));
|
||||
|
||||
if (!hasSession && !hasPendingSignup) {
|
||||
throw redirect({ to: '/onboard' });
|
||||
throw redirect({ to: '/login' });
|
||||
}
|
||||
},
|
||||
component: CreateComplexPage,
|
||||
component: SetupStepperPage,
|
||||
});
|
||||
@@ -1,18 +0,0 @@
|
||||
import { VerifyEmailPage } from '@/features/onboard/verify-email-page';
|
||||
import { createFileRoute, redirect } from '@tanstack/react-router';
|
||||
import { z } from 'zod';
|
||||
|
||||
const verifyEmailSearchSchema = z.object({
|
||||
email: z.string().email().optional(),
|
||||
});
|
||||
|
||||
export const Route = createFileRoute('/onboard/verify-email')({
|
||||
validateSearch: verifyEmailSearchSchema,
|
||||
beforeLoad: () => {
|
||||
const hasPendingSignup = Boolean(sessionStorage.getItem('pending-signup-email'));
|
||||
if (!hasPendingSignup) {
|
||||
throw redirect({ to: '/onboard' });
|
||||
}
|
||||
},
|
||||
component: VerifyEmailPage,
|
||||
});
|
||||
@@ -1,6 +0,0 @@
|
||||
import { OnboardVerifyPage } from '@/features/onboard/onboard-verify-page';
|
||||
import { createFileRoute } from '@tanstack/react-router';
|
||||
|
||||
export const Route = createFileRoute('/onboard/verify')({
|
||||
component: OnboardVerifyPage,
|
||||
});
|
||||
Reference in New Issue
Block a user