Skip to content

Conversation

@drifter089
Copy link
Owner

@drifter089 drifter089 commented Jan 9, 2026

Summary

Refactors the member profile page to eliminate duplicate components by reusing existing RoleCard and KpiCard components.

Changes

  • Create new RoleKpiPair component with paired layout (role info left, KPI right)
  • Update TeamSection to use the new component
  • Delete duplicate MemberRoleCard component
  • Responsive design: side-by-side on desktop, stacked on mobile

Summary by CodeRabbit

  • Refactor
    • Restructured member role card display with improved KPI integration and layout adjustments. Role cards now render in a single-column vertical layout with better KPI data presentation when available.

✏️ Tip: You can customize this high-level summary in your review settings.

Replace custom MemberRoleCard with existing RoleCard and KpiCard components.
Each role now displays as a paired layout with role info on left and KPI on right.
@vercel
Copy link

vercel bot commented Jan 9, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (UTC)
org-os Ready Ready Preview, Comment Jan 9, 2026 3:23pm

@coderabbitai
Copy link

coderabbitai bot commented Jan 9, 2026

📝 Walkthrough

Walkthrough

This PR removes the MemberRoleCard component and replaces it with a new RoleKpiPair component that restructures role and KPI display. The new component separates role card rendering from KPI/chart rendering using conditional logic based on dashboard chart availability. The team-section.tsx is updated to use the new component with an additional teamId prop.

Changes

Cohort / File(s) Summary
Component Removal
src/app/member/[id]/_components/member-role-card.tsx
Deleted 85-line component that rendered role cards with optional KPI metrics, charts, and effort points. Removed exported MemberRoleCard function and type aliases Role, DashboardMetrics, and interface MemberRoleCardProps.
Component Addition
src/app/member/[id]/_components/role-kpi-pair.tsx
New 68-line component that renders a role card paired with conditional KPI/chart rendering. Accepts role, optional dashboardChart, and teamId props. Renders RoleCard (read-only) with KpiCard when chart available, or loading placeholder when metric exists without chart. Uses grid layout conditionally based on KPI presence.
Component Integration
src/app/member/[id]/_components/team-section.tsx
Updated to use new RoleKpiPair instead of MemberRoleCard. Removed grid layout in favor of vertical stack (space-y-4). Added teamId prop passing to RoleKpiPair. Minor restructuring of role/chart data mapping logic.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

🐰 A card once whole, now split with care,
RoleKpiPair dances through the air,
MemberRoleCard bids farewell,
New structure rings a cleaner bell! ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: refactoring to reuse RoleCard and KpiCard components in the member page by removing MemberRoleCard and introducing RoleKpiPair.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@claude
Copy link
Contributor

claude bot commented Jan 9, 2026

Code Review - PR #367

Summary

This is an excellent refactoring that eliminates duplicate code by reusing existing RoleCard and KpiCard components. The PR successfully replaces the custom MemberRoleCard with a new RoleKpiPair component that composes the existing primitives.


✅ Strengths

  1. Excellent Code Reuse: Eliminates 85 lines of duplicate code by leveraging existing components. This aligns perfectly with the CLAUDE.md principle of avoiding duplication.

  2. Clean Component Composition: The new RoleKpiPair component follows React best practices by composing RoleCard and KpiCard rather than reimplementing their logic.

  3. Proper Type Safety: Uses proper TypeScript types from tRPC router outputs and correctly maps to RoleCardData.

  4. Responsive Design: Implements smart responsive behavior with side-by-side layout on desktop (lg:grid-cols-2) and stacked layout on mobile.

  5. Edge Case Handling: Properly handles three states:

    • Role with KPI chart (shows both)
    • Role with metric but no chart yet (shows loading placeholder)
    • Role without metric (shows only role card)
  6. Consistent Props: Properly passes configuration props (readOnly, showSettings={false}, enableDragDrop={false}) to disable interactive features in the member profile context.


