Redirect to pricing purchase after sign up#15
Conversation
WalkthroughThe pull request introduces enhancements to the frontend routing system by integrating a Changes
Sequence DiagramsequenceDiagram
participant User
participant LoginPage
participant AuthCallback
participant PricingPage
User->>LoginPage: Selects plan before login
LoginPage->>AuthCallback: Passes selected_plan
AuthCallback->>PricingPage: Redirects with selected_plan
PricingPage->>PricingPage: Automatically initiate checkout
Possibly related PRs
Poem
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
Deploying maple with
|
| Latest commit: |
6432bc9
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://78ce2a0d.maple-ca8.pages.dev |
| Branch Preview URL: | https://pricing-signup-redirect.maple-ca8.pages.dev |
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (6)
frontend/src/routes/auth.$provider.callback.tsx (2)
54-71: Consider reducing the redirect delay.The 2-second delay before redirect might be longer than necessary for a good user experience.
- }, 2000); + }, 1000);
128-131: Enhance the success message with more details.The current message could be more informative about what happens next.
- You have successfully authenticated with {formattedProvider}. - {sessionStorage.getItem("selected_plan") - ? "Redirecting to complete your plan selection..." - : "Redirecting to home page..."} + You have successfully authenticated with {formattedProvider}. + {sessionStorage.getItem("selected_plan") + ? "Redirecting to pricing page to complete your plan selection..." + : "Redirecting to your dashboard..."}frontend/src/routes/signup.tsx (1)
85-87: Consider consolidating OAuth plan handling.The plan storage logic is duplicated between GitHub and Google handlers.
+ const storeSelectedPlan = () => { + if (selected_plan) { + sessionStorage.setItem("selected_plan", selected_plan); + } + }; + const handleGitHubSignup = async () => { try { const { auth_url } = await os.initiateGitHubAuth(""); - if (selected_plan) { - sessionStorage.setItem("selected_plan", selected_plan); - } + storeSelectedPlan(); window.location.href = auth_url; } catch (error) { console.error("Failed to initiate GitHub signup:", error); setError("Failed to initiate GitHub signup. Please try again."); } }; const handleGoogleSignup = async () => { try { const { auth_url } = await os.initiateGoogleAuth(""); - if (selected_plan) { - sessionStorage.setItem("selected_plan", selected_plan); - } + storeSelectedPlan(); window.location.href = auth_url;Also applies to: 98-100
frontend/src/routes/pricing.tsx (3)
268-279: Consider adding error handling for invalid plan IDs.While the redirection logic is correct, consider adding validation for the plan ID before redirection to prevent potential issues with invalid selections.
const targetPlanName = product.name.toLowerCase(); +if (!product.id) { + console.error('Invalid product: missing ID'); + navigate({ to: "/signup" }); + return; +} if (!targetPlanName.includes("free")) { navigate({ to: "/signup",
363-371: Add cleanup and loading state management to the useEffect hook.The auto-checkout effect could benefit from these improvements:
- Add cleanup to prevent state updates after unmount
- Add loading state management to prevent multiple triggers
useEffect(() => { + let isSubscribed = true; + // If user is logged in and there's a selected plan, trigger checkout if (isLoggedIn && selected_plan && !isBillingStatusLoading) { + if (loadingProductId) return; // Prevent multiple triggers const product = products?.find((p) => p.id === selected_plan); if (product) { - handleButtonClick(product); + if (isSubscribed) { + handleButtonClick(product); + } } } + return () => { + isSubscribed = false; + }; -}, [isLoggedIn, selected_plan, isBillingStatusLoading, products]); +}, [isLoggedIn, selected_plan, isBillingStatusLoading, products, loadingProductId]);
614-619: Consider adding stricter validation for selected_plan.While the type validation is correct, consider adding validation to ensure the selected_plan matches a valid product ID pattern to prevent invalid values from being processed.
validateSearch: (search: Record<string, unknown>): PricingSearchParams => ({ - selected_plan: typeof search.selected_plan === "string" ? search.selected_plan : undefined, + selected_plan: typeof search.selected_plan === "string" && + /^prod_[A-Za-z0-9]{14,}$/.test(search.selected_plan) ? + search.selected_plan : undefined, success: typeof search.success === "boolean" ? search.success : undefined, canceled: typeof search.canceled === "boolean" ? search.canceled : undefined })
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
frontend/src/routes/__root.tsx(1 hunks)frontend/src/routes/auth.$provider.callback.tsx(2 hunks)frontend/src/routes/login.tsx(5 hunks)frontend/src/routes/pricing.tsx(5 hunks)frontend/src/routes/signup.tsx(5 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (1)
- GitHub Check: Cloudflare Pages
🔇 Additional comments (6)
frontend/src/routes/__root.tsx (2)
9-15: LGTM! Well-structured type definition.The
RootSearchParamstype properly defines all optional parameters needed across routes.
19-25: LGTM! Robust search parameter validation.The validation logic correctly handles type coercion for all parameters, ensuring type safety.
frontend/src/routes/signup.tsx (1)
13-14: LGTM! Consistent type handling.The
SignupSearchParamstype and validation logic align well with the root route implementation.Also applies to: 20-21
frontend/src/routes/login.tsx (1)
85-87: Consider consolidating OAuth plan handling.Similar to the signup route, the plan storage logic is duplicated between OAuth handlers.
Apply the same refactoring pattern suggested for the signup route to reduce code duplication.
Also applies to: 98-100
frontend/src/routes/pricing.tsx (2)
15-19: LGTM! Well-structured type definition.The
PricingSearchParamstype properly defines the optional parameters needed for plan selection and checkout status tracking.
134-134: LGTM! Proper usage of React Router hooks.The
selected_planextraction usingRoute.useSearch()follows React Router patterns correctly.
5c4828b to
6432bc9
Compare
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (1)
frontend/src/routes/pricing.tsx (1)
268-279: Consider extracting the free plan check to a constant.The implementation correctly handles navigation with plan selection, but the string check for free plans could be more maintainable.
Consider this improvement:
+const FREE_PLAN_IDENTIFIER = 'free'; + const handleButtonClick = (product: any) => { if (!isLoggedIn) { const targetPlanName = product.name.toLowerCase(); - if (!targetPlanName.includes("free")) { + if (!targetPlanName.includes(FREE_PLAN_IDENTIFIER)) { navigate({ to: "/signup", search: { next: "/pricing", selected_plan: product.id } }); return; } navigate({ to: "/signup" }); return; }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
frontend/src/routes/__root.tsx(1 hunks)frontend/src/routes/auth.$provider.callback.tsx(2 hunks)frontend/src/routes/login.tsx(5 hunks)frontend/src/routes/pricing.tsx(6 hunks)frontend/src/routes/signup.tsx(5 hunks)
🚧 Files skipped from review as they are similar to previous changes (4)
- frontend/src/routes/auth.$provider.callback.tsx
- frontend/src/routes/__root.tsx
- frontend/src/routes/login.tsx
- frontend/src/routes/signup.tsx
⏰ Context from checks skipped due to timeout of 90000ms (1)
- GitHub Check: Cloudflare Pages
🔇 Additional comments (4)
frontend/src/routes/pricing.tsx (4)
15-19: LGTM! Well-structured type definition.The
PricingSearchParamstype clearly defines the optional parameters needed for plan selection and payment status tracking.
134-134: LGTM! Clean parameter extraction.The implementation correctly extracts the
selected_planparameter using React Router's hook.
630-635: LGTM! Robust search parameter validation.The validation implementation correctly handles type checking and undefined cases for all search parameters.
363-387: Add products array existence check to prevent potential race condition.While the implementation handles loading states well, there's a potential race condition if the products array is accessed before it's loaded.
Consider adding an explicit check:
useEffect(() => { let isSubscribed = true; // If user is logged in and there's a selected plan, trigger checkout - if (isLoggedIn && selected_plan && !isBillingStatusLoading) { + if (isLoggedIn && selected_plan && !isBillingStatusLoading && products) { if (loadingProductId) return; // Prevent multiple triggers const product = products?.find((p) => p.id === selected_plan); if (product) { if (isSubscribed) { handleButtonClick(product); } } } return () => { isSubscribed = false; }; }, [ isLoggedIn, selected_plan, isBillingStatusLoading, products, loadingProductId, handleButtonClick ]);
Summary by CodeRabbit
Release Notes
New Features
Improvements
User Experience