Skip to content

[CSM Portal] case work-state actions, claim flow, and v2 contract realignment - #923

Merged
dilshanfardil merged 4 commits into
wso2-open-operations:v2from
rksk:csm-case-workstate-claimflow
Jun 24, 2026
Merged

[CSM Portal] case work-state actions, claim flow, and v2 contract realignment#923
dilshanfardil merged 4 commits into
wso2-open-operations:v2from
rksk:csm-case-workstate-claimflow

Conversation

@rksk

@rksk rksk commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

Depends on PR #893 - merge that first please.

Work state + claim flow

  • Surface the work sub-state (ongoing/paused) on the case detail header.
  • Pause/Resume the work sub-state from the action-bar More menu, shown only when the case is in progress and assigned to the current user.
  • Start work (open/waiting → in progress) enforces a single active case: look up the engineer's other ongoing cases, move this case to in progress, then either mark it ongoing (no conflict) or prompt to pause the other ongoing case(s) and make this one active.
  • Resolve assignee == me from assignedEngineer.email vs the JWT email. Search has no assignee/work-state filter, so "my ongoing cases" is narrowed by stateKeys:[work_in_progress] server-side and matched on assignee + workState === "ongoing" client-side (null work state is never ongoing).

UX

  • Case lifecycle state as a solid status chip (shared StateChip), consistent on list + detail; all case-list columns left-aligned.
  • Rename the Administration nav item and page heading to Settings.
  • Cases project filter loads the first page on open and lazy-loads more on scroll.
  • Rename the FE correlation header to X-CSM-Correlation-ID to match the gateway-safe backend header.

v2 contract realignment

  • PATCH /cases/{id}: stateKey / severityKey / workStateKey.
  • Case create: typeKey + severityKey + issueTypeKey.
  • Search filters: severityKeys (was priorityKeys); responses: severity (was priority); added reopened state and case type.

Notes

  • Backend still has no assignee search filter, so the cases-list Assignee filter stays disabled against live; the claim lookup uses the client-side match above.

Testing

  • pnpm build green · pnpm test 90 passed · pnpm lint clean

Summary by CodeRabbit

Release Notes

  • New Features

    • Added work state management to pause and resume case work.
    • Introduced case type and severity-based filtering for searches.
    • Added engineer reassignment with conflict detection for ongoing cases.
    • Enabled infinite scroll pagination for project selection during case creation.
  • Improvements

    • Refined case model: replaced priority with severity for better categorization.
    • Fixed current user assignment detection in case views.
    • Updated navigation label from "Administration" to "Settings."

@coderabbitai

coderabbitai Bot commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 3698903e-3ead-4b46-9ae7-4589c21accbf

📥 Commits

Reviewing files that changed from the base of the PR and between 556ffcf and 91fe568.

📒 Files selected for processing (19)
  • apps/csm-portal/webapp/src/api/backend/mappers.ts
  • apps/csm-portal/webapp/src/api/backend/types.ts
  • apps/csm-portal/webapp/src/components/StateChip.tsx
  • apps/csm-portal/webapp/src/config/csmNavItems.ts
  • apps/csm-portal/webapp/src/features/csm-admin/pages/CsmAdminLayout.tsx
  • apps/csm-portal/webapp/src/features/csm-cases/api/useFindMyOngoingCases.ts
  • apps/csm-portal/webapp/src/features/csm-cases/api/useGetCsmCaseDetail.ts
  • apps/csm-portal/webapp/src/features/csm-cases/api/useGetCsmCases.ts
  • apps/csm-portal/webapp/src/features/csm-cases/api/usePatchCsmCase.ts
  • apps/csm-portal/webapp/src/features/csm-cases/api/useProjectSearch.ts
  • apps/csm-portal/webapp/src/features/csm-cases/api/useQuickCaseSearch.ts
  • apps/csm-portal/webapp/src/features/csm-cases/components/AsyncProjectMultiSelect.tsx
  • apps/csm-portal/webapp/src/features/csm-cases/components/CaseActionBar.tsx
  • apps/csm-portal/webapp/src/features/csm-cases/components/CasesFilterBar.tsx
  • apps/csm-portal/webapp/src/features/csm-cases/components/CasesList.tsx
  • apps/csm-portal/webapp/src/features/csm-cases/pages/CsmCaseCreatePage.tsx
  • apps/csm-portal/webapp/src/features/csm-cases/pages/CsmCaseDetailPage.tsx
  • apps/csm-portal/webapp/src/features/csm-dashboard/api/useCaseComposition.ts
  • apps/csm-portal/webapp/src/features/csm-dashboard/api/useCaseCountsMatrix.ts
