Skip to content

Conversation

@drifter089
Copy link
Owner

@drifter089 drifter089 commented Dec 24, 2025

Summary

Replaces the over-engineered PipelineStatusProvider (315 lines) with a simple useDashboardCharts hook (~50 lines). Components now call tRPC mutations directly with local optimistic updates.

Key Changes

  • Created use-dashboard-charts.ts hook with conditional polling (3s while processing)
  • Removed PipelineStatusProvider context wrapper
  • Components define mutations locally with optimistic updates
  • Maintains same UX behavior with ~250 fewer lines of abstraction

Summary by CodeRabbit

  • New Features

    • Real-time polling for dashboard metrics while they are processing
    • Dashboard components now operate with team-scoped context for consistent per-team views
  • Refactor

    • Simplified dashboard provider architecture and page layout
    • Metric create/update/refresh flows moved to API-backed mutations with optimistic updates and improved UI feedback
  • Bug Fixes

    • More reliable processing and error indicators during metric operations

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

Replace PipelineStatusProvider (315 lines) with useDashboardCharts hook (~50 lines).
Components now call tRPC mutations directly with local optimistic updates.
Keeps conditional 3s polling only when metrics are processing.
@vercel
Copy link

vercel bot commented Dec 24, 2025

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

Project Deployment Review Updated (UTC)
org-os Ready Ready Preview, Comment Dec 24, 2025 10:39pm

@coderabbitai
Copy link

coderabbitai bot commented Dec 24, 2025

Warning

Rate limit exceeded

@drifter089 has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 19 minutes and 51 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between 4c28cad and 907988e.

📒 Files selected for processing (1)
  • src/app/dashboard/[teamId]/_components/dashboard-metric-card.tsx
📝 Walkthrough

Walkthrough

Replaces the centralized PipelineStatusProvider with a new client hook useDashboardCharts(teamId) and moves metric status/mutation handling into per-component TRPC mutations; teamId is propagated through dashboard components and metric creation flows now use TRPC with optimistic cache updates.

Changes

Cohort / File(s) Summary
Removed provider
src/app/dashboard/[teamId]/_components/pipeline-status-provider.tsx
Deleted the PipelineStatusProvider, its context, usePipelineStatus() hook, and all provider-scoped mutations and state.
New hook
src/app/dashboard/[teamId]/_components/use-dashboard-charts.ts
Added useDashboardCharts(teamId) — TRPC-backed query with conditional 3s polling when any chart has refreshStatus; exposes charts, isLoading, isError, isProcessing(metricId), and getError(metricId).
Dashboard content & page wiring
src/app/dashboard/[teamId]/_components/dashboard-content.tsx, src/app/dashboard/[teamId]/_components/dashboard-page-client.tsx, src/app/teams/[teamId]/page.tsx
DashboardContent now requires { teamId }; removed PipelineStatusProvider wrapping; page layout/ordering simplified; initialIntegrations prop moved to sidebar component.
Metric card & chart interactions
src/app/dashboard/[teamId]/_components/dashboard-metric-card.tsx, src/app/teams/[teamId]/_components/chart-node.tsx
DashboardMetricCard now accepts teamId; replaced provider-derived pipeline state with useDashboardCharts(teamId) selectors; added per-card TRPC mutations (refresh/regenerate/regenerateChartOnly/delete/update) with optimistic processing updates and adjusted render logic (processing/error flags, drawer title, delete state).
Metric creation flows
src/app/metric/_components/base/MetricDialogBase.tsx, src/app/metric/_components/manual/ManualMetricContent.tsx
Replaced pipeline-based creation with api.metric.create.useMutation, using utils.dashboard.getDashboardCharts.setData for optimistic cache updates and mutation-driven pending/error state.
Minor prop propagation
src/app/dashboard/[teamId]/_components/dashboard-content.tsx, src/app/teams/[teamId]/_components/chart-node.tsx
Passed teamId into metric-card rendering and updated chart-related prop usage to use charts from the new hook (e.g., charts.length).

Sequence Diagram(s)

sequenceDiagram
    participant UI as DashboardMetricCard (UI)
    participant Hook as useDashboardCharts (query/cache)
    participant API as TRPC (server)
    participant Cache as react-query utils

    Note over Hook, Cache: Hook polls when any chart.refreshStatus != null (3s)

    UI->>Hook: isProcessing(metricId) / getError(metricId)
    UI->>API: mutate.refresh/regenerate/delete/update (includes teamId)
    activate API
    API-->>UI: mutation response (success/error)
    deactivate API

    alt onMutate (optimistic)
        UI->>Cache: set optimistic refreshStatus="processing"
        Note right of Cache: UI shows processing state immediately
    end

    alt onSuccess
        API->>Cache: invalidate / set updated dashboard charts
        Cache-->>Hook: query data updated
        Hook-->>UI: charts updated (processing cleared when done)
    else onError
        Cache-->>UI: rollback optimistic state (onError path)
        UI-->>UI: show toast error
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

🐰 Hoppity-hop, the provider's gone,

Hooks sing metrics all day long,
teamId carried in my paw,
Mutations race—optimistic awe,
I nibble bugs and toast success! 🥕

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 12.50% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ 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 reflects the main change: replacing PipelineStatusProvider with a useDashboardCharts hook to simplify pipeline status management, which is the primary refactoring objective.

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.

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

