Skip to content

[customer portal][web] Refactor Dashboard Charts and the stat cards - #339

Merged
Rashmika998 merged 11 commits into
wso2-open-operations:customer-portal-milestone-1from
dileepapeiris:add-new-stat-endpoints
Mar 13, 2026
Merged

Rashmika998 merged 11 commits into
wso2-open-operations:customer-portal-milestone-1from
dileepapeiris:add-new-stat-endpoints

Conversation

@dileepapeiris

@dileepapeiris dileepapeiris commented Mar 13, 2026

Copy link
Copy Markdown
Contributor

Description

This pull request introduces several improvements and refactors to the dashboard charts and statistics API in the customer portal webapp. The main focus is on enabling API-driven data for the "Cases Trend" (now "Outstanding Engagements") chart, improving error and loading states, updating the API for project case statistics, and adding a new API hook for change request statistics. Test files and component props have also been updated to reflect these changes.

API and Data Handling Improvements:

  • Added a new hook, useGetProjectChangeRequestsStats, to fetch change request statistics for a project, including proper typing and error handling. (apps/customer-portal/webapp/src/api/useGetProjectChangeRequestsStats.ts)
  • Refactored useGetProjectCasesStats to accept a caseTypes filter, improved query key stability, and normalized the API response for consistency and robustness. (apps/customer-portal/webapp/src/api/useGetProjectCasesStats.ts) [1] [2] [3] [4]

Dashboard Chart Component Enhancements:

  • Updated the CasesTrendChart component to accept API-driven data via a new data prop, replaced hardcoded mock data, improved error and loading states, and ensured the total value is sourced from the API. (apps/customer-portal/webapp/src/components/dashboard/charts/CasesTrendChart.tsx) [1] [2] [3] [4] [5] [6] [7] [8]
  • Updated ChartLayout to pass the new engagements data prop to CasesTrendChart and renamed error prop for clarity. (apps/customer-portal/webapp/src/components/dashboard/charts/ChartLayout.tsx) [1] [2] [3]

UI/UX Improvements:

  • Enhanced tooltips in pie charts by setting a higher z-index to avoid overlap issues. (apps/customer-portal/webapp/src/components/dashboard/charts/ActiveCasesChart.tsx, apps/customer-portal/webapp/src/components/dashboard/charts/OutstandingIncidentsChart.tsx, apps/customer-portal/webapp/src/components/dashboard/charts/CasesTrendChart.tsx) [1] [2] [3]

Testing Updates:

  • Updated tests for CasesTrendChart and ChartLayout to align with the new data-driven approach, including checks for correct rendering of totals and data props. (apps/customer-portal/webapp/src/components/dashboard/charts/__tests__/CasesTrendChart.test.tsx, apps/customer-portal/webapp/src/components/dashboard/charts/__tests__/ChartLayout.test.tsx) [1] [2]

Mock and Test Data Adjustments:

  • Adjusted mock support stats response to match the updated backend response structure. (apps/customer-portal/webapp/src/api/__tests__/useGetProjectSupportStats.test.tsx)

Summary by CodeRabbit

  • New Features

    • Case type filtering (adds "engagement" case type) and change request statistics on the dashboard
    • Detailed engagement metrics and breakdowns surfaced in charts and stats
  • UI/UX Improvements

    • Clarified stat labels to show "Last 30d"
    • Improved chart loading (skeletons), legend values, and tooltip layering/z-index
  • Tests

    • Updated chart-related tests to use the new data-driven props
  • Chores

    • CI workflow push trigger disabled for one branch (manual runs remain)

