fix: med administration, use encounter end date for end date if avail#16331
fix: med administration, use encounter end date for end date if avail#16331Jacobjeevan wants to merge 2 commits intodevelopfrom
Conversation
There was a problem hiding this comment.
Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.
WalkthroughAdministrationTab now derives and initializes its current/end slot date state from the selected encounter's period.end when available, and adds a useEffect to resynchronize those states when the encounter changes; useEncounter is imported to access the selected encounter. ChangesEncounter-Based Current Date
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
Deploying care-preview with
|
| Latest commit: |
d24111d
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://66f4c561.care-preview-a7w.pages.dev |
| Branch Preview URL: | https://eng-3-medication-administrat.care-preview-a7w.pages.dev |
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/components/Medicine/MedicationAdministration/AdministrationTab.tsx (1)
127-137:⚠️ Potential issue | 🟠 Major | ⚡ Quick winResync slot state when encounter end date arrives after initial render.
Line 128 updates
currentDate, butendSlotDate/endSlotIndexare initialized only once. IfselectedEncounteris undefined on first render and loads later, the timeline remains seeded from “now” instead of the encounter end.Suggested fix
-import React, { useCallback, useMemo, useState } from "react"; +import React, { useCallback, useEffect, useMemo, useState } from "react"; @@ - const { selectedEncounter: encounter } = useEncounter(); - const currentDate = encounter?.period?.end - ? new Date(encounter.period.end) - : new Date(); + const { selectedEncounter: encounter } = useEncounter(); + const encounterEndDate = useMemo(() => { + if (!encounter?.period?.end) return null; + const parsedDate = new Date(encounter.period.end); + return Number.isNaN(parsedDate.getTime()) ? null : parsedDate; + }, [encounter?.period?.end]); + + const currentDate = encounterEndDate ?? new Date(); @@ const [endSlotDate, setEndSlotDate] = useState(currentDate); @@ const [endSlotIndex, setEndSlotIndex] = useState( Math.floor(currentDate.getHours() / 6), ); + + useEffect(() => { + if (!encounterEndDate) return; + setEndSlotDate(encounterEndDate); + setEndSlotIndex(Math.floor(encounterEndDate.getHours() / 6)); + }, [encounterEndDate]);🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/components/Medicine/MedicationAdministration/AdministrationTab.tsx` around lines 127 - 137, AdministrationTab initializes endSlotDate and endSlotIndex once from currentDate (derived from useEncounter().selectedEncounter) causing the timeline to stay at "now" if selectedEncounter loads after mount; add a useEffect in the AdministrationTab component that watches encounter?.period?.end (or encounter) and when it changes compute a new Date from encounter.period.end (fallback to new Date()), then call setEndSlotDate(newDate) and setEndSlotIndex(Math.floor(newDate.getHours() / 6)) to resync the slot state; reference the existing state setters setEndSlotDate and setEndSlotIndex and the currentDate calculation so the effect mirrors the original initialization logic.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/components/Medicine/MedicationAdministration/AdministrationTab.tsx`:
- Line 37: AdministrationTab currently calls useEncounter() directly which
throws when no EncounterProvider is present; change AdministrationTab to accept
an optional encounter prop (e.g., props.encounter) and remove the unguarded
useEncounter() call so the component uses the passed-in encounter when provided
and only calls useEncounter() as a fallback (or not at all) when you know the
component is wrapped; update places that render AdministrationTab (e.g.,
MedicationHistory, ClinicalHistoryPage) to either pass the encounter or render a
safe fallback UI when encounter is undefined, ensuring AdministrationTab handles
the no-encounter case without throwing.
---
Outside diff comments:
In `@src/components/Medicine/MedicationAdministration/AdministrationTab.tsx`:
- Around line 127-137: AdministrationTab initializes endSlotDate and
endSlotIndex once from currentDate (derived from
useEncounter().selectedEncounter) causing the timeline to stay at "now" if
selectedEncounter loads after mount; add a useEffect in the AdministrationTab
component that watches encounter?.period?.end (or encounter) and when it changes
compute a new Date from encounter.period.end (fallback to new Date()), then call
setEndSlotDate(newDate) and setEndSlotIndex(Math.floor(newDate.getHours() / 6))
to resync the slot state; reference the existing state setters setEndSlotDate
and setEndSlotIndex and the currentDate calculation so the effect mirrors the
original initialization logic.
🪄 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: 27d09ed6-0dc6-4cce-a06b-43ec0398c53f
📒 Files selected for processing (1)
src/components/Medicine/MedicationAdministration/AdministrationTab.tsx
| } from "@/types/emr/medicationRequest/medicationRequest"; | ||
| import medicationRequestApi from "@/types/emr/medicationRequest/medicationRequestApi"; | ||
|
|
||
| import { useEncounter } from "@/pages/Encounters/utils/EncounterProvider"; |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "1) Find AdministrationTab definition + all usages"
rg -nP --type=tsx '\bAdministrationTab\b' -C2
echo
echo "2) Find files importing AdministrationTab"
rg -nP --type=tsx 'import\s+.*\bAdministrationTab\b.*from\s+["'\''][^"'\'']+["'\'']' -C2
echo
echo "3) For each usage file, show nearby EncounterProvider/useEncounter context"
for f in $(rg -nP --type=tsx '\bAdministrationTab\b' | cut -d: -f1 | sort -u); do
echo "----- $f -----"
rg -nP --type=tsx 'EncounterProvider|useEncounter|<AdministrationTab\b' "$f" -C4 || true
doneRepository: ohcnetwork/care_fe
Length of output: 158
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "=== 1) Find AdministrationTab definition ==="
rg -n 'export.*AdministrationTab|function\s+AdministrationTab|const\s+AdministrationTab' -g '*.tsx' -g '*.ts'
echo
echo "=== 2) Find all imports of AdministrationTab ==="
rg -n 'import.*AdministrationTab' -g '*.tsx' -g '*.ts'
echo
echo "=== 3) Check AdministrationTab file for useEncounter ==="
cat -n src/components/Medicine/MedicationAdministration/AdministrationTab.tsx | head -50
echo
echo "=== 4) Find files that use <AdministrationTab ==="
rg -n '<AdministrationTab' -g '*.tsx' -C3
echo
echo "=== 5) Check EncounterProvider for context ==="
rg -n 'export.*EncounterProvider' -g '*.tsx' -g '*.ts'
echo
echo "=== 6) Find files that import EncounterProvider ==="
rg -n 'import.*EncounterProvider' -g '*.tsx' -g '*.ts'Repository: ohcnetwork/care_fe
Length of output: 10273
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "=== MedicationHistory.tsx context (around AdministrationTab usage at line 55) ==="
sed -n '1,100p' src/pages/Patient/History/MedicationHistory.tsx | cat -n
echo
echo "=== Check if MedicationHistory has EncounterProvider ==="
rg -n 'EncounterProvider' src/pages/Patient/History/MedicationHistory.tsx
echo
echo "=== MedicationRequestTable context (around AdministrationTab usage at line 143) ==="
sed -n '1,160p' src/components/Medicine/MedicationRequestTable/index.tsx | cat -n
echo
echo "=== Check encounterId prop in AdministrationTab calls ==="
rg -B2 -A5 '<AdministrationTab' src/pages/Patient/History/MedicationHistory.tsx src/components/Medicine/MedicationRequestTable/index.tsxRepository: ohcnetwork/care_fe
Length of output: 4545
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "=== Find where MedicationHistory is imported/used ==="
rg -n 'import.*MedicationHistory|<MedicationHistory' -g '*.tsx' -g '*.ts' -C2
echo
echo "=== Check AdministrationTab component body for useEncounter usage ==="
sed -n '116,200p' src/components/Medicine/MedicationAdministration/AdministrationTab.tsx | cat -n
echo
echo "=== Full search for useEncounter in AdministrationTab ==="
rg -n 'useEncounter' src/components/Medicine/MedicationAdministration/AdministrationTab.tsx
echo
echo "=== Check line 37 import and how it's used ==="
sed -n '37,120p' src/components/Medicine/MedicationAdministration/AdministrationTab.tsx | cat -nRepository: ohcnetwork/care_fe
Length of output: 7663
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "=== Check History/index.tsx for EncounterProvider context ==="
cat -n src/pages/Patient/History/index.tsx | head -100
echo
echo "=== Check if EncounterProvider wraps this page ==="
rg -n 'EncounterProvider' src/pages/Patient/History/index.tsxRepository: ohcnetwork/care_fe
Length of output: 3630
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "=== Check EncounterProvider implementation for useEncounter ==="
cat -n src/pages/Encounters/utils/EncounterProvider.tsx | head -150Repository: ohcnetwork/care_fe
Length of output: 5760
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "=== Search for useEncounter hook definition ==="
rg -n 'export.*function\s+useEncounter|export\s+const\s+useEncounter' src/pages/Encounters/utils/EncounterProvider.tsx -A5
echo
echo "=== Check the full useEncounter implementation ==="
sed -n '400,450p' src/pages/Encounters/utils/EncounterProvider.tsx | cat -n
echo
echo "=== Search for useContext call pattern ==="
rg -n 'useContext.*encounterContext' src/pages/Encounters/utils/EncounterProvider.tsx -A3Repository: ohcnetwork/care_fe
Length of output: 593
AdministrationTab will crash in MedicationHistory due to missing EncounterProvider.
Line 37's useEncounter() hook throws an error "useEncounter must be used within an EncounterProvider" when rendered outside that provider. AdministrationTab is used in src/pages/Patient/History/MedicationHistory.tsx (line 55) without EncounterProvider wrapping. The parent ClinicalHistoryPage also lacks this provider.
Options to resolve:
- Wrap MedicationHistory with EncounterProvider (requires encounter context)
- Make encounter data optional in AdministrationTab and handle the case when useEncounter is unavailable
- Extract medication administration display into a separate hook-free component for non-encounter contexts
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/components/Medicine/MedicationAdministration/AdministrationTab.tsx` at
line 37, AdministrationTab currently calls useEncounter() directly which throws
when no EncounterProvider is present; change AdministrationTab to accept an
optional encounter prop (e.g., props.encounter) and remove the unguarded
useEncounter() call so the component uses the passed-in encounter when provided
and only calls useEncounter() as a fallback (or not at all) when you know the
component is wrapped; update places that render AdministrationTab (e.g.,
MedicationHistory, ClinicalHistoryPage) to either pass the encounter or render a
safe fallback UI when encounter is undefined, ensuring AdministrationTab handles
the no-encounter case without throwing.
There was a problem hiding this comment.
Pull request overview
This PR aims to make medication administration timeline/gating respect an encounter’s period.end (when available) so completed/discharged encounters don’t continue to behave as if they’re ongoing.
Changes:
- Uses the selected encounter’s
period.endas the baseline “current” date instead of always usingnew Date(). - Wires
AdministrationTabto encounter context viauseEncounter().
Comments suppressed due to low confidence (1)
src/components/Medicine/MedicationAdministration/AdministrationTab.tsx:137
currentDateis computed fromencounter.period.end, butendSlotDate/endSlotIndexare initialized from it only on the first render. SinceselectedEncounteris fetched asynchronously, the initial render will often usenew Date()and the state will not update whenencounter.period.endbecomes available, so the timeline may still end at “now” instead of the encounter end. Consider syncing these state values when the encounter end changes (e.g., via an effect that initializes once), while avoiding overwriting user navigation.
const currentDate = encounter?.period?.end
? new Date(encounter.period.end)
: new Date();
const [endSlotDate, setEndSlotDate] = useState(currentDate);
const [showStopped, setShowStopped] = useState(false);
const [searchQuery, setSearchQuery] = useState("");
const [endSlotIndex, setEndSlotIndex] = useState(
Math.floor(currentDate.getHours() / 6),
);
| const { selectedEncounter: encounter } = useEncounter(); | ||
| const currentDate = encounter?.period?.end | ||
| ? new Date(encounter.period.end) | ||
| : new Date(); |
🎭 Playwright Test ResultsStatus: ❌ Failed
📊 Detailed results are available in the playwright-final-report artifact. Run: #8698 |
nihal467
left a comment
There was a problem hiding this comment.
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (1)
src/components/Medicine/MedicationAdministration/AdministrationTab.tsx (1)
127-127:⚠️ Potential issue | 🔴 Critical | 🏗️ Heavy lift
useEncounter()is still unguarded and can crash this component outside provider context.Line 127 hard-calls
useEncounter(), so any render path withoutEncounterProviderwill throw before fallback logic can run. This was already raised earlier and still appears unresolved in this patch.#!/bin/bash set -euo pipefail echo "1) Find AdministrationTab usage sites" rg -nP --type=tsx '<AdministrationTab\b' -C3 echo echo "2) Check each usage file for EncounterProvider context nearby" for f in $(rg -nP --type=tsx '<AdministrationTab\b' | cut -d: -f1 | sort -u); do echo "----- $f -----" rg -nP --type=tsx 'EncounterProvider|<AdministrationTab\b' "$f" -C5 || true done echo echo "3) Confirm unconditional hook call in AdministrationTab" rg -nP --type=tsx 'useEncounter\(\)' src/components/Medicine/MedicationAdministration/AdministrationTab.tsx -C2🤖 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/components/Medicine/MedicationAdministration/AdministrationTab.tsx` at line 127, AdministrationTab currently calls useEncounter() directly (const { selectedEncounter: encounter } = useEncounter()), which will throw if rendered outside an EncounterProvider; change this to safely read the context and handle missing provider: either use the EncounterContext via useContext(EncounterContext) (so it returns undefined when no provider) and then derive selectedEncounter with a fallback, or update/create a safe hook (e.g., useOptionalEncounter) that returns undefined instead of throwing; update AdministrationTab to use that safe read and guard code paths that rely on selectedEncounter to avoid crashes when no EncounterProvider is present.
🤖 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/components/Medicine/MedicationAdministration/AdministrationTab.tsx`:
- Around line 138-145: The effect in AdministrationTab.tsx that sets endSlotDate
and endSlotIndex reads encounter?.period?.end but only lists encounter?.id as a
dependency, so update the dependency array for that useEffect to include
encounter?.period?.end (or encounter?.period) in addition to encounter?.id; this
ensures the effect re-runs and calls setEndSlotDate and setEndSlotIndex when
encounter?.period?.end changes.
---
Duplicate comments:
In `@src/components/Medicine/MedicationAdministration/AdministrationTab.tsx`:
- Line 127: AdministrationTab currently calls useEncounter() directly (const {
selectedEncounter: encounter } = useEncounter()), which will throw if rendered
outside an EncounterProvider; change this to safely read the context and handle
missing provider: either use the EncounterContext via
useContext(EncounterContext) (so it returns undefined when no provider) and then
derive selectedEncounter with a fallback, or update/create a safe hook (e.g.,
useOptionalEncounter) that returns undefined instead of throwing; update
AdministrationTab to use that safe read and guard code paths that rely on
selectedEncounter to avoid crashes when no EncounterProvider is present.
🪄 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: c64029ed-ddf2-4178-aa7e-a2f83c504c47
📒 Files selected for processing (1)
src/components/Medicine/MedicationAdministration/AdministrationTab.tsx
| useEffect(() => { | ||
| const date = encounter?.period?.end | ||
| ? new Date(encounter.period.end) | ||
| : new Date(); | ||
| setEndSlotDate(date); | ||
| setEndSlotIndex(Math.floor(date.getHours() / 6)); | ||
| }, [encounter?.id]); | ||
|
|
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Verify the effect uses encounter.period.end while dependency array omits it.
rg -nPU '(?s)useEffect\(\(\)\s*=>\s*\{.*encounter\?\.period\?\.end.*\},\s*\[encounter\?\.id\]\);' src/components/Medicine/MedicationAdministration/AdministrationTab.tsxRepository: ohcnetwork/care_fe
Length of output: 312
🏁 Script executed:
sed -n '130,155p' src/components/Medicine/MedicationAdministration/AdministrationTab.tsxRepository: ohcnetwork/care_fe
Length of output: 896
🏁 Script executed:
head -50 src/components/Medicine/MedicationAdministration/AdministrationTab.tsx | tail -30Repository: ohcnetwork/care_fe
Length of output: 1284
🏁 Script executed:
rg -n "useEffect" src/components/Medicine/MedicationAdministration/AdministrationTab.tsxRepository: ohcnetwork/care_fe
Length of output: 162
Add missing dependency to effect; encounter?.period?.end changes won't trigger slot reset.
The effect reads encounter?.period?.end (lines 139–140) but depends only on encounter?.id (line 144). When period.end updates without the encounter ID changing, endSlotDate and endSlotIndex stay stale, breaking the slot calculation.
Suggested fix
- }, [encounter?.id]);
+ }, [encounter?.id, encounter?.period?.end]);📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| useEffect(() => { | |
| const date = encounter?.period?.end | |
| ? new Date(encounter.period.end) | |
| : new Date(); | |
| setEndSlotDate(date); | |
| setEndSlotIndex(Math.floor(date.getHours() / 6)); | |
| }, [encounter?.id]); | |
| useEffect(() => { | |
| const date = encounter?.period?.end | |
| ? new Date(encounter.period.end) | |
| : new Date(); | |
| setEndSlotDate(date); | |
| setEndSlotIndex(Math.floor(date.getHours() / 6)); | |
| }, [encounter?.id, encounter?.period?.end]); |
🤖 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/components/Medicine/MedicationAdministration/AdministrationTab.tsx`
around lines 138 - 145, The effect in AdministrationTab.tsx that sets
endSlotDate and endSlotIndex reads encounter?.period?.end but only lists
encounter?.id as a dependency, so update the dependency array for that useEffect
to include encounter?.period?.end (or encounter?.period) in addition to
encounter?.id; this ensures the effect re-runs and calls setEndSlotDate and
setEndSlotIndex when encounter?.period?.end changes.
|
@nihal467 this looks fine |

Proposed Changes
Tagging: @ohcnetwork/care-fe-code-reviewers
Merge Checklist
Summary by CodeRabbit