🧹 Nitpick comments (4)
src/app/metric/_components/base/MetricDialogBase.tsx (1)

92-98: Type assertion bypasses compile-time safety.

Manually enriching the result with null fields and casting as DashboardChartWithRelations will silently break if the type adds new required fields. Consider using a type-safe builder or partial type for optimistic cache entries, or validate the shape matches expectations.

src/app/metric/_components/manual/ManualMetricContent.tsx (1)

78-106: LGTM - mutation flow with proper error handling.

The mutation correctly handles success (cache update, toasts, callbacks) and error (state update, toast). The enrichedResult pattern is consistent with MetricDialogBase.

Consider extracting the enrichment logic into a shared utility to reduce duplication between this file and MetricDialogBase.tsx, since both construct similar DashboardChartWithRelations objects with null fields.

src/app/dashboard/[teamId]/_components/use-dashboard-charts.ts (1)

38-53: Consider memoizing chart lookup for frequent calls.

isProcessing and getError perform O(n) array searches on each call. If these are called frequently (e.g., for many cards), consider memoizing a lookup map:

🔎 Optional optimization
+ const chartByMetricId = useMemo(
+   () => new Map(charts.map((dc) => [dc.metric.id, dc])),
+   [charts],
+ );
+
  const isProcessing = useCallback(
    (metricId: string): boolean => {
-     const chart = charts.find((dc) => dc.metric.id === metricId);
+     const chart = chartByMetricId.get(metricId);
      return !!chart?.metric.refreshStatus;
    },
-   [charts],
+   [chartByMetricId],
  );
src/app/dashboard/[teamId]/_components/dashboard-metric-card.tsx (1)

55-66: Consider rollback on mutation error.

setOptimisticProcessing updates the cache in onMutate, but if the mutation fails, the optimistic update isn't rolled back. The metric will show "processing" until the next poll cycle (3s) corrects the state.

For better UX, consider using the onMutate/onError pattern with context:

🔎 Rollback pattern
  const refreshMutation = api.pipeline.refresh.useMutation({
-   onMutate: () => setOptimisticProcessing(metricId),
+   onMutate: () => {
+     const previous = utils.dashboard.getDashboardCharts.getData({ teamId });
+     setOptimisticProcessing(metricId);
+     return { previous };
+   },
+   onError: (err, _, context) => {
+     if (context?.previous) {
+       utils.dashboard.getDashboardCharts.setData({ teamId }, context.previous);
+     }
      toast.error("Refresh failed", { description: err.message });
+   },
-   onError: (err) =>
-     toast.error("Refresh failed", { description: err.message }),
  });
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 650c573 and 264bb44.

📒 Files selected for processing (9)
  • src/app/dashboard/[teamId]/_components/dashboard-content.tsx
  • src/app/dashboard/[teamId]/_components/dashboard-metric-card.tsx
  • src/app/dashboard/[teamId]/_components/dashboard-page-client.tsx
  • src/app/dashboard/[teamId]/_components/pipeline-status-provider.tsx
  • src/app/dashboard/[teamId]/_components/use-dashboard-charts.ts
  • src/app/metric/_components/base/MetricDialogBase.tsx
  • src/app/metric/_components/manual/ManualMetricContent.tsx
  • src/app/teams/[teamId]/_components/chart-node.tsx
  • src/app/teams/[teamId]/page.tsx
💤 Files with no reviewable changes (1)
  • src/app/dashboard/[teamId]/_components/pipeline-status-provider.tsx
🧰 Additional context used
📓 Path-based instructions (8)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx}: Use the tRPC dual API pattern: for server components, directly call tRPC server API (10x faster); for client components, use React hooks with TanStack Query
Use inline type imports with @trivago/prettier-plugin-sort-imports for consistent import ordering

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

Files:

  • src/app/dashboard/[teamId]/_components/dashboard-metric-card.tsx
  • src/app/metric/_components/manual/ManualMetricContent.tsx
  • src/app/dashboard/[teamId]/_components/use-dashboard-charts.ts
  • src/app/teams/[teamId]/page.tsx
  • src/app/dashboard/[teamId]/_components/dashboard-page-client.tsx
  • src/app/teams/[teamId]/_components/chart-node.tsx
  • src/app/metric/_components/base/MetricDialogBase.tsx
  • src/app/dashboard/[teamId]/_components/dashboard-content.tsx
src/app/dashboard/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Three-stage metrics transformation pipeline: Stage 1 (API → DataPoints via DataIngestionTransformer), Stage 2 (DataPoints → ChartConfig via ChartTransformer), Stage 3 (ChartConfig → UI via DashboardMetricChart with Recharts)

Files:

  • src/app/dashboard/[teamId]/_components/dashboard-metric-card.tsx
  • src/app/dashboard/[teamId]/_components/use-dashboard-charts.ts
  • src/app/dashboard/[teamId]/_components/dashboard-page-client.tsx
  • src/app/dashboard/[teamId]/_components/dashboard-content.tsx
src/app/dashboard/**/*.tsx

📄 CodeRabbit inference engine (CLAUDE.md)