✅ Files skipped from review due to trivial changes (3)
  • apps/csm-portal/webapp/src/features/csm-cases/components/CasesFilterBar.tsx
  • apps/csm-portal/webapp/src/features/csm-admin/pages/CsmAdminLayout.tsx
  • apps/csm-portal/webapp/src/config/csmNavItems.ts
🚧 Files skipped from review as they are similar to previous changes (16)
  • apps/csm-portal/webapp/src/features/csm-dashboard/api/useCaseCountsMatrix.ts
  • apps/csm-portal/webapp/src/features/csm-cases/pages/CsmCaseCreatePage.tsx
  • apps/csm-portal/webapp/src/components/StateChip.tsx
  • apps/csm-portal/webapp/src/api/backend/mappers.ts
  • apps/csm-portal/webapp/src/features/csm-cases/api/useQuickCaseSearch.ts
  • apps/csm-portal/webapp/src/features/csm-cases/api/useGetCsmCaseDetail.ts
  • apps/csm-portal/webapp/src/features/csm-cases/components/AsyncProjectMultiSelect.tsx
  • apps/csm-portal/webapp/src/features/csm-cases/components/CaseActionBar.tsx
  • apps/csm-portal/webapp/src/features/csm-cases/api/useFindMyOngoingCases.ts
  • apps/csm-portal/webapp/src/features/csm-cases/api/useGetCsmCases.ts
  • apps/csm-portal/webapp/src/features/csm-cases/components/CasesList.tsx
  • apps/csm-portal/webapp/src/features/csm-cases/api/usePatchCsmCase.ts
  • apps/csm-portal/webapp/src/features/csm-cases/api/useProjectSearch.ts
  • apps/csm-portal/webapp/src/features/csm-dashboard/api/useCaseComposition.ts
  • apps/csm-portal/webapp/src/api/backend/types.ts
  • apps/csm-portal/webapp/src/features/csm-cases/pages/CsmCaseDetailPage.tsx

📝 Walkthrough

Walkthrough

The PR aligns the CSM portal frontend with a new backend OpenAPI contract: renames priorityseverity across types, hooks, and filters; introduces workState (ongoing/paused) and a discriminated-union BeCaseUpdatePayload; adds useFindMyOngoingCases and usePatchCsmCaseById to power a conflict-resolution flow when starting work; adds infinite paginated project search; introduces a StateChip component; and renames the admin nav label to "Settings".

Changes

Cases Domain Upgrade