Introduce a new CaseType value `ENGAGEMENT` and update the comment to indicate these case types are used for case creation and stats filters. This adds support for an engagement case category in the customer-portal webapp.
Replace the single filters + cases stats flow with multiple case-type-specific queries: combined, default, service request, engagement, and change request stats. Remove useGetProjectFilters and getIncidentAndQueryIds and consolidate loading/error handling accordingly. Compute outstandingCases from default case stats, derive outstandingOperations from service request and change request APIs (replacing mocked values), and add outstandingEngagements from engagement stats. Update StatCard rendering to use the appropriate data, loading and error flags per card, and adjust ChartLayout props to accept engagements and finer-grained error/loading states.
Update dashboard statistic labels to indicate 30-day windows and extend response models to support new engagement and aggregate counts. Changes:
- apps/customer-portal/webapp/src/constants/dashboardConstants.ts: changed labels for resolvedCases and avgResponseTime to include “(Last 30d)”.
- apps/customer-portal/webapp/src/models/responses.ts: added EngagementTypeCount interface; added optional totalCount, activeCount, outstandingCount to ProjectCasesStats; added engagementTypeCount and outstandingEngagementTypeCount arrays; added optional activeCount and outstandingCount to ChangeRequestStatsResponse.
These additions enable the UI to display recent (30-day) metrics and engagement-type breakdowns plus optional aggregate counts.
Add tooltip wrapper z-index and reorganize JSX in ActiveCasesChart to ensure tooltip overlays correctly. In CasesTrendChart, accept a typed data prop and use safeData instead of hardcoded mock values; update color logic to gray out slices on error (when not loading) and compute total from incoming data. Revamp loading state to show skeleton placeholders, remove the ErrorIndicator in favor of a disabled placeholder, and enable legend values. Minor import/formatting cleanup included.
Add engagements data shape to ChartLayout props and pass it to CasesTrendChart (as data). Replace isErrorTrend with isErrorEngagements and include engagements fields (onboarding, migration, services, improvements, total). Also update OutstandingIncidentsChart PieChart tooltip to include wrapperStyle: { zIndex: 1000 } so tooltips render above other UI layers.
Modify the mocked CasesTrendChart component to accept a data prop and expose engagement fields (onboarding, migration, services, improvements, total) via data-* attributes. Update the test fixture to replace the previous casesTrend array with an engagements object to match the new prop shape while preserving the isLoading behavior.
Refactor CasesTrendChart tests to pass a shared baseData object to renders and verify center total behavior. Update the ChartLegend mock to include item values, remove the ErrorIndicator mock, and adjust the error-case assertion to expect the center total to show "--". Add a new test asserting the center displays the data.total (45) when data is provided.
Introduce useGetProjectChangeRequestsStats, a custom React hook that fetches change request statistics for a project. It uses react-query for caching, Asgardeo for auth state, and the app's authFetch client to call the backend (validates CUSTOMER_PORTAL_BACKEND_BASE_URL). The hook logs operations, normalizes the response into ChangeRequestStatsResponse, supports an optional enabled flag, and configures caching/refetch behavior (staleTime, gcTime, no auto refetch on mount/window focus/reconnect).
Import CaseType and add a typed caseTypes option to the hook. Include caseTypes in the queryKey and prefer explicit caseTypes array when building query params; fall back to the existing incidentId/queryId behavior for backwards compatibility. Build the request URL only when params exist, and normalize the API response into ProjectCasesStats with sensible defaults and field fallbacks (e.g. totalCases from totalCount, default arrays/zeros) to make the consumer more resilient to varying backend shapes.
Remove two obsolete inline comments in apps/customer-portal/webapp/src/api/useGetProjectCasesStats.ts that referenced preferred explicit case type identifiers and backwards compatibility with filters-based IDs. This is a cosmetic cleanup only and does not change runtime behavior.
@coderabbitai

coderabbitai Bot commented Mar 13, 2026

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

Refactors dashboard data fetching to use multiple case-type-specific stats hooks, adds a new change-request stats hook, extends models with engagement counts, updates charts to accept data props, and rewires DashboardPage to compute metrics from separate sources with consolidated loading/error handling.

Changes