Consolidate dashboard metric card duplication: add readOnly mode to dashboard-metric-card.tsx instead of maintaining separate public-dashboard-metric-card.tsx component

Files:

  • src/app/dashboard/[teamId]/_components/dashboard-metric-card.tsx
  • src/app/dashboard/[teamId]/_components/dashboard-page-client.tsx
  • src/app/dashboard/[teamId]/_components/dashboard-content.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/dashboard/[teamId]/_components/dashboard-metric-card.tsx
  • src/app/metric/_components/manual/ManualMetricContent.tsx
  • src/app/teams/[teamId]/page.tsx
  • src/app/dashboard/[teamId]/_components/dashboard-page-client.tsx
  • src/app/teams/[teamId]/_components/chart-node.tsx
  • src/app/metric/_components/base/MetricDialogBase.tsx
  • src/app/dashboard/[teamId]/_components/dashboard-content.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/dashboard/[teamId]/_components/dashboard-metric-card.tsx
  • src/app/metric/_components/manual/ManualMetricContent.tsx
  • src/app/teams/[teamId]/page.tsx
  • src/app/dashboard/[teamId]/_components/dashboard-page-client.tsx
  • src/app/teams/[teamId]/_components/chart-node.tsx
  • src/app/metric/_components/base/MetricDialogBase.tsx
  • src/app/dashboard/[teamId]/_components/dashboard-content.tsx
**/*.tsx

📄 CodeRabbit inference engine (GEMINI.md)

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

Files:

  • src/app/dashboard/[teamId]/_components/dashboard-metric-card.tsx
  • src/app/metric/_components/manual/ManualMetricContent.tsx
  • src/app/teams/[teamId]/page.tsx
  • src/app/dashboard/[teamId]/_components/dashboard-page-client.tsx
  • src/app/teams/[teamId]/_components/chart-node.tsx
  • src/app/metric/_components/base/MetricDialogBase.tsx
  • src/app/dashboard/[teamId]/_components/dashboard-content.tsx
src/app/metric/_components/**/*.tsx

📄 CodeRabbit inference engine (CLAUDE.md)

src/app/metric/_components/**/*.tsx: Metric dialogs should follow the pattern: [Provider]MetricDialog.tsx (dialog wrapper) + [Provider]MetricContent.tsx (form content) and be registered in src/app/metric/_components/index.ts
Use MetricDialogBase from base/ for shared metric dialog functionality to reduce duplication across provider-specific dialogs
Consider factory pattern for metric dialogs to reduce the 5 nearly identical wrapper components (currently duplicated across providers)

Files:

  • src/app/metric/_components/manual/ManualMetricContent.tsx
  • src/app/metric/_components/base/MetricDialogBase.tsx
src/app/**/*.ts

📄 CodeRabbit inference engine (GEMINI.md)

src/app/**/*.ts: Server Components must use import { api } from '@/trpc/server' for direct DB calls without HTTP overhead
For API routes with cron jobs and webhooks, ensure proper authentication and input validation

Files:

  • src/app/dashboard/[teamId]/_components/use-dashboard-charts.ts
🧠 Learnings (21)
📓 Common learnings
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-20T16:32:46.829Z
Learning: Applies to src/app/dashboard/**/*.{ts,tsx} : Three-stage metrics transformation pipeline: Stage 1 (API → DataPoints via DataIngestionTransformer), Stage 2 (DataPoints → ChartConfig via ChartTransformer), Stage 3 (ChartConfig → UI via DashboardMetricChart with Recharts)
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-20T16:32:46.829Z
Learning: Applies to src/app/dashboard/**/*.tsx : Consolidate dashboard metric card duplication: add readOnly mode to dashboard-metric-card.tsx instead of maintaining separate public-dashboard-metric-card.tsx component
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
📚 Learning: 2025-12-20T16:32:46.829Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-20T16:32:46.829Z
Learning: Applies to src/app/dashboard/**/*.tsx : Consolidate dashboard metric card duplication: add readOnly mode to dashboard-metric-card.tsx instead of maintaining separate public-dashboard-metric-card.tsx component

Applied to files:

  • src/app/dashboard/[teamId]/_components/dashboard-metric-card.tsx
  • src/app/metric/_components/manual/ManualMetricContent.tsx
  • src/app/dashboard/[teamId]/_components/use-dashboard-charts.ts
  • src/app/teams/[teamId]/page.tsx
  • src/app/dashboard/[teamId]/_components/dashboard-page-client.tsx
  • src/app/teams/[teamId]/_components/chart-node.tsx
  • src/app/metric/_components/base/MetricDialogBase.tsx
  • src/app/dashboard/[teamId]/_components/dashboard-content.tsx
📚 Learning: 2025-12-20T16:32:46.829Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-20T16:32:46.829Z
Learning: Applies to src/app/dashboard/**/*.{ts,tsx} : Three-stage metrics transformation pipeline: Stage 1 (API → DataPoints via DataIngestionTransformer), Stage 2 (DataPoints → ChartConfig via ChartTransformer), Stage 3 (ChartConfig → UI via DashboardMetricChart with Recharts)

