-
Notifications
You must be signed in to change notification settings - Fork 1
refactor: simplify pipeline status with hook replacing provider #264
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
Conversation
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.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
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 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. 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughReplaces the centralized PipelineStatusProvider with a new client hook Changes
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
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
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)
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 DashboardChartWithRelationswill 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
enrichedResultpattern is consistent withMetricDialogBase.Consider extracting the enrichment logic into a shared utility to reduce duplication between this file and
MetricDialogBase.tsx, since both construct similarDashboardChartWithRelationsobjects with null fields.src/app/dashboard/[teamId]/_components/use-dashboard-charts.ts (1)
38-53: Consider memoizing chart lookup for frequent calls.
isProcessingandgetErrorperformO(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.
setOptimisticProcessingupdates the cache inonMutate, 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/onErrorpattern 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
📒 Files selected for processing (9)
src/app/dashboard/[teamId]/_components/dashboard-content.tsxsrc/app/dashboard/[teamId]/_components/dashboard-metric-card.tsxsrc/app/dashboard/[teamId]/_components/dashboard-page-client.tsxsrc/app/dashboard/[teamId]/_components/pipeline-status-provider.tsxsrc/app/dashboard/[teamId]/_components/use-dashboard-charts.tssrc/app/metric/_components/base/MetricDialogBase.tsxsrc/app/metric/_components/manual/ManualMetricContent.tsxsrc/app/teams/[teamId]/_components/chart-node.tsxsrc/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 orderingUse TypeScript 5.9 with strict type checking for all frontend and backend code
Files:
src/app/dashboard/[teamId]/_components/dashboard-metric-card.tsxsrc/app/metric/_components/manual/ManualMetricContent.tsxsrc/app/dashboard/[teamId]/_components/use-dashboard-charts.tssrc/app/teams/[teamId]/page.tsxsrc/app/dashboard/[teamId]/_components/dashboard-page-client.tsxsrc/app/teams/[teamId]/_components/chart-node.tsxsrc/app/metric/_components/base/MetricDialogBase.tsxsrc/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.tsxsrc/app/dashboard/[teamId]/_components/use-dashboard-charts.tssrc/app/dashboard/[teamId]/_components/dashboard-page-client.tsxsrc/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.tsxsrc/app/dashboard/[teamId]/_components/dashboard-page-client.tsxsrc/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.tsxsrc/app/metric/_components/manual/ManualMetricContent.tsxsrc/app/teams/[teamId]/page.tsxsrc/app/dashboard/[teamId]/_components/dashboard-page-client.tsxsrc/app/teams/[teamId]/_components/chart-node.tsxsrc/app/metric/_components/base/MetricDialogBase.tsxsrc/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.tsxsrc/app/metric/_components/manual/ManualMetricContent.tsxsrc/app/teams/[teamId]/page.tsxsrc/app/dashboard/[teamId]/_components/dashboard-page-client.tsxsrc/app/teams/[teamId]/_components/chart-node.tsxsrc/app/metric/_components/base/MetricDialogBase.tsxsrc/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.tsxsrc/app/metric/_components/manual/ManualMetricContent.tsxsrc/app/teams/[teamId]/page.tsxsrc/app/dashboard/[teamId]/_components/dashboard-page-client.tsxsrc/app/teams/[teamId]/_components/chart-node.tsxsrc/app/metric/_components/base/MetricDialogBase.tsxsrc/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.tsxsrc/app/metric/_components/base/MetricDialogBase.tsx
src/app/**/*.ts
📄 CodeRabbit inference engine (GEMINI.md)
src/app/**/*.ts: Server Components must useimport { 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.tsxsrc/app/metric/_components/manual/ManualMetricContent.tsxsrc/app/dashboard/[teamId]/_components/use-dashboard-charts.tssrc/app/teams/[teamId]/page.tsxsrc/app/dashboard/[teamId]/_components/dashboard-page-client.tsxsrc/app/teams/[teamId]/_components/chart-node.tsxsrc/app/metric/_components/base/MetricDialogBase.tsxsrc/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.tsxsrc/app/metric/_components/manual/ManualMetricContent.tsxsrc/app/dashboard/[teamId]/_components/use-dashboard-charts.tssrc/app/teams/[teamId]/page.tsxsrc/app/dashboard/[teamId]/_components/dashboard-page-client.tsxsrc/app/teams/[teamId]/_components/chart-node.tsxsrc/app/metric/_components/base/MetricDialogBase.tsxsrc/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.tsxsrc/app/metric/_components/manual/ManualMetricContent.tsxsrc/app/dashboard/[teamId]/_components/use-dashboard-charts.tssrc/app/teams/[teamId]/_components/chart-node.tsxsrc/app/metric/_components/base/MetricDialogBase.tsxsrc/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.tsxsrc/app/dashboard/[teamId]/_components/use-dashboard-charts.tssrc/app/teams/[teamId]/page.tsxsrc/app/dashboard/[teamId]/_components/dashboard-page-client.tsxsrc/app/teams/[teamId]/_components/chart-node.tsxsrc/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.tsxsrc/app/metric/_components/manual/ManualMetricContent.tsxsrc/app/dashboard/[teamId]/_components/use-dashboard-charts.tssrc/app/teams/[teamId]/page.tsxsrc/app/dashboard/[teamId]/_components/dashboard-page-client.tsxsrc/app/teams/[teamId]/_components/chart-node.tsxsrc/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.tsxsrc/app/dashboard/[teamId]/_components/use-dashboard-charts.tssrc/app/teams/[teamId]/page.tsxsrc/app/dashboard/[teamId]/_components/dashboard-page-client.tsxsrc/app/teams/[teamId]/_components/chart-node.tsxsrc/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.tsxsrc/app/metric/_components/manual/ManualMetricContent.tsxsrc/app/metric/_components/base/MetricDialogBase.tsxsrc/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.tsxsrc/app/teams/[teamId]/page.tsxsrc/app/dashboard/[teamId]/_components/dashboard-page-client.tsxsrc/app/teams/[teamId]/_components/chart-node.tsxsrc/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.tsxsrc/app/metric/_components/manual/ManualMetricContent.tsxsrc/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.tsxsrc/app/metric/_components/manual/ManualMetricContent.tsxsrc/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.tsxsrc/app/metric/_components/manual/ManualMetricContent.tsxsrc/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.tsxsrc/app/dashboard/[teamId]/_components/use-dashboard-charts.tssrc/app/teams/[teamId]/page.tsxsrc/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.tssrc/app/teams/[teamId]/page.tsxsrc/app/dashboard/[teamId]/_components/dashboard-page-client.tsxsrc/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.tsxsrc/app/teams/[teamId]/_components/chart-node.tsxsrc/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
teamIdis 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
PipelineStatusProviderand elevation ofTeamStoreProviderto wrap all content is a clean architectural improvement. Props are correctly threaded through:initialIntegrationstoDashboardSidebarWithDragDrop, andteamIdto 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
teamIdfromChartNodeDatatoDashboardMetricCard, 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
PipelineStatusProviderand direct rendering ofDashboardContentandDashboardSidebaris clean. Both components callinguseDashboardCharts(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
handleSubmitprevents 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 destructurescharts,isLoading, andisError. The hook encapsulates the polling logic, keeping this component focused on rendering.
58-63: LGTM - correct prop threading.The
teamIdis correctly passed to eachDashboardMetricCard, 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
refetchIntervalcallback 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/regenerateChartOnlyuse optimistic processing statedelete/updateinvalidate cache on success (appropriate for destructive/modifying operations)- Error handlers provide user feedback via toasts
239-279: LGTM - ReadOnlyMetricCard follows consolidated pattern.The
ReadOnlyMetricCardexports from the same file asDashboardMetricCard, 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.
| 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); | ||
| } | ||
| }, | ||
| }); |
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.
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.
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: 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
onMutatebut don't roll back whenonErrorfires. 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
regenerateMutationandregenerateChartMutation.
249-285: Consider consolidating ReadOnlyMetricCard in a future refactor.The separate
ReadOnlyMetricCardcomponent duplicates structure from the main component. Consider adding areadOnlyprop toDashboardMetricCardto 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
📒 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 orderingUse 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
useDashboardChartsis well-executed:
- Correctly imports and uses tRPC React hooks (follows coding guidelines for client components).
DrawerTitleimport addresses the accessibility objective mentioned in the PR.teamIdprop 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:
handleRefreshappropriately differentiates between integration metrics and manual metrics.handleDeleteincludes confirmation dialog for safety.- Dependency arrays are correct (
useCallbackincludes stable mutation objects from React Query).
226-226: Excellent accessibility improvement.The
DrawerTitlewithsr-onlyclass 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.isPendingappropriately controls deletion UI state (line 232).Also applies to: 230-232
65-65: No action required. TherefreshStatusfield is defined asString?in the Prisma schema with no enum constraints, making "processing" a valid type-safe value.
* 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
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
use-dashboard-charts.tshook with conditional polling (3s while processing)Summary by CodeRabbit
New Features
Refactor
Bug Fixes
✏️ Tip: You can customize this high-level summary in your review settings.