feat(csm-timecards): searchable filters, minutes not hours, tighter approver gating - #1055
Conversation
…tighter approver gating Work item, engineer, and project filters now use a shared searchable multi-select instead of plain text/select fields. Time is tracked and shown in whole minutes everywhere, matching what the backend actually stores. Approvals tab is restricted to the real approver group instead of also granting it to generic admins. Removed the dead Category field from Log time (never sent to the backend). Fixed the Review button showing on your own submitted cards even though deciding your own card always 403s.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (4)
🚧 Files skipped from review as they are similar to previous changes (2)
📝 WalkthroughWalkthroughThis PR adds shared multi-select components, refactors cases filters to use them, and migrates timecard totals, validation, display, and filtering from hours to minutes. It also removes the timecard Category field, updates role checks, and adjusts e2e coverage for the new filter controls. ChangesShared multi-select components
Timecard minute migration
Estimated code review effort: 4 (Complex) | ~60 minutes Sequence Diagram(s)sequenceDiagram
participant User
participant SearchableMultiSelect
participant CsmTimeCardsPage
participant FilterBar
User->>SearchableMultiSelect: select project or case number
SearchableMultiSelect->>FilterBar: onChange(string[])
FilterBar->>CsmTimeCardsPage: update filter arrays
CsmTimeCardsPage->>CsmTimeCardsPage: recompute visible sheets and cards
CsmTimeCardsPage-->>User: render filtered results and chips
Possibly related PRs
Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 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.
Inline comments:
In `@apps/csm-portal/webapp/src/components/SearchableMultiSelect.tsx`:
- Around line 17-18: The SearchableMultiSelect component is using the React
namespace for HTMLAttributes without importing it, so TypeScript will fail.
Update the imports in SearchableMultiSelect.tsx to bring in HTMLAttributes
explicitly, and replace the props cast in the Autocomplete render logic with the
imported type instead of React.HTMLAttributes<HTMLLIElement>.
In `@apps/csm-portal/webapp/tests/e2e/specs/timecards/my-sheets.spec.ts`:
- Around line 100-107: The my-sheets e2e flow clears the work item filter but
does not verify the post-clear state. Update the test in the my-sheets spec
around tc.clearFilters() to assert the filter was removed or that the sheet/card
list returned to an unfiltered state, using the existing tc helper methods and
the caseNumber-specific visibility checks already in place.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 393ed4b0-f278-48f7-9c51-02b6b347a284
📒 Files selected for processing (21)
apps/csm-portal/webapp/src/components/MultiSelectField.tsxapps/csm-portal/webapp/src/components/SearchableMultiSelect.tsxapps/csm-portal/webapp/src/features/csm-cases/components/CasesFilterBar.tsxapps/csm-portal/webapp/src/features/csm-timecards/api/useTimeCards.tsapps/csm-portal/webapp/src/features/csm-timecards/api/useTimeSheets.tsapps/csm-portal/webapp/src/features/csm-timecards/components/CaseTimeCardsPanel.tsxapps/csm-portal/webapp/src/features/csm-timecards/components/LogTimeCardDialog.tsxapps/csm-portal/webapp/src/features/csm-timecards/components/TimeCardReviewDialog.tsxapps/csm-portal/webapp/src/features/csm-timecards/components/TimeSheetCard.tsxapps/csm-portal/webapp/src/features/csm-timecards/constants/timeCardConstants.tsapps/csm-portal/webapp/src/features/csm-timecards/hooks/useIsTeamLead.tsapps/csm-portal/webapp/src/features/csm-timecards/hooks/useTimecardRole.tsapps/csm-portal/webapp/src/features/csm-timecards/pages/CsmTimeCardsPage.tsxapps/csm-portal/webapp/src/features/csm-timecards/types/timeCards.tsapps/csm-portal/webapp/src/features/csm-timecards/utils/__tests__/timeCardTotals.test.tsapps/csm-portal/webapp/src/features/csm-timecards/utils/__tests__/timeSheetGrouping.test.tsapps/csm-portal/webapp/src/features/csm-timecards/utils/timeCardTotals.tsapps/csm-portal/webapp/src/features/csm-timecards/utils/timeSheetGrouping.tsapps/csm-portal/webapp/tests/e2e/pages/TimeCardsPage.tsapps/csm-portal/webapp/tests/e2e/specs/timecards/approvals.spec.tsapps/csm-portal/webapp/tests/e2e/specs/timecards/my-sheets.spec.ts
💤 Files with no reviewable changes (1)
- apps/csm-portal/webapp/src/features/csm-timecards/constants/timeCardConstants.ts
…owns Resolves the CasesFilterBar.tsx conflict: keeps the shared @components/ MultiSelectField.tsx extraction but updates its implementation to match dev-app-csm-portal's newer Autocomplete+chip look (was Select+checkbox), and drops the now-redundant local MultiSelectField/SearchableMultiSelect definitions and unused imports.
…ons#1055 Import HTMLAttributes explicitly in SearchableMultiSelect instead of relying on the ambient React namespace, matching MultiSelectField's existing style. Also assert the work-item filter actually clears in the my-sheets e2e test, not just that it applied.
|
Fixed both, pushed. Explicit React import in SearchableMultiSelect, and the my-sheets test now checks the filter actually clears. |
|
@coderabbitai review |
✅ Action performedReview finished.
|
|
@coderabbitai resume |
✅ Action performedReviews resumed. |
…ilter Reconciles the date-range filter and success-toast additions with the now-merged searchable multi-select filters from PR #1055 (project/work item/engineer went from plain strings to string[]).
Purpose
Follow-up usability and correctness fixes on top of #1028, found while continuing to exercise the time-cards feature: unwieldy free-text/plain-select filters, a real hours/minutes unit mismatch (the backend stores minutes; the form collected and displayed hours without converting), and two approver-gating gaps. No tracked issue number for this batch.
Goals
nonNegativeMinutes), not hours.Approach
MultiSelectFieldandSearchableMultiSelectout ofCasesFilterBar.tsxinto shared components undersrc/components/so csm-timecards (and any future feature) can reuse the same look/behavior instead of duplicating it.CasesFilterBar.tsxnow imports from there too — no behavior change for Cases./time-cardsare now searchable multi-selects, sourced from whatever's already loaded on the current tab/page (no new API calls introduced).CsmTimeCard.totalHours/CsmTimeSheet.totalHourstototalMinutesand made minutes the native unit end-to-end:usePostTimeCardno longer converts (form collects whole minutes directly),mapTimeCardno longer converts (direct passthrough), and every display (Log time dialog, case Time tracking panel, weekly sheet cards, review dialog) shows minutes.useTimecardRole()'sisApprovernow reflects only the dedicatedsn_customerservice_timecard_approvergroup;isAdminis tracked independently and no longer folded in.CaseTimeCardsPanel's Review button now checkscard.userId !== signed-in user.idbefore rendering.No screenshot yet — happy to add one or demo live if useful before merge.
User stories
Release note
Time-card filters (work item, engineer, project) are now searchable; logged time is now correctly tracked and displayed in minutes; the Approvals tab is now limited to designated time-card approvers.
Documentation
N/A — internal CSM portal UI, no external product documentation covers this feature.
Training
N/A — not training content.
Certification
N/A — no certification exam impact.
Marketing
N/A — internal tooling, not customer-facing marketing content.
Automation tests
Unit tests
pnpm run test— 128 tests pass, including rewritten/new coverage for the minutes conversion (timeCardTotals.test.ts) and sheet grouping (timeSheetGrouping.test.ts).Integration tests
Local Playwright E2E suite updated for the new searchable Work item filter (
TimeCardsPage.ts,my-sheets.spec.ts,approvals.spec.ts); full live run pending a fresh captured staging session.Security checks
Samples
N/A
Related PRs
Branches off #1028 (merged into
dev-app-csm-portal).Migrations (if applicable)
N/A — no data migration. Time cards were already stored in minutes server-side; this only fixes how the frontend collects/displays that value, going forward.
Test environment
Local dev server (
pnpm run dev), macOS, Chromium via Playwright, real staging backend (ServiceNow-backed entity-service).Learning
Confirmed the hours/minutes unit mismatch by cross-referencing entity-service's
nonNegativeMinutesvalidation helper name against a real pre-existing card'stotalTimevalue, which only made sense as minutes.Summary by CodeRabbit
New Features
Bug Fixes