Applied to files:

  • src/app/dashboard/[teamId]/_components/dashboard-metric-card.tsx
  • src/app/metric/_components/manual/ManualMetricContent.tsx
  • src/app/dashboard/[teamId]/_components/use-dashboard-charts.ts
  • src/app/teams/[teamId]/page.tsx
  • src/app/dashboard/[teamId]/_components/dashboard-page-client.tsx
  • src/app/teams/[teamId]/_components/chart-node.tsx
  • src/app/metric/_components/base/MetricDialogBase.tsx
  • src/app/dashboard/[teamId]/_components/dashboard-content.tsx
📚 Learning: 2025-12-20T16:32:46.829Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-20T16:32:46.829Z
Learning: Applies to src/app/metric/_components/**/*.tsx : Use MetricDialogBase from base/ for shared metric dialog functionality to reduce duplication across provider-specific dialogs

Applied to files:

  • src/app/dashboard/[teamId]/_components/dashboard-metric-card.tsx
  • src/app/metric/_components/manual/ManualMetricContent.tsx
  • src/app/dashboard/[teamId]/_components/use-dashboard-charts.ts
  • src/app/teams/[teamId]/_components/chart-node.tsx
  • src/app/metric/_components/base/MetricDialogBase.tsx
  • src/app/dashboard/[teamId]/_components/dashboard-content.tsx
📚 Learning: 2025-12-20T16:32:46.829Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-20T16:32:46.829Z
Learning: Applies to src/app/teams/[teamId]/**/*.tsx : Consolidate role node duplication: extract shared RoleNodeTemplate from role-node.tsx and public-role-node.tsx with isEditable prop instead of maintaining separate components

Applied to files:

  • src/app/dashboard/[teamId]/_components/dashboard-metric-card.tsx
  • src/app/dashboard/[teamId]/_components/use-dashboard-charts.ts
  • src/app/teams/[teamId]/page.tsx
  • src/app/dashboard/[teamId]/_components/dashboard-page-client.tsx
  • src/app/teams/[teamId]/_components/chart-node.tsx
  • src/app/dashboard/[teamId]/_components/dashboard-content.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/dashboard/[teamId]/_components/dashboard-metric-card.tsx
  • src/app/metric/_components/manual/ManualMetricContent.tsx
  • src/app/dashboard/[teamId]/_components/use-dashboard-charts.ts
  • src/app/teams/[teamId]/page.tsx
  • src/app/dashboard/[teamId]/_components/dashboard-page-client.tsx
  • src/app/teams/[teamId]/_components/chart-node.tsx
  • src/app/dashboard/[teamId]/_components/dashboard-content.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/dashboard/[teamId]/_components/dashboard-metric-card.tsx
  • src/app/dashboard/[teamId]/_components/use-dashboard-charts.ts
  • src/app/teams/[teamId]/page.tsx
  • src/app/dashboard/[teamId]/_components/dashboard-page-client.tsx
  • src/app/teams/[teamId]/_components/chart-node.tsx
  • src/app/dashboard/[teamId]/_components/dashboard-content.tsx
📚 Learning: 2025-12-20T16:32:46.829Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-20T16:32:46.829Z
Learning: Applies to src/app/metric/_components/**/*.tsx : Metric dialogs should follow the pattern: [Provider]MetricDialog.tsx (dialog wrapper) + [Provider]MetricContent.tsx (form content) and be registered in src/app/metric/_components/index.ts

Applied to files:

  • src/app/dashboard/[teamId]/_components/dashboard-metric-card.tsx
  • src/app/metric/_components/manual/ManualMetricContent.tsx
  • src/app/metric/_components/base/MetricDialogBase.tsx
  • src/app/dashboard/[teamId]/_components/dashboard-content.tsx
📚 Learning: 2025-12-20T16:32:46.829Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-20T16:32:46.829Z
Learning: Applies to src/app/teams/[teamId]/**/*.{ts,tsx} : For new canvas node types: create component in teams/[teamId]/_components/, add to TeamNode union in types/canvas.ts, register in nodeTypes in team-canvas.tsx, and update serialization in canvas-serialization.ts

Applied to files:

  • src/app/dashboard/[teamId]/_components/dashboard-metric-card.tsx
  • src/app/teams/[teamId]/page.tsx
  • src/app/dashboard/[teamId]/_components/dashboard-page-client.tsx
  • src/app/teams/[teamId]/_components/chart-node.tsx
  • src/app/dashboard/[teamId]/_components/dashboard-content.tsx
📚 Learning: 2025-12-20T16:32:46.829Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-20T16:32:46.829Z
Learning: Applies to src/app/metric/_components/**/*.tsx : Consider factory pattern for metric dialogs to reduce the 5 nearly identical wrapper components (currently duplicated across providers)

Applied to files:

  • src/app/dashboard/[teamId]/_components/dashboard-metric-card.tsx
  • src/app/metric/_components/manual/ManualMetricContent.tsx
  • src/app/metric/_components/base/MetricDialogBase.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/lib/metrics/**/*.ts : Metric transformation logic should be organized in `src/lib/metrics/` to support the 3-stage pipeline: Ingestion → Aggregation → Visualization

