-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Standardize UserRowItem #3192
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Standardize UserRowItem #3192
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
WalkthroughThis PR renames the public type Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes
Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (4)
apps/web/lib/zod/schemas/users.ts (1)
3-7: UserSchema email addition looks good; consider optional format validationAdding
email: z.string().nullable()cleanly extends the shared user shape and stays consistent withname/image. If you want to guarantee proper email formatting at this layer, you could switch toz.string().email().nullable(), but that’s optional depending on how strict you want this schema to be.apps/web/ui/partners/fraud-risks/fraud-events-tables/index.tsx (1)
1-1: Type rename is correct; consider typing tables to accept fraudEventGroupThe switch to
FraudEventGroupPropsforfraudEventGroupis consistent with the new shared type. As a follow‑up, you might consider tightening the table mapping to ensure each table component explicitly receives this prop, e.g.:-const FRAUD_EVENTS_TABLES: Partial<Record<FraudRuleType, React.ComponentType>> = { +const FRAUD_EVENTS_TABLES: Partial< + Record<FraudRuleType, React.ComponentType<{ fraudEventGroup: FraudEventGroupProps }>> +> = { // ... }; // ... - return <TableComponent />; + return <TableComponent fraudEventGroup={fraudEventGroup} />;That would let TypeScript enforce that all fraud event tables accept the same
fraudEventGroupshape.Also applies to: 21-33
apps/web/ui/users/user-row-item.tsx (1)
31-31: Consider adding fallback for tooltip display name.The tooltip displays
user.namedirectly without the fallback chain used elsewhere (line 18). Ifnameis null, this will render as empty. Consider using the same fallback for consistency:- <p className="text-sm font-medium">{user.name}</p> + <p className="text-sm font-medium">{name}</p>apps/web/ui/partners/fraud-risks/fraud-review-sheet.tsx (1)
202-206: Avatar fallback logic improved; consider consistent display name handling.The avatar source fallback to
user.idand alt text fallback chain are correctly implemented. However, similar touser-row-item.tsx, line 206 usesuser.namedirectly without the fallback chain. Consider extracting the display name to a variable for consistency:+ const displayName = user.name ?? user.email ?? user.id; <img src={user.image || `${OG_AVATAR_URL}${user.id}`} - alt={user.name ?? user.email ?? user.id} + alt={displayName} className="size-6 shrink-0 rounded-full" /> - <p className="text-sm font-medium">{user.name}</p> + <p className="text-sm font-medium">{displayName}</p>Also applies to: 223-224
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (15)
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/fraud/fraud-event-groups-table.tsx(5 hunks)apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/fraud/resolve-fraud-events-modal.tsx(3 hunks)apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/fraud/resolved/resolved-fraud-event-groups-table.tsx(6 hunks)apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/payouts/payout-paid-cell.tsx(3 hunks)apps/web/lib/api/fraud/get-grouped-fraud-events.ts(3 hunks)apps/web/lib/swr/use-fraud-event-groups.ts(2 hunks)apps/web/lib/types.ts(2 hunks)apps/web/lib/zod/schemas/fraud.ts(1 hunks)apps/web/lib/zod/schemas/payouts.ts(2 hunks)apps/web/lib/zod/schemas/users.ts(1 hunks)apps/web/tests/fraud/index.test.ts(2 hunks)apps/web/ui/partners/fraud-risks/commissions-on-hold-table.tsx(2 hunks)apps/web/ui/partners/fraud-risks/fraud-events-tables/index.tsx(2 hunks)apps/web/ui/partners/fraud-risks/fraud-review-sheet.tsx(4 hunks)apps/web/ui/users/user-row-item.tsx(1 hunks)
🧰 Additional context used
🧠 Learnings (9)
📚 Learning: 2025-11-24T09:10:12.536Z
Learnt from: devkiran
Repo: dubinc/dub PR: 3089
File: apps/web/lib/api/fraud/fraud-rules-registry.ts:17-25
Timestamp: 2025-11-24T09:10:12.536Z
Learning: In apps/web/lib/api/fraud/fraud-rules-registry.ts, the fraud rules `partnerCrossProgramBan` and `partnerDuplicatePayoutMethod` intentionally have stub implementations that return `{ triggered: false }` because they are partner-scoped rules handled separately during partner application/onboarding flows (e.g., in detect-record-fraud-application.ts), rather than being evaluated per conversion event like other rules in the registry. The stubs exist only to satisfy the `Record<FraudRuleType, ...>` type constraint.
Applied to files:
apps/web/tests/fraud/index.test.tsapps/web/ui/partners/fraud-risks/fraud-events-tables/index.tsxapps/web/lib/zod/schemas/fraud.tsapps/web/ui/partners/fraud-risks/commissions-on-hold-table.tsxapps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/fraud/resolved/resolved-fraud-event-groups-table.tsxapps/web/lib/types.tsapps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/fraud/resolve-fraud-events-modal.tsxapps/web/lib/swr/use-fraud-event-groups.tsapps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/fraud/fraud-event-groups-table.tsxapps/web/ui/partners/fraud-risks/fraud-review-sheet.tsx
📚 Learning: 2025-12-03T09:19:48.164Z
Learnt from: devkiran
Repo: dubinc/dub PR: 3175
File: apps/web/lib/actions/partners/bulk-reject-partner-applications.ts:14-21
Timestamp: 2025-12-03T09:19:48.164Z
Learning: In apps/web/lib/actions/partners/bulk-reject-partner-applications.ts, the bulkRejectPartnerApplicationsAction does not need explicit plan capability checks for fraud operations (when reportFraud is true) because the authorization is handled automatically by the underlying fraud operation functions (resolveFraudGroups, createFraudEvents) or through other automated mechanisms in the system.
Applied to files:
apps/web/tests/fraud/index.test.tsapps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/fraud/resolved/resolved-fraud-event-groups-table.tsxapps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/fraud/resolve-fraud-events-modal.tsxapps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/fraud/fraud-event-groups-table.tsxapps/web/ui/partners/fraud-risks/fraud-review-sheet.tsx
📚 Learning: 2025-11-24T08:55:31.332Z
Learnt from: devkiran
Repo: dubinc/dub PR: 3089
File: apps/web/app/(ee)/api/fraud-rules/route.ts:71-87
Timestamp: 2025-11-24T08:55:31.332Z
Learning: In apps/web/app/(ee)/api/fraud-rules/route.ts, fraud rules cannot be created in a disabled state. When using prisma.fraudRule.upsert, the create branch intentionally omits the disabledAt field (defaulting to null, meaning enabled), while the update branch allows toggling enabled/disabled state via the disabledAt field. This is a business logic constraint.
Applied to files:
apps/web/tests/fraud/index.test.ts
📚 Learning: 2025-08-16T11:14:00.667Z
Learnt from: devkiran
Repo: dubinc/dub PR: 2754
File: apps/web/lib/partnerstack/schemas.ts:47-52
Timestamp: 2025-08-16T11:14:00.667Z
Learning: The PartnerStack API always includes the `group` field in partner responses, so the schema should use `.nullable()` rather than `.nullish()` since the field is never omitted/undefined.
Applied to files:
apps/web/lib/zod/schemas/fraud.ts
📚 Learning: 2025-10-15T01:05:43.266Z
Learnt from: steven-tey
Repo: dubinc/dub PR: 2958
File: apps/web/app/app.dub.co/(dashboard)/[slug]/settings/members/page-client.tsx:432-457
Timestamp: 2025-10-15T01:05:43.266Z
Learning: In apps/web/app/app.dub.co/(dashboard)/[slug]/settings/members/page-client.tsx, defer refactoring the custom MenuItem component (lines 432-457) to use the shared dub/ui MenuItem component to a future PR, as requested by steven-tey.
Applied to files:
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/fraud/resolved/resolved-fraud-event-groups-table.tsxapps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/fraud/resolve-fraud-events-modal.tsxapps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/fraud/fraud-event-groups-table.tsx
📚 Learning: 2025-07-30T15:25:13.936Z
Learnt from: TWilson023
Repo: dubinc/dub PR: 2673
File: apps/web/ui/partners/rewards/add-edit-reward-sheet.tsx:56-66
Timestamp: 2025-07-30T15:25:13.936Z
Learning: In apps/web/ui/partners/rewards/add-edit-reward-sheet.tsx, the form schema uses partial condition objects to allow users to add empty/unconfigured condition fields without type errors, while submission validation uses strict schemas to ensure data integrity. This two-stage validation pattern improves UX by allowing progressive completion of complex forms.
Applied to files:
apps/web/lib/zod/schemas/payouts.ts
📚 Learning: 2025-07-17T06:41:45.620Z
Learnt from: devkiran
Repo: dubinc/dub PR: 2637
File: apps/web/app/(ee)/api/singular/webhook/route.ts:0-0
Timestamp: 2025-07-17T06:41:45.620Z
Learning: In the Singular integration (apps/web/app/(ee)/api/singular/webhook/route.ts), the event names in the singularToDubEvent object have intentionally different casing: "Copy GAID" and "copy IDFA". This casing difference is valid and should not be changed, as these are the correct event names expected from Singular.
Applied to files:
apps/web/lib/types.tsapps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/fraud/resolve-fraud-events-modal.tsx
📚 Learning: 2025-10-15T01:52:37.048Z
Learnt from: steven-tey
Repo: dubinc/dub PR: 2958
File: apps/web/app/(ee)/partners.dub.co/(dashboard)/profile/members/page-client.tsx:270-303
Timestamp: 2025-10-15T01:52:37.048Z
Learning: In React components with dropdowns or form controls that show modals for confirmation (e.g., role selection, delete confirmation), local state should be reverted to match the prop value when the modal is cancelled. This prevents the UI from showing an unconfirmed change. The solution is to either: (1) pass an onClose callback to the modal that resets the local state, or (2) observe modal visibility state and reset on close. Example context: RoleCell component in apps/web/app/(ee)/partners.dub.co/(dashboard)/profile/members/page-client.tsx where role dropdown should revert to user.role when UpdateUserModal is cancelled.
Applied to files:
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/fraud/resolve-fraud-events-modal.tsx
📚 Learning: 2025-08-26T15:05:55.081Z
Learnt from: TWilson023
Repo: dubinc/dub PR: 2736
File: apps/web/lib/swr/use-bounty.ts:11-16
Timestamp: 2025-08-26T15:05:55.081Z
Learning: In the Dub codebase, workspace authentication and route structures prevent endless loading states when workspaceId or similar route parameters are missing, so gating SWR loading states on parameter availability is often unnecessary.
Applied to files:
apps/web/lib/swr/use-fraud-event-groups.ts
🧬 Code graph analysis (13)
apps/web/tests/fraud/index.test.ts (1)
apps/web/lib/types.ts (1)
FraudEventGroupProps(676-676)
apps/web/ui/partners/fraud-risks/fraud-events-tables/index.tsx (1)
apps/web/lib/types.ts (1)
FraudEventGroupProps(676-676)
apps/web/lib/zod/schemas/fraud.ts (1)
apps/web/lib/zod/schemas/users.ts (1)
UserSchema(3-8)
apps/web/ui/partners/fraud-risks/commissions-on-hold-table.tsx (1)
apps/web/lib/types.ts (1)
FraudEventGroupProps(676-676)
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/fraud/resolved/resolved-fraud-event-groups-table.tsx (2)
packages/email/src/react-email.d.ts (1)
Row(9-9)apps/web/lib/types.ts (1)
FraudEventGroupProps(676-676)
apps/web/lib/zod/schemas/payouts.ts (1)
apps/web/lib/zod/schemas/users.ts (1)
UserSchema(3-8)
apps/web/lib/types.ts (1)
apps/web/lib/zod/schemas/fraud.ts (1)
groupedFraudEventSchema(12-28)
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/fraud/resolve-fraud-events-modal.tsx (1)
apps/web/lib/types.ts (1)
FraudEventGroupProps(676-676)
apps/web/lib/swr/use-fraud-event-groups.ts (1)
apps/web/lib/types.ts (1)
FraudEventGroupProps(676-676)
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/fraud/fraud-event-groups-table.tsx (2)
apps/web/lib/types.ts (1)
FraudEventGroupProps(676-676)packages/ui/src/table/table.tsx (1)
useTable(51-243)
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/payouts/payout-paid-cell.tsx (1)
packages/utils/src/constants/misc.ts (1)
OG_AVATAR_URL(29-29)
apps/web/ui/users/user-row-item.tsx (2)
apps/web/lib/types.ts (1)
UserProps(244-256)packages/utils/src/constants/misc.ts (1)
OG_AVATAR_URL(29-29)
apps/web/ui/partners/fraud-risks/fraud-review-sheet.tsx (2)
apps/web/lib/types.ts (1)
FraudEventGroupProps(676-676)packages/utils/src/constants/misc.ts (1)
OG_AVATAR_URL(29-29)
⏰ 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: build
🔇 Additional comments (15)
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/payouts/payout-paid-cell.tsx (1)
8-8: LGTM! Email field addition improves fallback options.The addition of the optional
PayoutPaidCellUserenables a better fallback chain for displaying user information when the name is unavailable.apps/web/lib/zod/schemas/payouts.ts (1)
8-8: Good reuse of UserSchema; verify all payout responses now include user.emailSwitching
usertoUserSchema.nullish()nicely centralizes the shape and allows email to propagate through payout responses. The only caveat is that any place constructingPayoutResponseSchemamust now include anuserwhen present; otherwise Zod parsing will start failing where it previously passed with just{ id, name, image }.Please double‑check the APIs/actions that produce
PayoutResponseSchemato ensure they populateuser.emailwherever a user object is returned.Also applies to: 69-77
apps/web/tests/fraud/index.test.ts (1)
1-1: FraudEventGroupProps rename in tests is consistentThe test now imports and uses
FraudEventGroupProps[]inwaitForFraudEvent, which matches the new exported alias in@/lib/types. No behavioral change; just a clean type rename.Also applies to: 237-253
apps/web/lib/api/fraud/get-grouped-fraud-events.ts (1)
13-31: User email propagation in grouped fraud events is wired correctlyAdding
userEmailtoQueryResult, selectingu.email AS userEmail, and threading it into theuserobject (email: event.userEmail) keeps the SQL, TypeScript type, andUserSchema(with nullable email) all in sync. This should satisfy the updatedgroupedFraudEventSchemawithout changing existing behavior for events whereuserIdis null.Also applies to: 66-86, 123-130
apps/web/ui/partners/fraud-risks/commissions-on-hold-table.tsx (1)
2-3: CommissionsOnHoldTable now correctly typed against FraudEventGroupPropsWiring
fraudEventGroup: FraudEventGroupPropsinto the props and using it to derivepartnerIdkeeps this table aligned with the canonicalgroupedFraudEventSchematype and the rest of the fraud UI.Also applies to: 23-27, 39-44
apps/web/lib/types.ts (1)
62-65: FraudEventGroupProps alias is correctly defined from groupedFraudEventSchemaImporting
groupedFraudEventSchemaand exportingFraudEventGroupProps = z.infer<typeof groupedFraudEventSchema>gives a single canonical type for grouped fraud events, matching the PascalCase convention you’re standardizing on.Also applies to: 676-677
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/fraud/resolve-fraud-events-modal.tsx (1)
7-7: Modal + hook now correctly use FraudEventGroupPropsTyping
fraudEventGroupasFraudEventGroupPropsin both the modal component anduseResolveFraudEventsModalkeeps this flow aligned with the shared grouped fraud event schema while preserving existing behavior aroundgroupKey,count, andpartner.Also applies to: 29-39, 168-174
apps/web/lib/swr/use-fraud-event-groups.ts (1)
5-5: LGTM!The type rename from
fraudEventGroupPropstoFraudEventGroupPropscorrectly follows PascalCase conventions for TypeScript types, and the usage is consistent throughout the hook.Also applies to: 29-29
apps/web/ui/users/user-row-item.tsx (1)
17-18: LGTM - Improved fallback logic.Using
user.idfor avatar fallback is more reliable thanuser.namesinceidis non-nullable in the schema, whilenamecan be null. The display name fallback chain (name ?? email ?? id) provides progressively useful information.apps/web/ui/partners/fraud-risks/fraud-review-sheet.tsx (1)
4-4: LGTM - Type rename applied consistently.The import and interface prop type are correctly updated to use
FraudEventGroupProps.Also applies to: 28-28
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/fraud/resolved/resolved-fraud-event-groups-table.tsx (3)
6-6: LGTM - Import updated consistently.
86-86: LGTM - Table column row types updated consistently.All
Row<FraudEventGroupProps>type annotations are correctly applied across the column definitions.Also applies to: 124-124, 138-138, 153-153
296-307: LGTM - Hook parameter type correctly updated.The
useCurrentFraudEventGroupfunction parameter type is correctly updated toFraudEventGroupProps[], maintaining consistency with the rest of the codebase.apps/web/lib/zod/schemas/fraud.ts (1)
27-27: LGTM - Schema expanded to include full user data with proper data source support.Broadening from
UserSchema.pick({ id, name, image })to the fullUserSchemaenables the email fallback chain used in UI components. The data source (get-grouped-fraud-events.ts) already fetches and provides theapps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/fraud/fraud-event-groups-table.tsx (1)
7-7: LGTM! Type renaming follows PascalCase convention.The consistent rename from
fraudEventGroupPropstoFraudEventGroupPropsacross all type annotations, generic parameters, and import statements properly follows TypeScript naming conventions for types.Also applies to: 87-87, 91-91, 103-103, 372-372, 468-468
| src={user.image || `${OG_AVATAR_URL}${user.id}`} | ||
| alt={user.name ?? user.email ?? user.id} | ||
| className="size-6 shrink-0 rounded-full" | ||
| /> | ||
| <p className="text-sm font-medium">{user.name}</p> | ||
| <p className="text-sm font-medium"> | ||
| {user.name ?? user.email ?? user.id} | ||
| </p> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add safeguards for undefined user.id in fallback chain.
The type definition allows id to be optional (id?: string), but the fallback logic assumes at least user.id will always be present. If all three fields (name, email, id) are undefined or null, this will result in:
- Avatar URL:
https://api.dub.co/og/avatar/undefined(broken image) - Alt text:
undefined(accessibility violation) - Display text:
undefined(blank/confusing UI)
Consider one of these approaches:
Option 1: Add a guard to ensure at least id exists
- {user && (
+ {user?.id && (
<img
src={user.image || `${OG_AVATAR_URL}${user.id}`}
alt={user.name ?? user.email ?? user.id}
className="size-5 shrink-0 rounded-full"
/>
)}Option 2: Add a fallback string constant
- src={user.image || `${OG_AVATAR_URL}${user.id}`}
- alt={user.name ?? user.email ?? user.id}
+ src={user.image || `${OG_AVATAR_URL}${user.id ?? 'unknown'}`}
+ alt={user.name ?? user.email ?? user.id ?? 'Unknown user'}Apply similar changes to lines 41-43 for the display text.
Also applies to: 84-85
🤖 Prompt for AI Agents
In
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/payouts/payout-paid-cell.tsx
around lines 37-43 (and also apply to 84-85), the fallback chain assumes user.id
exists which can yield "undefined" in the avatar URL, alt text, and display
text; fix this by adding a safe fallback constant (e.g., const FALLBACK_NAME =
"Unknown user") and use it for alt and display text when name, email, and id are
all falsy, and build the avatar src only when user.image exists or user.id is
defined (otherwise use a default avatar URL without interpolating undefined);
update the three usages (src, alt, and visible text) to use these guarded
fallbacks.
Summary by CodeRabbit
New Features
Refactor
✏️ Tip: You can customize this high-level summary in your review settings.