Skip to content

feat(estimates): show the real estimate value in view and module list rows - #299

Merged
martian56 merged 1 commit into
Devlaner:mainfrom
cavidelizade:feat/estimate-list-column
Jul 12, 2026
Merged

feat(estimates): show the real estimate value in view and module list rows#299
martian56 merged 1 commit into
Devlaner:mainfrom
cavidelizade:feat/estimate-list-column

Conversation

@cavidelizade

@cavidelizade cavidelizade commented Jul 12, 2026

Copy link
Copy Markdown
Contributor

Feature summary

The estimate column in the project view and module work-item lists rendered a hardcoded placeholder instead of the work item's real estimate. Both now resolve and display the actual estimate point value. This finishes the last user-facing gap in estimates (the systems + points + issue-detail picker landed in #222/#223).

Linked issues / discussion

Closes #127

User-facing behavior

In a project View and a Module's work-item list, when the Estimate display column is enabled, each row now shows the work item's estimate (e.g. 5) instead of a dash. Work items with no estimate still show .

What changed

  • apps/web/src/pages/ViewDetailPage.tsx and apps/web/src/pages/ModuleDetailPage.tsx: load the project's estimates alongside the other project data, and add an estimateValue(issue) helper that resolves issue.estimate_point_id against the loaded estimate points (the same resolution the issue-detail estimate picker uses). The estimate column renders that value.

Why this design

The issue-detail page already resolves an estimate point as estimates.flatMap(e => e.points).find(p => p.id === estimate_point_id).value. Reusing that exact approach keeps the list rows consistent with the detail view and avoids a new endpoint (estimates are already a per-project list).

Test plan

  • npm run typecheck, npm run lint (full) green.
  • Manual E2E against the running stack: created a "Points" estimate (1/2/3/5/8), assigned 5 to a work item, added it to a module, and confirmed the module list row shows 5 in the estimate column (previously ). Screenshot verified.

Out of scope (follow-ups)

  • The workspace-wide custom-view spreadsheet (WorkspaceViewsPage) still renders placeholder cells for estimate as well as module/cycle/link/attachment. Those cells span multiple projects and would need cross-project estimate/module resolution — a separate, broader gap than this issue.
  • The repo has no web unit-test harness (testing is Go-only per npm run validate), so this is verified via typecheck/lint/build + manual E2E rather than a new UI test.

AI assistance

  • AI tools were used — tool(s): Claude Code — and AI-assisted commits include a Co-Authored-By: trailer

Checklist

  • PR title follows Conventional Commits and is <= 100 chars
  • Acceptance criteria from the linked issue are met (estimate now shown in list rows)

Summary by CodeRabbit

  • New Features

    • Added work-item estimate values to module and view detail pages.
    • Estimate values are now matched to each work item and displayed in the estimate column.
  • Bug Fixes

    • Estimate data now clears correctly when loading fails.

… rows

The estimate column in the project view and module work-item lists rendered a
hardcoded placeholder. Both pages now load the project's estimates and resolve
each work item's estimate_point_id to its point value (mirroring the issue
detail estimate picker), falling back to the placeholder when a work item has
no estimate.

Closes Devlaner#127

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@cavidelizade
cavidelizade requested a review from a team as a code owner July 12, 2026 17:51
@coderabbitai

coderabbitai Bot commented Jul 12, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

ModuleDetailPage and ViewDetailPage now fetch estimate points and display the matching value for each work item, falling back to when no estimate point is assigned or found.

Changes

Estimate display

Layer / File(s) Summary
Estimate data loading
apps/web/src/pages/ModuleDetailPage.tsx, apps/web/src/pages/ViewDetailPage.tsx
Both pages fetch typed estimate data with estimateService, store it in state, and clear it when initial loading fails.
Estimate resolution and rendering
apps/web/src/pages/ModuleDetailPage.tsx, apps/web/src/pages/ViewDetailPage.tsx
Estimate point IDs are resolved to point values, which replace the previous placeholder content in the estimate columns.

Estimated code review effort: 2 (Simple) | ~10 minutes

Poem