Layer / File(s) Summary
Backend API types and mapper signatures
src/api/backend/types.ts, src/api/backend/mappers.ts, src/config/csmNavItems.ts, src/features/csm-admin/pages/CsmAdminLayout.tsx
Replaces BeCasePriority with BeCaseSeverity; adds BeCaseType, BeCaseWorkState, BeAssignedEngineerRef; rewrites BeCaseUpdatePayload as an exactly-one discriminated union; updates BeCaseCreatePayload, BeCaseSearchFilters, BeCaseSearchView; adjusts mapper function signatures; renames admin nav label from "Administration" to "Settings".
Data hooks: case detail, list, patch, and ongoing-cases lookup
src/features/csm-cases/api/useGetCsmCaseDetail.ts, src/features/csm-cases/api/useGetCsmCases.ts, src/features/csm-cases/api/usePatchCsmCase.ts, src/features/csm-cases/api/useFindMyOngoingCases.ts, src/features/csm-cases/api/useQuickCaseSearch.ts, src/features/csm-dashboard/api/useCaseComposition.ts, src/features/csm-dashboard/api/useCaseCountsMatrix.ts
Updates useGetCsmCaseDetail to derive assigneeIsMe from JWT email and map workState/severity; updates useGetCsmCases to send severityKeys and map title/workState/assignedEngineer; changes usePatchCsmCase return type to BeUpdateCaseResponse and adds usePatchCsmCaseById; adds useFindMyOngoingCases for conflict detection; updates useQuickCaseSearch to read c.title; updates dashboard fan-out hooks to send severityKeys.
Infinite paginated project search
src/features/csm-cases/api/useProjectSearch.ts, src/features/csm-cases/components/AsyncProjectMultiSelect.tsx, src/features/csm-cases/components/CasesFilterBar.tsx
Adds PROJECT_PAGE_SIZE, InfiniteProjectSearch, and useInfiniteProjectSearch using useInfiniteQuery; updates AsyncProjectMultiSelect to use the infinite hook with controlled open state and an onScroll listbox handler that triggers fetchNextPage.
StateChip component and CasesList rendering
src/components/StateChip.tsx, src/features/csm-cases/components/CasesList.tsx
Introduces StateChip mapping state to SemanticChip role/label via stateColor/stateLabel; updates CasesList to use StateChip, simplifies HEADER_CELLS to string[], and marks SeverityChip/StateChip as clickable.
CaseActionBar dynamic secondary actions
src/features/csm-cases/components/CaseActionBar.tsx
Refactors buildSecondaryItems to accept caseDetail and conditionally insert a toggle_work_state overflow item (pause/resume) for assigneeIsMe + work_in_progress cases; updates the reassign_engineer label.
Case creation payload update
src/features/csm-cases/pages/CsmCaseCreatePage.tsx
Updates handleSubmit to send typeKey: "support", severityKey, and issueTypeKey instead of the previous priority/issueType fields.
CsmCaseDetailPage: workState transitions, conflict resolution, and assignment
src/features/csm-cases/pages/CsmCaseDetailPage.tsx
Wires patchCaseById, findMyOngoingCases, StateChip, and dialog components; adds pauseConflict state; extends onAction to handle work_in_progress transitions with conflict detection, toggle_work_state, and reassign_engineer; adds onConfirmStartWork/onDeclineStartWork/onAssign callbacks; renders StateChip and work-state chip in header; conditionally renders pause-confirmation Dialog.

Sequence Diagram(s)

sequenceDiagram
  participant Engineer
  participant CsmCaseDetailPage
  participant useFindMyOngoingCases
  participant BackendApi
  participant usePatchCsmCaseById
  participant usePatchCsmCase

  Engineer->>CsmCaseDetailPage: action: start work / resume work
  CsmCaseDetailPage->>usePatchCsmCase: PATCH stateKey=work_in_progress
  CsmCaseDetailPage->>useFindMyOngoingCases: findMyOngoingCases(currentCaseId)
  useFindMyOngoingCases->>BackendApi: POST /cases/search stateKeys:[work_in_progress]
  BackendApi-->>useFindMyOngoingCases: BeCaseSearchView[]
  useFindMyOngoingCases->>useFindMyOngoingCases: filter workState=ongoing, assignee email, excludeId
  useFindMyOngoingCases-->>CsmCaseDetailPage: MyOngoingCase[]

  alt No conflicts
    CsmCaseDetailPage->>usePatchCsmCase: PATCH workStateKey=ongoing
    CsmCaseDetailPage->>Engineer: success feedback
  else Has conflicts
    CsmCaseDetailPage->>Engineer: show pauseConflict dialog
    Engineer->>CsmCaseDetailPage: onConfirmStartWork
    CsmCaseDetailPage->>usePatchCsmCaseById: PATCH workStateKey=paused (each conflict case)
    CsmCaseDetailPage->>usePatchCsmCase: PATCH workStateKey=ongoing
    CsmCaseDetailPage->>Engineer: success feedback
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • wso2-open-operations/cs-tools#919: Frontend contract/mappers and case-fetching hooks updated to consume the backend's renamed severity replacing priority, matching this PR's BeCaseSeverity adoption and severityKeys filter changes.
  • wso2-open-operations/cs-tools#890: The backend PatchCase/OpenAPI contract changes that this PR's frontend BeCaseUpdatePayload discriminated union and BeUpdateCaseResponse type align with.
  • wso2-open-operations/cs-tools#869: Both PRs modify useProjectSearch.ts and AsyncProjectMultiSelect.tsx; the retrieved PR introduced the initial type-ahead search that this PR upgrades to infinite scroll.