Applied to files:

  • src/app/dashboard/[teamId]/_components/dashboard-metric-card.tsx
  • src/app/metric/_components/manual/ManualMetricContent.tsx
  • src/app/metric/_components/base/MetricDialogBase.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: The Metrics Pipeline processes data through 3 stages: DataIngestionTransformer (Raw API → MetricDataPoint), ChartTransformer (MetricDataPoint → Chart Config), and Visualization (Chart Config → Recharts UI)

Applied to files:

  • src/app/dashboard/[teamId]/_components/dashboard-metric-card.tsx
  • src/app/metric/_components/manual/ManualMetricContent.tsx
  • src/app/metric/_components/base/MetricDialogBase.tsx
📚 Learning: 2025-12-20T16:32:46.829Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-20T16:32:46.829Z
Learning: Applies to src/app/teams/[teamId]/**/*.{ts,tsx} : Use auto-save system with debounce (2s delay) that serializes nodes/edges to tRPC mutation, with beforeunload sendBeacon fallback for unsaved changes

Applied to files:

  • src/app/metric/_components/manual/ManualMetricContent.tsx
  • src/app/dashboard/[teamId]/_components/use-dashboard-charts.ts
  • src/app/teams/[teamId]/page.tsx
  • src/app/teams/[teamId]/_components/chart-node.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 prisma/schema.prisma : When modifying the Prisma schema, especially for Metric Transformers, ensure AI-generated code generation and execution logic is updated accordingly

Applied to files:

  • src/app/metric/_components/manual/ManualMetricContent.tsx
📚 Learning: 2025-12-20T16:32:46.829Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-20T16:32:46.829Z
Learning: Applies to **/*canvas*.{ts,tsx} : Use React Flow primitives (BaseNode, BaseHandle, ZoomSlider) from src/components/react-flow/ for consistent canvas styling

Applied to files:

  • src/app/metric/_components/manual/ManualMetricContent.tsx
📚 Learning: 2025-12-20T16:32:46.829Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-20T16:32:46.829Z
Learning: Applies to src/app/teams/[teamId]/**/*.{ts,tsx} : Use Zustand store with Context pattern (TeamStoreContext) and access via useTeamStore hook. For callbacks that need current state, use useTeamStoreApi() to avoid stale closures.

Applied to files:

  • src/app/dashboard/[teamId]/_components/use-dashboard-charts.ts
  • src/app/teams/[teamId]/page.tsx
  • src/app/dashboard/[teamId]/_components/dashboard-page-client.tsx
  • src/app/dashboard/[teamId]/_components/dashboard-content.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/**/*/*.tsx : Client Components must use `import { api } from '@/trpc/react'` for standard HTTP/Hooks wrapper

Applied to files:

  • src/app/dashboard/[teamId]/_components/use-dashboard-charts.ts
📚 Learning: 2025-12-20T16:32:46.829Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-20T16:32:46.829Z
Learning: Applies to **/*.{ts,tsx} : Use the tRPC dual API pattern: for server components, directly call tRPC server API (10x faster); for client components, use React hooks with TanStack Query

Applied to files:

  • src/app/dashboard/[teamId]/_components/use-dashboard-charts.ts
📚 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]/**/*.ts : Canvas changes must be debounced (2s) and saved via `editSession` logic to handle concurrent team edits safely

Applied to files:

  • src/app/teams/[teamId]/page.tsx
  • src/app/teams/[teamId]/_components/chart-node.tsx
  • src/app/dashboard/[teamId]/_components/dashboard-content.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/lib/canvas/**/*.ts : Reusable Canvas logic (stores, hooks) should be organized in `src/lib/canvas/` for sharing between Team Canvas components

Applied to files:

  • src/app/teams/[teamId]/page.tsx
📚 Learning: 2025-12-20T16:32:46.829Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-20T16:32:46.829Z
Learning: Applies to src/app/teams/[teamId]/**/*.{ts,tsx} : Cache-first node pattern: Role nodes store only roleId; fetch display data from TanStack Query cache using useRoleData hook rather than storing denormalized data

Applied to files:

  • src/app/teams/[teamId]/_components/chart-node.tsx
🧬 Code graph analysis (7)
src/app/dashboard/[teamId]/_components/dashboard-metric-card.tsx (7)
src/types/dashboard.ts (1)
  • DashboardChartWithRelations (3-4)
src/app/dashboard/[teamId]/_components/use-dashboard-charts.ts (1)
  • useDashboardCharts (20-56)
src/lib/metrics/transformer-types.ts (1)
  • ChartTransformResult (56-71)
src/lib/integrations/github.ts (1)
  • name (18-18)
src/lib/integrations/youtube.ts (1)
  • name (15-15)
src/lib/integrations/google-sheets.ts (1)
  • name (15-15)
src/lib/integrations/posthog.ts (1)
  • name (15-15)
src/app/metric/_components/manual/ManualMetricContent.tsx (2)
src/trpc/react.tsx (1)
  • api (28-28)
src/types/dashboard.ts (1)
  • DashboardChartWithRelations (3-4)
src/app/dashboard/[teamId]/_components/use-dashboard-charts.ts (2)
src/types/dashboard.ts (1)
  • DashboardChartWithRelations (3-4)
src/trpc/react.tsx (1)
  • api (28-28)
src/app/dashboard/[teamId]/_components/dashboard-page-client.tsx (2)
src/app/dashboard/[teamId]/_components/dashboard-content.tsx (1)
  • DashboardContent (12-69)
