[Customer Portal MicroApp] feat: show recent chats/cases by activity, allow replying to chats - #1032
Conversation
…pdate SupportPage sorting logic
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughChat messaging and compose behavior were updated, detail identifiers can now render and copy multiple IDs, and SupportPage now loads Cases and Chats by updated time without the previous status filters. ChangesChat messaging and compose flow
Detail identifier display
Support tab queries
Estimated code review effort: 3 (Moderate) | ~25 minutes Possibly related PRs
Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Pull request overview
Updates the Customer Portal microapp Support experience so dashboard previews reflect most recent activity (not just creation time / “outstanding” statuses), and enables replying within an existing chat conversation from the chat detail view.
Changes:
- Removed hard “outstanding” status filtering for Support page chat/case preview widgets and switched sorting to
updatedOn desc. - Added a
StickyCommentBartoChatDetailPagewired to the existingchats.sendmutation, with toast error handling and query invalidation to refresh the transcript.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| apps/customer-portal/microapp/src/pages/SupportPage.tsx | Removes status-based filtering for chat/case previews and sorts by updatedOn to reflect recent activity. |
| apps/customer-portal/microapp/src/pages/ChatDetailPage.tsx | Adds reply input to chat detail and hooks it up to the send-message mutation + transcript refresh. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@apps/customer-portal/microapp/src/pages/ChatDetailPage.tsx`:
- Around line 58-61: The send handler in ChatDetailPage checks comment.trim()
but still passes the raw comment into mutation.mutate, so whitespace can be
stored. Update handleSend to use the trimmed value for the mutation payload, and
keep the empty-check based on the same trimmed value so the guard and sent
message stay consistent.
🪄 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: c24659bd-35b2-4291-92ea-0ccb1467c692
📒 Files selected for processing (2)
apps/customer-portal/microapp/src/pages/ChatDetailPage.tsxapps/customer-portal/microapp/src/pages/SupportPage.tsx
Give Novera messages the same circular gradient Bot-icon avatar and
no-bubble layout the webapp uses, switch message timestamps from
relative ("5 hours ago") to absolute date/time to match the webapp,
and disable the reply box once a conversation is resolved or converted
to a case.
…ebapp The webapp's ChatInput disappears entirely (returns null) once a conversation is closed, rather than showing a disabled input. Mirror that instead of graying out the box.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@apps/customer-portal/microapp/src/pages/ChatPage.tsx`:
- Line 191: The timestamp generation in ChatPage is passing a Date object into
useDateTime().format, which reinterprets it as UTC and can shift the displayed
time. Update the timestamp creation at both call sites in ChatPage to preserve
the instant before formatting, using new Date().toISOString() or equivalent, and
keep the change scoped to the timestamp fields that currently call format(new
Date()).
🪄 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: 8af110e9-1c36-4a35-8633-57e89559689e
📒 Files selected for processing (4)
apps/customer-portal/microapp/src/components/features/chat/MessageBubble.tsxapps/customer-portal/microapp/src/config/constants.tsxapps/customer-portal/microapp/src/pages/ChatDetailPage.tsxapps/customer-portal/microapp/src/pages/ChatPage.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
- apps/customer-portal/microapp/src/pages/ChatDetailPage.tsx
Chat input already requires the send button to submit (Enter is not bound to send). Add an opt-in multiline mode to StickyCommentBar and enable it for the two chat surfaces so Enter now grows the textarea with a newline, matching normal textarea behavior, instead of being a no-op. Other StickyCommentBar consumers (case/service/engagement/sra detail pages) are unaffected since multiline defaults to off.
CommonMark collapses single newlines into a space, so a message typed across multiple lines (now possible since Enter inserts a newline) rendered back as one line. Convert each newline to a markdown hard break before rendering.
CaseDetailPage shows two IDs (internal + external case number) in the header. Add a single copy icon next to them that copies both IDs together, with a brief checkmark confirmation.
Wrap the case-ID copy button in a Tooltip that reads "Copy" and flips to "Copied!" on click, and bump the icon from 14px to 16px.
MUI Tooltip only shows while actively hovered, so it could vanish right after the click if the cursor moved even slightly. Control the open state so it stays visible for the full 2s confirmation window regardless of hover.
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
apps/customer-portal/microapp/src/components/features/detail/StickyCommentBar.tsx (1)
44-61: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winMultiline + default
submitOnEnteris a silent footgun.
submitOnEnterdefaults totrue, so any future caller enablingmultilinewithout explicitly settingsubmitOnEnter={false}will have Enter always submit (viapreventDefault), silently blocking newline entry despitemultilinebeing on. Consider deriving the newline-vs-submit behavior directly frommultiline(e.g., only allow Enter-to-submit when not multiline, or support Shift+Enter to insert a newline while Enter submits) so the two props can't drift out of sync.♻️ Example: couple behavior to `multiline` instead of relying on caller-supplied `submitOnEnter`
- const handleKeyDown = (event: KeyboardEvent<HTMLInputElement | HTMLTextAreaElement>) => { - if (submitOnEnter && event.key === "Enter" && hasContent) { - event.preventDefault(); - send(); - } - }; + const handleKeyDown = (event: KeyboardEvent<HTMLInputElement | HTMLTextAreaElement>) => { + if (event.key !== "Enter" || !hasContent) return; + const shouldSubmit = multiline ? submitOnEnter && !event.shiftKey : submitOnEnter; + if (shouldSubmit) { + event.preventDefault(); + send(); + } + };🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/customer-portal/microapp/src/components/features/detail/StickyCommentBar.tsx` around lines 44 - 61, The Enter handling in StickyCommentBar is currently driven by submitOnEnter alone, which can conflict with multiline and block newline entry. Update handleKeyDown (and any related send logic in StickyCommentBar) so Enter-to-submit is derived from multiline behavior instead of relying on callers to keep submitOnEnter in sync, for example by disabling plain Enter submit when multiline is true or by supporting Shift+Enter for newlines. Keep the behavior coupled to the StickyCommentBar props so future multiline usage cannot silently prevent text entry.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@apps/customer-portal/microapp/src/components/features/detail/OverlineSlot.tsx`:
- Around line 43-51: The copy feedback timer in OverlineSlot’s handleCopy has no
cleanup, so add a ref-backed timeout in the component and clear it before
scheduling a new one and when the component unmounts. Use useRef and useEffect
in OverlineSlot to store the timer id, cancel any existing timeout before
calling setTimeout, and return a cleanup function that clears the pending timer
so setCopied(false) is never called after unmount or after a newer copy action.
In `@apps/customer-portal/microapp/src/pages/CaseDetailPage.tsx`:
- Around line 144-149: Restore the `id` fallback in `CaseDetailPage` by changing
the `OverlineSlot` props so it still receives `data.internalId` when
`data.number` is missing. The issue is in the `ids` conditional passed to
`OverlineSlot`, which currently becomes `undefined` and prevents the fallback
display; update the `ids` logic in `CaseDetailPage` so the component can render
the internal ID as intended.
---
Nitpick comments:
In
`@apps/customer-portal/microapp/src/components/features/detail/StickyCommentBar.tsx`:
- Around line 44-61: The Enter handling in StickyCommentBar is currently driven
by submitOnEnter alone, which can conflict with multiline and block newline
entry. Update handleKeyDown (and any related send logic in StickyCommentBar) so
Enter-to-submit is derived from multiline behavior instead of relying on callers
to keep submitOnEnter in sync, for example by disabling plain Enter submit when
multiline is true or by supporting Shift+Enter for newlines. Keep the behavior
coupled to the StickyCommentBar props so future multiline usage cannot silently
prevent text entry.
🪄 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: 505a281a-7545-4c88-8093-8493b7faf391
📒 Files selected for processing (6)
apps/customer-portal/microapp/src/components/features/detail/OverlineSlot.tsxapps/customer-portal/microapp/src/components/features/detail/StickyCommentBar.tsxapps/customer-portal/microapp/src/components/shared/TypewriterText.tsxapps/customer-portal/microapp/src/pages/CaseDetailPage.tsxapps/customer-portal/microapp/src/pages/ChatDetailPage.tsxapps/customer-portal/microapp/src/pages/ChatPage.tsx
🚧 Files skipped from review as they are similar to previous changes (2)
- apps/customer-portal/microapp/src/pages/ChatPage.tsx
- apps/customer-portal/microapp/src/pages/ChatDetailPage.tsx
…verlineSlot.tsx Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Purpose
The Support page's Chats and Cases dashboard preview widgets were hard-filtered to a fixed set of "outstanding" status IDs and sorted by creation date. Items that changed status after creation (e.g. reopened, or just updated) wouldn't surface in the recent list, and "most recent" didn't reflect actual recent activity. Separately, the chat detail view was read-only — no way to reply within an existing conversation once opened from the Support page.
Goals
Approach
SupportPage.tsx— removed thestateKeys/statusIdsfilters fromChatItemListContentandCaseItemListContent, and changedsortByfrom{ field: "createdOn", order: "desc" }to{ field: "updatedOn", order: "desc" }for both.updatedOnwas already a supported sort field on the backend (ConversationSortField/CaseSortFieldenums), just unused by the frontend.ChatDetailPage.tsx— added aStickyCommentBar(the same reusable component used onCaseDetailPage.tsx/ChatPage.tsx) wired to the existingchats.sendmutation, which was already implemented inservices/chats.tsand backed by the existingPOST /projects/{id}/conversations/{conversationId}/messagesendpoint, but previously unused. On send, the mutation invalidates the chat's comments query so the reply and the AI's response (persisted server-side) appear in the transcript. Includes anonErrortoast on send failure and disables the input untilprojectIdis resolved (avoids firing the mutation with a null project id on a direct deep-link/hard-refresh).Known follow-up
The Cases widget is still labeled "Outstanding Cases" / "Active support tickets" (
TAB_CONFIG.case) even though it no longer filters by status — left as-is per product decision; worth revisiting the copy in a follow-up if it reads as misleading.User stories
As a customer portal user, I want to see my most recently active chats and cases on the Support page dashboard regardless of status, and I want to continue a conversation from an existing chat instead of only being able to start new ones.
Release note
Support page dashboard now shows recently updated chats and cases of any status, sorted by last activity. Users can send follow-up messages from an existing chat's detail page.
Documentation
N/A — UI behavior change only, no new user-facing workflow beyond existing chat/case viewing.
Automation tests
tsc --noEmit(clean); live UI verification not performed in this environment (no local Asgardeo/backend auth configured) — please verify the reply flow and dashboard sorting against a real project before merging.Security checks
Related PRs
N/A — rebased directly on
v2; no dependency on other open PRs (the "guard against invalid user timezone" fix referenced during development, #1015, is already merged intov2).Test environment
Node v26.3.0, macOS 26.5.1, verified via
tsc --noEmitonly — live browser verification pending (see Automation tests).Summary by CodeRabbit