🔍 Minor Observations

  1. Color Fallback: Line 26 uses a hardcoded fallback color #3b82f6:

    color: role.color ?? "#3b82f6",

    This is reasonable, but consider checking if there's a shared constant for the default role color in src/lib/role/role-constants.ts to maintain consistency.

  2. Loading State UX: The "KPI data loading..." message (line 63) is simple but functional. Consider:

    • Adding a Loader2 spinner for visual consistency with other loading states in the codebase
    • This is minor and current implementation is acceptable
  3. No Tests: No test coverage for the new component. While not blocking, consider adding basic tests given the component handles multiple conditional states.


🎯 Architecture & Patterns

Follows CLAUDE.md Guidelines:

  • Uses shared UI components from src/components/
  • Proper TypeScript with tRPC types
  • No over-engineering - solution is appropriately scoped
  • Responsive design with Tailwind utilities

Component Design:

  • Clear single responsibility
  • Proper prop typing
  • Good separation of concerns

Integration:

  • TeamSection properly updated to use new component
  • Maintains existing functionality with cleaner implementation

🔒 Security & Performance

  • No security concerns: Component is client-side display only, uses existing secure components
  • Performance: Neutral to positive impact (less code, same render behavior)
  • No bundle size concerns: Net reduction in code

📝 Recommendations

  1. Optional Enhancement: Consider extracting the default color constant if it exists elsewhere in the codebase:

    import { DEFAULT_ROLE_COLOR } from "@/lib/role/role-constants";
    // ...
    color: role.color ?? DEFAULT_ROLE_COLOR,
  2. Loading State Enhancement (optional, low priority):

    {hasMetricButNoChart && (
      <div className="border-border/60 text-muted-foreground flex items-center justify-center gap-2 rounded-lg border border-dashed p-6">
        <Loader2 className="h-4 w-4 animate-spin" />
        <span className="text-sm">KPI data loading...</span>
      </div>
    )}
  3. Test Coverage (optional): Add basic component tests for the three conditional rendering states.


✅ Verdict

LGTM - Approve with minor optional suggestions

This is a well-executed refactoring that:

  • ✅ Reduces code duplication (net -18 lines)
  • ✅ Improves maintainability
  • ✅ Follows established patterns
  • ✅ No breaking changes
  • ✅ Proper responsive design
  • ✅ Type-safe implementation

The suggestions above are optional improvements and should not block merging. Great work! 🚀

@drifter089 drifter089 merged commit 1b381b7 into main Jan 9, 2026
4 of 5 checks passed
Copy link

@coderabbitai coderabbitai bot left a 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