Cohort / File(s) Summary
API Hooks
apps/customer-portal/webapp/src/api/useGetProjectCasesStats.ts, apps/customer-portal/webapp/src/api/useGetProjectChangeRequestsStats.ts
Added caseTypes filter support to cases stats hook and added a new useGetProjectChangeRequestsStats React Query hook with auth, logging, and response mapping.
Models & Constants
apps/customer-portal/webapp/src/models/responses.ts, apps/customer-portal/webapp/src/constants/supportConstants.ts, apps/customer-portal/webapp/src/constants/dashboardConstants.ts
Added EngagementTypeCount and expanded ProjectCasesStats/ChangeRequestStatsResponse; added ENGAGEMENT CaseType; updated two dashboard label strings.
Dashboard Page
apps/customer-portal/webapp/src/pages/DashboardPage.tsx
Replaced single combined stats flow with multiple per-type stats hooks, recomputed metrics (outstandingOperations, outstandingEngagements, etc.), simplified loading logic, and consolidated error handling.
Chart Components
apps/customer-portal/webapp/src/components/dashboard/charts/CasesTrendChart.tsx, apps/customer-portal/webapp/src/components/dashboard/charts/ChartLayout.tsx, apps/customer-portal/webapp/src/components/dashboard/charts/ActiveCasesChart.tsx, apps/customer-portal/webapp/src/components/dashboard/charts/OutstandingIncidentsChart.tsx
CasesTrendChart now accepts a data prop and uses skeletons for loading/error; ChartLayout prop shape updated to pass engagements; Pie charts add tooltip wrapperStyle: { zIndex: 1000 }; minor rendering reorganizations.
Tests
apps/customer-portal/webapp/src/components/dashboard/charts/__tests__/CasesTrendChart.test.tsx, apps/customer-portal/webapp/src/components/dashboard/charts/__tests__/ChartLayout.test.tsx, apps/customer-portal/webapp/src/api/__tests__/useGetProjectSupportStats.test.tsx
Updated tests/mocks to the new data/engagements shapes, adjusted assertions for legend and center totals, and replaced sessionChats with resolvedRecently in a fixture.
CI Workflow
.github/workflows/e2e-tests.yml
Commented out push trigger for branch customer-portal-milestone-1, leaving manual workflow_dispatch enabled.

Sequence Diagram(s)

mermaid
sequenceDiagram
participant Dashboard as DashboardPage
participant HookCases as useGetProjectCasesStats
participant HookCR as useGetProjectChangeRequestsStats
participant AuthClient as AuthApiClient
participant Backend as Backend API
Dashboard->>HookCases: request stats (caseTypes)
Dashboard->>HookCR: request change-request stats (projectId)
HookCases->>AuthClient: signed request
HookCR->>AuthClient: signed request
AuthClient->>Backend: GET /project/stats?caseTypes=...
Backend-->>AuthClient: JSON stats
AuthClient-->>HookCases: parsed response
AuthClient-->>HookCR: parsed response
HookCases-->>Dashboard: normalized ProjectCasesStats
HookCR-->>Dashboard: ChangeRequestStatsResponse
Note right of Dashboard: Dashboard aggregates sources → UI

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • Rashmika998
  • cloby99
  • shayanmalinda

Poem

🐰
I hopped through code with carrot-bright eyes,
Split stats like paths beneath dashboard skies.
Charts now sip numbers, neat and new,
Engagements counted, insights brew —
A rabbit cheers: refine and rise! 🥕

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description check ✅ Passed The description is largely complete with clear sections covering purpose/goals, API improvements, component enhancements, UI improvements, and testing updates. However, it lacks several template sections like Release note, Documentation, Training, and other formal documentation requirements.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Title check ✅ Passed The title 'Refactor Dashboard Charts and the stat cards' accurately reflects the main changes - refactoring dashboard chart components and statistic card elements to use API-driven data instead of mock data.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
📝 Coding Plan
  • Generate coding plan for human review 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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@dileepapeiris dileepapeiris self-assigned this Mar 13, 2026
@dileepapeiris dileepapeiris added Type/Improvement Marks enhancements or improvements to existing features Type/Task General task that does not fit into other categories Type/UX Refers to user experience-related tasks or issues App/Customer Portal Area/Frontend Platform/Web labels Mar 13, 2026
@dileepapeiris dileepapeiris changed the title Add new stat endpoints [customer portal ][web] Refactor Dashboard Charts and the stat cards Mar 13, 2026