src/app/dashboard/[teamId]/_components/dashboard-sidebar.tsx (1)
  • DashboardSidebar (61-368)
src/app/teams/[teamId]/_components/chart-node.tsx (1)
src/app/dashboard/[teamId]/_components/dashboard-metric-card.tsx (1)
  • DashboardMetricCard (32-237)
src/app/metric/_components/base/MetricDialogBase.tsx (3)
src/trpc/react.tsx (1)
  • api (28-28)
src/types/dashboard.ts (1)
  • DashboardChartWithRelations (3-4)
src/app/metric/_components/base/index.ts (1)
  • MetricCreateInput (2-2)
src/app/dashboard/[teamId]/_components/dashboard-content.tsx (2)
src/app/dashboard/[teamId]/_components/use-dashboard-charts.ts (1)
  • useDashboardCharts (20-56)
src/app/dashboard/[teamId]/_components/dashboard-metric-card.tsx (1)
  • DashboardMetricCard (32-237)
🔇 Additional comments (10)
src/app/metric/_components/base/MetricDialogBase.tsx (1)

101-107: LGTM - conditional cache update based on teamId.

The cache update is correctly scoped to team-specific queries. When teamId is undefined, the metric is still created server-side; consumers without a team context will need to handle cache invalidation separately if needed.

src/app/teams/[teamId]/page.tsx (1)

123-151: LGTM - clean layout simplification.

The removal of PipelineStatusProvider and elevation of TeamStoreProvider to wrap all content is a clean architectural improvement. Props are correctly threaded through: initialIntegrations to DashboardSidebarWithDragDrop, and teamId to all child components that need it.

src/app/teams/[teamId]/_components/chart-node.tsx (1)

122-125: LGTM - correctly propagates teamId to DashboardMetricCard.

The change properly threads the teamId from ChartNodeData to DashboardMetricCard, aligning with the updated component signature and enabling team-scoped cache operations.

src/app/dashboard/[teamId]/_components/dashboard-page-client.tsx (1)

49-60: LGTM - simplified component structure.

The removal of PipelineStatusProvider and direct rendering of DashboardContent and DashboardSidebar is clean. Both components calling useDashboardCharts(teamId) internally is fine since React Query deduplicates identical queries.

src/app/metric/_components/manual/ManualMetricContent.tsx (1)

108-119: LGTM - clean validation before mutation.

Input validation in handleSubmit prevents unnecessary network calls. The early return on invalid state is appropriate.

src/app/dashboard/[teamId]/_components/dashboard-content.tsx (2)

12-13: LGTM - clean hook integration.

The component correctly uses useDashboardCharts(teamId) and destructures charts, isLoading, and isError. The hook encapsulates the polling logic, keeping this component focused on rendering.


58-63: LGTM - correct prop threading.

The teamId is correctly passed to each DashboardMetricCard, enabling team-scoped mutations and cache operations within the card component.

src/app/dashboard/[teamId]/_components/use-dashboard-charts.ts (1)

16-36: LGTM - well-designed hook with conditional polling.

The refetchInterval callback correctly enables 3s polling only when metrics are processing, stopping when all complete. This is a significant improvement over the previous provider's complexity.

src/app/dashboard/[teamId]/_components/dashboard-metric-card.tsx (2)

68-96: LGTM - mutations with appropriate handlers.

The mutation definitions are well-structured:

  • refresh/regenerate/regenerateChartOnly use optimistic processing state
  • delete/update invalidate cache on success (appropriate for destructive/modifying operations)
  • Error handlers provide user feedback via toasts

239-279: LGTM - ReadOnlyMetricCard follows consolidated pattern.

The ReadOnlyMetricCard exports from the same file as DashboardMetricCard, aligning with the coding guideline to consolidate dashboard metric card duplication. It correctly uses direct metric properties for status checks since it doesn't need team-scoped mutations.

Comment on lines +90 to +116
const createMutation = api.metric.create.useMutation({
onSuccess: (result) => {
const enrichedResult = {
...result,
goalProgress: null,
valueLabel: null,
dataDescription: null,
metric: { ...result.metric, goal: null },
} as DashboardChartWithRelations;

// Update cache for this team
if (teamId) {
utils.dashboard.getDashboardCharts.setData({ teamId }, (old) => {
if (!old) return [enrichedResult];
if (old.some((dc) => dc.id === result.id)) return old;
return [...old, enrichedResult];
});
}

toast.success("KPI created", { description: "Building your chart..." });
setOpen(false);
onSuccess?.();
} catch {
},
onError: () => {
toast.error("Failed to create KPI");
} finally {
setIsCreating(false);
}
},
});
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

Error state is set but never populated on mutation failure.

The error state at line 70 is cleared on submit (line 119) but the onError handler (lines 113-115) only shows a toast without updating the error state. Meanwhile, line 154 renders the error. Consider populating the error state:

     onError: () => {
+      setError("Failed to create KPI");
       toast.error("Failed to create KPI");
     },