Suggested labels

Type/New Feature, Type/Improvement, Area/Frontend, App/CSM Portal

Suggested reviewers

  • cloby99
  • Rashmika998

Poem

🐰 Hop! Priority's gone, severity's here,
Work states flow—ongoing or paused, never fear.
Infinite projects scroll endlessly by,
Conflict dialogs pop up as cases fly.
StateChip glows with the right color and role—
A brand-new contract, now perfectly whole! 🌟

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 65.52% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ❓ Inconclusive The PR description covers Purpose (depends on PR #893), Goals (work state, UX, contract alignment), Approach (detailed implementation notes), User stories (implied via the feature descriptions), Release note (testing results included), but lacks several required sections like Documentation, Training, Certification, Marketing, structured Automation tests, Security checks, Samples, and Migrations. Complete the description by adding the missing template sections: Documentation (link or N/A explanation), Training, Certification, Marketing, Automation tests (unit and integration with coverage), Security checks (three yes/no items), Samples, Migrations, Test environment, and Learning. Alternatively, clarify which sections are intentionally omitted as N/A.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title concisely and accurately summarizes the three main changes: work-state actions, claim flow, and v2 contract realignment, directly matching the primary objectives of the changeset.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ 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.

Actionable comments posted: 6

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
apps/csm-portal/webapp/src/features/csm-cases/api/useGetCsmCases.ts (1)

214-235: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Map the assigned engineer returned by search.

BeCaseSearchView now exposes assignedEngineer, but the list mapper still renders every row as Unassigned, so assigned cases show incorrect assignee data in the list.

Suggested mapping fix
       const cases: CsmCaseRow[] = (casesResponse.cases ?? []).map((c) => {
         const projectId = c.project?.id ?? "";
         const accountId = projectAccount.get(projectId) ?? "";
+        const assignee =
+          c.assignedEngineer?.name?.trim() ||
+          c.assignedEngineer?.email ||
+          "Unassigned";
         return {
@@
-          // No assignee field on the backend yet; surfaced as "Unassigned".
-          assignee: "Unassigned",
+          assignee,
           assigneeIsMe: false,
🤖 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/csm-portal/webapp/src/features/csm-cases/api/useGetCsmCases.ts` around
lines 214 - 235, The case mapper in useGetCsmCases is hardcoding assignee as
"Unassigned" and assigneeIsMe as false, but the backend response now includes
the assignedEngineer field. Update the map function that transforms
casesResponse.cases into CsmCaseRow objects to extract and use the actual
assignedEngineer data from the case object c instead of these hardcoded values,
determining the assignee name and whether it matches the current user based on
the assignedEngineer field returned by the backend.
🧹 Nitpick comments (2)
apps/csm-portal/webapp/src/features/csm-cases/components/CsmCaseCommentInput.tsx (1)

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

Avoid effect-driven state correction for the locked reply mode.

setInternal(true) inside useEffect conflicts with the repo’s react-hooks/set-state-in-effect convention. Move the correction to render-time, or derive an effectiveInternal = publicReplyLocked || internal value and use that for UI/submission reads.

♻️ Proposed localized fix
-  useEffect,
   useMemo,
   const publicReplyLocked = !!publicCommentDisabledReason;
-  useEffect(() => {
-    if (publicReplyLocked && !internal) setInternal(true);
-  }, [publicReplyLocked, internal]);
+  if (publicReplyLocked && !internal) {
+    setInternal(true);
+  }

Based on learnings, apps/csm-portal/webapp follows the react-hooks/set-state-in-effect rule: do not call setState inside useEffect; use React’s render-time adjustment pattern instead.

Also applies to: 209-211

🤖 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/csm-portal/webapp/src/features/csm-cases/components/CsmCaseCommentInput.tsx`
at line 37, The CsmCaseCommentInput component violates the
react-hooks/set-state-in-effect convention by calling setInternal(true) inside a
useEffect hook around line 37 (and again around lines 209-211). Instead of
modifying state within the effect, create a derived value at render-time by
computing effectiveInternal = publicReplyLocked || internal, and use this
derived value throughout the component for UI rendering and form submission
logic rather than relying on the state mutation within the effect. This ensures
the locked reply mode correction happens during the render phase rather than as
an effect side-effect.

Source: Learnings

apps/csm-portal/webapp/src/api/backend/mappers.ts (1)

27-68: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Finish the severity terminology in the mapper API.

The backend type is now BeCaseSeverity, but the exported helper names still say Priority, which leaks the removed contract vocabulary into new severity-key call sites.

Suggested rename
-export function severityFromPriority(
-  priority: BeCaseSeverity | undefined,
+export function severityFromBeSeverity(
+  severity: BeCaseSeverity | undefined,
 ): Severity {
-  switch (priority) {
+  switch (severity) {
@@
-export function priorityFromSeverity(severity: Severity): BeCaseSeverity {
+export function beSeverityFromUiSeverity(severity: Severity): BeCaseSeverity {

Then update imports/call sites that currently call severityFromPriority or priorityFromSeverity.

🤖 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/csm-portal/webapp/src/api/backend/mappers.ts` around lines 27 - 68, The
function names severityFromPriority and priorityFromSeverity use outdated
terminology since the backend type is now BeCaseSeverity instead of
BeCasePriority. Rename severityFromPriority to severityFromBeSeverity and
priorityFromSeverity to beSeverityFromSeverity to maintain consistent severity
terminology throughout the mapper API. Then update all call sites throughout the
codebase that reference these old function names with the new ones.
🤖 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/api/backend/types.ts`:
- Around line 186-195: The typeKey field in the BeCaseCreatePayload interface
currently accepts any BeCaseType value, but the comment indicates the portal
only creates support cases. Narrow the type of the typeKey field in
BeCaseCreatePayload from BeCaseType to a literal type constraint that only
allows the support case type value, preventing callers from accidentally passing
non-creatable case types while still compiling.

In `@apps/csm-portal/webapp/src/features/csm-cases/api/useProjectSearch.ts`:
- Around line 109-114: The getNextPageParam function in useProjectSearch.ts has
a pagination guard issue where if hasMore is true but the backend returns an
empty projects page, the offset calculation using allPages.reduce will not
advance (remaining at 0), causing subsequent scroll-triggered fetches to
repeatedly hit the same page. To fix this, add logic to ensure the next offset
advances even when a page returns no projects. Consider either: keeping track of
a minimum offset increment when hasMore is true, or adding a safety check that
advances the offset by at least 1 when the current page is empty but hasMore
indicates more data exists. This prevents infinite loops of requests fetching
the same empty page.

In
`@apps/csm-portal/webapp/src/features/csm-cases/components/AsyncProjectMultiSelect.tsx`:
- Around line 68-74: The useInfiniteProjectSearch hook destructuring in
AsyncProjectMultiSelect is missing an error state that should be captured
alongside the existing properties (projects, isFetching, isFetchingNextPage,
hasNextPage, fetchNextPage). Add the error property to the destructured values
from useInfiniteProjectSearch, then at line 148 where the empty state message is
rendered, add a conditional check to display an explicit error message when the
error state exists instead of defaulting all non-fetching empty states to "No
projects found".

In `@apps/csm-portal/webapp/src/features/csm-cases/components/CaseActionBar.tsx`:
- Around line 207-218: The condition in the CaseActionBar component currently
requires caseDetail.workState to be truthy before showing the toggle_work_state
action, but this hides the action for work_in_progress cases where workState is
null. Remove the caseDetail.workState check from the condition so that the
action is shown for all work_in_progress cases where assigneeIsMe is true. Then
update the paused variable logic to treat anything other than "ongoing"
(including null) as a paused state, so that null workState cases show "Resume
work" as the label.

In `@apps/csm-portal/webapp/src/features/csm-cases/pages/CsmCaseDetailPage.tsx`:
- Around line 477-481: In the toggle_work_state action handler, split the logic
based on the direction of the transition. When transitioning from "paused" to
"ongoing" (resuming work), route through the same conflict detection flow that
is used when starting work (using findMyOngoingCases and the confirmation
dialog), rather than directly calling patchCase.mutate(). Keep the direct patch
for the "ongoing" to "paused" transition. This ensures that resuming a paused
case checks for existing ongoing cases before allowing the state change,
preventing engineers from having multiple concurrent active cases.
- Around line 393-398: The try-catch block around the findMyOngoingCases
function call is silently ignoring lookup failures and continuing with an empty
others array, which allows the case to be marked as ongoing without verifying if
another case is already active. Instead of catching and continuing with the
empty array, remove the catch block or re-throw the error so that the transition
is blocked when the ongoing-case lookup fails, ensuring the error is properly
surfaced rather than allowing the operation to proceed with incomplete
information.

---

Outside diff comments:
In `@apps/csm-portal/webapp/src/features/csm-cases/api/useGetCsmCases.ts`:
- Around line 214-235: The case mapper in useGetCsmCases is hardcoding assignee
as "Unassigned" and assigneeIsMe as false, but the backend response now includes
the assignedEngineer field. Update the map function that transforms
casesResponse.cases into CsmCaseRow objects to extract and use the actual
assignedEngineer data from the case object c instead of these hardcoded values,
determining the assignee name and whether it matches the current user based on
the assignedEngineer field returned by the backend.

---

Nitpick comments:
In `@apps/csm-portal/webapp/src/api/backend/mappers.ts`:
- Around line 27-68: The function names severityFromPriority and
priorityFromSeverity use outdated terminology since the backend type is now
BeCaseSeverity instead of BeCasePriority. Rename severityFromPriority to
severityFromBeSeverity and priorityFromSeverity to beSeverityFromSeverity to
maintain consistent severity terminology throughout the mapper API. Then update
all call sites throughout the codebase that reference these old function names
with the new ones.

In
`@apps/csm-portal/webapp/src/features/csm-cases/components/CsmCaseCommentInput.tsx`:
- Line 37: The CsmCaseCommentInput component violates the
react-hooks/set-state-in-effect convention by calling setInternal(true) inside a
useEffect hook around line 37 (and again around lines 209-211). Instead of
modifying state within the effect, create a derived value at render-time by
computing effectiveInternal = publicReplyLocked || internal, and use this
derived value throughout the component for UI rendering and form submission
logic rather than relying on the state mutation within the effect. This ensures
the locked reply mode correction happens during the render phase rather than as
an effect side-effect.
🪄 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: 01e8fac4-ad14-4fbc-b2d4-1a9a2c6bf9c1

📥 Commits

Reviewing files that changed from the base of the PR and between 451a3d6 and 49953db.

📒 Files selected for processing (29)
  • apps/csm-portal/webapp/src/api/backend/client.ts
  • apps/csm-portal/webapp/src/api/backend/mappers.ts
  • apps/csm-portal/webapp/src/api/backend/types.ts
  • apps/csm-portal/webapp/src/components/StateChip.tsx
  • apps/csm-portal/webapp/src/config/csmNavItems.ts
  • apps/csm-portal/webapp/src/features/csm-admin/pages/CsmAdminLayout.tsx
  • apps/csm-portal/webapp/src/features/csm-cases/api/mocks/casesMocks.ts
  • apps/csm-portal/webapp/src/features/csm-cases/api/useFindMyOngoingCases.ts
  • apps/csm-portal/webapp/src/features/csm-cases/api/useGetCsmCaseDetail.ts
  • apps/csm-portal/webapp/src/features/csm-cases/api/useGetCsmCases.ts
  • apps/csm-portal/webapp/src/features/csm-cases/api/usePatchCsmCase.ts
  • apps/csm-portal/webapp/src/features/csm-cases/api/useProjectSearch.ts
  • apps/csm-portal/webapp/src/features/csm-cases/api/useQuickCaseSearch.ts
  • apps/csm-portal/webapp/src/features/csm-cases/components/AssignEngineerDialog.tsx
  • apps/csm-portal/webapp/src/features/csm-cases/components/AsyncProjectMultiSelect.tsx
  • apps/csm-portal/webapp/src/features/csm-cases/components/CaseActionBar.tsx
  • apps/csm-portal/webapp/src/features/csm-cases/components/CasesFilterBar.tsx
  • apps/csm-portal/webapp/src/features/csm-cases/components/CasesList.tsx
  • apps/csm-portal/webapp/src/features/csm-cases/components/CsmCaseCommentInput.tsx
  • apps/csm-portal/webapp/src/features/csm-cases/pages/CsmCaseCreatePage.tsx
  • apps/csm-portal/webapp/src/features/csm-cases/pages/CsmCaseDetailPage.tsx
  • apps/csm-portal/webapp/src/features/csm-cases/types/csmCases.ts
  • apps/csm-portal/webapp/src/features/csm-cases/utils/caseWorkState.test.ts
  • apps/csm-portal/webapp/src/features/csm-cases/utils/caseWorkState.ts
  • apps/csm-portal/webapp/src/features/csm-dashboard/api/useCaseComposition.ts
  • apps/csm-portal/webapp/src/features/csm-dashboard/api/useCaseCountsMatrix.ts
  • apps/csm-portal/webapp/src/features/csm-dashboard/types/abtDashboard.ts
  • apps/csm-portal/webapp/src/utils/correlationId.test.ts
  • apps/csm-portal/webapp/src/utils/correlationId.ts

Comment thread apps/csm-portal/webapp/src/api/backend/types.ts
Comment thread apps/csm-portal/webapp/src/features/csm-cases/components/CaseActionBar.tsx Outdated
Comment thread apps/csm-portal/webapp/src/features/csm-cases/pages/CsmCaseDetailPage.tsx Outdated
Comment thread apps/csm-portal/webapp/src/features/csm-cases/pages/CsmCaseDetailPage.tsx Outdated
rksk added a commit to rksk/os-cs-tools that referenced this pull request Jun 23, 2026
…e-case on resume, list assignee mapping, project-search guards
@rksk

rksk commented Jun 24, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 24, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

dilshanfardil
dilshanfardil previously approved these changes Jun 24, 2026
@rksk
rksk dismissed dilshanfardil’s stale review June 24, 2026 04:12

The merge-base changed after approval.

rksk added 4 commits June 24, 2026 04:14
…lignment

Builds on the case-write-contract work with the case work-state lifecycle,
the start-work claim flow, identity-aware gating, list/nav UX polish, and a
realignment of the FE contract layer to the latest entity/BFF changes.

Work state + claim flow
- Surface the work sub-state (ongoing/paused) on the case detail header.
- Pause/Resume the work sub-state from the case action-bar "More" menu,
  shown only when the case is in progress and assigned to the current user.
- Starting work on a case (open/waiting -> in progress) enforces a single
  active case: look up the engineer's other ongoing cases, move this case to
  in progress, then either mark it ongoing (no conflict) or prompt to pause
  the other ongoing case(s) and make this one active.
- Resolve assignee == current user from assignedEngineer.email vs the JWT
  email (the search has no assignee filter, so "my ongoing cases" is found by
  state on the server + assignee/ongoing match on the client; null work state
  is never treated as ongoing).

UX
- Render case lifecycle state as a solid status chip (shared StateChip),
  consistent on the list and detail; left-align all case-list columns.
- Rename the "Administration" nav item and page heading to "Settings".
- Cases project filter loads the first page on open and lazy-loads more on
  scroll (and narrows as you type).
- Rename the FE correlation header to X-CSM-Correlation-ID to match the
  gateway-safe backend header.

v2 contract realignment
- PATCH /cases/{id}: stateKey / severityKey / workStateKey (was state /
  priority / workState).
- Case create: typeKey + severityKey + issueTypeKey.
- Case search filters: severityKeys (was priorityKeys); drop unsupported
  fields. Responses: severity (was priority); add reopened state and case type.
…e-case on resume, list assignee mapping, project-search guards
@rksk
rksk force-pushed the csm-case-workstate-claimflow branch from 556ffcf to 91fe568 Compare June 24, 2026 04:15
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