🤖 Fix all issues with AI agents
In @src/app/member/[id]/_components/role-kpi-pair.tsx:
- Around line 61-65: The current placeholder shown when hasMetricButNoChart is
true is ambiguous; update the UI to distinguish between "no chart configured"
and "still loading" by either changing the message in the hasMetricButNoChart
branch to a clearer statement like "No KPI data available" (or "KPI chart not
configured") and/or wire in an explicit loading flag from where dashboardChart
is populated; specifically, update the JSX branch that checks
hasMetricButNoChart (and references role.metricId and the dashboardChart lookup)
to show the clearer static message or conditionalize on a new loading boolean so
genuine loading uses "Loading KPI data…" while missing chart shows "No KPI data
available."
🧹 Nitpick comments (1)
src/app/member/[id]/_components/role-kpi-pair.tsx (1)

22-36: Consider using a theme constant for the color fallback.

The hardcoded color "#3b82f6" could be extracted to a theme constant for better maintainability.

♻️ Example: Using a theme constant
+import { DEFAULT_ROLE_COLOR } from "@/lib/constants/theme";

 const roleCardData: RoleCardData = {
   id: role.id,
   title: role.title,
   purpose: role.purpose,
-  color: role.color ?? "#3b82f6",
+  color: role.color ?? DEFAULT_ROLE_COLOR,
   effortPoints: role.effortPoints,
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 471197e and 2473556.

📒 Files selected for processing (3)
  • src/app/member/[id]/_components/member-role-card.tsx
  • src/app/member/[id]/_components/role-kpi-pair.tsx
  • src/app/member/[id]/_components/team-section.tsx
💤 Files with no reviewable changes (1)
  • src/app/member/[id]/_components/member-role-card.tsx
🧰 Additional context used
📓 Path-based instructions (6)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (GEMINI.md)

Use TypeScript 5.9 with strict type checking for all frontend and backend code

Files:

  • src/app/member/[id]/_components/team-section.tsx
  • src/app/member/[id]/_components/role-kpi-pair.tsx
src/**/*.tsx

📄 CodeRabbit inference engine (GEMINI.md)

Prefer Server Components for initial data fetching; use Client Components ('use client') only for interactivity

Files:

  • src/app/member/[id]/_components/team-section.tsx
  • src/app/member/[id]/_components/role-kpi-pair.tsx
src/**/*/*.tsx

📄 CodeRabbit inference engine (GEMINI.md)

Client Components must use import { api } from '@/trpc/react' for standard HTTP/Hooks wrapper

Files:

  • src/app/member/[id]/_components/team-section.tsx
  • src/app/member/[id]/_components/role-kpi-pair.tsx
**/*.tsx

📄 CodeRabbit inference engine (GEMINI.md)

Use Tailwind CSS 4 for styling with shadcn/ui and Radix UI primitive components

Files:

  • src/app/member/[id]/_components/team-section.tsx
  • src/app/member/[id]/_components/role-kpi-pair.tsx
src/app/**/*.tsx

📄 CodeRabbit inference engine (CLAUDE.md)

src/app/**/*.tsx: Use the dual tRPC API pattern: direct calls in Server Components (api.team.getById) for 10x faster performance, and React hooks in Client Components (api.team.getById.useQuery)
Use getUserDisplayName(userId, members) utility (client-side sync) from @/lib/helpers/get-user-name for displaying user names in components

Files:

  • src/app/member/[id]/_components/team-section.tsx
  • src/app/member/[id]/_components/role-kpi-pair.tsx
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Use @trivago/prettier-plugin-sort-imports with inline type imports for import organization

Files:

  • src/app/member/[id]/_components/team-section.tsx
  • src/app/member/[id]/_components/role-kpi-pair.tsx
🧠 Learnings (15)
📓 Common learnings
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-29T12:52:42.935Z
Learning: Applies to src/app/teams/[teamId]/_components/role-node.tsx,src/app/teams/[teamId]/_components/public-role-node.tsx : These role node components are 75% identical and should be consolidated. Extract shared `RoleNodeTemplate` component with `isEditable` prop to DRY up the code.
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-29T21:27:04.176Z
Learning: Applies to src/app/(teams|org)/**/*.tsx : Use shared MembersList component at src/components/member/member-list.tsx for displaying members in canvas sidebar and org page; it includes getMemberDisplayInfo() utility for initials/name logic
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-29T12:52:42.935Z
Learning: Applies to src/components/dashboard-metric-card.tsx,src/app/dashboard/[teamId]/_components/public-dashboard-metric-card.tsx : Dashboard metric cards are duplicated with public variant. Consolidate into single component with `readOnly` mode prop instead of maintaining separate components.
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-29T21:27:04.176Z
Learning: Applies to src/app/teams/[teamId]/_components/**/*.tsx : Implement cache-first node pattern for role nodes: store only roleId in node data, fetch display data from TanStack Query cache using useRoleData hook
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-29T21:27:04.176Z
Learning: Applies to src/hooks/**/*.ts : For role-metric cache updates, optimistically update both role cache (role.getByTeamId) and dashboard cache (dashboard.getDashboardCharts) to maintain UI consistency
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: GEMINI.md:0-0
Timestamp: 2025-12-20T22:12:00.576Z
Learning: Applies to src/app/teams/[teamId]/**/*.tsx : React Flow nodes must store minimal data (e.g., just `roleId`); fetch full Role data from TanStack Query cache in the Node component to keep canvas and sidebars in sync
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-29T12:52:42.935Z
Learning: Applies to src/app/dashboard/[teamId]/**/*.{ts,tsx} : Dashboard cache updates for role-metric assignments must update both `role.getByTeamId` and `dashboard.getDashboardCharts` caches during mutations. Use onMutate for optimistic updates on both caches, then invalidate both on success.
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-29T12:52:42.935Z
Learning: Applies to src/app/teams/[teamId]/**/*.{ts,tsx} : Cache-first node system: Role nodes store only `roleId` in node.data. Display data must be fetched from TanStack Query cache using the `useRoleData()` hook which queries the `role.getByTeamId` procedure.
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-29T21:27:04.176Z
Learning: Applies to src/server/api/**/*.ts : Use enrichRolesWithUserNames() for flat role arrays and enrichChartRolesWithUserNames() for nested chart roles from src/server/api/utils/organization-members.ts
📚 Learning: 2025-12-29T12:52:42.935Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-29T12:52:42.935Z
Learning: Applies to src/app/teams/[teamId]/_components/role-node.tsx,src/app/teams/[teamId]/_components/public-role-node.tsx : These role node components are 75% identical and should be consolidated. Extract shared `RoleNodeTemplate` component with `isEditable` prop to DRY up the code.

Applied to files:

  • src/app/member/[id]/_components/team-section.tsx
  • src/app/member/[id]/_components/role-kpi-pair.tsx
📚 Learning: 2025-12-29T21:27:04.176Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-29T21:27:04.176Z
Learning: Applies to src/app/teams/[teamId]/_components/**/*.tsx : Implement cache-first node pattern for role nodes: store only roleId in node data, fetch display data from TanStack Query cache using useRoleData hook

Applied to files:

  • src/app/member/[id]/_components/team-section.tsx
  • src/app/member/[id]/_components/role-kpi-pair.tsx
📚 Learning: 2025-12-20T22:12:00.576Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: GEMINI.md:0-0
Timestamp: 2025-12-20T22:12:00.576Z
Learning: Applies to src/app/teams/[teamId]/**/*.tsx : React Flow nodes must store minimal data (e.g., just `roleId`); fetch full Role data from TanStack Query cache in the Node component to keep canvas and sidebars in sync

Applied to files:

  • src/app/member/[id]/_components/team-section.tsx
  • src/app/member/[id]/_components/role-kpi-pair.tsx
📚 Learning: 2025-12-29T12:52:42.935Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-29T12:52:42.935Z
Learning: Applies to src/components/dashboard-metric-card.tsx,src/app/dashboard/[teamId]/_components/public-dashboard-metric-card.tsx : Dashboard metric cards are duplicated with public variant. Consolidate into single component with `readOnly` mode prop instead of maintaining separate components.

Applied to files:

  • src/app/member/[id]/_components/team-section.tsx
  • src/app/member/[id]/_components/role-kpi-pair.tsx
📚 Learning: 2025-12-29T21:27:04.176Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-29T21:27:04.176Z
Learning: Applies to src/app/(teams|org)/**/*.tsx : Use shared MembersList component at src/components/member/member-list.tsx for displaying members in canvas sidebar and org page; it includes getMemberDisplayInfo() utility for initials/name logic

Applied to files:

  • src/app/member/[id]/_components/team-section.tsx
  • src/app/member/[id]/_components/role-kpi-pair.tsx
📚 Learning: 2025-12-29T12:52:42.935Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-29T12:52:42.935Z
Learning: Applies to src/app/dashboard/[teamId]/**/*.{ts,tsx} : Dashboard cache updates for role-metric assignments must update both `role.getByTeamId` and `dashboard.getDashboardCharts` caches during mutations. Use onMutate for optimistic updates on both caches, then invalidate both on success.

Applied to files:

  • src/app/member/[id]/_components/team-section.tsx
  • src/app/member/[id]/_components/role-kpi-pair.tsx
📚 Learning: 2025-12-29T21:27:04.176Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-29T21:27:04.176Z
Learning: Applies to src/hooks/**/*.ts : For role-metric cache updates, optimistically update both role cache (role.getByTeamId) and dashboard cache (dashboard.getDashboardCharts) to maintain UI consistency

Applied to files:

  • src/app/member/[id]/_components/team-section.tsx
  • src/app/member/[id]/_components/role-kpi-pair.tsx
📚 Learning: 2025-12-29T12:52:42.935Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-29T12:52:42.935Z
Learning: Applies to src/app/teams/[teamId]/**/*.{ts,tsx} : Cache-first node system: Role nodes store only `roleId` in node.data. Display data must be fetched from TanStack Query cache using the `useRoleData()` hook which queries the `role.getByTeamId` procedure.

Applied to files:

  • src/app/member/[id]/_components/team-section.tsx
  • src/app/member/[id]/_components/role-kpi-pair.tsx
📚 Learning: 2025-12-20T22:12:00.576Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: GEMINI.md:0-0
Timestamp: 2025-12-20T22:12:00.576Z
Learning: Applies to src/app/teams/[teamId]/**/*.tsx : Avoid modifying `enrichNodesWithRoleData` flow without understanding the complete canvas serialization logic for saving/loading React Flow nodes to the database

Applied to files:

  • src/app/member/[id]/_components/team-section.tsx
  • src/app/member/[id]/_components/role-kpi-pair.tsx
📚 Learning: 2025-12-29T21:27:04.176Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-29T21:27:04.176Z
Learning: Applies to src/server/api/**/*.ts : Use enrichRolesWithUserNames() for flat role arrays and enrichChartRolesWithUserNames() for nested chart roles from src/server/api/utils/organization-members.ts

Applied to files:

  • src/app/member/[id]/_components/team-section.tsx
📚 Learning: 2025-12-29T21:27:04.176Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-29T21:27:04.176Z
Learning: Applies to src/app/(metric|dashboard)/**/*.tsx : Use three-stage metrics transformation: API → DataPoints (DataIngestionTransformer), DataPoints → ChartConfig (ChartTransformer), ChartConfig → UI (DashboardMetricChart)

Applied to files:

  • src/app/member/[id]/_components/team-section.tsx
  • src/app/member/[id]/_components/role-kpi-pair.tsx
📚 Learning: 2025-12-29T12:52:42.935Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-29T12:52:42.935Z
Learning: Applies to src/components/member/member-list.tsx : The MembersList component is consolidated and reused by both canvas sidebar (canvas-side-panels.tsx) and org page (MembersListClient.tsx). Use this component for all member list displays to maintain consistency.

Applied to files:

  • src/app/member/[id]/_components/team-section.tsx
📚 Learning: 2025-12-29T21:27:04.176Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-29T21:27:04.176Z
Learning: Applies to src/app/metric/_components/**/*.tsx : Use shared MetricDialogBase component from base/ for all metric dialog implementations

Applied to files:

  • src/app/member/[id]/_components/team-section.tsx
  • src/app/member/[id]/_components/role-kpi-pair.tsx
📚 Learning: 2025-12-29T21:27:04.176Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-29T21:27:04.176Z
Learning: Applies to src/app/metric/_components/**/*.tsx : Create metric dialogs with pattern: [Provider]MetricDialog.tsx (dialog wrapper) + [Provider]MetricContent.tsx (form content) in src/app/metric/_components/[provider]/, then register in index.ts

Applied to files:

  • src/app/member/[id]/_components/role-kpi-pair.tsx
🧬 Code graph analysis (2)
src/app/member/[id]/_components/team-section.tsx (1)
src/app/member/[id]/_components/role-kpi-pair.tsx (1)
  • RoleKpiPair (17-68)
src/app/member/[id]/_components/role-kpi-pair.tsx (4)
src/trpc/react.tsx (1)
  • RouterOutputs (42-42)
src/components/role/role-card.tsx (2)
  • RoleCardData (28-42)
  • RoleCard (329-329)
src/lib/utils.ts (1)
  • cn (4-6)
src/app/member/[id]/_components/member-role-card.tsx (1)
  • MemberRoleCard (17-85)
⏰ 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: claude-review
🔇 Additional comments (3)
src/app/member/[id]/_components/role-kpi-pair.tsx (1)

1-15: LGTM: Clean setup with correct Next.js and tRPC patterns.

The component follows the client component pattern with proper type inference from RouterOutputs, which aligns with the coding guidelines for tRPC usage in client components.

src/app/member/[id]/_components/team-section.tsx (2)

16-16: LGTM: Successfully refactored to use the new RoleKpiPair component.

This change eliminates the duplicate MemberRoleCard component in favor of composing RoleCard and KpiCard, which aligns with the codebase pattern of consolidating duplicate components.


77-89: LGTM: Correct integration of RoleKpiPair with proper prop passing.

The layout change to space-y-4 is appropriate since each RoleKpiPair manages its own internal grid layout. The teamId prop is correctly passed, and the conditional dashboardChart lookup preserves the original logic.

Comment on lines +61 to +65
{hasMetricButNoChart && (
<div className="border-border/60 text-muted-foreground flex items-center justify-center rounded-lg border border-dashed p-6">
<span className="text-sm">KPI data loading...</span>
</div>
)}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Clarify the loading state message.

The message "KPI data loading..." might be misleading. This condition fires when role.metricId exists but no corresponding dashboardChart was found in the map. This could indicate:

  • The chart data hasn't been fetched yet
  • The metric exists but has no chart configured
  • A data inconsistency

Consider a more accurate message like "No KPI data available" or adding actual loading state tracking if the data is genuinely loading.

💬 Suggested alternative
 {hasMetricButNoChart && (
   <div className="border-border/60 text-muted-foreground flex items-center justify-center rounded-lg border border-dashed p-6">
-    <span className="text-sm">KPI data loading...</span>
+    <span className="text-sm">No KPI data available</span>
   </div>
 )}
📝 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.

Suggested change
{hasMetricButNoChart && (
<div className="border-border/60 text-muted-foreground flex items-center justify-center rounded-lg border border-dashed p-6">
<span className="text-sm">KPI data loading...</span>
</div>
)}
{hasMetricButNoChart && (
<div className="border-border/60 text-muted-foreground flex items-center justify-center rounded-lg border border-dashed p-6">
<span className="text-sm">No KPI data available</span>
</div>
)}
🤖 Prompt for AI Agents
In @src/app/member/[id]/_components/role-kpi-pair.tsx around lines 61 - 65, The
current placeholder shown when hasMetricButNoChart is true is ambiguous; update
the UI to distinguish between "no chart configured" and "still loading" by
either changing the message in the hasMetricButNoChart branch to a clearer
statement like "No KPI data available" (or "KPI chart not configured") and/or
wire in an explicit loading flag from where dashboardChart is populated;
specifically, update the JSX branch that checks hasMetricButNoChart (and
references role.metricId and the dashboardChart lookup) to show the clearer
static message or conditionalize on a new loading boolean so genuine loading
uses "Loading KPI data…" while missing chart shows "No KPI data available."

drifter089 added a commit that referenced this pull request Jan 9, 2026
Replace custom MemberRoleCard with existing RoleCard and KpiCard components.
Each role now displays as a paired layout with role info on left and KPI on right.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants