feat: update auth screens UI - #27
Conversation
… border by default
…contact/donation buttons, and polish
…gnment, change FAQ icon rotation to 90deg
…FAQ icon rotates to X
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (6)
✅ Files skipped from review due to trivial changes (2)
🚧 Files skipped from review as they are similar to previous changes (4)
📝 WalkthroughWalkthroughThis PR refactors login and signup into a two-step email-then-code flow, adds route-conditional marketing sections and a donation CTA, and updates several marketing page and component styles. ChangesTwo-step auth flow
Marketing layout and styling updates
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant User
participant LoginForm
participant AuthCodeForm
participant onSubmitCode
User->>LoginForm: Submit email
LoginForm->>LoginForm: Store email in state
LoginForm->>AuthCodeForm: Render with mode="login"
User->>AuthCodeForm: Submit 6-digit code
AuthCodeForm->>onSubmitCode: Forward validated code
Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
⚔️ Resolve merge conflicts
Comment |
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (2)
src/features/marketing/components/conditional-layout-sections.tsx (1)
10-11: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueConsider centralizing route lists.
Route strings are inline and duplicated as literals; extracting a small constants array (e.g.
FAQ_ROUTES,HIDE_CTA_ROUTES) would make future route additions less error-prone.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/features/marketing/components/conditional-layout-sections.tsx` around lines 10 - 11, The route checks in conditional-layout-sections are using inline string literals, which makes route updates easy to miss. Extract the route values used by showFaq and showCta into shared constants arrays such as FAQ_ROUTES and HIDE_CTA_ROUTES, then update the conditional logic to reference those constants instead of hardcoded path strings.src/features/marketing/components/donation-cta-section.tsx (1)
1-37: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚖️ Poor tradeoffDuplicate of
CtaSection.This component's structure, container classes, and hover/gradient behavior closely mirror
cta-section.tsx(per the provided context snippet), differing only in heading/body copy and link target. Consider extracting a shared base CTA component parameterized bytitle,description,href, andlinkTextto avoid maintaining two near-identical implementations.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/features/marketing/components/donation-cta-section.tsx` around lines 1 - 37, DonationCtaSection is a near-duplicate of CtaSection, so refactor the shared layout and hover/gradient Link behavior into a reusable CTA base component. Extract the common structure from DonationCtaSection and cta-section.tsx into a parameterized component that accepts title, description, href, and linkText, then update DonationCtaSection to pass its specific copy and donation destination instead of maintaining a separate copy of the same markup.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/features/auth/components/auth-code-form.tsx`:
- Around line 28-33: The auth flow in AuthCodeForm can silently do nothing
because onSubmitCode and onResendCode are optional while the current callers
omit them. Tighten the contract in AuthCodeFormProps by making the callbacks
required, or add an explicit disabled/error state in AuthCodeForm and its
submit/resend handlers until the callers provide them. Update the related
login/signup call sites and any handler usage in AuthCodeForm so submitting a
code and clicking “Resend code” always triggers real auth behavior or is clearly
blocked.
In `@src/features/auth/components/auth-google-button.tsx`:
- Around line 31-40: AuthGoogleButton currently renders a non-functional button
and blocks the Google auth flow because it only accepts label and never forwards
an action handler. Update AuthGoogleButton to accept and pass through button
props (especially onClick and any other needed Button props) to the underlying
Button component, while keeping the existing label and GoogleMark rendering so
login/signup forms can wire the OAuth action.
In `@src/features/auth/components/login-form.tsx`:
- Around line 39-51: The login flow in onSubmit only stores the email and
advances to AuthCodeForm without starting the challenge, so wire the real auth
request before setting loginEmail. Update login-form.tsx to call the
login-code/start-challenge API in onSubmit, then pass the resulting onSubmitCode
and onResendCode handlers into AuthCodeForm so the user can verify and resend
the code. Use the existing onSubmit, setLoginEmail, and AuthCodeForm symbols to
locate the flow and keep the step transition only after the challenge is
initiated.
In `@src/features/auth/components/signup-form.tsx`:
- Around line 48-59: The signup flow in signup-form.tsx only stores local state
in onSubmit and then renders AuthCodeForm without actually creating or verifying
a signup challenge, and it drops the submitted name. Update onSubmit and the
AuthCodeForm props wiring so the signup challenge is created/verified through
explicit handlers before advancing, and make sure signupStep.name is preserved
and passed along with signupStep.email throughout the flow.
---
Nitpick comments:
In `@src/features/marketing/components/conditional-layout-sections.tsx`:
- Around line 10-11: The route checks in conditional-layout-sections are using
inline string literals, which makes route updates easy to miss. Extract the
route values used by showFaq and showCta into shared constants arrays such as
FAQ_ROUTES and HIDE_CTA_ROUTES, then update the conditional logic to reference
those constants instead of hardcoded path strings.
In `@src/features/marketing/components/donation-cta-section.tsx`:
- Around line 1-37: DonationCtaSection is a near-duplicate of CtaSection, so
refactor the shared layout and hover/gradient Link behavior into a reusable CTA
base component. Extract the common structure from DonationCtaSection and
cta-section.tsx into a parameterized component that accepts title, description,
href, and linkText, then update DonationCtaSection to pass its specific copy and
donation destination instead of maintaining a separate copy of the same markup.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: feba1eed-e0f9-4bb2-bcfc-e3d0786f68b8
📒 Files selected for processing (13)
src/app/(marketing)/donation/page.tsxsrc/app/(marketing)/layout.tsxsrc/app/(marketing)/login/page.tsxsrc/app/(marketing)/page.tsxsrc/app/(marketing)/signup/page.tsxsrc/features/auth/components/auth-code-form.tsxsrc/features/auth/components/auth-google-button.tsxsrc/features/auth/components/login-form.tsxsrc/features/auth/components/signup-form.tsxsrc/features/marketing/components/conditional-layout-sections.tsxsrc/features/marketing/components/donation-cta-section.tsxsrc/features/marketing/components/faq.tsxsrc/features/marketing/components/mission-sections.tsx
💤 Files with no reviewable changes (1)
- src/app/(marketing)/page.tsx
| type AuthCodeFormProps = React.ComponentProps<"div"> & { | ||
| email: string | ||
| mode: "login" | "signup" | ||
| onDifferentAccount?: () => void | ||
| onResendCode?: () => void | ||
| onSubmitCode?: (code: string) => void | Promise<void> |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Prevent auth actions from silently no-oping.
onSubmitCode and onResendCode are optional, and the current login/signup callers omit them. That means submitting a valid code and clicking “Resend code” can complete with no verification or resend request. Make these callbacks required, or render an explicit disabled/error state until they are provided.
Proposed contract tightening
type AuthCodeFormProps = React.ComponentProps<"div"> & {
email: string
mode: "login" | "signup"
onDifferentAccount?: () => void
- onResendCode?: () => void
- onSubmitCode?: (code: string) => void | Promise<void>
+ onResendCode: () => void | Promise<void>
+ onSubmitCode: (code: string) => void | Promise<void>
}
@@
const onSubmit = async (data: z.infer<typeof codeSchema>) => {
- await onSubmitCode?.(data.code)
+ await onSubmitCode(data.code)
}Also applies to: 59-60, 117-123
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/features/auth/components/auth-code-form.tsx` around lines 28 - 33, The
auth flow in AuthCodeForm can silently do nothing because onSubmitCode and
onResendCode are optional while the current callers omit them. Tighten the
contract in AuthCodeFormProps by making the callbacks required, or add an
explicit disabled/error state in AuthCodeForm and its submit/resend handlers
until the callers provide them. Update the related login/signup call sites and
any handler usage in AuthCodeForm so submitting a code and clicking “Resend
code” always triggers real auth behavior or is clearly blocked.
| export function AuthGoogleButton({ label }: { label: string }) { | ||
| return ( | ||
| <Button | ||
| type="button" | ||
| variant="outline" | ||
| className="h-[53px] w-full gap-2.5 rounded-[60px] border-[#d9d9d9] bg-white px-5 py-4 text-base font-medium text-ma-text hover:bg-[#f5f5f5]" | ||
| > | ||
| <GoogleMark /> | ||
| {label} | ||
| </Button> |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Expose a Google auth action.
This renders an inert type="button" and the login/signup forms pass no handler, so the Google option never starts OAuth. Accept/pass through button props so callers can wire the auth action.
Proposed prop forwarding
+import type { ComponentProps } from "react"
import { Button } from "`@/shared/ui/button`"
+import { cn } from "`@/shared/utils`"
@@
-export function AuthGoogleButton({ label }: { label: string }) {
+type AuthGoogleButtonProps = ComponentProps<typeof Button> & {
+ label: string
+}
+
+export function AuthGoogleButton({
+ label,
+ className,
+ type = "button",
+ ...props
+}: AuthGoogleButtonProps) {
return (
<Button
- type="button"
+ type={type}
variant="outline"
- className="h-[53px] w-full gap-2.5 rounded-[60px] border-[`#d9d9d9`] bg-white px-5 py-4 text-base font-medium text-ma-text hover:bg-[`#f5f5f5`]"
+ className={cn(
+ "h-[53px] w-full gap-2.5 rounded-[60px] border-[`#d9d9d9`] bg-white px-5 py-4 text-base font-medium text-ma-text hover:bg-[`#f5f5f5`]",
+ className,
+ )}
+ {...props}
>📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| export function AuthGoogleButton({ label }: { label: string }) { | |
| return ( | |
| <Button | |
| type="button" | |
| variant="outline" | |
| className="h-[53px] w-full gap-2.5 rounded-[60px] border-[#d9d9d9] bg-white px-5 py-4 text-base font-medium text-ma-text hover:bg-[#f5f5f5]" | |
| > | |
| <GoogleMark /> | |
| {label} | |
| </Button> | |
| type AuthGoogleButtonProps = ComponentProps<typeof Button> & { | |
| label: string | |
| } | |
| export function AuthGoogleButton({ | |
| label, | |
| className, | |
| type = "button", | |
| ...props | |
| }: AuthGoogleButtonProps) { | |
| return ( | |
| <Button | |
| type={type} | |
| variant="outline" | |
| className={cn( | |
| "h-[53px] w-full gap-2.5 rounded-[60px] border-[`#d9d9d9`] bg-white px-5 py-4 text-base font-medium text-ma-text hover:bg-[`#f5f5f5`]", | |
| className, | |
| )} | |
| {...props} | |
| > | |
| <GoogleMark /> | |
| {label} | |
| </Button> | |
| ) | |
| } |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/features/auth/components/auth-google-button.tsx` around lines 31 - 40,
AuthGoogleButton currently renders a non-functional button and blocks the Google
auth flow because it only accepts label and never forwards an action handler.
Update AuthGoogleButton to accept and pass through button props (especially
onClick and any other needed Button props) to the underlying Button component,
while keeping the existing label and GoogleMark rendering so login/signup forms
can wire the OAuth action.
| const onSubmit = async (data: z.infer<typeof formSchema>) => { | ||
| try { | ||
| await authClient.signIn.email(data) | ||
| } catch (error) { | ||
| console.error(error) | ||
| } | ||
| setLoginEmail(data.email) | ||
| } | ||
|
|
||
| if (loginEmail) { | ||
| return ( | ||
| <AuthCodeForm | ||
| email={loginEmail} | ||
| mode="login" | ||
| onDifferentAccount={() => setLoginEmail(null)} | ||
| className={className} | ||
| {...props} | ||
| /> |
There was a problem hiding this comment.
🎯 Functional Correctness | 🔴 Critical | 🏗️ Heavy lift
Start and verify the login challenge before switching steps.
Line 40 only saves the email, then the next screen says a code was sent. No login-code request is made, and AuthCodeForm receives no onSubmitCode/onResendCode, so the login flow cannot complete. Wire the real auth calls before advancing and pass verify/resend handlers into AuthCodeForm.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/features/auth/components/login-form.tsx` around lines 39 - 51, The login
flow in onSubmit only stores the email and advances to AuthCodeForm without
starting the challenge, so wire the real auth request before setting loginEmail.
Update login-form.tsx to call the login-code/start-challenge API in onSubmit,
then pass the resulting onSubmitCode and onResendCode handlers into AuthCodeForm
so the user can verify and resend the code. Use the existing onSubmit,
setLoginEmail, and AuthCodeForm symbols to locate the flow and keep the step
transition only after the challenge is initiated.
| const onSubmit = async (data: z.infer<typeof formSchema>) => { | ||
| try { | ||
| const { error } = await authClient.signUp.email({ | ||
| name: data.name, | ||
| email: data.email, | ||
| password: data.password, | ||
| callbackURL: "/", | ||
| }) | ||
| if (error) { | ||
| console.error(error) | ||
| } | ||
| } catch (error) { | ||
| console.error(error) | ||
| } | ||
| setSignupStep(data) | ||
| } | ||
|
|
||
| if (signupStep) { | ||
| return ( | ||
| <AuthCodeForm | ||
| email={signupStep.email} | ||
| mode="signup" | ||
| onDifferentAccount={() => setSignupStep(null)} | ||
| className={className} | ||
| {...props} |
There was a problem hiding this comment.
🎯 Functional Correctness | 🔴 Critical | 🏗️ Heavy lift
Wire the signup challenge and preserve the submitted name.
Line 49 only moves local state forward. No signup/code request is made, AuthCodeForm has no verify/resend callbacks, and signupStep.name is never used after this step. Pass handlers that create/verify the signup challenge with both name and email before showing a successful signup path.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/features/auth/components/signup-form.tsx` around lines 48 - 59, The
signup flow in signup-form.tsx only stores local state in onSubmit and then
renders AuthCodeForm without actually creating or verifying a signup challenge,
and it drops the submitted name. Update onSubmit and the AuthCodeForm props
wiring so the signup challenge is created/verified through explicit handlers
before advancing, and make sure signupStep.name is preserved and passed along
with signupStep.email throughout the flow.
Summary\n- Updated login and signup page layouts\n- Refreshed login-form and signup-form components\n- Added new auth-code-form and auth-google-button components
Summary by CodeRabbit