I’m a rabbit with estimates bright,
Points now hop into view just right.
A dash appears when none are found,
While values bloom across the ground.
Hop, hop—detail pages shine!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning For [#127], the PR only covers list-row estimates; it misses estimate/issue-type management, detail views, and tests. Either implement the remaining [#127] requirements or retitle/relink the PR to the narrower list-row estimate-display scope.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly describes the main UI change and follows Conventional Commits.
Description check ✅ Passed The PR description covers summary, linked issue, behavior, implementation, tests, scope, AI, and checklist.
Out of Scope Changes check ✅ Passed No unrelated changes are evident; the diff stays focused on estimate display in the two targeted UI pages.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick comments (3)
apps/web/src/pages/ModuleDetailPage.tsx (2)

496-501: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Pre-build an estimate point lookup map for O(1) resolution.

estimateValue calls estimates.flatMap((e) => e.points).find(...) on every issue in every render, allocating a new array each time. For lists with many issues this is wasteful. A useMemo that builds a Map<pointId, value> once per estimates change gives O(1) lookups.

♻️ Suggested refactor
+ const estimatePointMap = useMemo(() => {
+   const m = new Map<string, string>();
+   for (const e of estimates) for (const p of e.points) m.set(p.id, p.value);
+   return m;
+ }, [estimates]);

  const estimateValue = (issue: IssueApiResponse) => {
    if (!issue.estimate_point_id) return '—';
-   return (
-     estimates.flatMap((e) => e.points).find((p) => p.id === issue.estimate_point_id)?.value ?? '—'
-   );
+   return estimatePointMap.get(issue.estimate_point_id) ?? '—';
  };
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/web/src/pages/ModuleDetailPage.tsx` around lines 496 - 501, Update the
estimate lookup near estimateValue to use a useMemo-built Map keyed by estimate
point ID, recomputing only when estimates changes. Then have estimateValue
return the mapped value with the existing '—' fallback, removing the per-call
flatMap and find allocation.

496-501: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Extract the estimateValue helper to a shared utility.

The same estimateValue logic is duplicated in ViewDetailPage.tsx (lines 857-862) and a similar flatMap-and-find pattern exists in IssueDetailPage.tsx. Extracting a shared buildEstimatePointMap(estimates) or resolveEstimateValue(estimates, issue) utility would eliminate triplication and ensure consistent fallback behavior.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/web/src/pages/ModuleDetailPage.tsx` around lines 496 - 501, Extract the
duplicated estimate lookup logic from estimateValue in ModuleDetailPage and its
counterparts in ViewDetailPage and IssueDetailPage into a shared utility,
preferably a resolveEstimateValue or buildEstimatePointMap helper. Update all
callers to use it, preserving the existing em-dash fallback for missing
estimate_point_id or unmatched points and consistent estimate resolution.
apps/web/src/pages/ViewDetailPage.tsx (1)

857-862: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Pre-build an estimate point lookup map for O(1) resolution.

Same as ModuleDetailPage.tsxestimateValue allocates a new flat array per call per issue. A useMemo Map eliminates the repeated flatMap.

♻️ Suggested refactor
+ const estimatePointMap = useMemo(() => {
+   const m = new Map<string, string>();
+   for (const e of estimates) for (const p of e.points) m.set(p.id, p.value);
+   return m;
+ }, [estimates]);

  const estimateValue = (issue: IssueApiResponse) => {
    if (!issue.estimate_point_id) return '—';
-   return (
-     estimates.flatMap((e) => e.points).find((p) => p.id === issue.estimate_point_id)?.value ?? '—'
-   );
+   return estimatePointMap.get(issue.estimate_point_id) ?? '—';
  };
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/web/src/pages/ViewDetailPage.tsx` around lines 857 - 862, Update the
estimate lookup logic near estimateValue in ViewDetailPage to build a memoized
Map of estimate point IDs to values with useMemo, rather than calling
estimates.flatMap(...).find(...) for each issue. Have estimateValue resolve
issue.estimate_point_id directly from this map while preserving the existing '—'
fallback for missing IDs or values.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@apps/web/src/pages/ModuleDetailPage.tsx`:
- Around line 496-501: Update the estimate lookup near estimateValue to use a
useMemo-built Map keyed by estimate point ID, recomputing only when estimates
changes. Then have estimateValue return the mapped value with the existing '—'
fallback, removing the per-call flatMap and find allocation.
- Around line 496-501: Extract the duplicated estimate lookup logic from
estimateValue in ModuleDetailPage and its counterparts in ViewDetailPage and
IssueDetailPage into a shared utility, preferably a resolveEstimateValue or
buildEstimatePointMap helper. Update all callers to use it, preserving the
existing em-dash fallback for missing estimate_point_id or unmatched points and
consistent estimate resolution.

In `@apps/web/src/pages/ViewDetailPage.tsx`:
- Around line 857-862: Update the estimate lookup logic near estimateValue in
ViewDetailPage to build a memoized Map of estimate point IDs to values with
useMemo, rather than calling estimates.flatMap(...).find(...) for each issue.
Have estimateValue resolve issue.estimate_point_id directly from this map while
preserving the existing '—' fallback for missing IDs or values.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: d1209fcf-8c12-47b9-a1b4-e5df6a53344a

📥 Commits

Reviewing files that changed from the base of the PR and between c745572 and def2016.

📒 Files selected for processing (2)
  • apps/web/src/pages/ModuleDetailPage.tsx
  • apps/web/src/pages/ViewDetailPage.tsx

@martian56
martian56 merged commit 1dfab36 into Devlaner:main Jul 12, 2026
2 checks passed
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.

[FEAT] Finish estimates and issue types end to end

2 participants