🤖 Prompt for AI Agents
In src/app/metric/_components/base/MetricDialogBase.tsx around lines 90 to 116,
the mutation onError only shows a toast and does not populate the component's
error state (which is cleared on submit at line 119 and later rendered at line
154); update the onError handler to set the error state with the mutation error
message/details (extracting from the error object returned by the mutation,
e.g., error.message or error.data?.message) so the UI renders the error, while
still calling toast.error; ensure the error state type matches expected
rendering and consider clearing or preserving other state as appropriate.

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: 0

🧹 Nitpick comments (2)
src/app/dashboard/[teamId]/_components/dashboard-metric-card.tsx (2)

60-89: Implement proper rollback for failed optimistic updates.

The mutations (refresh, regenerate, regenerateChartOnly) apply optimistic updates in onMutate but don't roll back when onError fires. If a mutation fails, the UI will incorrectly display "processing" for up to 3 seconds until the next poll corrects it.

🔎 Recommended pattern with rollback on error
 const refreshMutation = api.pipeline.refresh.useMutation({
-  onMutate: () => setOptimisticProcessing(metricId),
-  onError: (err) =>
-    toast.error("Refresh failed", { description: err.message }),
+  onMutate: () => {
+    setOptimisticProcessing(metricId);
+    const previousData = utils.dashboard.getDashboardCharts.getData({ teamId });
+    return { previousData };
+  },
+  onError: (err, variables, context) => {
+    if (context?.previousData) {
+      utils.dashboard.getDashboardCharts.setData({ teamId }, context.previousData);
+    }
+    toast.error("Refresh failed", { description: err.message });
+  },
 });

Apply the same pattern to regenerateMutation and regenerateChartMutation.


249-285: Consider consolidating ReadOnlyMetricCard in a future refactor.

The separate ReadOnlyMetricCard component duplicates structure from the main component. Consider adding a readOnly prop to DashboardMetricCard to eliminate this duplication and simplify maintenance.

Based on learnings, consolidating dashboard metric card duplication is preferred over maintaining separate components.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 264bb44 and 4c28cad.

📒 Files selected for processing (1)
  • src/app/dashboard/[teamId]/_components/dashboard-metric-card.tsx
🧰 Additional context used
📓 Path-based instructions (6)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx}: Use the tRPC dual API pattern: for server components, directly call tRPC server API (10x faster); for client components, use React hooks with TanStack Query
Use inline type imports with @trivago/prettier-plugin-sort-imports for consistent import ordering

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

Files:

  • src/app/dashboard/[teamId]/_components/dashboard-metric-card.tsx
src/app/dashboard/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Three-stage metrics transformation pipeline: Stage 1 (API → DataPoints via DataIngestionTransformer), Stage 2 (DataPoints → ChartConfig via ChartTransformer), Stage 3 (ChartConfig → UI via DashboardMetricChart with Recharts)

Files:

  • src/app/dashboard/[teamId]/_components/dashboard-metric-card.tsx
src/app/dashboard/**/*.tsx

📄 CodeRabbit inference engine (CLAUDE.md)

Consolidate dashboard metric card duplication: add readOnly mode to dashboard-metric-card.tsx instead of maintaining separate public-dashboard-metric-card.tsx component

Files:

  • src/app/dashboard/[teamId]/_components/dashboard-metric-card.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/dashboard/[teamId]/_components/dashboard-metric-card.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/dashboard/[teamId]/_components/dashboard-metric-card.tsx
**/*.tsx

📄 CodeRabbit inference engine (GEMINI.md)

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

Files:

  • src/app/dashboard/[teamId]/_components/dashboard-metric-card.tsx
🧠 Learnings (12)
📓 Common learnings
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-20T16:32:46.829Z
Learning: Applies to src/app/dashboard/**/*.{ts,tsx} : Three-stage metrics transformation pipeline: Stage 1 (API → DataPoints via DataIngestionTransformer), Stage 2 (DataPoints → ChartConfig via ChartTransformer), Stage 3 (ChartConfig → UI via DashboardMetricChart with Recharts)
📚 Learning: 2025-12-20T16:32:46.829Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-20T16:32:46.829Z
Learning: Applies to src/app/dashboard/**/*.tsx : Consolidate dashboard metric card duplication: add readOnly mode to dashboard-metric-card.tsx instead of maintaining separate public-dashboard-metric-card.tsx component

Applied to files:

  • src/app/dashboard/[teamId]/_components/dashboard-metric-card.tsx
📚 Learning: 2025-12-20T16:32:46.829Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-20T16:32:46.829Z
Learning: Applies to src/app/dashboard/**/*.{ts,tsx} : Three-stage metrics transformation pipeline: Stage 1 (API → DataPoints via DataIngestionTransformer), Stage 2 (DataPoints → ChartConfig via ChartTransformer), Stage 3 (ChartConfig → UI via DashboardMetricChart with Recharts)

Applied to files:

  • src/app/dashboard/[teamId]/_components/dashboard-metric-card.tsx
📚 Learning: 2025-12-20T16:32:46.829Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-20T16:32:46.829Z
Learning: Applies to src/app/metric/_components/**/*.tsx : Use MetricDialogBase from base/ for shared metric dialog functionality to reduce duplication across provider-specific dialogs

Applied to files:

  • src/app/dashboard/[teamId]/_components/dashboard-metric-card.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/dashboard/[teamId]/_components/dashboard-metric-card.tsx