@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: 1

Caution

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

⚠️ Outside diff range comments (1)
apps/customer-portal/webapp/src/api/__tests__/useGetProjectSupportStats.test.tsx (1)

47-50: ⚠️ Potential issue | 🔴 Critical

Remove the local mockAuthFetch definition; the global setup already provides it.

mockAuthFetch is properly connected through the global vitest setup file (vitest.setup.ts), which mocks @api/useAuthApiClient to return mockAuthFetch. However, the test file defines its own local mockAuthFetch at line 47, creating a separate instance that is not wired to the hook. When the error test at line 116 modifies this local mockAuthFetch with mockResolvedValueOnce, the change does not affect what the hook actually uses—the global mock is what's connected. This makes the error test ineffective.

Fix: Either import and reuse the global mockAuthFetch from the setup file, or remove the local definition entirely and rely on the global mock. Modifying the global mock should work correctly once the local definition is removed.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@apps/customer-portal/webapp/src/api/__tests__/useGetProjectSupportStats.test.tsx`
around lines 47 - 50, Remove the local mockAuthFetch definition in the test file
so tests use the globally provided mock from vitest.setup.ts; locate and delete
the const mockAuthFetch = vi.fn().mockResolvedValue(...) declaration in
useGetProjectSupportStats.test.tsx and ensure tests that call
mockAuthFetch.mockResolvedValueOnce(...) are operating on the global mock (no
local re-declaration) so the hook receives the intended mocked responses.
🧹 Nitpick comments (7)
apps/customer-portal/webapp/src/api/useGetProjectChangeRequestsStats.ts (1)

88-91: Add AbortError guard to preserve cancellation behavior.

Consistent with other API hooks in this codebase, re-throw AbortError before logging to preserve React Query cancellation behavior.

♻️ Add AbortError guard
       } catch (error) {
+        if (error instanceof DOMException && error.name === "AbortError") {
+          throw error;
+        }
         logger.error("[useGetProjectChangeRequestsStats] Error:", error);
         throw error;
       }

Based on learnings: "In hooks that pass React Query's signal to authFetch... if error instanceof DOMException && error.name === 'AbortError' then throw error before logging."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/customer-portal/webapp/src/api/useGetProjectChangeRequestsStats.ts`
around lines 88 - 91, The catch block in useGetProjectChangeRequestsStats
currently logs all errors, which swallows React Query cancellation semantics;
update the catch in the async function that calls authFetch (inside
useGetProjectChangeRequestsStats) to first detect and re-throw AbortError (e.g.,
if error is a DOMException and error.name === 'AbortError') before calling
logger.error and re-throwing other errors, so cancellation is preserved.
apps/customer-portal/webapp/src/api/useGetProjectCasesStats.ts (1)

121-124: Consider handling AbortError to preserve cancellation behavior.

Per established patterns in this codebase, hooks using authFetch with React Query's signal should re-throw AbortError before logging to preserve query cancellation behavior.

♻️ Add AbortError guard
       } catch (error) {
+        if (error instanceof DOMException && error.name === "AbortError") {
+          throw error;
+        }
         logger.error("[useGetProjectCasesStats] Error:", error);
         throw error;
       }

