[ENG-783] Added popup to indicate appointment clash/duplication - #16589
[ENG-783] Added popup to indicate appointment clash/duplication#16589shivankacker wants to merge 2 commits into
Conversation
|
WalkthroughChangesAppointment booking now checks selected slots against the patient’s upcoming appointments, displays duplicate or overlap alerts with localized actions, and carries acknowledged-overlap state through desktop and drawer booking flows. Appointment conflict booking
Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
Greptile SummaryThis PR adds appointment conflict warnings to the booking flow. The main changes are:
Confidence Score: 5/5This looks safe to merge.
Important Files Changed
Reviews (2): Last reviewed commit: "fixes" | Re-trigger Greptile |
There was a problem hiding this comment.
Pull request overview
Adds an appointment conflict/duplication warning flow to the appointment slot selection UX, so staff get an explicit prompt when selecting a potentially conflicting slot.
Changes:
- Fetches a patient’s upcoming appointments and checks for “duplicate” (same resource/day) and “clash” (time overlap with another practitioner) when a slot is clicked.
- Shows a conflict UI (Popover on desktop, Drawer on mobile) with actions to pick another slot or continue anyway, and surfaces a follow-up warning banner after acknowledgement.
- Adds new i18n strings for the conflict UI.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
| src/pages/Appointments/BookAppointment/BookAppointmentDetails.tsx | Tracks conflict acknowledgement state, passes conflict-check context to the slot picker, and shows an acknowledgement warning. |
| src/pages/Appointments/BookAppointment/AppointmentSlotPicker.tsx | Implements conflict detection (via upcoming appointments query) and renders the conflict prompt UI via Popover/Drawer. |
| src/pages/Appointments/BookAppointment/AppointmentConflictAlert.tsx | New UI component for the conflict prompt content and actions. |
| public/locale/en.json | Adds translations for conflict prompt, actions, and warning text. |
There was a problem hiding this comment.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/pages/Appointments/BookAppointment/AppointmentSlotPicker.tsx (1)
120-203: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winConflict check can run against stale/incomplete data while
patientAppointmentsQueryis still loading.
checkForConflictreadspatientAppointmentsQuery.data?.results ?? [](line 125) directly insidehandleSlotClick, with no check againstpatientAppointmentsQuery.isLoading/isFetching. If the user clicks a slot before this query resolves (e.g. slow network),appointmentsis treated as an empty list and a genuine duplicate/clash is silently missed — no warning is shown for a conflict that does exist.Consider disabling slot selection (or short-circuiting
handleSlotClick) whilepatientAppointmentsQuery.isLoadingis true, or surfacing a loading state so users don't click through before the check is possible.🤖 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 `@src/pages/Appointments/BookAppointment/AppointmentSlotPicker.tsx` around lines 120 - 203, Prevent conflict evaluation in handleSlotClick while patientAppointmentsQuery is loading or fetching, so incomplete appointment data cannot be treated as conflict-free. Short-circuit before selecting or checking the slot (or otherwise surface the loading state), while preserving the existing selection and conflict behavior once patientAppointmentsQuery has finished loading.
🤖 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 `@src/pages/Appointments/BookAppointment/AppointmentConflictAlert.tsx`:
- Around line 57-63: Add an accessible name to the icon-only close button in
AppointmentConflictAlert by supplying a descriptive aria-label, while preserving
its existing onClick={onClose} behavior and styling.
In `@src/pages/Appointments/BookAppointment/AppointmentSlotPicker.tsx`:
- Around line 105-118: Update the patientAppointmentsQuery queryKey to include
facilityId alongside patientId, keeping it synchronized with the facility
queryParams used by the queryFn so facility changes fetch and cache the correct
appointment data for checkForConflict.
- Around line 370-428: Update the conflict alert dismissal paths in
AppointmentSlotPicker’s conflictAlertContent, Drawer onOpenChange, and Popover
onOpenChange handlers so closing via the X, Escape, or outside click clears the
alert and calls handleSlotSelect(undefined). Keep the explicit onContinueAnyway
acknowledgment flow unchanged, and ensure every non-explicit dismissal deselects
the conflicting slot.
---
Outside diff comments:
In `@src/pages/Appointments/BookAppointment/AppointmentSlotPicker.tsx`:
- Around line 120-203: Prevent conflict evaluation in handleSlotClick while
patientAppointmentsQuery is loading or fetching, so incomplete appointment data
cannot be treated as conflict-free. Short-circuit before selecting or checking
the slot (or otherwise surface the loading state), while preserving the existing
selection and conflict behavior once patientAppointmentsQuery has finished
loading.
🪄 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: Repository UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: 6c8aed2a-6d6a-4bbb-868a-2e940654ed65
📒 Files selected for processing (4)
public/locale/en.jsonsrc/pages/Appointments/BookAppointment/AppointmentConflictAlert.tsxsrc/pages/Appointments/BookAppointment/AppointmentSlotPicker.tsxsrc/pages/Appointments/BookAppointment/BookAppointmentDetails.tsx
🎭 Playwright Test ResultsStatus: ✅ Passed
📊 Detailed results are available in the playwright-final-report artifact. Run: #10369 |
Deploying care-preview with
|
| Latest commit: |
d9997a0
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://a5641da1.care-preview-a7w.pages.dev |
| Branch Preview URL: | https://appointment-clash-popup.care-preview-a7w.pages.dev |
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (6)
src/pages/Appointments/BookAppointment/AppointmentSlotPicker.tsx (5)
209-212: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick winReset conflict state when the patient changes.
conflictAlertstores a full appointment, but this reset effect excludespatientId. If the picker remains mounted while switching patients, the previous patient’s appointment details can remain attached to the selected slot.🤖 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 `@src/pages/Appointments/BookAppointment/AppointmentSlotPicker.tsx` around lines 209 - 212, Update the conflict-alert reset useEffect in AppointmentSlotPicker to include patientId in its dependency array, ensuring conflictAlert is cleared when the selected patient changes alongside the existing resource and date changes.
452-465: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winUse an interface for
TokenSlotButtonprops.The component currently uses an inline object type. Extract a
TokenSlotButtonPropsinterface, as required by the repository’s TypeScript guidelines.🤖 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 `@src/pages/Appointments/BookAppointment/AppointmentSlotPicker.tsx` around lines 452 - 465, Replace the inline props object type on TokenSlotButton with a named TokenSlotButtonProps interface, preserving the existing slot, availability, selectedSlotId, onClick, className, and ref types, and use that interface in the component declaration.Source: Coding guidelines
392-395: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winClear acknowledgement when the selected slot changes.
The supplied parent wiring only sets
hasOverlapAcknowledgedtotrue. After “Continue anyway,” selecting a different non-conflicting slot can leave the warning displayed for the wrong slot. Add a reset/boolean callback or clear the parent state whenever selection changes.🤖 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 `@src/pages/Appointments/BookAppointment/AppointmentSlotPicker.tsx` around lines 392 - 395, Update the conflict acknowledgement flow around AppointmentSlotPicker’s onContinueAnyway callback so changing the selected appointment slot clears the parent’s hasOverlapAcknowledged state. Add or wire a reset/boolean callback through the relevant selection-change handler, while preserving the existing onConflictAcknowledged behavior for continuing with the current conflicting slot.
124-130: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winMake conflict validation authoritative for every selection path.
While appointments are loading or the query errors,
data?.results ?? []is treated as “no appointments,” allowing the slot to be selected without validation. The first auto-selected slot also goes throughhandleSlotSelectdirectly, bypassinghandleSlotClickentirely. Block selection until the query succeeds and route automatic selection through the same conflict-aware path.Also applies to: 193-205, 255-259
🤖 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 `@src/pages/Appointments/BookAppointment/AppointmentSlotPicker.tsx` around lines 124 - 130, Make conflict validation authoritative in checkForConflict and all selection paths: prevent selection while patientAppointmentsQuery is loading or has errored instead of treating missing results as empty. Route the first auto-selected slot through handleSlotClick (or the shared conflict-aware selection flow) rather than calling handleSlotSelect directly, while preserving normal handleSlotSelect behavior after validation succeeds.Source: Coding guidelines
423-437: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winAdd an accessible name to the desktop conflict popover.
PopoverContentstill renders withoutaria-labelledby/aria-label; reuse the conflict title fromAppointmentConflictAlertso assistive tech gets a stable dialog name.🤖 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 `@src/pages/Appointments/BookAppointment/AppointmentSlotPicker.tsx` around lines 423 - 437, Add an accessible name to the desktop conflict PopoverContent in AppointmentSlotPicker by reusing the conflict title exposed by AppointmentConflictAlert via aria-labelledby or aria-label. Keep the existing popover behavior and content unchanged while ensuring the rendered dialog has a stable name for assistive technologies.Source: Coding guidelines
src/pages/Appointments/BookAppointment/AppointmentConflictAlert.tsx (1)
69-74: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winUse locale-aware formatting for appointment timestamps.
These medical timestamps use fixed
date-fnsformats, so month names, ordering, AM/PM markers, locale, and timezone presentation do not follow the active locale. Use the repository’s localized date/time formatter.Also applies to: 108-110, 121-124
🤖 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 `@src/pages/Appointments/BookAppointment/AppointmentConflictAlert.tsx` around lines 69 - 74, Replace the fixed date-fns format calls in AppointmentConflictAlert, including the occurrences around existingStart and the additional timestamp blocks, with the repository’s locale-aware date/time formatter. Ensure appointment dates and times use the active locale’s ordering, month names, markers, and timezone presentation while preserving the existing timestamp values and display structure.Source: Coding guidelines
🤖 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.
Outside diff comments:
In `@src/pages/Appointments/BookAppointment/AppointmentConflictAlert.tsx`:
- Around line 69-74: Replace the fixed date-fns format calls in
AppointmentConflictAlert, including the occurrences around existingStart and the
additional timestamp blocks, with the repository’s locale-aware date/time
formatter. Ensure appointment dates and times use the active locale’s ordering,
month names, markers, and timezone presentation while preserving the existing
timestamp values and display structure.
In `@src/pages/Appointments/BookAppointment/AppointmentSlotPicker.tsx`:
- Around line 209-212: Update the conflict-alert reset useEffect in
AppointmentSlotPicker to include patientId in its dependency array, ensuring
conflictAlert is cleared when the selected patient changes alongside the
existing resource and date changes.
- Around line 452-465: Replace the inline props object type on TokenSlotButton
with a named TokenSlotButtonProps interface, preserving the existing slot,
availability, selectedSlotId, onClick, className, and ref types, and use that
interface in the component declaration.
- Around line 392-395: Update the conflict acknowledgement flow around
AppointmentSlotPicker’s onContinueAnyway callback so changing the selected
appointment slot clears the parent’s hasOverlapAcknowledged state. Add or wire a
reset/boolean callback through the relevant selection-change handler, while
preserving the existing onConflictAcknowledged behavior for continuing with the
current conflicting slot.
- Around line 124-130: Make conflict validation authoritative in
checkForConflict and all selection paths: prevent selection while
patientAppointmentsQuery is loading or has errored instead of treating missing
results as empty. Route the first auto-selected slot through handleSlotClick (or
the shared conflict-aware selection flow) rather than calling handleSlotSelect
directly, while preserving normal handleSlotSelect behavior after validation
succeeds.
- Around line 423-437: Add an accessible name to the desktop conflict
PopoverContent in AppointmentSlotPicker by reusing the conflict title exposed by
AppointmentConflictAlert via aria-labelledby or aria-label. Keep the existing
popover behavior and content unchanged while ensuring the rendered dialog has a
stable name for assistive technologies.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: e1c38c01-9a8c-4fec-be6c-e2ae692ad640
📒 Files selected for processing (3)
public/locale/en.jsonsrc/pages/Appointments/BookAppointment/AppointmentConflictAlert.tsxsrc/pages/Appointments/BookAppointment/AppointmentSlotPicker.tsx
💤 Files with no reviewable changes (1)
- public/locale/en.json
|
Conflicts have been detected against the base branch. Please merge the base branch into your branch.
|
Proposed Changes
Tagging: @ohcnetwork/care-fe-code-reviewers
Merge Checklist
Summary by CodeRabbit
New Features
Enhancements