📚 Learning: 2025-12-20T16:32:46.829Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-20T16:32:46.829Z
Learning: Applies to src/app/teams/[teamId]/**/*.tsx : Consolidate role node duplication: extract shared RoleNodeTemplate from role-node.tsx and public-role-node.tsx with isEditable prop instead of maintaining separate components

Applied to files:

  • src/app/dashboard/[teamId]/_components/dashboard-metric-card.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/dashboard/[teamId]/_components/dashboard-metric-card.tsx
📚 Learning: 2025-12-20T16:32:46.829Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-20T16:32:46.829Z
Learning: Applies to src/app/metric/_components/**/*.tsx : Metric dialogs should follow the pattern: [Provider]MetricDialog.tsx (dialog wrapper) + [Provider]MetricContent.tsx (form content) and be registered in src/app/metric/_components/index.ts

Applied to files:

  • src/app/dashboard/[teamId]/_components/dashboard-metric-card.tsx
📚 Learning: 2025-12-20T16:32:46.829Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-20T16:32:46.829Z
Learning: Applies to src/app/metric/_components/**/*.tsx : Consider factory pattern for metric dialogs to reduce the 5 nearly identical wrapper components (currently duplicated across providers)

Applied to files:

  • src/app/dashboard/[teamId]/_components/dashboard-metric-card.tsx
📚 Learning: 2025-12-20T16:32:46.829Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-20T16:32:46.829Z
Learning: Applies to src/app/teams/[teamId]/**/*.{ts,tsx} : For new canvas node types: create component in teams/[teamId]/_components/, add to TeamNode union in types/canvas.ts, register in nodeTypes in team-canvas.tsx, and update serialization in canvas-serialization.ts

Applied to files:

  • src/app/dashboard/[teamId]/_components/dashboard-metric-card.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]/**/*.ts : Canvas changes must be debounced (2s) and saved via `editSession` logic to handle concurrent team edits safely

Applied to files:

  • src/app/dashboard/[teamId]/_components/dashboard-metric-card.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: The Metrics Pipeline processes data through 3 stages: DataIngestionTransformer (Raw API → MetricDataPoint), ChartTransformer (MetricDataPoint → Chart Config), and Visualization (Chart Config → Recharts UI)

Applied to files:

  • src/app/dashboard/[teamId]/_components/dashboard-metric-card.tsx
🧬 Code graph analysis (1)
src/app/dashboard/[teamId]/_components/dashboard-metric-card.tsx (5)
src/types/dashboard.ts (1)
  • DashboardChartWithRelations (3-4)
src/trpc/react.tsx (1)
  • api (28-28)
src/app/dashboard/[teamId]/_components/use-dashboard-charts.ts (1)
  • useDashboardCharts (20-56)
src/lib/metrics/transformer-types.ts (2)
  • ChartTransformResult (56-71)
  • Cadence (89-89)
src/components/ui/drawer.tsx (1)
  • DrawerTitle (134-134)
🔇 Additional comments (6)
src/app/dashboard/[teamId]/_components/dashboard-metric-card.tsx (6)

11-16: LGTM! Clean refactoring to hook-based architecture.

The migration from PipelineStatusProvider to useDashboardCharts is well-executed:

  • Correctly imports and uses tRPC React hooks (follows coding guidelines for client components).
  • DrawerTitle import addresses the accessibility objective mentioned in the PR.
  • teamId prop enables proper team-scoped data fetching.

Also applies to: 25-25, 30-30, 34-34, 39-39, 43-44


91-101: LGTM! Delete and update mutations follow best practices.

These mutations correctly use cache invalidation on success with proper error handling. The pattern differs from the refresh/regenerate mutations appropriately—delete and update complete immediately, while refresh/regenerate queue asynchronous pipeline jobs.


106-152: LGTM! Event handlers are well-structured.

All handlers correctly integrate with the new mutation-based architecture:

  • handleRefresh appropriately differentiates between integration metrics and manual metrics.
  • handleDelete includes confirmation dialog for safety.
  • Dependency arrays are correct (useCallback includes stable mutation objects from React Query).

226-226: Excellent accessibility improvement.

The DrawerTitle with sr-only class correctly provides an accessible name for the drawer while keeping it visually hidden. This directly addresses the commit message objective.


157-219: LGTM! Render logic correctly uses new state.

The rendering properly integrates with the new hook-based state management:

  • Error badge correctly displays when error && !processing (line 159).
  • Processing state correctly propagated to child components (lines 216, 230).
  • deleteMutation.isPending appropriately controls deletion UI state (line 232).

Also applies to: 230-232


65-65: No action required. The refreshStatus field is defined as String? in the Prisma schema with no enum constraints, making "processing" a valid type-safe value.

@drifter089 drifter089 merged commit 0765923 into main Dec 24, 2025
4 checks passed
drifter089 added a commit that referenced this pull request Dec 25, 2025
* refactor: simplify pipeline status with hook replacing provider

Replace PipelineStatusProvider (315 lines) with useDashboardCharts hook (~50 lines).
Components now call tRPC mutations directly with local optimistic updates.
Keeps conditional 3s polling only when metrics are processing.

* fix: add accessible title to metric drawer

* fix: invalidate dashboard cache on pipeline mutations
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