Based on learnings: "In hooks that pass React Query's signal to authFetch... if error instanceof DOMException && error.name === 'AbortError' then throw error before logging."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/customer-portal/webapp/src/api/useGetProjectCasesStats.ts` around lines
121 - 124, In the catch block of the useGetProjectCasesStats hook where
authFetch is called (the catch that currently logs via logger.error in
useGetProjectCasesStats.ts), add an AbortError guard: if the caught error is a
DOMException with name 'AbortError' re-throw it immediately to preserve React
Query cancellation semantics before performing any logging; otherwise continue
to log the error and re-throw. Ensure this check runs first in the catch so
authFetch + React Query signal cancellations are not masked.
apps/customer-portal/webapp/src/constants/dashboardConstants.ts (1)

74-79: Consider clarifying the label for resolved cases.

The label "Support Cases (Last 30d)" for resolvedCases id may be ambiguous — it could be interpreted as total cases rather than resolved cases. Consider "Resolved Cases (Last 30d)" for clarity.

💡 Suggested label clarification
   {
     id: "resolvedCases",
-    label: "Support Cases (Last 30d)",
+    label: "Resolved Cases (Last 30d)",
     icon: CheckCircle,
     iconColor: "success",
     tooltipText: "Successfully closed and resolved cases",
   },
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/customer-portal/webapp/src/constants/dashboardConstants.ts` around lines
74 - 79, Update the dashboardConstants entry for id "resolvedCases" to make the
label explicit that these are resolved items; change the label from "Support
Cases (Last 30d)" to "Resolved Cases (Last 30d)" in the object where id ===
"resolvedCases" (look for the object with id: "resolvedCases", label: "Support
Cases (Last 30d)", icon: CheckCircle, iconColor: "success", tooltipText:
"Successfully closed and resolved cases").
apps/customer-portal/webapp/src/components/dashboard/charts/CasesTrendChart.tsx (1)

62-93: Consider using chartSource for name consistency.

The chartData construction hardcodes category names ("Onboarding", "Migration", etc.) rather than deriving them from chartSource. This could lead to inconsistencies if OUTSTANDING_ENGAGEMENTS_CATEGORY_CHART_DATA names change.

