[TASK-13870] Feat: Add identity verification button in profile page#1169
[TASK-13870] Feat: Add identity verification button in profile page#1169Zishan-7 merged 3 commits intopeanut-wallet-devfrom
Conversation
WalkthroughAdds a Shield SVG icon and registers it in the Icon registry; extends ProfileMenuItem with customizable trailing icon and altered onClick rendering; integrates KYC-aware UI in Profile with a modal and new Identity Verification menu entry; adds IdentityVerification view and mobile route page. Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested reviewers
📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: CHILL Plan: Pro 💡 Knowledge Base configuration:
You can enable these sources in your CodeRabbit configuration. 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
✨ Finishing Touches
🧪 Generate unit tests
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR/Issue comments)Type Other keywords and placeholders
CodeRabbit Configuration File (
|
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
Actionable comments posted: 7
🧹 Nitpick comments (10)
src/components/Global/Icons/shield.tsx (1)
5-5: Default decorative a11y attributes for SVG iconsSet aria-hidden and focusable defaults so decorative icons aren’t announced. Consumers can still override via props.
- <svg width="17" height="21" viewBox="0 0 17 21" fill="none" xmlns="http://www.w3.org/2000/svg" {...props}> + <svg + width="17" + height="21" + viewBox="0 0 17 21" + fill="none" + xmlns="http://www.w3.org/2000/svg" + aria-hidden="true" + focusable="false" + {...props} + >src/components/Global/Icons/Icon.tsx (1)
192-201: Replace fill prop on Icon with className or style.color
We found ~20 instances of<Icon … fill="…">across multiple components. Migrate these to Tailwind text-color classes (e.g.,text-black,text-success-3) orstyle={{ color }}so icons leveragingcurrentColor(like ShieldIcon) render correctly.src/components/Profile/index.tsx (2)
26-26: KYC status check is fine; consider widening if backend enums vary in caseIf backend could return 'APPROVED' or similar, normalize before compare to reduce brittleness.
-const isKycApproved = user?.user.kycStatus === 'approved' +const isKycApproved = (user?.user.kycStatus ?? '').toLowerCase() === 'approved'
44-44: Minor: redundant fallbackfullName already falls back to username; the “|| username” here is redundant.
-<ProfileHeader name={fullName || username} username={username} isVerified={isKycApproved} /> +<ProfileHeader name={fullName} username={username} isVerified={isKycApproved} />src/components/Profile/components/ProfileMenuItem.tsx (1)
42-47: Trailing icon classes: provide a small default when endIcon is setIf endIcon is provided without endIconClassName, className becomes undefined. Consider a tiny default size for consistency.
- className={twMerge(endIcon ? endIconClassName : 'rotate-90')} + className={twMerge(endIcon ? (endIconClassName ?? 'size-4') : 'rotate-90')}src/components/Profile/views/IdentityVerification.view.tsx (5)
48-49: Trim composed full name before sending to API.Avoid trailing spaces when last name is empty.
- fullName: `${data.firstName} ${data.lastName}`, + fullName: `${data.firstName} ${data.lastName}`.trim(),
29-31: More robust name parsing from fullName.Handle extra whitespace and multiple spaces.
- const [firstName, ...lastNameParts] = (user?.user.fullName ?? '').split(' ') - const lastName = lastNameParts.join(' ') + const [firstName, ...lastNameParts] = (user?.user.fullName ?? '') + .trim() + .split(/\s+/) + .filter(Boolean) + const lastName = lastNameParts.join(' ')
32-39: Reduce redundant useMemo deps.
firstName/lastNamederive fromfullName; no need to depend on all three.- [user?.user.fullName, user?.user.email, firstName, lastName] + [user?.user.fullName, user?.user.email]
68-68: Prefer router.back() for back behavior.Better matches user expectation and preserves history.
- <NavHeader title="Identity Verification" onPrev={() => router.replace('/profile')} /> + <NavHeader title="Identity Verification" onPrev={() => router.back()} />
41-64: Type the submit handler’s return for consistency with form.Makes intent explicit and avoids accidental return shapes.
- const handleUserDetailsSubmit = async (data: UserDetailsFormData) => { + const handleUserDetailsSubmit = async ( + data: UserDetailsFormData + ): Promise<{ error?: string }> => {
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (6)
src/app/(mobile-ui)/profile/indentity-verification/page.tsx(1 hunks)src/components/Global/Icons/Icon.tsx(3 hunks)src/components/Global/Icons/shield.tsx(1 hunks)src/components/Profile/components/ProfileMenuItem.tsx(5 hunks)src/components/Profile/index.tsx(5 hunks)src/components/Profile/views/IdentityVerification.view.tsx(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (4)
src/components/Profile/index.tsx (1)
src/context/authContext.tsx (1)
useAuth(182-188)
src/components/Profile/views/IdentityVerification.view.tsx (5)
src/context/authContext.tsx (1)
useAuth(182-188)src/hooks/useKycFlow.ts (1)
useKycFlow(38-186)src/components/AddMoney/UserDetailsForm.tsx (2)
UserDetailsFormData(7-11)UserDetailsForm(20-113)src/app/actions/users.ts (1)
updateUserById(12-35)src/components/Kyc/KycVerificationInProgressModal.tsx (1)
KycVerificationInProgressModal(12-54)
src/components/Global/Icons/Icon.tsx (1)
src/components/Global/Icons/shield.tsx (1)
ShieldIcon(3-16)
src/components/Profile/components/ProfileMenuItem.tsx (1)
src/components/Global/Icons/Icon.tsx (2)
IconName(63-122)Icon(192-201)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Deploy-Preview
🔇 Additional comments (6)
src/components/Global/Icons/Icon.tsx (1)
60-60: LGTM: Shield icon wired into the icon registryImport, union type, and mapping look correct. No runtime concerns.
Also applies to: 122-122, 189-190
src/components/Profile/index.tsx (3)
11-12: LGTM: Modal deps importedImports for ActionModal and useState are fine.
16-16: LGTM: Local modal stateState wiring is straightforward.
115-129: LGTM: “Already verified” modal UXClear message and single CTA works. Consider adding analytics event on open/close if you track KYC funnels.
src/components/Profile/components/ProfileMenuItem.tsx (2)
6-6: LGTM: Using tailwind-merge for dynamic icon classesSolid choice to avoid class conflicts.
16-18: LGTM: endIcon APINew props are minimal and useful for trailing indicators.
There was a problem hiding this comment.
Actionable comments posted: 0
♻️ Duplicate comments (1)
src/components/Profile/views/IdentityVerification.view.tsx (1)
1-3: Server-only import inside a client component (will break at build/hydration).
updateUserByIdfromapp/actions/usersusescookies()(server-only). Importing it in a"use client"component will fail in Next.js.Apply this diff to switch to a client-safe wrapper (ensure the wrapper exists):
'use client' -import { updateUserById } from '@/app/actions/users' +import { updateUserById } from '@/lib/client/users'I can add the minimal client helper and API route if you want me to push a follow-up patch.
🧹 Nitpick comments (2)
src/components/Profile/views/IdentityVerification.view.tsx (2)
21-29: Refresh user on KYC approval via hook callback.
PassonKycSuccesstouseKycFlowto fetch fresh user data when status flips to approved.- } = useKycFlow() + } = useKycFlow({ + onKycSuccess: async () => { + await fetchUser() + }, + })
31-41: Normalize name parsing and simplify memo dependencies.
Trim/collapse whitespace and compute first/last inside the memo; reduces re-computation and handles edge cases (single names, extra spaces).- const [firstName, ...lastNameParts] = (user?.user.fullName ?? '').split(' ') - const lastName = lastNameParts.join(' ') - - const initialUserDetails: Partial<UserDetailsFormData> = useMemo( - () => ({ - firstName: user?.user.fullName ? firstName : '', - lastName: user?.user.fullName ? lastName : '', - email: user?.user.email ?? '', - }), - [user?.user.fullName, user?.user.email, firstName, lastName] - ) + const initialUserDetails: Partial<UserDetailsFormData> = useMemo(() => { + const fullName = (user?.user.fullName ?? '').trim() + const [first, ...rest] = fullName ? fullName.split(/\s+/) : ['', ''] + return { + firstName: first || '', + lastName: rest.join(' ') || '', + email: user?.user.email ?? '', + } + }, [user?.user.fullName, user?.user.email])
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (3)
src/app/(mobile-ui)/profile/identity-verification/page.tsx(1 hunks)src/components/Profile/index.tsx(5 hunks)src/components/Profile/views/IdentityVerification.view.tsx(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- src/components/Profile/index.tsx
🧰 Additional context used
🧠 Learnings (3)
📚 Learning: 2025-08-20T09:08:19.266Z
Learnt from: kushagrasarathe
PR: peanutprotocol/peanut-ui#1112
File: src/components/Claim/Link/views/BankFlowManager.view.tsx:336-343
Timestamp: 2025-08-20T09:08:19.266Z
Learning: In the KYC flow implementation, `setJustCompletedKyc` must be called after `await fetchUser()` in the `handleKycSuccess` callback. Setting `justCompletedKyc` before fetching the user would cause a re-fetching loop because `handleKycSuccess` is set in a useEffect inside the KYC hook, which would cause the UI flow to get stuck in one view.
Applied to files:
src/components/Profile/views/IdentityVerification.view.tsx
📚 Learning: 2025-06-22T16:10:53.167Z
Learnt from: kushagrasarathe
PR: peanutprotocol/peanut-ui#915
File: src/hooks/useKycFlow.ts:96-124
Timestamp: 2025-06-22T16:10:53.167Z
Learning: The `initiateKyc` function in `src/app/actions/users.ts` already includes comprehensive error handling with try-catch blocks and returns structured responses with either `{ data }` or `{ error }` fields, so additional try-catch blocks around its usage are not needed.
Applied to files:
src/components/Profile/views/IdentityVerification.view.tsx
📚 Learning: 2025-08-11T10:35:02.715Z
Learnt from: kushagrasarathe
PR: peanutprotocol/peanut-ui#1078
File: src/hooks/useKycFlow.ts:129-141
Timestamp: 2025-08-11T10:35:02.715Z
Learning: In the KYC flow implementation in `src/hooks/useKycFlow.ts`, when Terms of Service (ToS) is accepted, there will always be a KYC link available in the `apiResponse`. The system ensures this invariant, so defensive checks for missing KYC links after ToS acceptance are unnecessary.
Applied to files:
src/components/Profile/views/IdentityVerification.view.tsx
🧬 Code graph analysis (1)
src/components/Profile/views/IdentityVerification.view.tsx (6)
src/context/authContext.tsx (1)
useAuth(182-188)src/hooks/useKycFlow.ts (1)
useKycFlow(38-186)src/components/AddMoney/UserDetailsForm.tsx (2)
UserDetailsFormData(7-11)UserDetailsForm(20-113)src/app/actions/users.ts (1)
updateUserById(12-35)src/components/0_Bruddle/Button.tsx (1)
Button(76-267)src/components/Kyc/KycVerificationInProgressModal.tsx (1)
KycVerificationInProgressModal(12-54)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Deploy-Preview
🔇 Additional comments (3)
src/app/(mobile-ui)/profile/identity-verification/page.tsx (1)
4-10: LGTM: page wires the view inside PageContainer correctly.
Straightforward server page rendering a client view; no issues spotted.src/components/Profile/views/IdentityVerification.view.tsx (2)
81-89: Good guardrails on CTA (prevents double actions).
Button correctly reflectsisUpdatingUser || isKycLoadingfor loading/disabled states.
93-93: User-facing errors surfaced properly.
CombininguserUpdateErrorandkycErrorensures visibility of both failure modes.
|
Wait for prod release before merging |
…-verification-button
No description provided.