Add ActivityRing component and update to program owner activity#3342
Add ActivityRing component and update to program owner activity#3342steven-tey merged 3 commits intomainfrom
Conversation
Introduces a new ActivityRing component for visualizing positive and negative metrics. Refactors PartnerCrossProgramSummary to use ActivityRing and improves loading and stat row presentation. Exports ActivityRing from the UI package.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
📝 WalkthroughWalkthroughReplaces per-item cross-program metric rendering with a consolidated ActivityRing visualization and two StatRow entries, adds a LoadingSkeleton early return, and exports the new ActivityRing from the UI package. Data is destructured into totalPrograms, trustedPrograms, and removedPrograms. Changes
Sequence Diagram(s)(omitted) Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested reviewers
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
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.
Actionable comments posted: 0
🧹 Nitpick comments (1)
apps/web/ui/partners/fraud-risks/partner-cross-program-summary.tsx (1)
4-4: Remove unusedUserimport.
Useris imported but not used anywhere in this file.Suggested fix
-import { ActivityRing, User, UserCheck, UserXmark } from "@dub/ui"; +import { ActivityRing, UserCheck, UserXmark } from "@dub/ui";
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
apps/web/ui/partners/fraud-risks/partner-cross-program-summary.tsxpackages/ui/src/activity-ring.tsxpackages/ui/src/index.tsx
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-11-24T16:36:36.196Z
Learnt from: CR
Repo: dubinc/dub PR: 0
File: packages/hubspot-app/CLAUDE.md:0-0
Timestamp: 2025-11-24T16:36:36.196Z
Learning: Applies to packages/hubspot-app/app/cards/**/*.{js,jsx,ts,tsx} : Only components exported from the `hubspot/ui-extensions` npm package can be used in card components
Applied to files:
packages/ui/src/index.tsx
📚 Learning: 2025-05-29T04:45:18.504Z
Learnt from: devkiran
Repo: dubinc/dub PR: 2448
File: packages/email/src/templates/partner-program-summary.tsx:0-0
Timestamp: 2025-05-29T04:45:18.504Z
Learning: In the PartnerProgramSummary email template (packages/email/src/templates/partner-program-summary.tsx), the stat titles are hardcoded constants ("Clicks", "Leads", "Sales", "Earnings") that will always match the ICONS object keys after toLowerCase() conversion, so icon lookup failures are not possible.
Applied to files:
apps/web/ui/partners/fraud-risks/partner-cross-program-summary.tsx
⏰ 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 (9)
packages/ui/src/index.tsx (1)
6-6: LGTM!The new
activity-ringexport follows the established alphabetical ordering pattern in this barrel file.apps/web/ui/partners/fraud-risks/partner-cross-program-summary.tsx (2)
6-45: Clean refactor with proper loading state handling.The component correctly handles loading states, destructures data cleanly, and integrates well with the new
ActivityRingcomponent. The separation between the visual ring and the textualStatRowcomponents provides good information density.
47-83: LGTM!The
StatRowandLoadingSkeletonhelpers are clean and well-structured. The skeleton dimensions appropriately match the loaded content layout.packages/ui/src/activity-ring.tsx (6)
6-20: Well-documented props interface.The JSDoc comments on each prop provide clear guidance for consumers of this component.
37-88: LGTM!The geometry helper functions are mathematically sound. The -90 degree offset in
polarToCartesiancorrectly positions 0° at the top, and the arc path generation follows standard SVG conventions.
108-156: Arc calculation logic is sound.The minimum arc visibility enforcement correctly handles edge cases where one value is very small relative to the other. The sequential checks work correctly because with the current constants (
MIN_ARC_DEGREES=30,availableSweep=330), it's impossible for both sweeps to be below the minimum simultaneously.
158-162: LGTM!The radius calculations correctly account for SVG stroke positioning, and the proportional
fillInnerRadiusensures the component scales consistently.
164-188: LGTM!The memoization is appropriately used for the icon selection and color determination.
190-299: Clean SVG rendering with proper layering.The SVG structure correctly layers filled arcs behind strokes, and the conditional rendering based on state is well-organized. The centered icon implementation is clean.
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (1)
packages/ui/src/activity-ring.tsx (1)
158-188: Consider simplifying unused intermediate variables.
positiveColorandnegativeColor(lines 187-188) are assigned from COLORS but could be inlined directly in the JSX since they never change. This is a minor nitpick—the current approach is also fine if you anticipate future dynamic color logic.
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
apps/web/ui/partners/fraud-risks/partner-cross-program-summary.tsxpackages/ui/src/activity-ring.tsx
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-05-29T04:45:18.504Z
Learnt from: devkiran
Repo: dubinc/dub PR: 2448
File: packages/email/src/templates/partner-program-summary.tsx:0-0
Timestamp: 2025-05-29T04:45:18.504Z
Learning: In the PartnerProgramSummary email template (packages/email/src/templates/partner-program-summary.tsx), the stat titles are hardcoded constants ("Clicks", "Leads", "Sales", "Earnings") that will always match the ICONS object keys after toLowerCase() conversion, so icon lookup failures are not possible.
Applied to files:
apps/web/ui/partners/fraud-risks/partner-cross-program-summary.tsx
🧬 Code graph analysis (1)
apps/web/ui/partners/fraud-risks/partner-cross-program-summary.tsx (1)
packages/ui/src/activity-ring.tsx (1)
ActivityRing(92-270)
⏰ 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 (9)
packages/ui/src/activity-ring.tsx (4)
1-35: LGTM! Well-structured type definitions and constants.The props interface is well-documented with JSDoc comments, and the color constants are clearly named. The GAP_ANGLE and MIN_ARC_DEGREES constants provide good configurability for the visual appearance.
37-88: LGTM! Clean SVG path generation helpers.The polar-to-cartesian conversion and arc path generation functions are mathematically correct. The
describeFilledArcfunction properly creates a closed donut-slice path by drawing the outer arc, connecting to the inner arc, and closing the path.
101-156: Verify behavior when both values are at the minimum arc threshold.The minimum arc visibility logic at lines 135-142 handles each value independently. If both
positiveValueandnegativeValueare non-zero but have extremely skewed ratios (e.g., 1:1000), the first condition adjusts the minority arc toMIN_ARC_DEGREES, leaving plenty of room for the majority arc. However, consider adding a comment explaining why the conditions can't conflict (after expanding one arc, the remaining sweep is always > MIN_ARC_DEGREES).Also, when one value is exactly 0, the stroke arc still renders with zero sweep (start === end), which may produce a tiny dot with
strokeLinecap="round"in some browsers—though this is likely imperceptible.
190-269: LGTM! Clean SVG rendering with proper conditional logic.The component correctly renders filled arcs only when values are positive, ensuring the neutral state (both values = 0) shows only stroke arcs. The icon overlay is properly centered and responds to the computed state. Good use of the
cnutility for className composition.apps/web/ui/partners/fraud-risks/partner-cross-program-summary.tsx (5)
4-4: LGTM! Clean import of new UI components.The ActivityRing and icon components are properly imported from the shared UI package.
15-20: LGTM! Good defensive loading check.The early return handles both the loading state and the case where
crossProgramSummaryis undefined/null, preventing runtime errors during data fetching.
22-45: LGTM! Clean integration of ActivityRing with StatRow layout.The component properly wires up the trusted/removed values to the positive/negative props of ActivityRing, with appropriate icons for each state. The flex layout with
min-w-0 growensures proper text truncation behavior if needed.
47-65: LGTM! Simple and effective StatRow component.The component is well-typed and renders a clean label-value pair layout. The typography classes provide appropriate visual hierarchy.
67-89: LGTM! LoadingSkeleton properly mirrors the actual content layout.The skeleton dimensions match the rendered content structure—
size-10(40px) matches ActivityRing's default size, and the placeholder widths approximate the stat row content. The consistent use ofanimate-pulseandbg-neutral-200follows common loading state patterns.
Introduces a new
ActivityRingcomponent for visualizing positive and negative metrics. RefactorsPartnerCrossProgramSummaryto useActivityRingand improves loading and row presentation.Component is also used in the fraud review drawer.
Neutral
Trustworthy leading
Removed leading
Summary by CodeRabbit
✏️ Tip: You can customize this high-level summary in your review settings.