💡 Derive names from chartSource
       : [
           {
-            name: "Onboarding",
+            name: chartSource[0].name,
             value: safeData.onboarding,
             color: chartSource[0].color,
           },
           {
-            name: "Migration",
+            name: chartSource[1].name,
             value: safeData.migration,
             color: chartSource[1].color,
           },
           {
-            name: "Services",
+            name: chartSource[2].name,
             value: safeData.services,
             color: chartSource[2].color,
           },
           {
-            name: "Improvements",
+            name: chartSource[3].name,
             value: safeData.improvements,
             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 62 - 93, The chartData in CasesTrendChart currently hardcodes
category names instead of using chartSource, risking name drift; update the
non-error branch that builds chartData to derive each item's name and color from
chartSource (e.g., use chartSource[0].name and chartSource[0].color) while
keeping values from safeData (safeData.onboarding, safeData.migration, etc.), or
better yet map chartSource to an array of objects where the value is looked up
from safeData by a consistent key mapping; ensure references are to chartData,
chartSource, safeData, and OUTSTANDING_ENGAGEMENTS_CATEGORY_CHART_DATA so names
remain consistent.
apps/customer-portal/webapp/src/pages/DashboardPage.tsx (2)

382-392: Clarify average response time trend color logic.

The trend color is hardcoded to "success" regardless of direction. For response time, a decrease (negative rate) typically means faster responses, which is positive. However, combining direction: "down" with color: "success" may confuse users.

Consider adding a brief inline comment explaining the intentional semantics, or using a neutral color like "info" for clarity.

💡 Example clarification
               if (
                 typeof changeRate?.averageResponseTime === "number"
               ) {
                 const rate = changeRate.averageResponseTime;
+                // For response time, decreasing (down) is good (faster), increasing (up) is bad
                 trend = {
                   value: `${rate >= 0 ? "+" : ""}${rate}%`,
                   direction: rate >= 0 ? "up" : "down",
-                  color: "success",
+                  color: rate <= 0 ? "success" : "warning", // faster is good, slower is concerning
                 };
               }
🤖 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 382 -
392, The trend color for averageResponseTime is currently always set to
"success" which contradicts the direction logic (direction: "down" can mean
improved/faster responses); update the logic in the block that reads
combinedCasesStats?.changeRate and averageResponseTime so color reflects
semantic meaning (e.g., set color = "success" when rate < 0 because a negative
response time change is good, otherwise "danger", or use a neutral "info"), or
add a clear inline comment next to the trend assignment explaining that a
downward direction represents improvement and therefore uses the "success"
color; adjust the assignment to the trend variable (value, direction, color)
accordingly so UI is unambiguous.

229-235: Extract engagement type labels to constants.

The label strings "Onboarding", "Migration", "New Feature / Improvement", and "Consultancy" are hardcoded here. These should be extracted to a constant (e.g., in dashboardConstants.ts or supportConstants.ts) to avoid typos and ensure consistency with the API contract.

♻️ Suggested refactor

In dashboardConstants.ts or a similar constants file:

export const ENGAGEMENT_TYPE_LABELS = {
  ONBOARDING: "Onboarding",
  MIGRATION: "Migration",
  IMPROVEMENTS: "New Feature / Improvement",
  SERVICES: "Consultancy",
} as const;

Then in DashboardPage.tsx:

+import { ENGAGEMENT_TYPE_LABELS } from "@constants/dashboardConstants";
 ...
-    const onboarding = getCount("Onboarding");
-    const migration = getCount("Migration");
-    const improvements = getCount("New Feature / Improvement");
-    const services = getCount("Consultancy");
+    const onboarding = getCount(ENGAGEMENT_TYPE_LABELS.ONBOARDING);
+    const migration = getCount(ENGAGEMENT_TYPE_LABELS.MIGRATION);
+    const improvements = getCount(ENGAGEMENT_TYPE_LABELS.IMPROVEMENTS);
+    const services = getCount(ENGAGEMENT_TYPE_LABELS.SERVICES);
🤖 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 229 -
235, The four hardcoded engagement labels used by getCount ("Onboarding",
"Migration", "New Feature / Improvement", "Consultancy") should be extracted to
a shared constant (e.g., export ENGAGEMENT_TYPE_LABELS with keys ONBOARDING,
MIGRATION, IMPROVEMENTS, SERVICES) and imported into DashboardPage.tsx; replace
the literal strings in the getCount calls (used when setting onboarding,
migration, improvements, services) with the corresponding ENGAGEMENT_TYPE_LABELS
properties to ensure consistency with the API and avoid typos.
apps/customer-portal/webapp/src/components/dashboard/charts/__tests__/ChartLayout.test.tsx (1)

78-84: Consider adding a test to verify engagements data is passed to CasesTrendChart.

The mock captures data-onboarding, data-migration, etc. attributes (lines 35-39), but no test currently asserts that these values are correctly passed from mockProps.engagements. This would strengthen coverage for the new data prop wiring.

💡 Suggested test case
+  it("should pass engagements data to CasesTrendChart", () => {
+    render(<ChartLayout {...mockProps} />);
+
+    const trendChart = screen.getByTestId("cases-trend-chart");
+    expect(trendChart).toHaveAttribute("data-onboarding", "1");
+    expect(trendChart).toHaveAttribute("data-migration", "2");
+    expect(trendChart).toHaveAttribute("data-services", "3");
+    expect(trendChart).toHaveAttribute("data-improvements", "4");
+    expect(trendChart).toHaveAttribute("data-total", "10");
+  });
🤖 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 78 - 84, Add a unit test in ChartLayout.test.tsx that verifies
mockProps.engagements is forwarded to CasesTrendChart by rendering ChartLayout
with the existing mockProps and asserting the DOM node for CasesTrendChart
contains the expected data attributes (data-onboarding, data-migration,
data-services, data-improvements, data-total) equal to 1,2,3,4,10 respectively;
locate the rendered CasesTrendChart element using the same selector/test-id used
in the file (the element inspected already on lines capturing
data-onboarding..data-total) and assert each attribute matches
mockProps.engagements values to cover the new prop wiring.
🤖 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/api/useGetProjectChangeRequestsStats.ts`:
- Around line 44-45: The query key for useGetProjectChangeRequestsStats
currently collides with another hook; update its queryKey to include a
discriminator (e.g., [ApiQueryKeys.CHANGE_REQUEST_STATS, "raw", id] or similar)
so the cached shape (ChangeRequestStatsResponse) does not conflict with the
transformed ChangeRequestStats; also update the hook's error handling in the
same function to detect AbortError and re-throw it before logging (check for
DOMException with name "AbortError" and throw) so cancelled fetches are not
treated as normal errors by React Query (apply these changes inside
useGetProjectChangeRequestsStats and reference
ApiQueryKeys.CHANGE_REQUEST_STATS, ChangeRequestStatsResponse, and the hook name
to locate the code).

---

Outside diff comments:
In
`@apps/customer-portal/webapp/src/api/__tests__/useGetProjectSupportStats.test.tsx`:
- Around line 47-50: Remove the local mockAuthFetch definition in the test file
so tests use the globally provided mock from vitest.setup.ts; locate and delete
the const mockAuthFetch = vi.fn().mockResolvedValue(...) declaration in
useGetProjectSupportStats.test.tsx and ensure tests that call
mockAuthFetch.mockResolvedValueOnce(...) are operating on the global mock (no
local re-declaration) so the hook receives the intended mocked responses.

---

Nitpick comments:
In `@apps/customer-portal/webapp/src/api/useGetProjectCasesStats.ts`:
- Around line 121-124: In the catch block of the useGetProjectCasesStats hook
where authFetch is called (the catch that currently logs via logger.error in
useGetProjectCasesStats.ts), add an AbortError guard: if the caught error is a
DOMException with name 'AbortError' re-throw it immediately to preserve React
Query cancellation semantics before performing any logging; otherwise continue
to log the error and re-throw. Ensure this check runs first in the catch so
authFetch + React Query signal cancellations are not masked.

In `@apps/customer-portal/webapp/src/api/useGetProjectChangeRequestsStats.ts`:
- Around line 88-91: The catch block in useGetProjectChangeRequestsStats
currently logs all errors, which swallows React Query cancellation semantics;
update the catch in the async function that calls authFetch (inside
useGetProjectChangeRequestsStats) to first detect and re-throw AbortError (e.g.,
if error is a DOMException and error.name === 'AbortError') before calling
logger.error and re-throwing other errors, so cancellation is preserved.

In
`@apps/customer-portal/webapp/src/components/dashboard/charts/__tests__/ChartLayout.test.tsx`:
- Around line 78-84: Add a unit test in ChartLayout.test.tsx that verifies
mockProps.engagements is forwarded to CasesTrendChart by rendering ChartLayout
with the existing mockProps and asserting the DOM node for CasesTrendChart
contains the expected data attributes (data-onboarding, data-migration,
data-services, data-improvements, data-total) equal to 1,2,3,4,10 respectively;
locate the rendered CasesTrendChart element using the same selector/test-id used
in the file (the element inspected already on lines capturing
data-onboarding..data-total) and assert each attribute matches
mockProps.engagements values to cover the new prop wiring.

In
`@apps/customer-portal/webapp/src/components/dashboard/charts/CasesTrendChart.tsx`:
- Around line 62-93: The chartData in CasesTrendChart currently hardcodes
category names instead of using chartSource, risking name drift; update the
non-error branch that builds chartData to derive each item's name and color from
chartSource (e.g., use chartSource[0].name and chartSource[0].color) while
keeping values from safeData (safeData.onboarding, safeData.migration, etc.), or
better yet map chartSource to an array of objects where the value is looked up
from safeData by a consistent key mapping; ensure references are to chartData,
chartSource, safeData, and OUTSTANDING_ENGAGEMENTS_CATEGORY_CHART_DATA so names
remain consistent.

In `@apps/customer-portal/webapp/src/constants/dashboardConstants.ts`:
- Around line 74-79: Update the dashboardConstants entry for id "resolvedCases"
to make the label explicit that these are resolved items; change the label from
"Support Cases (Last 30d)" to "Resolved Cases (Last 30d)" in the object where id
=== "resolvedCases" (look for the object with id: "resolvedCases", label:
"Support Cases (Last 30d)", icon: CheckCircle, iconColor: "success",
tooltipText: "Successfully closed and resolved cases").

In `@apps/customer-portal/webapp/src/pages/DashboardPage.tsx`:
- Around line 382-392: The trend color for averageResponseTime is currently
always set to "success" which contradicts the direction logic (direction: "down"
can mean improved/faster responses); update the logic in the block that reads
combinedCasesStats?.changeRate and averageResponseTime so color reflects
semantic meaning (e.g., set color = "success" when rate < 0 because a negative
response time change is good, otherwise "danger", or use a neutral "info"), or
add a clear inline comment next to the trend assignment explaining that a
downward direction represents improvement and therefore uses the "success"
color; adjust the assignment to the trend variable (value, direction, color)
accordingly so UI is unambiguous.
- Around line 229-235: The four hardcoded engagement labels used by getCount
("Onboarding", "Migration", "New Feature / Improvement", "Consultancy") should
be extracted to a shared constant (e.g., export ENGAGEMENT_TYPE_LABELS with keys
ONBOARDING, MIGRATION, IMPROVEMENTS, SERVICES) and imported into
DashboardPage.tsx; replace the literal strings in the getCount calls (used when
setting onboarding, migration, improvements, services) with the corresponding
ENGAGEMENT_TYPE_LABELS properties to ensure consistency with the API and avoid
typos.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 62c521f5-5332-4dc2-9315-01ebe77ea2e2

📥 Commits

Reviewing files that changed from the base of the PR and between 031f80f and 82c550b.

📒 Files selected for processing (13)
  • apps/customer-portal/webapp/src/api/__tests__/useGetProjectSupportStats.test.tsx
  • apps/customer-portal/webapp/src/api/useGetProjectCasesStats.ts
  • apps/customer-portal/webapp/src/api/useGetProjectChangeRequestsStats.ts
  • apps/customer-portal/webapp/src/components/dashboard/charts/ActiveCasesChart.tsx
  • apps/customer-portal/webapp/src/components/dashboard/charts/CasesTrendChart.tsx
  • apps/customer-portal/webapp/src/components/dashboard/charts/ChartLayout.tsx
  • apps/customer-portal/webapp/src/components/dashboard/charts/OutstandingIncidentsChart.tsx
  • apps/customer-portal/webapp/src/components/dashboard/charts/__tests__/CasesTrendChart.test.tsx
  • apps/customer-portal/webapp/src/components/dashboard/charts/__tests__/ChartLayout.test.tsx
  • apps/customer-portal/webapp/src/constants/dashboardConstants.ts
  • apps/customer-portal/webapp/src/constants/supportConstants.ts
  • apps/customer-portal/webapp/src/models/responses.ts
  • apps/customer-portal/webapp/src/pages/DashboardPage.tsx

@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: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/e2e-tests.yml:
- Around line 20-23: The workflow currently only has workflow_dispatch enabled
and the push trigger is commented out; re-enable an automatic trigger by
uncommenting and restoring the push block to include the target branch (e.g.,
restore the push: branches: - customer-portal-milestone-1 block) so E2E tests
run on pushes to customer-portal-milestone-1 while leaving workflow_dispatch in
place for manual runs.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 169b9834-0c66-4bdf-835d-0a066a53a8f1

📥 Commits

Reviewing files that changed from the base of the PR and between 82c550b and 0323005.

📒 Files selected for processing (1)
  • .github/workflows/e2e-tests.yml

Comment thread .github/workflows/e2e-tests.yml
@dileepapeiris dileepapeiris changed the title [customer portal ][web] Refactor Dashboard Charts and the stat cards [customer portal][web] Refactor Dashboard Charts and the stat cards Mar 13, 2026
@Rashmika998
Rashmika998 merged commit 364199c into wso2-open-operations:customer-portal-milestone-1 Mar 13, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

App/Customer Portal Area/Frontend Platform/Web Type/Improvement Marks enhancements or improvements to existing features Type/Task General task that does not fit into other categories Type/UX Refers to user experience-related tasks or issues

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants