Skip to content

[Customer Portal][FE][Web] Enhance Timezone Handling, Type Safety, Infinite Query Typing, and UI/UX Improvements in Customer Portal - #454

Merged
Rashmika998 merged 25 commits into
wso2-open-operations:dev-app-customer-portal-v1.0.xfrom
dileepapeiris:fix-time-stamp-issue
Apr 2, 2026
Merged

Rashmika998 merged 25 commits into
wso2-open-operations:dev-app-customer-portal-v1.0.xfrom
dileepapeiris:fix-time-stamp-issue

Conversation

@dileepapeiris

@dileepapeiris dileepapeiris commented Apr 2, 2026 •

Copy link
Copy Markdown
Contributor

Description

Closes (https://github.com/wso2-enterprise/digiops-cs/issues/1497, https://github.com/wso2-enterprise/digiops-cs/issues/1520)

This pull request introduces several improvements and bug fixes across the customer portal webapp, focusing on timezone handling for call scheduling, filter state typing, infinite query typing, and minor UI/UX adjustments. The most significant changes are grouped below:

Timezone Handling and Call Scheduling Improvements

  • Updated all call scheduling modals (RequestCallModal, ApproveCallRequestModal) and call request display (CallRequestCard) to consistently handle and display preferred times in the user's selected timezone. This includes passing userTimeZone to formatting and conversion utilities, ensuring accurate time representation and conversion throughout the scheduling flow. [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] [14]

Type Safety and Filter Improvements

  • Improved typing for filters in the cases table and related components by allowing filter values to be string | number | undefined, reducing type errors and improving clarity. This includes the introduction of a CasesTableFilterValues interface and updates to filter-related props and state. [1] [2] [3] [4]
  • Fixed a type assertion in the FilterPopover component to ensure select values are treated as strings, preventing runtime issues with filter value types.

API Query Typing

  • Updated infinite query hooks (usePostDeploymentProductsSearchInfinite, usePostProjectDeploymentsSearchInfinite) to correctly type their return values as UseInfiniteQueryResult<InfiniteData<...>, Error>, aligning with React Query's expectations for paginated data. [1] [2] [3] [4]

UI/UX and Security

  • Enhanced the security of dynamic HTML rendering in SecurityReportAnalysis by sanitizing content with DOMPurify before injecting it with dangerouslySetInnerHTML. [1] [2]
  • Improved navigation and state retention for the details panel by passing a returnTo state with navigation links, and removed a redundant "Request type" section for service requests. [1] [2]
  • Updated the AppLayout to correctly identify service request details pages, ensuring consistent styling and layout for these routes. [1] [2]

Miscellaneous

  • Added a missing import of useLocation in AllCasesPage.tsx to support navigation or state-related logic.

Import the InfiniteData type and update the JSDoc and function signature for usePostDeploymentProductsSearchInfinite to return UseInfiniteQueryResult<InfiniteData<DeployedProductsResponsePayload>, Error>. This is a type-only change to accurately reflect the paginated/infinite query result shape returned by useInfiniteQuery.
Import the InfiniteData type and update the JSDoc and function signature of usePostProjectDeploymentsSearchInfinite to return UseInfiniteQueryResult<InfiniteData<ProjectDeploymentsListResponse>, Error>. This aligns the declared return type with react-query's useInfiniteQuery wrapping of paginated results and improves type accuracy for consumers.
Explicitly cast tempFilters[field.id] to string for the Select value prop. tempFilters is typed as Record<string, unknown>, so the cast ensures the value matches Select<string> expectations and satisfies TypeScript type checking.
Relax the type of the `filters` prop to `Record<string, string | number | undefined>` so optional/absent filter entries are supported and TypeScript callers that may leave filters unset don't error. No runtime behavior changes.
Introduce a CasesTableFilterValues interface to explicitly type filter entries (statusId, severityId, issueTypes, deploymentId) as string|number|undefined. Use this type for the filters state and for the computed effectiveFilters to improve type safety and clarify the optional deploymentId handling when includeDeploymentFilter is false.
Replace the previous useGetDeployments query with usePostProjectDeploymentsSearchInfinite to support paginated/infinite loading of deployments. The change initializes the infinite query with pageSize: 10 and enabled based on projectId, flattens pages into a deploymentsList, and passes that list to the component. Added callback props and flags for pagination: onLoadMoreDeployments (calls fetchNextPage guarded by hasNextPage and !isFetchingNextPage), hasMoreDeployments, and isFetchingMoreDeployments.
Remove the isActiveFilterPrimitive function from support.ts. This cleans up dead/unused code that checked whether a filter value was active (non-empty string, number, or boolean). No other logic was changed in this file.
Add DOMPurify import and start adding a dangerouslySetInnerHTML prop to the Typography that renders the security report. The intent is to render sanitized HTML from uploaded reports to avoid XSS (using DOMPurify), but the inserted dangerouslySetInnerHTML line in this diff is incomplete and should be completed to call DOMPurify.sanitize(...) with the report content to ensure safe rendering.
Read location.state via useLocation and derive a returnTo value, then update the back button to navigate to returnTo when present (falling back to navigating up ".."). This adds useLocation to imports and introduces a typed optional returnTo extraction to preserve caller navigation intent.
Introduce operationsPath and pass it as navigation state so service/change request list and detail routes know how to return to the Operations page. Also simplify payload construction by always including activeServiceRequests/activeChangeRequests when enabled (using ?? 0) instead of conditionally spreading undefined values. This ensures consistent numeric values and preserves a returnTo path for downstream navigation.
Import DOMPurify and render the header copy using dangerouslySetInnerHTML with DOMPurify.sanitize (defense-in-depth against XSS). Also extract returnTo from location.state and update the back button to navigate to returnTo when present (falling back to ".."), and include a biome-ignore lint comment for the intentional use of dangerouslySetInnerHTML.
When handling the back action, check location.state for an optional returnTo string and navigate there if present. If returnTo is not provided, fall back to the existing logic that derives the base path from the current pathname (operations vs support). Includes a narrow TypeScript type assertion for location.state.
When handling the back action in CaseDetailsPage, read a returnTo value from location.state and navigate to it if present. This adds a typed check and early return so callers can redirect back to an arbitrary referrer; existing behavior for engagement routes and the default project navigation is preserved.
Import DOMPurify and replace the old stripHtmlTags fallback with a renderHtmlContent helper that sanitizes and dangerously sets HTML (with a biome-ignore lint comment) and shows appropriate fallback text when fields are empty. Add handling for location.state.returnTo so the back button can navigate to a provided return path. Refactor multiple sections (description, impact, service outage, communication/rollback/test plans) to use the new renderer and simplify the Service Outage UI layout.
Read an optional returnTo URL from useLocation state and have the back button navigate to it when present. Import DOMPurify and replace the header Typography text with a sanitized dangerouslySetInnerHTML render to ensure any HTML is safe (keeps component="div" and a biome-ignore lint comment).
Modify ConversationDetailsPage handleBack to check for a returnTo value on location.state and navigate there if present. If no returnTo is provided, existing fallback behavior (history length / projectId routing) remains unchanged. Adds a type assertion for location.state and an early return after navigation.
Add a new isServiceRequestDetailsPage boolean in AppLayout to match service-requests detail routes (both project-scoped and global, under support or operations). Include this flag in isDetailsStylePage so service request detail pages use the details-style layout.
Extract returnTo from location.state and make the back button navigate to it when present; fall back to the parent route otherwise. Import DOMPurify and replace the subtitle Typography string with a sanitized dangerouslySetInnerHTML rendering (with a biome-ignore lint comment) to safely support HTML content in the subtitle. Changes are localized to ChangeRequestsPage.tsx.
Import DOMPurify and render the announcements description using dangerouslySetInnerHTML with DOMPurify.sanitize. This replaces the plain Typography text with a sanitized HTML string (static/trusted copy) and adds a lint ignore comment for the intentional use of dangerouslySetInnerHTML to ensure safe rendering.
Introduce supportPath and pass { returnTo: supportPath } into navigations from SupportPage (view my/all cases, case detail, view my/all conversations, conversation detail). Also preserve conversationSummary when navigating to a conversation. This enables target pages to navigate back to the support page.
Use formatUtcToLocal to render preferredTimes in the selected scheduling timezone for UI display. Updated formatPreferredTimes to accept an optional userTimeZone and replaced the backend-only formatter. Added userTimeZone prop to CallRequestCard and passed it to the formatter so displayed times reflect the user's chosen timezone.
Wrap state updates in queueMicrotask to avoid synchronous state changes during render, and thread userTimeZone through preferred-time conversion helpers. Also adjust effect/dependency lists (add userTimeZone) and reference minTick inside the memo to ensure proper recomputation. These changes ensure correct local/UTC conversions and prevent React timing/update issues.
Pass userTimeZone into datetime conversion helpers and include it in relevant effect/callback dependencies so preferred times are computed in the user's timezone. Add void minDatetimeTick to the minDatetimeLocal memo (and include minDatetimeTick in deps) to force recompute when the tick changes. Defer form state updates with queueMicrotask in a couple places to avoid synchronous update ordering issues. Minor cleanup of mapping/return logic in the preferred times normalization.
Pass a returnTo state (location.pathname + location.search) when linking to related change requests so the UI can navigate back. Also remove the conditional rendering block that displayed the "Request type" for service requests (isServiceRequest && !isSecurityReportAnalysis). No other UI logic changed.
Replace ad-hoc string assembly/parsing with timezone-aware helpers for call request datetime handling. callRequestPreferredTimeFromDatetimeLocal now uses datetimeLocalWallTimeToUtcMs and returns a real UTC ISO string; callRequestApiPreferredTimeToDatetimeLocal delegates to toDatetimeLocalInTimeZoneFromApiString. Both functions accept an optional profileTimeZone parameter. Removes legacy regex-based assembly/parsing and centralizes conversion logic to improve correctness across time zones.
@dileepapeiris dileepapeiris self-assigned this Apr 2, 2026
@coderabbitai

coderabbitai Bot commented Apr 2, 2026 •

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

This PR updates React Query infinite-query type signatures, improves HTML sanitization with DOMPurify across multiple pages, implements timezone-aware datetime conversions for call scheduling, adds navigation state tracking (returnTo) across support and case pages, refines filter type definitions, adjusts deployment fetching to use infinite scroll pagination, and adds layout detection for service request details pages.

Changes

Cohort / File(s) Summary
React Query Infinite-Query Typing
src/api/usePostDeploymentProductsSearch.ts, src/api/usePostProjectDeploymentsSearch.ts
Updated return type of infinite-query hooks from UseInfiniteQueryResult<T, Error> to UseInfiniteQueryResult<InfiniteData<T>, Error> by adding InfiniteData import and adjusting generic parameters.
Filter Type Definitions
src/components/common/filter-panel/FilterPopover.tsx, src/components/dashboard/cases-table/CasesFilters.tsx, src/components/dashboard/cases-table/CasesTable.tsx
Widened filter prop types to allow undefined values, added explicit string casting for controlled Select components, and introduced internal CasesTableFilterValues interface with optional known filter keys.
HTML Sanitization with DOMPurify
src/components/security/SecurityReportAnalysis.tsx, src/pages/AllCasesPage.tsx, src/pages/AnnouncementsPage.tsx, src/pages/ChangeRequestDetailsPage.tsx, src/pages/ChangeRequestsPage.tsx, src/pages/ServiceRequestsPage.tsx
Replaced plain text rendering with dangerouslySetInnerHTML fed through DOMPurify.sanitize() for HTML content display across multiple pages.
Call Request Timezone Handling
src/components/support/case-details/calls-tab/ApproveCallRequestModal.tsx, src/components/support/case-details/calls-tab/CallRequestCard.tsx, src/components/support/case-details/calls-tab/RequestCallModal.tsx, src/utils/support.ts
Updated call-request time conversion functions to accept optional profileTimeZone parameter, implemented proper UTC/local datetime conversions, and refactored modal initialization logic using queueMicrotask for state updates.
Navigation State & Return-To Tracking
src/components/dashboard/cases-table/CaseDetailsDetailsPanel.tsx, src/pages/AllCasesPage.tsx, src/pages/AllConversationsPage.tsx, src/pages/CaseDetailsPage.tsx, src/pages/ConversationDetailsPage.tsx, src/pages/ServiceRequestDetailsPage.tsx, src/pages/ChangeRequestsPage.tsx, src/pages/SupportPage.tsx, src/pages/OperationsPage.tsx
Added location.state.returnTo checks in navigation handlers and passing returnTo state through React Router during page transitions to enable returning to previous page context.
Deployment & Layout Improvements
src/layouts/AppLayout.tsx, src/pages/ServiceRequestsPage.tsx
Added service request details page detection for consistent layout styling and switched deployment data fetching from standard query to infinite-search pagination with usePostProjectDeploymentsSearchInfinite.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested labels

Type/Improvement, Type/Task, App/Customer Portal, Area/Frontend, Platform/Web

Suggested reviewers

  • Rashmika998

Poem

🐰 A rabbit hops through code so fine,
Sanitizing HTML with DOMPurify divine,
Timezones tamed and nav states trace,
Infinite queries find their proper place! ✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed Docstring coverage is 95.65% which is sufficient. The required threshold is 80.00%.
Description check ✅ Passed The PR description is comprehensive and well-structured, covering major changes including timezone handling, type safety improvements, API query typing, UI/UX enhancements, and security fixes with detailed reference links.
Title check ✅ Passed The title comprehensively and accurately describes the main changes: timezone handling improvements, type safety enhancements, infinite query typing fixes, and UI/UX improvements across the customer portal.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@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 labels Apr 2, 2026
@dileepapeiris dileepapeiris changed the title Fix time stamp issue [Customer Portal][FE][Web] Enhance Timezone Handling, Type Safety, Infinite Query Typing, and UI/UX Improvements in Customer Portal Apr 2, 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 (5)
apps/customer-portal/webapp/src/pages/AllCasesPage.tsx (2)

101-104: ⚠️ Potential issue | 🟠 Major

Deployments query should be permission/readiness-gated.

At Line 103, enabled: !!projectId still triggers deployments fetches before project context is ready and for users without deployment access.

🔧 Proposed fix
   const deploymentsQuery = usePostProjectDeploymentsSearchInfinite(projectId || "", {
     pageSize: 10,
-    enabled: !!projectId,
+    enabled: !!projectId && projectDetailsReady && permissions.hasDeployments,
   });
Based on learnings: In `apps/customer-portal/webapp/src/pages/AllCasesPage.tsx` (PR `#453`), this query should be gated by `projectDetailsReady && permissions.hasDeployments` to avoid unnecessary/forbidden calls.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/customer-portal/webapp/src/pages/AllCasesPage.tsx` around lines 101 -
104, The deployments query currently enables fetches when only projectId is
truthy; change the enabled flag on usePostProjectDeploymentsSearchInfinite
(where deploymentsQuery is created) to gate requests until projectDetailsReady
is true and the user has deployment access by using: enabled:
projectDetailsReady && permissions.hasDeployments && !!projectId (keeping
existing pageSize and other options).

155-159: ⚠️ Potential issue | 🟠 Major

Page loader can remain stuck when stats request errors.

At Line 158, !!projectId && !hasStatsResponse keeps isStatsLoading true even when isStatsError is true.

🔧 Proposed fix
   const isStatsLoading =
     isProjectContextLoading ||
     isStatsQueryLoading ||
-    (!!projectId && !hasStatsResponse);
+    (!!projectId && !hasStatsResponse && !isStatsError);
Based on learnings: In `apps/customer-portal/webapp/src/pages/AllCasesPage.tsx` (PR `#436`), this missing `!isStatsError` guard causes the page-level loader to hang indefinitely on stats failures.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/customer-portal/webapp/src/pages/AllCasesPage.tsx` around lines 155 -
159, The isStatsLoading expression (const isStatsLoading = ...) incorrectly
keeps the page loader active when a stats request errors because it evaluates
(!!projectId && !hasStatsResponse) without checking isStatsError; update the
condition used to compute isStatsLoading (the const named isStatsLoading in
AllCasesPage.tsx) to include a guard that ensures !isStatsError (e.g., require
!isStatsError alongside !hasStatsResponse) so that when isStatsError is true the
loader will not remain stuck.
apps/customer-portal/webapp/src/api/usePostDeploymentProductsSearch.ts (1)

58-62: ⚠️ Potential issue | 🟠 Major

Controlled pagination is being overridden by caller input.

request?.pagination is spread after offset/limit, so stale caller values can silently replace the intended page parameters and cause repeated/incorrect pages.

🔧 Proposed fix
   const payload: DeployedProductSearchRequest = {
     ...(request ?? {}),
     pagination: {
-      offset,
-      limit,
       ...(request?.pagination ?? {}),
+      offset,
+      limit,
     },
   };
Based on learnings: In `apps/customer-portal/webapp/src/api/usePostDeploymentProductsSearch.ts` (PR `#453`), spreading caller pagination after `offset`/`limit` breaks controlled pagination and should be reversed.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/customer-portal/webapp/src/api/usePostDeploymentProductsSearch.ts`
around lines 58 - 62, The pagination object currently sets offset and limit then
spreads request?.pagination which lets caller-supplied offset/limit override
controlled values; in the usePostDeploymentProductsSearch code change the spread
order so pagination merges like {...(request?.pagination ?? {}), offset, limit}
(or place offset/limit after the spread) to ensure the internal offset and limit
take precedence over request?.pagination and prevent stale caller page values
from replacing controlled pagination.
apps/customer-portal/webapp/src/api/usePostProjectDeploymentsSearch.ts (1)

52-58: ⚠️ Potential issue | 🟠 Major

Let the controlled page arguments override caller pagination.

request?.pagination is still spread after offset/limit, so any caller-provided pagination can overwrite the page param. That breaks both usePostProjectDeploymentsSearchInfinite and usePostProjectDeploymentsSearchAll by re-requesting the same page or walking duplicate offsets.

Suggested fix
   const payload: DeploymentSearchRequest = {
     ...(request ?? {}),
     pagination: {
-      offset,
-      limit,
       ...(request?.pagination ?? {}),
+      offset,
+      limit,
     },
   };
Based on learnings, in `apps/customer-portal/webapp/src/api/usePostProjectDeploymentsSearch.ts`, `request?.pagination` must be spread before `offset` and `limit` so the controlled page arguments always win.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/customer-portal/webapp/src/api/usePostProjectDeploymentsSearch.ts`
around lines 52 - 58, The payload builds a DeploymentSearchRequest where
request?.pagination is currently spread after controlled offset/limit allowing
callers to overwrite page args; fix by spreading request?.pagination before
offset and limit so controlled page arguments (offset, limit) always
override—update the payload construction in usePostProjectDeploymentsSearch.ts
(the DeploymentSearchRequest payload object) to merge ...(request?.pagination ??
{}) first, then set offset and limit.
apps/customer-portal/webapp/src/pages/support/change-requests/ChangeRequestDetailsPage.tsx (1)

685-687: ⚠️ Potential issue | 🟡 Minor

Format the approval timestamps before rendering.

The header already uses formatDateTime(), but the Approval Information card still prints raw API timestamps. That leaves this page with mixed timestamp formats and bypasses the fix in one of the most visible metadata sections.

Suggested fix
                 <Typography variant="body2">
-                  {changeRequest.createdOn}
+                  {changeRequest.createdOn
+                    ? formatDateTime(changeRequest.createdOn)
+                    : "Not available"}
                 </Typography>
@@
                 <Typography variant="body2">
-                  {changeRequest.approvedOn || "Not available"}
+                  {changeRequest.approvedOn
+                    ? formatDateTime(changeRequest.approvedOn)
+                    : "Not available"}
                 </Typography>
Based on learnings, in `apps/customer-portal/webapp/src/pages/support/change-requests/ChangeRequestDetailsPage.tsx`, `changeRequest.createdOn` is already formatted in the header and should not be rendered as a raw API string in the Approval Information card.

Also applies to: 714-715

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

In
`@apps/customer-portal/webapp/src/pages/support/change-requests/ChangeRequestDetailsPage.tsx`
around lines 685 - 687, The Approval Information card is rendering raw API
timestamps (e.g., changeRequest.createdOn and other timestamp fields in the same
card) while the header uses formatDateTime(); update the card to call
formatDateTime(...) for those fields instead of printing raw strings. Locate the
Approval Information block in ChangeRequestDetailsPage and replace direct uses
of changeRequest.createdOn (and the other timestamp props referenced near the
same area) with formatDateTime(changeRequest.createdOn) (and formatDateTime for
each timestamp) so all displayed timestamps use the same formatted output.
🧹 Nitpick comments (2)
apps/customer-portal/webapp/src/components/common/filter-panel/FilterPopover.tsx (1)

182-182: Type cast improves Select compatibility; consider applying same pattern to TextField.

The explicit as string cast correctly ensures the Select<string> component receives a string value. However, the TextField at line 228 uses the same pattern without the cast:

value={tempFilters[field.id] || ""}

For consistency and type safety, consider applying the same cast there as well.

♻️ Suggested consistency fix
               <TextField
                 key={field.id}
-                value={tempFilters[field.id] || ""}
+                value={(tempFilters[field.id] as string) || ""}
                 onChange={handleTextChange(field.id)}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@apps/customer-portal/webapp/src/components/common/filter-panel/FilterPopover.tsx`
at line 182, The TextField value uses tempFilters[field.id] without a type
assertion, which is inconsistent with the Select<string> usage and can cause
type mismatches; update the TextField's value expression in FilterPopover.tsx to
mirror the Select usage by casting to string (e.g., use (tempFilters[field.id]
as string) || "") so the TextField receives a properly typed string; locate the
TextField render block that references tempFilters and field.id and apply the
same cast pattern for consistency and type safety.
apps/customer-portal/webapp/src/components/support/case-details/calls-tab/ApproveCallRequestModal.tsx (1)

122-128: Consider using a clearer pattern for the minTick dependency.

The void minTick; statement works but is non-obvious. A brief comment would clarify intent.

💡 Suggested improvement for clarity
   const minDatetimeLocal = useMemo(
     () => {
-      void minTick;
+      void minTick; // Reference to trigger recomputation every minute
       return computeMinScheduleDatetimeLocalForTimeZone(null, userTimeZone);
     },
     [userTimeZone, minTick],
   );
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@apps/customer-portal/webapp/src/components/support/case-details/calls-tab/ApproveCallRequestModal.tsx`
around lines 122 - 128, The useMemo for minDatetimeLocal currently includes a
non-obvious "void minTick;" to force minTick into the dependency array; replace
this with a clearer pattern: explicitly reference minTick in the memo body or
add a one-line comment explaining that minTick is used solely to re-evaluate the
memo when the tick changes (e.g., "/* depend on minTick to refresh value */"),
so update the compute block that sets minDatetimeLocal (the useMemo that calls
computeMinScheduleDatetimeLocalForTimeZone with userTimeZone) to either directly
use minTick in its computation or add the explanatory comment and keep minTick
in the dependency list for clarity.
🤖 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/ServiceRequestsPage.tsx`:
- Line 71: The primary Back/header button in ServiceRequestsPage is still
calling navigate("..") and ignores the previously computed returnTo variable;
update those button handlers (the normal header Back button and the primary Back
button used on success/error paths) to use the same logic as the error-state
button by calling navigate(returnTo ?? "..") (i.e., prefer returnTo when
present, fallback to ".."). Locate usages of navigate("..") within the
ServiceRequestsPage component and replace them with navigate(returnTo ?? ".."),
ensuring they reference the existing returnTo variable declared near the top of
the component.
- Around line 103-106: The deployments query is enabled too early; change the
usePostProjectDeploymentsSearchInfinite call so it only runs when the page has
finished readiness checks and the user is allowed to use deployment filters —
i.e. update the options for usePostProjectDeploymentsSearchInfinite (the
deploymentsQuery invocation) to set enabled to a conjunction of projectId,
projectDetailsReady, and the permission/feature flag used by this page (e.g.
canUseDeploymentFilter or deploymentsAllowed) so the hook only fires when all
readiness/permission guards are true.

---

Outside diff comments:
In `@apps/customer-portal/webapp/src/api/usePostDeploymentProductsSearch.ts`:
- Around line 58-62: The pagination object currently sets offset and limit then
spreads request?.pagination which lets caller-supplied offset/limit override
controlled values; in the usePostDeploymentProductsSearch code change the spread
order so pagination merges like {...(request?.pagination ?? {}), offset, limit}
(or place offset/limit after the spread) to ensure the internal offset and limit
take precedence over request?.pagination and prevent stale caller page values
from replacing controlled pagination.

In `@apps/customer-portal/webapp/src/api/usePostProjectDeploymentsSearch.ts`:
- Around line 52-58: The payload builds a DeploymentSearchRequest where
request?.pagination is currently spread after controlled offset/limit allowing
callers to overwrite page args; fix by spreading request?.pagination before
offset and limit so controlled page arguments (offset, limit) always
override—update the payload construction in usePostProjectDeploymentsSearch.ts
(the DeploymentSearchRequest payload object) to merge ...(request?.pagination ??
{}) first, then set offset and limit.

In `@apps/customer-portal/webapp/src/pages/AllCasesPage.tsx`:
- Around line 101-104: The deployments query currently enables fetches when only
projectId is truthy; change the enabled flag on
usePostProjectDeploymentsSearchInfinite (where deploymentsQuery is created) to
gate requests until projectDetailsReady is true and the user has deployment
access by using: enabled: projectDetailsReady && permissions.hasDeployments &&
!!projectId (keeping existing pageSize and other options).
- Around line 155-159: The isStatsLoading expression (const isStatsLoading =
...) incorrectly keeps the page loader active when a stats request errors
because it evaluates (!!projectId && !hasStatsResponse) without checking
isStatsError; update the condition used to compute isStatsLoading (the const
named isStatsLoading in AllCasesPage.tsx) to include a guard that ensures
!isStatsError (e.g., require !isStatsError alongside !hasStatsResponse) so that
when isStatsError is true the loader will not remain stuck.

In
`@apps/customer-portal/webapp/src/pages/support/change-requests/ChangeRequestDetailsPage.tsx`:
- Around line 685-687: The Approval Information card is rendering raw API
timestamps (e.g., changeRequest.createdOn and other timestamp fields in the same
card) while the header uses formatDateTime(); update the card to call
formatDateTime(...) for those fields instead of printing raw strings. Locate the
Approval Information block in ChangeRequestDetailsPage and replace direct uses
of changeRequest.createdOn (and the other timestamp props referenced near the
same area) with formatDateTime(changeRequest.createdOn) (and formatDateTime for
each timestamp) so all displayed timestamps use the same formatted output.

---

Nitpick comments:
In
`@apps/customer-portal/webapp/src/components/common/filter-panel/FilterPopover.tsx`:
- Line 182: The TextField value uses tempFilters[field.id] without a type
assertion, which is inconsistent with the Select<string> usage and can cause
type mismatches; update the TextField's value expression in FilterPopover.tsx to
mirror the Select usage by casting to string (e.g., use (tempFilters[field.id]
as string) || "") so the TextField receives a properly typed string; locate the
TextField render block that references tempFilters and field.id and apply the
same cast pattern for consistency and type safety.

In
`@apps/customer-portal/webapp/src/components/support/case-details/calls-tab/ApproveCallRequestModal.tsx`:
- Around line 122-128: The useMemo for minDatetimeLocal currently includes a
non-obvious "void minTick;" to force minTick into the dependency array; replace
this with a clearer pattern: explicitly reference minTick in the memo body or
add a one-line comment explaining that minTick is used solely to re-evaluate the
memo when the tick changes (e.g., "/* depend on minTick to refresh value */"),
so update the compute block that sets minDatetimeLocal (the useMemo that calls
computeMinScheduleDatetimeLocalForTimeZone with userTimeZone) to either directly
use minTick in its computation or add the explanatory comment and keep minTick
in the dependency list for clarity.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 2369e4c7-55fc-48fd-b2db-832301dfc20b

📥 Commits

Reviewing files that changed from the base of the PR and between 2c982c4 and e631f42.

📒 Files selected for processing (23)
  • apps/customer-portal/webapp/src/api/usePostDeploymentProductsSearch.ts
  • apps/customer-portal/webapp/src/api/usePostProjectDeploymentsSearch.ts
  • apps/customer-portal/webapp/src/components/common/filter-panel/FilterPopover.tsx
  • apps/customer-portal/webapp/src/components/dashboard/cases-table/CasesFilters.tsx
  • apps/customer-portal/webapp/src/components/dashboard/cases-table/CasesTable.tsx
  • apps/customer-portal/webapp/src/components/security/SecurityReportAnalysis.tsx
  • apps/customer-portal/webapp/src/components/support/case-details/calls-tab/ApproveCallRequestModal.tsx
  • apps/customer-portal/webapp/src/components/support/case-details/calls-tab/CallRequestCard.tsx
  • apps/customer-portal/webapp/src/components/support/case-details/calls-tab/RequestCallModal.tsx
  • apps/customer-portal/webapp/src/components/support/case-details/details-tab/CaseDetailsDetailsPanel.tsx
  • apps/customer-portal/webapp/src/layouts/AppLayout.tsx
  • apps/customer-portal/webapp/src/pages/AllCasesPage.tsx
  • apps/customer-portal/webapp/src/pages/AllConversationsPage.tsx
  • apps/customer-portal/webapp/src/pages/AnnouncementsPage.tsx
  • apps/customer-portal/webapp/src/pages/CaseDetailsPage.tsx
  • apps/customer-portal/webapp/src/pages/ConversationDetailsPage.tsx
  • apps/customer-portal/webapp/src/pages/OperationsPage.tsx
  • apps/customer-portal/webapp/src/pages/ServiceRequestDetailsPage.tsx
  • apps/customer-portal/webapp/src/pages/ServiceRequestsPage.tsx
  • apps/customer-portal/webapp/src/pages/SupportPage.tsx
  • apps/customer-portal/webapp/src/pages/support/change-requests/ChangeRequestDetailsPage.tsx
  • apps/customer-portal/webapp/src/pages/support/change-requests/ChangeRequestsPage.tsx
  • apps/customer-portal/webapp/src/utils/support.ts

Comment thread apps/customer-portal/webapp/src/pages/ServiceRequestsPage.tsx
Comment thread apps/customer-portal/webapp/src/pages/ServiceRequestsPage.tsx
@Rashmika998
Rashmika998 merged commit 923b235 into wso2-open-operations:dev-app-customer-portal-v1.0.x Apr 2, 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