[Customer Portal] [web] Refactor dashboard charts and support cases table - #334
Conversation
Refactor DashboardPage to simplify case statistics and chart inputs. Removed the OUTSTANDING_ENGAGEMENTS_CHART_DATA import and the heavy activeCases and casesTrend useMemo logic. outstandingCases now derives severity counts directly from SEVERITY_API_LABELS and applies isManagedCloudSubscription only to catastrophic counts. Introduced a temporary outstandingOperations object (placeholder static values) and pass it as the activeCases prop to ChartLayout while removing casesTrend from the props. Overall this reduces complexity and streamlines the data surface passed to chart components.
Adjust SupportPage unit test to expect the updated label text. The assertion for "Chat Sessions" was replaced with "Resolved Recently" in apps/customer-portal/webapp/src/pages/__tests__/SupportPage.test.tsx to match the UI/requirements change.
- Tighten StatConfigItem.icon type to ComponentType<{ size?: number }>.
- Update dashboard stat labels (Total Interactions, Active Interactions, Resolved support cases).
- Replace active-cases chart mapping with Service Requests / Change Requests entries and add OUTSTANDING_ENGAGEMENTS_CATEGORY_CHART_DATA for Onboarding/Migration/Services/Improvements; remove old case-type entries.
- Update support stat config: swap MessageSquare -> FileCheck, rename key sessionChats -> resolvedRecently and label to "Resolved Recently".
- Remove useOldUrlRedirect import and invocation from AppLayout to disable legacy URL redirect behavior.
- Modify ProjectSupportStats model: introduce resolvedRecently and reorder fields (activeChats moved after resolvedChats).
Note: Several stat keys and chart constants were renamed/reshaped; update any code that references the old keys/constants accordingly.
Refactor CasesTrendChart to render a pie (outstanding engagements) instead of a stacked bar: use OUTSTANDING_ENGAGEMENTS_CATEGORY_CHART_DATA, render slices/Cells, show center total, and update loading/error states and legend source. Update ChartLayout to remove the casesTrend prop and related excludeS0 usage and adjust chart-related types/props. Fix OutstandingIncidentsChart to use OUTSTANDING_INCIDENTS_CHART_DATA (and update title to "Outstanding Support Cases"), simplify its data shape, and honor excludeS0 filtering. Adjust a unit test (CasesOverviewStatCard.test) to match renamed/reordered stats fields. Swap the Operations nav icon to Cog in appLayoutConstants. Overall: chart type changes, data source/constants alignment, type/prop cleanups, and minor UI/text updates.
Update ActiveCases chart and related tests to use the new data fields (serviceRequests, changeRequests, total) and change the card title from "Active Engagements" to "Outstanding Operations". Adjust ChartLayout and OutstandingIncidentsChart test fixtures/totals to match the new shape and segment counts, and update OutstandingIncidentsChart title to "Outstanding Support Cases". Revise CasesTrendChart tests to mock and assert a pie-based chart (Pie/PieChart) and update expectations accordingly. All test files updated to reflect the new data shape and UI text changes.
Replace the separate case type chip/column with a severity-focused chip rendered in the Details column. Update imports and styling to use severity colors, remove getCaseTypeChipConfig usage, and eliminate the duplicate Severity column. Remove the caseTypes filter from CasesTable and clean up unused helper imports. Adjust header copy to "Outstanding Support Cases" and update tests: remove the case-type chip test and update the header test to match the new title and copy.
📝 WalkthroughWalkthroughConsolidates case categorization to severity-first display, removes case-type filtering, simplifies active-case metrics to service/change requests, converts a trend chart from bar to pie, updates dashboard labels/icons, adapts related models/hooks, and updates tests and layout usage to match the new data shapes and UI text. Changes
Sequence Diagram(s)(omitted) Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
📝 Coding Plan for PR comments
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: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (3)
apps/customer-portal/webapp/src/pages/__tests__/SupportPage.test.tsx (1)
288-316:⚠️ Potential issue | 🟡 MinorMock data key doesn't match the updated stat config key.
The test mock provides
sessionChats: 15(line 294), but the stat config now uses key"resolvedRecently"(per supportConstants.ts changes). The assertionexpect(screen.getByText("15")).toBeInTheDocument()(line 307) may pass for the wrong reason or fail if the component properly uses theresolvedRecentlykey.Update the mock data to include
resolvedRecentlyinstead of (or in addition to)sessionChats:💚 Proposed fix for mock data
mockUseGetProjectSupportStats.mockReturnValue({ isLoading: false, data: { ongoingCases: 10, activeChats: 5, - sessionChats: 15, + resolvedRecently: 15, resolvedChats: 20, }, });Note: This fix should be applied to all test cases in this file that mock
useGetProjectSupportStats(lines 292-297, 319-326, 343-350).🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/customer-portal/webapp/src/pages/__tests__/SupportPage.test.tsx` around lines 288 - 316, The mock returned by mockUseGetProjectSupportStats uses the old key sessionChats; update all mocks in this test file (where mockUseGetProjectSupportStats is set) to include the new resolvedRecently key (and remove or replace sessionChats) so the SupportPage component receives { ongoingCases, activeChats, resolvedRecently, resolvedChats } and the assertions continue to check the correct displayed values; ensure every occurrence (including the other test blocks) is updated to match the new stat config.apps/customer-portal/webapp/src/components/dashboard/charts/__tests__/OutstandingIncidentsChart.test.tsx (1)
115-134:⚠️ Potential issue | 🟡 MinorTest data and assertions are inconsistent.
Two issues in this test:
Line 122:
total: 5doesn't match the sum of the values (medium: 5 + high: 3 = 8). The total should be8.Line 130: Expects
7segments, but the previous test (line 112) correctly expects5segments for the same data shape. WithserviceRequestandsecurityReportAnalysisfields removed, there are only 5 severity-based segments.💚 Proposed fix
const incompleteData = { low: 0, medium: 5, high: 3, critical: 0, catastrophic: 0, - total: 5, + total: 8, }; render( <OutstandingIncidentsChart data={incompleteData} isLoading={false} />, ); const segments = screen.getAllByTestId("pie-segment"); - expect(segments.length).toBe(7); + expect(segments.length).toBe(5);🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/customer-portal/webapp/src/components/dashboard/charts/__tests__/OutstandingIncidentsChart.test.tsx` around lines 115 - 134, The test for OutstandingIncidentsChart uses inconsistent data and assertions: update the incompleteData object so total equals the sum of severity values (set total to 8) and adjust the segment count assertion to match the current chart shape (change expect(segments.length).toBe(7) to expect(segments.length).toBe(5)); locate the test by the it description "should render all segments even with missing data values" and the incompleteData variable used in render(<OutstandingIncidentsChart data={incompleteData} isLoading={false} />).apps/customer-portal/webapp/src/components/dashboard/charts/__tests__/ActiveCasesChart.test.tsx (1)
112-128:⚠️ Potential issue | 🔴 CriticalTest assertion will fail: expects 6 segments but only 2 exist.
ACTIVE_CASES_CHART_DATA(indashboardConstants.tslines 90-101) contains only 2 items: "Service Requests (SR)" and "Change Requests (CR)". TheActiveCasesChartcomponent maps over this array to create pie segments, so the chart will render 2 segments, not 6.🐛 Proposed fix
render(<ActiveCasesChart data={incompleteData} isLoading={false} />); // Verify that all segments are still rendered (value will be undefined) const segments = screen.getAllByTestId("pie-segment"); - // We expect 6 segments because ACTIVE_CASES_CHART_DATA has 6 items - expect(segments).toHaveLength(6); + // We expect 2 segments because ACTIVE_CASES_CHART_DATA has 2 items (serviceRequests, changeRequests) + expect(segments).toHaveLength(2); // Verify that the missing value was defaulted to 0 const values = segments.map((s) => s.getAttribute("data-value")); expect(values).toContain("0");🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/customer-portal/webapp/src/components/dashboard/charts/__tests__/ActiveCasesChart.test.tsx` around lines 112 - 128, The test wrongly asserts 6 segments but ACTIVE_CASES_CHART_DATA only has 2 items so update the test in ActiveCasesChart.test.tsx to assert against the actual data length: import or reference ACTIVE_CASES_CHART_DATA and use expect(segments).toHaveLength(ACTIVE_CASES_CHART_DATA.length) (or change hardcoded 6 to 2) and keep the existing check that missing values are defaulted to "0"; this ensures the test reflects the behavior of ActiveCasesChart which maps over ACTIVE_CASES_CHART_DATA to render segments.
🧹 Nitpick comments (7)
apps/customer-portal/webapp/src/components/dashboard/charts/CasesTrendChart.tsx (2)
163-171: Legend displaysvalue: 0for all items.The legend maps all items with
value: 0, which means the legend won't show actual counts. If the legend should display the chart values, usechartDatainstead ofchartSource:♻️ Proposed fix to show actual values in legend
{!isLoading && ( <ChartLegend - data={chartSource.map((item) => ({ - name: item.name, - value: 0, - color: item.color, - }))} + data={chartData.map((item) => ({ + name: item.name, + value: item.value ?? 0, + color: item.color, + }))} isError={isError} + showValues /> )}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/customer-portal/webapp/src/components/dashboard/charts/CasesTrendChart.tsx` around lines 163 - 171, Legend is incorrectly populated with value: 0 because ChartLegend is being fed chartSource; change the data prop to map chartData (not chartSource) so the legend shows real counts, e.g. pass chartData.map(item => ({ name: item.name, value: item.value /* or item.y depending on your series shape */, color: item.color })) to ChartLegend while keeping the isError/isLoading guards intact; update references to ChartLegend, chartSource, and chartData accordingly.
55-60: Hardcoded chart data values should be sourced from props or API.The chart values are hardcoded (
12, 8, 15, 10) rather than being passed via props or fetched from an API. This appears to be placeholder data for the UI, but:
- There's no
TODOcomment indicating this is temporary- The component will display static data regardless of actual engagements
If this is intentional for the initial UI implementation, consider adding a comment to clarify the temporary nature and track the follow-up work.
📝 Suggested documentation
: isLoading ? [] - : [ + : // TODO: Replace with actual data from props/API once backend is ready + [ { name: "Onboarding", value: 12, color: chartSource[0].color }, { name: "Migration", value: 8, color: chartSource[1].color }, { name: "Services", value: 15, color: chartSource[2].color }, { name: "Improvements", value: 10, color: chartSource[3].color }, ];🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/customer-portal/webapp/src/components/dashboard/charts/CasesTrendChart.tsx` around lines 55 - 60, The CasesTrendChart component currently uses hardcoded data values (12, 8, 15, 10) which should be replaced with dynamic input: change the static array to take values from a prop (e.g., a prop named trendData) or from the existing API/fetch call and map them to the shape [{name, value, color}] using chartSource for colors; ensure you provide a safe fallback (empty array) and update the component prop types/TS interface to accept trendData. If the hardcoded values are intentionally temporary, add a single-line TODO comment above the array mentioning it's placeholder test data and create a follow-up ticket or TODO identifier so this can be replaced with real data later; reference the CasesTrendChart component and chartSource when making these changes.apps/customer-portal/webapp/src/components/dashboard/charts/__tests__/CasesTrendChart.test.tsx (1)
81-97: Consider adding test coverage for error state.The component has error handling logic (lines 47-52, 87-103, 143-159 in CasesTrendChart.tsx), but there's no test verifying the error state renders correctly (e.g., greyed-out chart, ErrorIndicator displayed).
💚 Suggested test for error state
it("should render error state correctly", () => { render(<CasesTrendChart isLoading={false} isError={true} />); expect(screen.getByTestId("pie-chart")).toBeInTheDocument(); // Error indicator should be present expect(screen.getByText(/outstanding engagements/i)).toBeInTheDocument(); });🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/customer-portal/webapp/src/components/dashboard/charts/__tests__/CasesTrendChart.test.tsx` around lines 81 - 97, Add a new test case in the CasesTrendChart.test.tsx suite that renders the CasesTrendChart component with isLoading={false} and isError={true} (e.g., a test named "should render error state correctly"); assert that the pie chart container (getByTestId("pie-chart")) is still rendered but that the error UI is shown by checking for the ErrorIndicator or greyed-out state (use getByText(/outstanding engagements/i) or the specific error element test id if available, such as "error-indicator"), ensuring the component's error branch in CasesTrendChart is covered.apps/customer-portal/webapp/src/pages/DashboardPage.tsx (1)
158-165: Add a TODO comment to document this placeholder data.The
outstandingOperationsobject uses hardcoded static values. Based on learnings from similar patterns inOperationsPage.tsx, this is likely intentional as a placeholder until the real operations stats API is implemented. Adding a TODO comment would clarify this intent for future maintainers.📝 Proposed documentation
+ // TODO: Replace with actual API data once operations stats API is implemented. + // Currently hardcoded as a UI placeholder matching OperationsPage pattern. const outstandingOperations = useMemo( () => ({ serviceRequests: 12, changeRequests: 8, total: 20, }), [], );🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/customer-portal/webapp/src/pages/DashboardPage.tsx` around lines 158 - 165, The hardcoded outstandingOperations object returned by useMemo in DashboardPage.tsx is a placeholder; add a TODO comment above the declaration (referencing outstandingOperations and the useMemo block) documenting that these static values are temporary and should be replaced by real API-driven operation stats (similar to OperationsPage.tsx), and include a note/link or task ID for when/how to wire the actual operations stats API.apps/customer-portal/webapp/src/components/dashboard/charts/ChartLayout.tsx (1)
44-54: Update JSDoc to remove stalecasesTrendreference.The JSDoc at line 51 still documents
@param {Array} props.casesTrendbut this prop has been removed fromChartLayoutProps.📝 Proposed fix
/** * ChartLayout component displays multiple chart sections including * outstanding engagements (severities + case types), active cases, and cases trend. * * `@param` {ChartLayoutProps} props - Component props * `@param` {Object} props.outstandingCases - Severity and case type counts for Outstanding Engagements chart. - * `@param` {Object} props.activeCases - State counts for Active Engagements chart. - * `@param` {Array} props.casesTrend - Array of trend data for Cases Trend chart. + * `@param` {Object} props.activeCases - Service/change request counts for Outstanding Operations chart. * `@param` {boolean} props.isLoading - Flag indicating if the data is loading. * `@returns` {JSX.Element} The chart layout element. */🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/customer-portal/webapp/src/components/dashboard/charts/ChartLayout.tsx` around lines 44 - 54, The JSDoc for the ChartLayout component is stale: remove the now-removed prop reference and type for casesTrend from the comment block (update the JSDoc above the ChartLayout component and ChartLayoutProps declaration), ensuring the `@param` list matches actual ChartLayoutProps (keep outstandingCases, activeCases, isLoading, etc.), and update the short description if needed to no longer mention casesTrend so the documentation reflects current props.apps/customer-portal/webapp/src/components/dashboard/charts/__tests__/ChartLayout.test.tsx (1)
70-79: Remove stalecasesTrendfrom test mock props.The
casesTrendprop is no longer part ofChartLayoutProps(it was removed fromChartLayout.tsx), so this data inmockPropsis unused and misleading.🧹 Proposed cleanup
activeCases: { serviceRequests: 12, changeRequests: 8, total: 20, }, - casesTrend: [ - { - period: "2026-Q1", - critical: 10, - high: 20, - medium: 30, - low: 40, - catastrophic: 5, - }, - ], isLoading: false, };🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/customer-portal/webapp/src/components/dashboard/charts/__tests__/ChartLayout.test.tsx` around lines 70 - 79, Remove the stale casesTrend entry from the test mock props in ChartLayout.test.tsx: locate the mockProps object used to render ChartLayout (the variable named mockProps) and delete the casesTrend array and any references to it since ChartLayoutProps no longer includes casesTrend; ensure the mockProps shape matches the current ChartLayoutProps so tests only pass valid props to the ChartLayout component.apps/customer-portal/webapp/src/components/dashboard/cases-table/CasesTable.tsx (1)
67-104: Remove the orphanedcaseTypesrequest branch.The filter UI no longer sets
filters.caseTypes, so Line 114 is now dead request-building code. Leaving it behind makes the outgoing filter shape drift from the controls this component actually renders.Suggested cleanup
filters: { statusId: filters.statusId ? Number(filters.statusId) : undefined, statusIds: filters.statusId ? undefined : [...OUTSTANDING_STATUS_IDS], severityId: filters.severityId ? Number(filters.severityId) : undefined, issueId: filters.issueTypes ? Number(filters.issueTypes) : undefined, deploymentId: filters.deploymentId || undefined, - caseTypes: filters.caseTypes?.length ? [filters.caseTypes] : undefined, },Also applies to: 106-115
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/customer-portal/webapp/src/components/dashboard/cases-table/CasesTable.tsx` around lines 67 - 104, The code builds request filters for a now-unused "caseTypes" branch while the UI never sets filters.caseTypes; update the filter-building logic to remove the orphaned branch so the outgoing filter shape matches the rendered controls. Locate the dynamicFilterFields definition and any request-construction that references caseTypes (search for "caseTypes" and the code around dynamicFilterFields and the request builder that uses filters.caseTypes) and delete the branch and related mapping logic; ensure only active fields (statusId, severityId, issueTypes, deploymentId and their option sources like filtersMetadata and deploymentsData) are used when composing the filters for the request.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In
`@apps/customer-portal/webapp/src/components/dashboard/cases-table/CasesList.tsx`:
- Around line 76-77: In the CasesList component adjust the fallback TableRow
colSpan to match the current header column count (5) instead of the stale 6 used
in the empty/error message rows; locate the TableRow render blocks that
currently set colSpan={6} (around the empty/error states) and change them to
colSpan={5} or compute the span dynamically from the header array (e.g.,
headerCells.length) so the fallback message aligns with the table columns.
In `@apps/customer-portal/webapp/src/constants/supportConstants.ts`:
- Around line 279-283: The test mock in SupportPage.test.tsx doesn't match the
ProjectSupportStats interface: update the mock object used for the stats (the
one that currently contains sessionChats: 15) to use resolvedRecently: 15 so the
"Resolved Recently" stat card receives the correct value; ensure the mock's
property name matches ProjectSupportStats.resolvedRecently and rerun the test to
confirm the assertion on the "Resolved Recently" card passes.
In `@apps/customer-portal/webapp/src/models/responses.ts`:
- Around line 155-160: The ProjectSupportStats interface expects
resolvedRecently but the backend returns sessionChats, so update the API hook
that currently directly casts the backend response to ProjectSupportStats to map
sessionChats → resolvedRecently (or change the backend to return
resolvedRecently); specifically, locate the API hook that performs the direct
cast and transform the response object so it contains resolvedRecently:
response.sessionChats before casting to the ProjectSupportStats type, ensuring
the interface (ProjectSupportStats) and tests/mocks remain consistent.
---
Outside diff comments:
In
`@apps/customer-portal/webapp/src/components/dashboard/charts/__tests__/ActiveCasesChart.test.tsx`:
- Around line 112-128: The test wrongly asserts 6 segments but
ACTIVE_CASES_CHART_DATA only has 2 items so update the test in
ActiveCasesChart.test.tsx to assert against the actual data length: import or
reference ACTIVE_CASES_CHART_DATA and use
expect(segments).toHaveLength(ACTIVE_CASES_CHART_DATA.length) (or change
hardcoded 6 to 2) and keep the existing check that missing values are defaulted
to "0"; this ensures the test reflects the behavior of ActiveCasesChart which
maps over ACTIVE_CASES_CHART_DATA to render segments.
In
`@apps/customer-portal/webapp/src/components/dashboard/charts/__tests__/OutstandingIncidentsChart.test.tsx`:
- Around line 115-134: The test for OutstandingIncidentsChart uses inconsistent
data and assertions: update the incompleteData object so total equals the sum of
severity values (set total to 8) and adjust the segment count assertion to match
the current chart shape (change expect(segments.length).toBe(7) to
expect(segments.length).toBe(5)); locate the test by the it description "should
render all segments even with missing data values" and the incompleteData
variable used in render(<OutstandingIncidentsChart data={incompleteData}
isLoading={false} />).
In `@apps/customer-portal/webapp/src/pages/__tests__/SupportPage.test.tsx`:
- Around line 288-316: The mock returned by mockUseGetProjectSupportStats uses
the old key sessionChats; update all mocks in this test file (where
mockUseGetProjectSupportStats is set) to include the new resolvedRecently key
(and remove or replace sessionChats) so the SupportPage component receives {
ongoingCases, activeChats, resolvedRecently, resolvedChats } and the assertions
continue to check the correct displayed values; ensure every occurrence
(including the other test blocks) is updated to match the new stat config.
---
Nitpick comments:
In
`@apps/customer-portal/webapp/src/components/dashboard/cases-table/CasesTable.tsx`:
- Around line 67-104: The code builds request filters for a now-unused
"caseTypes" branch while the UI never sets filters.caseTypes; update the
filter-building logic to remove the orphaned branch so the outgoing filter shape
matches the rendered controls. Locate the dynamicFilterFields definition and any
request-construction that references caseTypes (search for "caseTypes" and the
code around dynamicFilterFields and the request builder that uses
filters.caseTypes) and delete the branch and related mapping logic; ensure only
active fields (statusId, severityId, issueTypes, deploymentId and their option
sources like filtersMetadata and deploymentsData) are used when composing the
filters for the request.
In
`@apps/customer-portal/webapp/src/components/dashboard/charts/__tests__/CasesTrendChart.test.tsx`:
- Around line 81-97: Add a new test case in the CasesTrendChart.test.tsx suite
that renders the CasesTrendChart component with isLoading={false} and
isError={true} (e.g., a test named "should render error state correctly");
assert that the pie chart container (getByTestId("pie-chart")) is still rendered
but that the error UI is shown by checking for the ErrorIndicator or greyed-out
state (use getByText(/outstanding engagements/i) or the specific error element
test id if available, such as "error-indicator"), ensuring the component's error
branch in CasesTrendChart is covered.
In
`@apps/customer-portal/webapp/src/components/dashboard/charts/__tests__/ChartLayout.test.tsx`:
- Around line 70-79: Remove the stale casesTrend entry from the test mock props
in ChartLayout.test.tsx: locate the mockProps object used to render ChartLayout
(the variable named mockProps) and delete the casesTrend array and any
references to it since ChartLayoutProps no longer includes casesTrend; ensure
the mockProps shape matches the current ChartLayoutProps so tests only pass
valid props to the ChartLayout component.
In
`@apps/customer-portal/webapp/src/components/dashboard/charts/CasesTrendChart.tsx`:
- Around line 163-171: Legend is incorrectly populated with value: 0 because
ChartLegend is being fed chartSource; change the data prop to map chartData (not
chartSource) so the legend shows real counts, e.g. pass chartData.map(item => ({
name: item.name, value: item.value /* or item.y depending on your series shape
*/, color: item.color })) to ChartLegend while keeping the isError/isLoading
guards intact; update references to ChartLegend, chartSource, and chartData
accordingly.
- Around line 55-60: The CasesTrendChart component currently uses hardcoded data
values (12, 8, 15, 10) which should be replaced with dynamic input: change the
static array to take values from a prop (e.g., a prop named trendData) or from
the existing API/fetch call and map them to the shape [{name, value, color}]
using chartSource for colors; ensure you provide a safe fallback (empty array)
and update the component prop types/TS interface to accept trendData. If the
hardcoded values are intentionally temporary, add a single-line TODO comment
above the array mentioning it's placeholder test data and create a follow-up
ticket or TODO identifier so this can be replaced with real data later;
reference the CasesTrendChart component and chartSource when making these
changes.
In `@apps/customer-portal/webapp/src/components/dashboard/charts/ChartLayout.tsx`:
- Around line 44-54: The JSDoc for the ChartLayout component is stale: remove
the now-removed prop reference and type for casesTrend from the comment block
(update the JSDoc above the ChartLayout component and ChartLayoutProps
declaration), ensuring the `@param` list matches actual ChartLayoutProps (keep
outstandingCases, activeCases, isLoading, etc.), and update the short
description if needed to no longer mention casesTrend so the documentation
reflects current props.
In `@apps/customer-portal/webapp/src/pages/DashboardPage.tsx`:
- Around line 158-165: The hardcoded outstandingOperations object returned by
useMemo in DashboardPage.tsx is a placeholder; add a TODO comment above the
declaration (referencing outstandingOperations and the useMemo block)
documenting that these static values are temporary and should be replaced by
real API-driven operation stats (similar to OperationsPage.tsx), and include a
note/link or task ID for when/how to wire the actual operations stats API.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: c9670787-26a5-498e-982c-bc1ef70e2e0c
📒 Files selected for processing (21)
apps/customer-portal/webapp/src/components/dashboard/cases-table/CasesList.tsxapps/customer-portal/webapp/src/components/dashboard/cases-table/CasesTable.tsxapps/customer-portal/webapp/src/components/dashboard/cases-table/CasesTableHeader.tsxapps/customer-portal/webapp/src/components/dashboard/cases-table/__tests__/CasesList.test.tsxapps/customer-portal/webapp/src/components/dashboard/cases-table/__tests__/CasesTableHeader.test.tsxapps/customer-portal/webapp/src/components/dashboard/charts/ActiveCasesChart.tsxapps/customer-portal/webapp/src/components/dashboard/charts/CasesTrendChart.tsxapps/customer-portal/webapp/src/components/dashboard/charts/ChartLayout.tsxapps/customer-portal/webapp/src/components/dashboard/charts/OutstandingIncidentsChart.tsxapps/customer-portal/webapp/src/components/dashboard/charts/__tests__/ActiveCasesChart.test.tsxapps/customer-portal/webapp/src/components/dashboard/charts/__tests__/CasesTrendChart.test.tsxapps/customer-portal/webapp/src/components/dashboard/charts/__tests__/ChartLayout.test.tsxapps/customer-portal/webapp/src/components/dashboard/charts/__tests__/OutstandingIncidentsChart.test.tsxapps/customer-portal/webapp/src/components/support/cases-overview-stats/__tests__/CasesOverviewStatCard.test.tsxapps/customer-portal/webapp/src/constants/appLayoutConstants.tsapps/customer-portal/webapp/src/constants/dashboardConstants.tsapps/customer-portal/webapp/src/constants/supportConstants.tsapps/customer-portal/webapp/src/layouts/AppLayout.tsxapps/customer-portal/webapp/src/models/responses.tsapps/customer-portal/webapp/src/pages/DashboardPage.tsxapps/customer-portal/webapp/src/pages/__tests__/SupportPage.test.tsx
💤 Files with no reviewable changes (2)
- apps/customer-portal/webapp/src/layouts/AppLayout.tsx
- apps/customer-portal/webapp/src/components/dashboard/cases-table/tests/CasesList.test.tsx
Several dashboard-related fixes and test updates: parse project support stats defensively (map sessionChats -> resolvedRecently and default numeric fields to 0), adjust cases table layout (colSpan -> 5) and remove an incorrect caseTypes wrapper. Improve CasesTrendChart placeholder/error behavior (unified loading/error chart data, circular skeleton, center error indicator, legend uses actual chartData values) and update ChartLayout docs. Update tests to mock/import constants and error indicator, and adjust expectations (ActiveCasesChart, CasesTrendChart, OutstandingIncidentsChart). Add a TODO and mock outstandingOperations in DashboardPage and update SupportPage test mocks to use resolvedRecently.
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (3)
apps/customer-portal/webapp/src/components/dashboard/charts/__tests__/OutstandingIncidentsChart.test.tsx (1)
112-112: Prefer the shared chart config over hardcoded5.Both assertions duplicate the current severity bucket count from
dashboardConstants.ts. If the legend config changes, these tests will fail for maintenance reasons rather than behavior. Using the shared constant keeps the tests aligned with the component contract.♻️ Suggested change
+import { OUTSTANDING_INCIDENTS_CHART_DATA } from "../../../constants/dashboardConstants"; ... - expect(segments.length).toBe(5); + expect(segments.length).toBe(OUTSTANDING_INCIDENTS_CHART_DATA.length); ... - expect(segments.length).toBe(5); + expect(segments.length).toBe(OUTSTANDING_INCIDENTS_CHART_DATA.length);Also applies to: 130-130
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/customer-portal/webapp/src/components/dashboard/charts/__tests__/OutstandingIncidentsChart.test.tsx` at line 112, Replace the hardcoded numeric expectation (expect(segments.length).toBe(5)) in OutstandingIncidentsChart.test.tsx with the shared chart config from dashboardConstants.ts so the test uses the authoritative severity bucket count (e.g., expect(segments.length).toBe(SEVERITY_BUCKETS.length)); do the same for the other assertion at the second occurrence — import the SEVERITY_BUCKETS (or the exact exported severity bucket constant) from dashboardConstants and use its .length in both assertions to keep tests aligned with the component contract.apps/customer-portal/webapp/src/components/dashboard/charts/__tests__/CasesTrendChart.test.tsx (1)
50-63: Assert the pie data mapping, not just the container mount.This refactor changes the chart’s data shape, but the loaded-state test still passes as long as the pie container renders. Since the mock already emits each slice’s
nameandvalue, add assertions against the expected entries so broken bucket mapping gets caught.Example improvement
+import { OUTSTANDING_ENGAGEMENTS_CATEGORY_CHART_DATA } from "@constants/dashboardConstants"; @@ it("should render pie chart and legend when data is loaded", () => { render(<CasesTrendChart isLoading={false} />); expect(screen.getByTestId("pie-chart")).toBeInTheDocument(); expect(screen.getByTestId("chart-legend")).toBeInTheDocument(); + expect(screen.getAllByTestId("pie-segment")).toHaveLength( + OUTSTANDING_ENGAGEMENTS_CATEGORY_CHART_DATA.length, + ); + OUTSTANDING_ENGAGEMENTS_CATEGORY_CHART_DATA.forEach(({ name }) => { + expect(screen.getByText(name)).toBeInTheDocument(); + }); });Also applies to: 100-103
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/customer-portal/webapp/src/components/dashboard/charts/__tests__/CasesTrendChart.test.tsx` around lines 50 - 63, The test for CasesTrendChart mounts the mocked Pie (the Pie render in the test file) but only asserts the container exists; update the test in CasesTrendChart.test.tsx to also assert the mapped slice entries by selecting the rendered pie segments (data-testid="pie-segment") and verifying each segment's displayed name and data-value match the mock data passed into the Pie prop (check the mock data array used in the test and assert each segment's text content equals item.name and its data-value equals item.value) so broken bucket mapping is caught.apps/customer-portal/webapp/src/pages/DashboardPage.tsx (1)
123-146: Prefer a single label-to-count map here.This walks
outstandingSeverityCountonce per severity and depends onSEVERITY_API_LABELSstaying positionally ordered. Normalizing counts once by label would make this cheaper and less brittle.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/customer-portal/webapp/src/pages/DashboardPage.tsx` around lines 123 - 146, Refactor the outstandingCases useMemo to first build a label->count map from casesStats?.outstandingSeverityCount (e.g., const countsByLabel = new Map(...) or an object) so you iterate the array once, then read counts with countsByLabel.get(SEVERITY_API_LABELS[i]) (or countsByLabel[...]) for catastrophic, critical, high, medium, low; keep the existing catastrophic gating via isManagedCloudSubscription and compute total = catastrophic + critical + high + medium + low. Update references in outstandingCases to use the map to avoid repeated finds and positional coupling to SEVERITY_API_LABELS.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In
`@apps/customer-portal/webapp/src/components/dashboard/charts/__tests__/CasesTrendChart.test.tsx`:
- Around line 89-91: Update the test and component props to assert the renamed
card copy "Outstanding Support Cases" everywhere: in the test file
CasesTrendChart.test.tsx change the expectation in the normal render spec
(currently checking /Outstanding Engagements/i) to /Outstanding Support Cases/i
and tighten the error-state test (the one around lines 106-110) to assert the
same text appears; also check the CasesTrendChart component where it renders
ErrorIndicator and change the entityName prop from "outstanding engagements" to
"outstanding support cases" so the test and runtime copy match (look for the
CasesTrendChart component and the ErrorIndicator usage).
In `@apps/customer-portal/webapp/src/pages/DashboardPage.tsx`:
- Around line 158-166: The DashboardPage currently uses a hard-coded useMemo
block named outstandingOperations (serviceRequests/changeRequests/total) which
must be removed; instead initialize outstandingOperations as the same
loading/empty placeholder state used by OperationsPage (keep it undefined/null
or use the same loading flag/component/pattern from OperationsPage) and render
the same skeleton/placeholder UI until the real operations stats API is
available; update any references in DashboardPage that expect those counts to
handle the loading/empty shape (e.g., check for undefined or a loading boolean)
and reuse the OperationsPage placeholder component or hook so no fabricated
totals are shown.
---
Nitpick comments:
In
`@apps/customer-portal/webapp/src/components/dashboard/charts/__tests__/CasesTrendChart.test.tsx`:
- Around line 50-63: The test for CasesTrendChart mounts the mocked Pie (the Pie
render in the test file) but only asserts the container exists; update the test
in CasesTrendChart.test.tsx to also assert the mapped slice entries by selecting
the rendered pie segments (data-testid="pie-segment") and verifying each
segment's displayed name and data-value match the mock data passed into the Pie
prop (check the mock data array used in the test and assert each segment's text
content equals item.name and its data-value equals item.value) so broken bucket
mapping is caught.
In
`@apps/customer-portal/webapp/src/components/dashboard/charts/__tests__/OutstandingIncidentsChart.test.tsx`:
- Line 112: Replace the hardcoded numeric expectation
(expect(segments.length).toBe(5)) in OutstandingIncidentsChart.test.tsx with the
shared chart config from dashboardConstants.ts so the test uses the
authoritative severity bucket count (e.g.,
expect(segments.length).toBe(SEVERITY_BUCKETS.length)); do the same for the
other assertion at the second occurrence — import the SEVERITY_BUCKETS (or the
exact exported severity bucket constant) from dashboardConstants and use its
.length in both assertions to keep tests aligned with the component contract.
In `@apps/customer-portal/webapp/src/pages/DashboardPage.tsx`:
- Around line 123-146: Refactor the outstandingCases useMemo to first build a
label->count map from casesStats?.outstandingSeverityCount (e.g., const
countsByLabel = new Map(...) or an object) so you iterate the array once, then
read counts with countsByLabel.get(SEVERITY_API_LABELS[i]) (or
countsByLabel[...]) for catastrophic, critical, high, medium, low; keep the
existing catastrophic gating via isManagedCloudSubscription and compute total =
catastrophic + critical + high + medium + low. Update references in
outstandingCases to use the map to avoid repeated finds and positional coupling
to SEVERITY_API_LABELS.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 017a8082-38c3-4d72-a8a0-f8af08806646
📒 Files selected for processing (10)
apps/customer-portal/webapp/src/api/useGetProjectSupportStats.tsapps/customer-portal/webapp/src/components/dashboard/cases-table/CasesList.tsxapps/customer-portal/webapp/src/components/dashboard/cases-table/CasesTable.tsxapps/customer-portal/webapp/src/components/dashboard/charts/CasesTrendChart.tsxapps/customer-portal/webapp/src/components/dashboard/charts/ChartLayout.tsxapps/customer-portal/webapp/src/components/dashboard/charts/__tests__/ActiveCasesChart.test.tsxapps/customer-portal/webapp/src/components/dashboard/charts/__tests__/CasesTrendChart.test.tsxapps/customer-portal/webapp/src/components/dashboard/charts/__tests__/OutstandingIncidentsChart.test.tsxapps/customer-portal/webapp/src/pages/DashboardPage.tsxapps/customer-portal/webapp/src/pages/__tests__/SupportPage.test.tsx
🚧 Files skipped from review as they are similar to previous changes (2)
- apps/customer-portal/webapp/src/components/dashboard/cases-table/CasesTable.tsx
- apps/customer-portal/webapp/src/pages/tests/SupportPage.test.tsx
2aad3b6
into
wso2-open-operations:customer-portal-milestone-1
Description
This pull request introduces significant UI and data structure updates to the customer portal's dashboard, focusing on support case and chart components. The main changes include simplifying and clarifying the cases table, updating chart data structures and visualizations, and aligning terminology across the dashboard for consistency. Several unused or redundant props and fields have been removed to streamline the codebase.
Cases Table and List Simplification:
getCaseTypeChipConfigand associated tests) have been removed from theCasesListandCasesTablecomponents. The table now displays "Details" and "Severity" columns instead, with severity chips styled directly by severity color. ([[1]](https://github.com/wso2-open-operations/cs-tools/pull/334/files#diff-74dfb7252084452649b61f363c089e191728c0eb9e9577df80aa3d3cdbbc1c8aL40-R40),[[2]](https://github.com/wso2-open-operations/cs-tools/pull/334/files#diff-74dfb7252084452649b61f363c089e191728c0eb9e9577df80aa3d3cdbbc1c8aL79-L83),[[3]](https://github.com/wso2-open-operations/cs-tools/pull/334/files#diff-74dfb7252084452649b61f363c089e191728c0eb9e9577df80aa3d3cdbbc1c8aL173-R186),[[4]](https://github.com/wso2-open-operations/cs-tools/pull/334/files#diff-74dfb7252084452649b61f363c089e191728c0eb9e9577df80aa3d3cdbbc1c8aL240-L266),[[5]](https://github.com/wso2-open-operations/cs-tools/pull/334/files#diff-6be84cf2739a974b8634dd053dda7fa2c59bfccaea7a3308e4ee6e372a7bf843L29-R29),[[6]](https://github.com/wso2-open-operations/cs-tools/pull/334/files#diff-6be84cf2739a974b8634dd053dda7fa2c59bfccaea7a3308e4ee6e372a7bf843L108-L113),[[7]](https://github.com/wso2-open-operations/cs-tools/pull/334/files#diff-70fe60b4314cdfec92533d25fa0423ffa3b2dc3cf38e7758c08e5fdaacd1e695L161-L187))Dashboard Chart Data and Visualization Updates:
serviceRequest,securityReportAnalysis, and old case status buckets have been removed or replaced with new ones such asserviceRequestsandchangeRequests. ([[1]](https://github.com/wso2-open-operations/cs-tools/pull/334/files#diff-aadc8bc08f62bd569dd003ca599367981831ba2e4581f20eedd59441f8bf78e7L31-R32),[[2]](https://github.com/wso2-open-operations/cs-tools/pull/334/files#diff-aadc8bc08f62bd569dd003ca599367981831ba2e4581f20eedd59441f8bf78e7L56-R53),[[3]](https://github.com/wso2-open-operations/cs-tools/pull/334/files#diff-ae8dca086695d2662f4c284ee44fc10886a58ddd1792a2b995259c0975814e94L30-L50),[[4]](https://github.com/wso2-open-operations/cs-tools/pull/334/files#diff-ae8dca086695d2662f4c284ee44fc10886a58ddd1792a2b995259c0975814e94L72),[[5]](https://github.com/wso2-open-operations/cs-tools/pull/334/files#diff-13d05e4ec277ee9fc955ee605aa8a5a16d128c2d6e63d300366cd7b47402bdacL36-L37),[[6]](https://github.com/wso2-open-operations/cs-tools/pull/334/files#diff-13d05e4ec277ee9fc955ee605aa8a5a16d128c2d6e63d300366cd7b47402bdacL65-R70))[[1]](https://github.com/wso2-open-operations/cs-tools/pull/334/files#diff-c6c15cdfe6059549f9dfdfcb85b439565dd96897a4402175972e52989e20aca1L19-L39),[[2]](https://github.com/wso2-open-operations/cs-tools/pull/334/files#diff-c6c15cdfe6059549f9dfdfcb85b439565dd96897a4402175972e52989e20aca1L48-R86),[[3]](https://github.com/wso2-open-operations/cs-tools/pull/334/files#diff-c6c15cdfe6059549f9dfdfcb85b439565dd96897a4402175972e52989e20aca1L97-R165))[[1]](https://github.com/wso2-open-operations/cs-tools/pull/334/files#diff-13d05e4ec277ee9fc955ee605aa8a5a16d128c2d6e63d300366cd7b47402bdacL27-R27),[[2]](https://github.com/wso2-open-operations/cs-tools/pull/334/files#diff-13d05e4ec277ee9fc955ee605aa8a5a16d128c2d6e63d300366cd7b47402bdacL94-R90))UI/UX and Terminology Consistency:
[[1]](https://github.com/wso2-open-operations/cs-tools/pull/334/files#diff-5b253a6b51d1300a33736a4415fb9f59894deffd354304337b53375c21375f50L62-R64),[[2]](https://github.com/wso2-open-operations/cs-tools/pull/334/files#diff-aadc8bc08f62bd569dd003ca599367981831ba2e4581f20eedd59441f8bf78e7L83-R75),[[3]](https://github.com/wso2-open-operations/cs-tools/pull/334/files#diff-13d05e4ec277ee9fc955ee605aa8a5a16d128c2d6e63d300366cd7b47402bdacL94-R90),[[4]](https://github.com/wso2-open-operations/cs-tools/pull/334/files#diff-2bba04177feddbe1ce73c5bfc6eb7a6aa49f072e5b7d75ee7750da4ed96e4db3L67-R67),[[5]](https://github.com/wso2-open-operations/cs-tools/pull/334/files#diff-c6c15cdfe6059549f9dfdfcb85b439565dd96897a4402175972e52989e20aca1L48-R86),[[6]](https://github.com/wso2-open-operations/cs-tools/pull/334/files#diff-c6c15cdfe6059549f9dfdfcb85b439565dd96897a4402175972e52989e20aca1L85-R102))Code and Prop Cleanup:
[[1]](https://github.com/wso2-open-operations/cs-tools/pull/334/files#diff-ae8dca086695d2662f4c284ee44fc10886a58ddd1792a2b995259c0975814e94L30-L50),[[2]](https://github.com/wso2-open-operations/cs-tools/pull/334/files#diff-ae8dca086695d2662f4c284ee44fc10886a58ddd1792a2b995259c0975814e94L72),[[3]](https://github.com/wso2-open-operations/cs-tools/pull/334/files#diff-ae8dca086695d2662f4c284ee44fc10886a58ddd1792a2b995259c0975814e94L103-L106),[[4]](https://github.com/wso2-open-operations/cs-tools/pull/334/files#diff-c6c15cdfe6059549f9dfdfcb85b439565dd96897a4402175972e52989e20aca1L19-L39),[[5]](https://github.com/wso2-open-operations/cs-tools/pull/334/files#diff-c6c15cdfe6059549f9dfdfcb85b439565dd96897a4402175972e52989e20aca1L48-R86))Testing Updates:
[[1]](https://github.com/wso2-open-operations/cs-tools/pull/334/files#diff-70fe60b4314cdfec92533d25fa0423ffa3b2dc3cf38e7758c08e5fdaacd1e695L161-L187),[[2]](https://github.com/wso2-open-operations/cs-tools/pull/334/files#diff-2bba04177feddbe1ce73c5bfc6eb7a6aa49f072e5b7d75ee7750da4ed96e4db3L67-R67))These changes collectively modernize the dashboard UI, clarify support case presentation, and ensure consistency in both data and terminology across the portal.
Summary by CodeRabbit
New Features
Bug Fixes
UI/UX Changes