fix(ux): empty repo state opens add modal, signup requires email verification#225
Conversation
- Add onAddClick prop to RepoList component - Support controlled mode in AddRepoForm (isOpen, onOpenChange) - Wire up DashboardHome to pass state between components - Empty state now opens the add repository modal when clicked
- Show 'Check your email' screen after signup instead of redirecting - Handle email_not_confirmed error gracefully in login form - Show helpful error messages for common auth issues - Prevent fake email signups by requiring verification
|
@DevanshuNEU is attempting to deploy a commit to the Dev's projects Team on Vercel. A member of the Team first needs to authorize it. |
📝 WalkthroughWalkthroughAdds controlled/uncontrolled visibility to AddRepoForm and wires it from RepoList and DashboardHome; makes RepoList empty state actionable; adds resendVerification to AuthContext; introduces post-signup email verification UI and improves login error messaging. Changes
Sequence DiagramssequenceDiagram
actor User
participant RepoList as "Repo List"
participant DashboardHome as "Dashboard Home"
participant AddRepoForm as "AddRepoForm"
User->>RepoList: Click empty-state button
RepoList->>DashboardHome: onAddClick()
DashboardHome->>DashboardHome: set showAddForm = true
DashboardHome->>AddRepoForm: isOpen={true}, onOpenChange={setShowAddForm}
AddRepoForm-->>User: Display modal/form
User->>AddRepoForm: Submit form
AddRepoForm->>DashboardHome: onOpenChange(false)
DashboardHome->>DashboardHome: set showAddForm = false
AddRepoForm-->>User: Close modal
sequenceDiagram
actor User
participant SignupForm as "Signup Form"
participant Backend as "Backend Service"
participant EmailVerif as "Email Verification UI"
User->>SignupForm: Submit signup
SignupForm->>Backend: POST /signup
Backend-->>SignupForm: Success
SignupForm->>EmailVerif: set emailSent = true
EmailVerif-->>User: Show verification UI (instructions)
User->>EmailVerif: Click "Resend" / "Use different email" / "Back to login"
EmailVerif->>SignupForm: trigger resend/reset/navigation as requested
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~22 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
frontend/src/components/RepoList.tsx (1)
122-128: Rules of Hooks violation:useMemocalled after conditional returns.
useMemoon line 122 is placed after the early returns on lines 99 and 101-119. React requires hooks to be called in the same order on every render. This will cause runtime errors or unpredictable behavior when the component transitions between empty/loading and populated states.🐛 Move useMemo before conditional returns
export function RepoList({ repos, selectedRepo, onSelect, onAddClick, loading }: RepoListProps) { + const sortedRepos = useMemo(() => { + return [...repos].sort((a, b) => { + if (a.status === 'indexed' && b.status !== 'indexed') return -1 + if (b.status === 'indexed' && a.status !== 'indexed') return 1 + return (b.file_count || 0) - (a.file_count || 0) + }) + }, [repos]) + if (loading) return <RepoGridSkeleton count={3} /> if (repos.length === 0) { return ( <motion.button onClick={onAddClick} // ... rest of empty state </motion.button> ) } - const sortedRepos = useMemo(() => { - return [...repos].sort((a, b) => { - if (a.status === 'indexed' && b.status !== 'indexed') return -1 - if (b.status === 'indexed' && a.status !== 'indexed') return 1 - return (b.file_count || 0) - (a.file_count || 0) - }) - }, [repos]) - return ( <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4"> {sortedRepos.map((repo, index) => (
🤖 Fix all issues with AI agents
In `@frontend/src/components/AddRepoForm.tsx`:
- Around line 20-22: The current controlled/uncontrolled logic misbehaves when
isOpen is provided without onOpenChange because showForm uses isOpen while
setShowForm falls back to setInternalOpen; update the component so that when
isOpen !== undefined and onOpenChange is undefined you either (A) enforce this
at the type level by making onOpenChange required whenever isOpen is passed
(adjust prop types / TS discriminated union to require onOpenChange when isOpen
is present), or (B) add a runtime guard: detect the misconfiguration (isOpen !==
undefined && onOpenChange === undefined) and set setShowForm to a no-op that
calls console.warn (or processLogger) explaining the required pairing, while
ensuring showForm remains driven by isOpen and button/cancel handlers call
onOpenChange if present; reference the variables showForm, setShowForm, isOpen,
onOpenChange, internalOpen, setInternalOpen to locate and update the logic.
🧹 Nitpick comments (3)
frontend/src/components/auth/SignupForm.tsx (1)
95-102: Consider clarifying "try again" behavior or adding resend functionality.The "try again" button resets to the signup form rather than resending the verification email. Users might expect clicking "try again" to resend the email to the same address. Consider either:
- Renaming to "use a different email" for clarity, or
- Adding a dedicated "Resend verification email" action that calls the Supabase resend API
frontend/src/components/AddRepoForm.tsx (1)
35-42: Consider hiding the built-in trigger button in controlled mode.When used in controlled mode (with
isOpen/onOpenChange), the parent typically provides its own trigger mechanism. The always-visible "Add Repository" button might be redundant or could cause confusion.If this dual-trigger behavior is intentional (as it appears to be in DashboardHome), you can disregard this suggestion.
♻️ Optional: hide button in controlled mode
+ {isOpen === undefined && ( <Button onClick={() => setShowForm(true)} disabled={loading} className="bg-primary hover:bg-primary/90 text-primary-foreground gap-2" > <Plus className="w-4 h-4" /> Add Repository </Button> + )}frontend/src/components/RepoList.tsx (1)
103-109: Empty state button is clickable but may be a no-op.When
onAddClickisundefined, the button has hover/tap animations and cursor-pointer styling but does nothing on click. Consider either disabling the button or rendering a non-interactive element whenonAddClickis not provided.♻️ Optional: disable button when no handler
<motion.button onClick={onAddClick} + disabled={!onAddClick} initial={{ opacity: 0 }} animate={{ opacity: 1 }} whileHover={{ scale: 1.01 }} whileTap={{ scale: 0.99 }} - className="w-full bg-card border border-dashed border-border hover:border-primary/40 rounded-xl p-16 text-center transition-colors cursor-pointer focus:outline-none focus:ring-2 focus:ring-primary/50" + className={`w-full bg-card border border-dashed border-border rounded-xl p-16 text-center transition-colors focus:outline-none focus:ring-2 focus:ring-primary/50 ${onAddClick ? 'hover:border-primary/40 cursor-pointer' : 'cursor-default'}`} >
- Animated Send icon with spring physics - Glow effect on icon container - Staggered fade-in animations for content - Email displayed in monospace badge - Better visual hierarchy and spacing
- Move useMemo before conditional returns (React hooks rule violation) - Disable empty state button when onAddClick handler not provided - Use discriminated union types for AddRepoForm controlled mode - Hide trigger button in controlled mode (parent provides trigger) - Rename 'try again' to 'use a different email' for clarity
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@frontend/src/components/auth/SignupForm.tsx`:
- Around line 151-157: The "try again" button currently only toggles emailSent
via setEmailSent(false) which returns users to the signup form without resending
verification; update the behavior so it either triggers the real resend flow or
clearly matches the UI: if you want the minimal fix, change the button to clear
the signup inputs (reset the email/password state variables) and keep
setEmailSent(false) and update the visible copy from "try again" to "Edit email"
or "Go back"; if you prefer to implement resend, call the existing
resendVerificationEmail (or create a new resendVerification function) from the
onClick handler and keep emailSent true while showing appropriate success/error
feedback. Ensure you modify the SignupForm component handlers and reference
setEmailSent, emailSent and the email/password state variables when making this
change.
There was a problem hiding this comment.
Actionable comments posted: 0
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
frontend/src/components/auth/SignupForm.tsx (1)
19-41: Clear password state after successful signup.
AftersetEmailSent(true), passwords remain in state and will repopulate if the user goes back. Clearing them avoids retaining sensitive values.🔧 Proposed fix
try { await signUp(email, password) setEmailSent(true) + setPassword('') + setConfirmPassword('') } catch (err: any) { setError(err.message || 'Signup failed') } finally {
- Add resendVerification to AuthContext using Supabase resend API - Add proper resend button with loading state in verification screen - Show success message when email is resent - Separate 'Resend email' and 'Use different email' actions - Clear form state when going back to signup form - Display errors in verification screen
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@frontend/src/components/auth/SignupForm.tsx`:
- Around line 25-45: The resend flow leaves stale error state visible across
transitions: update handleResend to clear any existing error at the start
(setError('')), setResendSuccess(false) before awaiting resendVerification, and
clear errors on success (setError('')) so old error messages don't persist after
a successful retry; also ensure handleGoBack clears resend-specific error state
(setResendSuccess(false) and setError('')) to avoid surfacing the resend error
on the main signup form, and disable the “Use different email” action while
resendLoading is true (guard the control/UI using resendLoading) so users cannot
navigate away during an in-flight resend.
- Clear error at start of handleResend to remove stale messages - Clear error on resend success - Disable 'Use different email' button during resend loading - Disable 'Back to login' link during resend loading - Prevents navigation away during in-flight resend request
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Description
1. Empty state click not working
Users with no repositories saw a "+" icon but clicking it did nothing. Now clicking anywhere on the empty state opens the Add Repository modal.
2. No email verification on signup
Anyone could sign up with fake emails and start indexing repos, wasting server resources. Now signup shows a "Check your email" screen and requires verification before login.
Changes
RepoList.tsx- Empty state is now a clickable button withonAddClickpropAddRepoForm.tsx- Supports controlled open/close stateDashboardHome.tsx- Wires empty state click to open the modalSignupForm.tsx- Shows verification screen after signupLoginForm.tsx- Shows "verify your email" error instead of generic failureScreenshots
Empty state now clickable, signup shows verification screen
Config required
Enable "Confirm email" in Supabase → Authentication → Settings
Summary by CodeRabbit
New Features
Bug Fixes
✏️ Tip: You can customize this high-level summary in your review settings.