Skip to content

[Customer Portal][Web] Integrate Change Request Stats API & Add Deployment Filter to All Cases - #289

Merged
Rashmika998 merged 12 commits into
wso2-open-operations:customer-portal-milestone-1from
dileepapeiris:feat/add-CR-Stats
Mar 3, 2026
Merged

Rashmika998 merged 12 commits into
wso2-open-operations:customer-portal-milestone-1from
dileepapeiris:feat/add-CR-Stats

Conversation

@dileepapeiris

@dileepapeiris dileepapeiris commented Mar 2, 2026 •

Copy link
Copy Markdown
Contributor

Description

This pull request adds a new API hook for fetching change request statistics and integrates it into the change requests page, replacing the previous mock stats implementation. It also introduces support for a deployment filter in the all cases search bar and filter components by fetching deployments from the API and passing them as props.

Change Request Stats API Integration

Deployment Filter Support in All Cases

  • Fetched deployments via the useGetDeployments hook and passed them to the all cases search bar and filter components. (apps/customer-portal/webapp/src/pages/AllCasesPage.tsx, [1] [2] [3]
  • Updated props and logic in AllCasesSearchBar and AllCasesFilters to support and render deployment filter options. (apps/customer-portal/webapp/src/components/support/all-cases/AllCasesSearchBar.tsx, [1] [2] [3] [4]; apps/customer-portal/webapp/src/components/support/all-cases/AllCasesFilters.tsx, [5] [6] [7] [8]

Summary by CodeRabbit

  • New Features

    • Deployment-based filtering added across case lists and dashboard tables.
    • Live change-request statistics integrated, replacing mock data and powering stats cards.
    • Conversation context persistence so conversation IDs carry through from chat to case creation.
  • Bug Fixes

    • Improved loading/error handling and export flow to wait for real stats before exporting.
    • UI cleanup: external link icon removed from case titles.

Introduce a new hook useGetProjectChangeRequestStats to fetch and map change request stats from the backend (with response type ChangeRequestStatsResponse). Add a new ApiQueryKeys entry (CHANGE_REQUEST_STATS). Integrate the hook into ChangeRequestsPage: import and call the hook, remove the previous mocked stats, use the hook's loading/error states for the stat cards, and ensure exports wait for stats to be available. Includes mapping logic to derive scheduled, inProgress, and completed counts from API state counts and basic error/log handling.
Reformat useGetProjectChangeRequestStats.ts for readability (multi-line imports, function params, arrays, and logger calls) and clean up whitespace; no behavioral changes to the mapping logic. In ChangeRequestsPage.tsx, wrap setIsExporting(false) in setTimeout(..., 0) when handling export success/error to defer the state update and avoid synchronous React state updates during render or while unmounting.
Wire project deployments into the all-cases filters so the deployment dropdown uses real deployment items instead of generic metadata. Added optional deployments props to AllCasesFilters and AllCasesSearchBar, imported the ProjectDeploymentItem type, and updated AllCasesFilters to build options from deployments (label = type.label || name, value = id) when the filter id is "deployment". AllCasesPage now fetches deployments via useGetDeployments and passes them through to the search bar; when deployments are not present, the component falls back to the existing metadata-based options.
@dileepapeiris dileepapeiris self-assigned this Mar 2, 2026
@dileepapeiris dileepapeiris added Type/New Feature Represents a request or task for a new feature 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 2, 2026
@coderabbitai

coderabbitai Bot commented Mar 2, 2026 •

Copy link
Copy Markdown
Contributor

Warning

Rate limit exceeded

@dileepapeiris has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 17 minutes and 56 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between 7572bfd and 1035506.

📒 Files selected for processing (2)
  • apps/customer-portal/webapp/src/pages/ChangeRequestsPage.tsx
  • apps/customer-portal/webapp/src/pages/CreateCasePage.tsx
📝 Walkthrough

Walkthrough

Adds a typed React Query hook to fetch project change-request stats, threads deployment data into cases UI for deployment-based filters, wires real stats into ChangeRequestsPage export/UX, and propagates an optional conversationId through case creation and chat navigation.

Changes

Cohort / File(s) Summary
API Query Hook
apps/customer-portal/webapp/src/api/useGetProjectChangeRequestStats.ts
New React Query hook (uses auth state) that GETs ${window.config.CUSTOMER_PORTAL_BACKEND_BASE_URL}/projects/{projectId}/stats/change-requests, maps ChangeRequestStatsResponse → ChangeRequestStats, logs lifecycle, validates response, and sets query options (key [CHANGE_REQUEST_STATS, projectId], staleTime 5m, gcTime 10m).
Types & Constants
apps/customer-portal/webapp/src/models/responses.ts, apps/customer-portal/webapp/src/constants/apiConstants.ts
Added ChangeRequestStatsResponse interface and ApiQueryKeys.CHANGE_REQUEST_STATS key.
UI: Deployment filters (prop threading)
apps/customer-portal/webapp/src/components/support/all-cases/AllCasesFilters.tsx, apps/customer-portal/webapp/src/components/support/all-cases/AllCasesSearchBar.tsx
Introduced deployments?: ProjectDeploymentItem[] prop and threaded it from AllCasesSearchBar → AllCasesFilters to populate deployment filter options when provided.
Pages: integration & data flow
apps/customer-portal/webapp/src/pages/AllCasesPage.tsx, apps/customer-portal/webapp/src/pages/ChangeRequestsPage.tsx
AllCasesPage now fetches deployments and forwards them to AllCasesSearchBar. ChangeRequestsPage uses useGetProjectChangeRequestStats, replaces mocked stats with real API data, updates export flow to wait for stats, and wires stat cards to real loading/error states.
Tables: deployment source swap
apps/customer-portal/webapp/src/components/dashboard/cases-table/CasesTable.tsx
Switched deployment filter options to use useGetDeployments results (with fallbacks) and maps labels using mapSeverityToDisplay where applicable.
API shape & request model
apps/customer-portal/webapp/src/models/requests.ts
Added optional conversationId?: string to CreateCaseRequest to carry conversation context when creating cases.
Pages: conversationId persistence & propagation
apps/customer-portal/webapp/src/pages/CreateCasePage.tsx, apps/customer-portal/webapp/src/pages/NoveraChatPage.tsx
CreateCasePage persists conversationId to sessionStorage and includes it in create payload; NoveraChatPage includes conversationId in navigation state and updates callback deps.
Minor UI tweak
apps/customer-portal/webapp/src/components/dashboard/cases-table/CasesList.tsx
Removed ExternalLink icon import and its rendering next to case titles.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant ChangeRequestsPage
    participant AuthState
    participant useGetProjectChangeRequestStats
    participant APIServer
    participant StatCards

    User->>ChangeRequestsPage: open page with projectId
    ChangeRequestsPage->>AuthState: read isSignedIn / isLoading
    AuthState-->>ChangeRequestsPage: auth ready/values

    ChangeRequestsPage->>useGetProjectChangeRequestStats: init hook (projectId)
    Note over useGetProjectChangeRequestStats: enabled when signed in & auth not loading

    useGetProjectChangeRequestStats->>APIServer: GET /projects/{id}/stats/change-requests (Authorization)
    APIServer-->>useGetProjectChangeRequestStats: ChangeRequestStatsResponse (JSON)
    useGetProjectChangeRequestStats->>useGetProjectChangeRequestStats: mapChangeRequestStats()
    useGetProjectChangeRequestStats-->>ChangeRequestsPage: ChangeRequestStats / error

    ChangeRequestsPage->>StatCards: render with data / loading / error
    StatCards-->>User: display stats
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • Rashmika998
  • cloby99

Poem

🐰 Hops of data, fresh and bright,
Deployments queue up in filter light,
Mocks step back as stats arrive,
Conversation IDs tucked to thrive,
A rabbit cheers — the app's alive! 🥕

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main changes: integrating a Change Request Stats API and adding a deployment filter to All Cases.
Description check ✅ Passed The PR description covers the key changes with detailed explanations of what was added and modified, including file references and organized sections for both major features.
Docstring Coverage ✅ Passed Docstring coverage is 87.50% which is sufficient. The required threshold is 80.00%.

✏️ 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

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
apps/customer-portal/webapp/src/pages/ChangeRequestsPage.tsx (1)

168-200: Consider using a ref or restructuring to avoid setTimeout for state updates.

The setTimeout(..., 0) pattern at lines 174 and 189 works but is fragile. It's used to avoid synchronous state updates during the effect execution. A cleaner approach would be to track export completion with a separate ref or restructure the effect to avoid the timing issue.

That said, the current implementation is functional and the condition at line 179-180 (infiniteData && stats) correctly ensures all data is available before PDF generation.

💡 Optional: Use a ref to track pending state change
+  const pendingExportReset = useRef(false);
+
+  useEffect(() => {
+    if (pendingExportReset.current) {
+      pendingExportReset.current = false;
+      setIsExporting(false);
+    }
+  });

   useEffect(() => {
     if (isExporting) {
       if (isInfiniteError) {
         console.error("Failed to fetch change requests for export");
-        setTimeout(() => setIsExporting(false), 0);
+        pendingExportReset.current = true;
       } else if (
         !isInfiniteLoading &&
         !hasNextPage &&
         !isFetchingNextPage &&
         infiniteData &&
         stats
       ) {
         const allChangeRequests =
           infiniteData.pages.flatMap(
             (page: { changeRequests: ChangeRequestItem[] }) =>
               page.changeRequests,
           ) || [];
         generateChangeRequestsSchedulePdf(allChangeRequests, stats);
-        setTimeout(() => setIsExporting(false), 0);
+        pendingExportReset.current = true;
       }
     }
   }, [/* ... */]);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/customer-portal/webapp/src/pages/ChangeRequestsPage.tsx` around lines
168 - 200, The effect handling export completion uses setTimeout(..., 0) to
avoid a synchronous state update; replace that pattern by tracking the pending
export with a ref or by restructuring effects so setIsExporting(false) is called
outside the same synchronous render pass: e.g., introduce an exportingRef
(useRef<boolean>) that you set true when starting export and clear to false when
the export work finishes (after generateChangeRequestsSchedulePdf returns), or
move the setIsExporting(false) call into a separate useEffect that watches a
completed flag (e.g., a new exportCompleted state or the exportingRef) so you
can call setIsExporting(false) without setTimeout; update references to
isExporting, setIsExporting, useEffect, infiniteData, stats, isInfiniteError,
and generateChangeRequestsSchedulePdf accordingly.
apps/customer-portal/webapp/src/api/useGetProjectChangeRequestStats.ts (1)

33-65: Consider using IDs instead of hardcoded label strings for state matching.

The mapping logic relies on exact string matches for state labels (e.g., "Scheduled", "Implement", "Customer Approval"). If the API changes label text (e.g., localization, typo fixes), the mapping will silently return 0 for affected states.

Since stateCount items include an id field, consider matching by ID if those IDs are stable, or adding a fallback/warning when expected labels aren't found.

💡 Optional: Add logging when expected states are missing
 function mapChangeRequestStats(
   response: ChangeRequestStatsResponse,
 ): ChangeRequestStats {
   const { totalCount, stateCount } = response;

+  // Log warning if expected states are missing
+  const allExpectedLabels = [
+    "Scheduled",
+    "Implement",
+    "Review",
+    "Customer Approval",
+    "Customer Review",
+    "Closed",
+    "Canceled",
+    "Rollback",
+  ];
+  const foundLabels = stateCount.map((s) => s.label);
+  const missing = allExpectedLabels.filter((l) => !foundLabels.includes(l));
+  if (missing.length > 0) {
+    console.warn(
+      `[mapChangeRequestStats] Expected state labels not found: ${missing.join(", ")}`,
+    );
+  }

   // Find scheduled count (label: "Scheduled")
   const scheduled =
     stateCount.find((state) => state.label === "Scheduled")?.count ?? 0;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/customer-portal/webapp/src/api/useGetProjectChangeRequestStats.ts`
around lines 33 - 65, The mapChangeRequestStats function currently matches
states by hardcoded label strings (stateCount items), which is brittle; update
mapChangeRequestStats to match by state.id instead (e.g., replace
inProgressLabels/scheduled/completed label arrays with corresponding stable ID
arrays like inProgressIds/scheduledIds/completedIds and use state.id for
filter/reduce), keep a backward-compatible fallback to label matching if IDs are
missing, and optionally emit a warning (e.g., console.warn or your app logger)
when expected IDs/labels are not found so missing states are detectable.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@apps/customer-portal/webapp/src/api/useGetProjectChangeRequestStats.ts`:
- Around line 33-65: The mapChangeRequestStats function currently matches states
by hardcoded label strings (stateCount items), which is brittle; update
mapChangeRequestStats to match by state.id instead (e.g., replace
inProgressLabels/scheduled/completed label arrays with corresponding stable ID
arrays like inProgressIds/scheduledIds/completedIds and use state.id for
filter/reduce), keep a backward-compatible fallback to label matching if IDs are
missing, and optionally emit a warning (e.g., console.warn or your app logger)
when expected IDs/labels are not found so missing states are detectable.

In `@apps/customer-portal/webapp/src/pages/ChangeRequestsPage.tsx`:
- Around line 168-200: The effect handling export completion uses
setTimeout(..., 0) to avoid a synchronous state update; replace that pattern by
tracking the pending export with a ref or by restructuring effects so
setIsExporting(false) is called outside the same synchronous render pass: e.g.,
introduce an exportingRef (useRef<boolean>) that you set true when starting
export and clear to false when the export work finishes (after
generateChangeRequestsSchedulePdf returns), or move the setIsExporting(false)
call into a separate useEffect that watches a completed flag (e.g., a new
exportCompleted state or the exportingRef) so you can call setIsExporting(false)
without setTimeout; update references to isExporting, setIsExporting, useEffect,
infiniteData, stats, isInfiniteError, and generateChangeRequestsSchedulePdf
accordingly.

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0d7d8ec and 9b9f505.

📒 Files selected for processing (7)
  • apps/customer-portal/webapp/src/api/useGetProjectChangeRequestStats.ts
  • apps/customer-portal/webapp/src/components/support/all-cases/AllCasesFilters.tsx
  • apps/customer-portal/webapp/src/components/support/all-cases/AllCasesSearchBar.tsx
  • apps/customer-portal/webapp/src/constants/apiConstants.ts
  • apps/customer-portal/webapp/src/models/responses.ts
  • apps/customer-portal/webapp/src/pages/AllCasesPage.tsx
  • apps/customer-portal/webapp/src/pages/ChangeRequestsPage.tsx

@dileepapeiris dileepapeiris changed the title Feat/add cr stats [Customer Portal][Web] Integrate Change Request Stats API & Add Deployment Filter to All Cases Mar 2, 2026
Add an optional conversationId to the CreateCaseRequest model and thread it through the UI flow so chat conversations can be linked to newly created cases. CreateCasePage: accept conversationId from location state and include it in the case payload when present. NoveraChatPage: include conversationId in navigation state when routing to the create-case page and add it to the useCallback dependency array. These changes ensure the chat conversation ID is preserved and sent with case creation requests.
Fetch deployments in CasesTable and use them to populate the Deployment filter options. Adds useGetDeployments import and hook call (useGetDeployments(projectId)), replaces previous filtersMetadata.deploymentTypes usage with deploymentsData.deployments, and falls back to d.type?.label || d.name for the option label. This ensures the filter reflects actual deployments for the project.

@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

🧹 Nitpick comments (1)
apps/customer-portal/webapp/src/components/dashboard/cases-table/CasesTable.tsx (1)

52-54: Consider including deployments loading and error states for consistent UX.

The useGetDeployments hook exposes isFetching and isError, but these are not destructured here. If the deployments API is slower than the filters API, the FilterPopover could open while deployment options are still loading (showing an empty dropdown). Similarly, a failed deployments fetch would silently result in an empty dropdown.

Consider including these states and propagating them to the FilterPopover:

♻️ Suggested improvement
   // Fetch deployments for the deployment filter
-  const { data: deploymentsData } = useGetDeployments(projectId);
+  const {
+    data: deploymentsData,
+    isFetching: isFetchingDeployments,
+    isError: isErrorDeployments,
+  } = useGetDeployments(projectId);

Then update the FilterPopover props (around lines 249-250):

-        isLoading={isFetchingFilters || isAuthLoading}
-        isError={isErrorFilters}
+        isLoading={isFetchingFilters || isFetchingDeployments || isAuthLoading}
+        isError={isErrorFilters || isErrorDeployments}
🤖 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 52 - 54, The deployments fetch currently only destructures data
from useGetDeployments (deploymentsData) and ignores isFetching/isError which
can cause an empty or silent-failure dropdown; update the useGetDeployments call
to also destructure isFetching and isError, then pass those flags into the
FilterPopover props (e.g., loading/deploymentsLoading and
error/deploymentsError) so the FilterPopover can show a loading state or an
error message when useGetDeployments (function name) is still fetching or
failed; ensure any prop names you add align with FilterPopover's expected props
or add new props to FilterPopover to consume these states.
🤖 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/pages/CreateCasePage.tsx`:
- Line 209: conversationId is read only from location.state so it is lost on
refresh; update CreateCasePage to initialize conversationId from location.state
|| sessionStorage and persist any conversationId changes back to sessionStorage
before you build the case payload (affects the same logic used when constructing
the payload in the create case handler/buildPayload). Specifically: when
initializing the component state for conversationId, check sessionStorage for a
saved value if location.state?.conversationId is undefined; whenever
conversationId is set or updated (the state setter used in CreateCasePage and
before calling the function that builds the payload/createCase handler), write
it into sessionStorage so the value survives a page refresh.

---

Nitpick comments:
In
`@apps/customer-portal/webapp/src/components/dashboard/cases-table/CasesTable.tsx`:
- Around line 52-54: The deployments fetch currently only destructures data from
useGetDeployments (deploymentsData) and ignores isFetching/isError which can
cause an empty or silent-failure dropdown; update the useGetDeployments call to
also destructure isFetching and isError, then pass those flags into the
FilterPopover props (e.g., loading/deploymentsLoading and
error/deploymentsError) so the FilterPopover can show a loading state or an
error message when useGetDeployments (function name) is still fetching or
failed; ensure any prop names you add align with FilterPopover's expected props
or add new props to FilterPopover to consume these states.

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9b9f505 and e15db18.

📒 Files selected for processing (4)
  • apps/customer-portal/webapp/src/components/dashboard/cases-table/CasesTable.tsx
  • apps/customer-portal/webapp/src/models/requests.ts
  • apps/customer-portal/webapp/src/pages/CreateCasePage.tsx
  • apps/customer-portal/webapp/src/pages/NoveraChatPage.tsx

Comment thread apps/customer-portal/webapp/src/pages/CreateCasePage.tsx
Use mapSeverityToDisplay when building severity filter options in CasesTable so severity values are rendered with display-friendly labels. Added import from @utils/support and applied the mapper to the severity metadata mapping.
Remove the ExternalLink import and its rendered icon from apps/customer-portal/webapp/src/components/dashboard/cases-table/CasesList.tsx. Cleans up an unused import and removes the external link icon displayed next to case titles.
Add CONVERSATION_ID_STORAGE_KEY and manage conversationId state so it survives page refreshes. Initialize conversationId from locationState or sessionStorage, sync updates to sessionStorage via useEffect, and prefer the stored conversationId when building the case payload. Also remove the stored conversationId on successful case creation and add console.error logging for sessionStorage failures.
Import and use the useLogger hook in CreateCasePage.tsx, replacing direct console.error calls with logger.error for centralized logging and better observability. Also add logger to relevant useEffect dependency arrays to satisfy hook dependency rules and avoid stale closures.
Rashmika998
Rashmika998 previously approved these changes Mar 3, 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: 2

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/pages/ChangeRequestsPage.tsx (1)

169-199: ⚠️ Potential issue | 🟠 Major

Handle stats-query failure in export flow to avoid stuck “Exporting...” state.

At Line 171, only infinite-query errors reset isExporting. If stats fails (Line 179 remains falsy), export never completes and the button can stay disabled.

🔧 Proposed fix
   useEffect(() => {
     if (isExporting) {
-      if (isInfiniteError) {
+      if (isInfiniteError || isStatsError) {
         // eslint-disable-next-line react-hooks/set-state-in-effect
         setIsExporting(false);
       } else if (
         !isInfiniteLoading &&
         !hasNextPage &&
         !isFetchingNextPage &&
         infiniteData &&
         stats
       ) {
         // Success case - all data fetched
         const allChangeRequests =
           infiniteData.pages.flatMap(
             (page: { changeRequests: ChangeRequestItem[] }) =>
               page.changeRequests,
           ) || [];
         generateChangeRequestsSchedulePdf(allChangeRequests, stats);
         setTimeout(() => setIsExporting(false), 0);
       }
     }
   }, [
     isExporting,
     isInfiniteLoading,
     isInfiniteError,
+    isStatsError,
     hasNextPage,
     isFetchingNextPage,
     infiniteData,
     stats,
   ]);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/customer-portal/webapp/src/pages/ChangeRequestsPage.tsx` around lines
169 - 199, The export useEffect currently only clears isExporting on
infinite-query errors (isInfiniteError) but never handles failures of the stats
query, so when stats is falsy the export can hang; update the effect that
watches isExporting to also detect the stats failure state (or "not loading and
errored" for the stats query) and call setIsExporting(false) in that branch, or
treat missing stats as an error path before calling
generateChangeRequestsSchedulePdf; ensure you reference the same symbols
(useEffect, isExporting, isInfiniteError, isInfiniteLoading, hasNextPage,
isFetchingNextPage, infiniteData, stats, setIsExporting,
generateChangeRequestsSchedulePdf) so the logic aborts the export when stats
failed instead of waiting indefinitely.
🧹 Nitpick comments (1)
apps/customer-portal/webapp/src/pages/CreateCasePage.tsx (1)

181-181: Use the centralized logger consistently for storage errors.

useLogger is introduced, but Line 239 and Line 252 still use console.error, which splits error reporting.

Suggested patch
-    } catch (e) {
-      console.error("Failed to parse stored classification data", e);
+    } catch (e) {
+      logger.error("Failed to parse stored classification data", e);
       return undefined;
     }
@@
-      } catch (e) {
-        console.error(
-          "Failed to store classification data in sessionStorage",
-          e,
-        );
+      } catch (e) {
+        logger.error(
+          "Failed to store classification data in sessionStorage",
+          e,
+        );
       }
@@
-  }, [locationState?.classificationResponse, STORAGE_KEY]);
+  }, [locationState?.classificationResponse, STORAGE_KEY, logger]);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/customer-portal/webapp/src/pages/CreateCasePage.tsx` at line 181, The
file introduces const logger = useLogger() in the CreateCasePage component but
still uses console.error for storage failures; replace those console.error calls
with logger.error and pass the error object and a clear contextual message
(e.g., "failed saving draft" or "failed uploading attachment") so all storage
errors use the centralized logger (look for the console.error usages in
CreateCasePage and update them to logger.error with the error and context).
🤖 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/pages/CreateCasePage.tsx`:
- Around line 295-306: The useEffect for conversationId only writes to
sessionStorage when conversationId is truthy, leaving stale values behind;
update the effect in CreateCasePage.tsx to handle both cases by calling
sessionStorage.setItem(CONVERSATION_ID_STORAGE_KEY, conversationId) when
conversationId is defined/truthy and
sessionStorage.removeItem(CONVERSATION_ID_STORAGE_KEY) (inside the same
try/catch that logs via logger.error) when conversationId is falsy/undefined, so
the stored value is cleared; keep the existing error handling around both
operations and reference the existing conversationId,
CONVERSATION_ID_STORAGE_KEY, logger, and the useEffect callback.
- Around line 727-728: The sessionStorage cleanup in the create-case success
handler can throw and interrupt the onSuccess flow; wrap the calls that remove
STORAGE_KEY and CONVERSATION_ID_STORAGE_KEY in a safe guard (e.g., check typeof
sessionStorage !== "undefined" and/or wrap
sessionStorage.removeItem(STORAGE_KEY) and
sessionStorage.removeItem(CONVERSATION_ID_STORAGE_KEY) in a try/catch) inside
the onSuccess handler so any error is caught and logged but does not prevent the
subsequent navigation or success logic.

---

Outside diff comments:
In `@apps/customer-portal/webapp/src/pages/ChangeRequestsPage.tsx`:
- Around line 169-199: The export useEffect currently only clears isExporting on
infinite-query errors (isInfiniteError) but never handles failures of the stats
query, so when stats is falsy the export can hang; update the effect that
watches isExporting to also detect the stats failure state (or "not loading and
errored" for the stats query) and call setIsExporting(false) in that branch, or
treat missing stats as an error path before calling
generateChangeRequestsSchedulePdf; ensure you reference the same symbols
(useEffect, isExporting, isInfiniteError, isInfiniteLoading, hasNextPage,
isFetchingNextPage, infiniteData, stats, setIsExporting,
generateChangeRequestsSchedulePdf) so the logic aborts the export when stats
failed instead of waiting indefinitely.

---

Nitpick comments:
In `@apps/customer-portal/webapp/src/pages/CreateCasePage.tsx`:
- Line 181: The file introduces const logger = useLogger() in the CreateCasePage
component but still uses console.error for storage failures; replace those
console.error calls with logger.error and pass the error object and a clear
contextual message (e.g., "failed saving draft" or "failed uploading
attachment") so all storage errors use the centralized logger (look for the
console.error usages in CreateCasePage and update them to logger.error with the
error and context).

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e15db18 and 7572bfd.

📒 Files selected for processing (8)
  • apps/customer-portal/webapp/src/components/dashboard/cases-table/CasesList.tsx
  • apps/customer-portal/webapp/src/components/dashboard/cases-table/CasesTable.tsx
  • apps/customer-portal/webapp/src/constants/apiConstants.ts
  • apps/customer-portal/webapp/src/models/requests.ts
  • apps/customer-portal/webapp/src/models/responses.ts
  • apps/customer-portal/webapp/src/pages/ChangeRequestsPage.tsx
  • apps/customer-portal/webapp/src/pages/CreateCasePage.tsx
  • apps/customer-portal/webapp/src/pages/NoveraChatPage.tsx
💤 Files with no reviewable changes (1)
  • apps/customer-portal/webapp/src/components/dashboard/cases-table/CasesList.tsx
🚧 Files skipped from review as they are similar to previous changes (4)
  • apps/customer-portal/webapp/src/constants/apiConstants.ts
  • apps/customer-portal/webapp/src/components/dashboard/cases-table/CasesTable.tsx
  • apps/customer-portal/webapp/src/pages/NoveraChatPage.tsx
  • apps/customer-portal/webapp/src/models/requests.ts

Comment thread apps/customer-portal/webapp/src/pages/CreateCasePage.tsx
Comment thread apps/customer-portal/webapp/src/pages/CreateCasePage.tsx Outdated
Replace console.error with logger.error in CreateCasePage and add logger to effect deps. Make sessionStorage interactions more robust by wrapping reads/writes/removals in try/catch, removing the conversationId key when undefined, and logging failures during cleanup after case creation. In ChangeRequestsPage, include stats loading/error flags in the export completion effect and add them to the effect dependency list so exports wait for stats and properly handle stats errors. These changes improve error reporting and resilience for sessionStorage and export flows.
@Rashmika998
Rashmika998 merged commit 3456bdc into wso2-open-operations:customer-portal-milestone-1 Mar 3, 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/New Feature Represents a request or task for a new feature 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