refactor(ui): improve UI and responsiveness for patient prescription …#67
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
WalkthroughReworks the prescription UI: replaces the rounded white container with a full-width light-gray gradient header and inner white content card, updates download button behavior and labels, adds a Doctor Signature block, and tightens responsive typography across prescription subcomponents; PDF generation logic and exports remain unchanged. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant UI as PrescriptionSection (UI)
participant PDF as PDFGenerator (async)
note right of UI #f6f8ff: Header + Download Button\nInner white content card\nDoctor Signature block
User->>UI: Clicks Download
UI->>UI: setLoading(true) (show "Generating…")
UI->>PDF: requestPDF(appointmentData)
PDF-->>UI: pdfBlob (async)
UI->>User: trigger browser download(pdfBlob)
UI->>UI: setLoading(false) (restore button label)
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (3)
client/src/components/Patient/AppointmentDetails/prescription/Tests.jsx (1)
6-14: Consider larger minimum font size for instructions.The responsive styling is well-implemented, but
text-[10px](line 12) may be too small for comfortable reading on mobile devices. Consider usingtext-xs(12px) as the minimum size for better accessibility.Apply this diff if you'd like to improve readability:
- <p className="text-green-600 text-[10px] sm:text-sm mt-0.5 sm:mt-1"> + <p className="text-green-600 text-xs sm:text-sm mt-0.5 sm:mt-1">client/src/components/Patient/AppointmentDetails/prescription/Medications.jsx (2)
11-15: Consider larger minimum font size for table headers.Using
text-[10px](10px) for table headers may make them difficult to read on mobile devices, especially for users with visual impairments. Consider usingtext-xs(12px) as the minimum for better accessibility.Apply this diff to improve readability:
- <th className="text-left p-1.5 sm:p-3 font-medium text-[10px] sm:text-sm">Med</th> - <th className="text-left p-1.5 sm:p-3 font-medium text-[10px] sm:text-sm">Dose</th> - <th className="text-left p-1.5 sm:p-3 font-medium text-[10px] sm:text-sm">Freq</th> - <th className="text-left p-1.5 sm:p-3 font-medium text-[10px] sm:text-sm">Days</th> - <th className="text-left p-1.5 sm:p-3 font-medium text-[10px] sm:text-sm">Notes</th> + <th className="text-left p-1.5 sm:p-3 font-medium text-xs sm:text-sm">Med</th> + <th className="text-left p-1.5 sm:p-3 font-medium text-xs sm:text-sm">Dose</th> + <th className="text-left p-1.5 sm:p-3 font-medium text-xs sm:text-sm">Freq</th> + <th className="text-left p-1.5 sm:p-3 font-medium text-xs sm:text-sm">Days</th> + <th className="text-left p-1.5 sm:p-3 font-medium text-xs sm:text-sm">Notes</th>
21-35: Consider larger minimum font size for table cells.Medical information in table cells uses
text-[10px](10px) which may be challenging to read. Considertext-xs(12px) as a more accessible minimum font size for critical medical data.Apply this diff to improve readability:
- <td className="p-1.5 sm:p-3 font-medium text-gray-900 text-[10px] sm:text-sm"> + <td className="p-1.5 sm:p-3 font-medium text-gray-900 text-xs sm:text-sm"> {med.name} </td> - <td className="p-1.5 sm:p-3 text-gray-600 text-[10px] sm:text-sm"> + <td className="p-1.5 sm:p-3 text-gray-600 text-xs sm:text-sm"> {med.dosage} </td> - <td className="p-1.5 sm:p-3 text-gray-600 text-[10px] sm:text-sm"> + <td className="p-1.5 sm:p-3 text-gray-600 text-xs sm:text-sm"> {med.frequency} </td> - <td className="p-1.5 sm:p-3 text-gray-600 text-[10px] sm:text-sm"> + <td className="p-1.5 sm:p-3 text-gray-600 text-xs sm:text-sm"> {med.duration} </td> - <td className="p-1.5 sm:p-3 text-gray-600 text-[10px] sm:text-sm"> + <td className="p-1.5 sm:p-3 text-gray-600 text-xs sm:text-sm"> {med.instructions || 'As directed'} </td>
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (7)
client/src/components/Patient/AppointmentDetails/PrescriptionSection.jsx(1 hunks)client/src/components/Patient/AppointmentDetails/prescription/Diagnosis.jsx(1 hunks)client/src/components/Patient/AppointmentDetails/prescription/FollowUp.jsx(1 hunks)client/src/components/Patient/AppointmentDetails/prescription/Medications.jsx(1 hunks)client/src/components/Patient/AppointmentDetails/prescription/Notes.jsx(1 hunks)client/src/components/Patient/AppointmentDetails/prescription/PrescriptionDate.jsx(1 hunks)client/src/components/Patient/AppointmentDetails/prescription/Tests.jsx(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
client/src/components/Patient/AppointmentDetails/PrescriptionSection.jsx (2)
client/src/components/Patient/AppointmentDetails/prescription/PrescriptionDate.jsx (1)
PrescriptionDate(3-9)client/src/pages/patient/AppointmentDetails.jsx (2)
prescription(15-15)appointment(13-13)
client/src/components/Patient/AppointmentDetails/prescription/FollowUp.jsx (1)
client/src/components/Patient/AppointmentDetails/utils/formatters.js (2)
formatDate(1-8)formatDate(1-8)
🔇 Additional comments (7)
client/src/components/Patient/AppointmentDetails/prescription/FollowUp.jsx (1)
8-9: LGTM! Responsive typography applied correctly.The responsive text sizing improves mobile readability while maintaining proper hierarchy on larger screens.
client/src/components/Patient/AppointmentDetails/prescription/Notes.jsx (1)
6-9: LGTM! Consistent responsive styling.The responsive padding and text sizing align well with the overall prescription UI redesign.
client/src/components/Patient/AppointmentDetails/prescription/Diagnosis.jsx (1)
6-9: LGTM! Responsive styling matches other components.The changes maintain visual consistency across the prescription section while improving mobile responsiveness.
client/src/components/Patient/AppointmentDetails/prescription/PrescriptionDate.jsx (1)
5-5: LGTM! Appropriate responsive adjustments.The padding and text size changes improve the component's appearance on smaller screens while maintaining readability.
client/src/components/Patient/AppointmentDetails/prescription/Medications.jsx (1)
7-7: Verify horizontal overflow handling.Changing from
overflow-x-autotooverflow-hiddenmay cause content to be cut off if medication names or instructions are long on narrow screens. Please test with longer text content to ensure truncation doesn't hide important medical information.client/src/components/Patient/AppointmentDetails/PrescriptionSection.jsx (2)
26-44: LGTM! Well-designed responsive header.The new header design with the professional layout and responsive download button (showing "Download" on larger screens and "PDF" on mobile) is a great improvement to the UI.
47-64: Well-structured content container with doctor signature.The new content layout with proper spacing and the addition of the doctor signature block enhances the professional appearance of the prescription. The responsive spacing adjustments work well.
-Remove the debug console.log -Fix the typo in tailwind class name -Add space between Dr and FirstName
There was a problem hiding this comment.
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)
client/src/components/Patient/AppointmentDetails/PrescriptionSection.jsx (1)
17-17: Refactor to remove state setter coupling from utility function.The review identifies a valid architectural issue. Verification confirms
setDownloadLoadingis passed to and called within the utility, creating tight coupling and risking setState warnings if the component unmounts during async PDF generation. Additionally, loading state is redundantly set twice (before the call and inside the utility).Required changes:
client/src/components/Patient/AppointmentDetails/utils/pdfGenerator.js:3— RemovesetDownloadLoadingparameterclient/src/components/Patient/AppointmentDetails/utils/pdfGenerator.js:7— Delete thesetDownloadLoading(true);lineclient/src/components/Patient/AppointmentDetails/PrescriptionSection.jsx:17— RemovesetDownloadLoadingargument from the callThe component's existing try/finally pattern already manages loading state correctly; the utility should only return a Promise.
🧹 Nitpick comments (2)
client/src/components/Patient/AppointmentDetails/PrescriptionSection.jsx (2)
35-43: Download button: a11y + readiness checks.Make the button accessible and avoid enabling it until data is ready. Add focus ring, ARIA, and proper type.
- <button - onClick={handleDownloadPDF} - disabled={downloadLoading} - className="flex items-center gap-1.5 px-2.5 sm:px-3 py-1.5 sm:py-2 bg-white text-indigo-600 border-0 rounded-md text-xs sm:text-sm font-medium cursor-pointer hover:-translate-y-0.5 hover:shadow-lg transition-all disabled:opacity-60 disabled:cursor-not-allowed" - > - <Download size={14} /> + <button + type="button" + onClick={handleDownloadPDF} + disabled={downloadLoading || !prescription || !appointment} + aria-label={downloadLoading ? 'Generating PDF' : 'Download prescription PDF'} + aria-busy={downloadLoading} + className="flex items-center gap-1.5 px-2.5 sm:px-3 py-1.5 sm:py-2 bg-white text-indigo-600 border-0 rounded-md text-xs sm:text-sm font-medium cursor-pointer hover:-translate-y-0.5 hover:shadow-lg transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-indigo-500 disabled:opacity-60 disabled:cursor-not-allowed" + > + <Download size={14} aria-hidden="true" /> <span className="hidden sm:inline">{downloadLoading ? 'Generating...' : 'Download'}</span> <span className="sm:hidden">PDF</span> </button>
30-33: Optional: theming-friendly icon/text color.If dark mode is used, prefer
text-gray-900 dark:text-gray-50over hardtext-black.- <Pill className="text-black" size={20} /> + <Pill className="text-gray-900 dark:text-gray-50" size={20} />
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
client/src/components/Patient/AppointmentDetails/PrescriptionSection.jsx(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
client/src/components/Patient/AppointmentDetails/PrescriptionSection.jsx (7)
client/src/components/Patient/AppointmentDetails/prescription/PrescriptionDate.jsx (1)
PrescriptionDate(3-9)client/src/pages/patient/AppointmentDetails.jsx (2)
prescription(15-15)appointment(13-13)client/src/components/Patient/AppointmentDetails/prescription/Diagnosis.jsx (1)
Diagnosis(1-12)client/src/components/Patient/AppointmentDetails/prescription/Medications.jsx (1)
Medications(1-43)client/src/components/Patient/AppointmentDetails/prescription/Tests.jsx (1)
Tests(1-21)client/src/components/Patient/AppointmentDetails/prescription/Notes.jsx (1)
Notes(1-12)client/src/components/Patient/AppointmentDetails/prescription/FollowUp.jsx (1)
FollowUp(3-12)
🔇 Additional comments (1)
client/src/components/Patient/AppointmentDetails/PrescriptionSection.jsx (1)
58-61: Signature block looks good.Spacing and class typo from earlier review are fixed; console debug removed. ✅
| <button | ||
| <div className="w-full bg-gray-50 p-2 sm:p-3 min-h-screen flex flex-col"> | ||
| {/* Professional Prescription Header */} | ||
| <div className="flex justify-between items-center px-3 sm:px-4 py-2.5 sm:py-3 bg-gradient-to-r rounded-t-lg"> |
There was a problem hiding this comment.
Gradient missing color stops.
bg-gradient-to-r does nothing without from-*/to-*. Add stops or remove the utility.
- <div className="flex justify-between items-center px-3 sm:px-4 py-2.5 sm:py-3 bg-gradient-to-r rounded-t-lg">
+ <div className="flex justify-between items-center px-3 sm:px-4 py-2.5 sm:py-3 bg-gradient-to-r from-white to-gray-100 rounded-t-lg">📝 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.
| <div className="flex justify-between items-center px-3 sm:px-4 py-2.5 sm:py-3 bg-gradient-to-r rounded-t-lg"> | |
| <div className="flex justify-between items-center px-3 sm:px-4 py-2.5 sm:py-3 bg-gradient-to-r from-white to-gray-100 rounded-t-lg"> |
🤖 Prompt for AI Agents
In client/src/components/Patient/AppointmentDetails/PrescriptionSection.jsx
around line 28, the div uses the Tailwind class "bg-gradient-to-r" without any
color stops so the gradient has no effect; either add appropriate "from-<color>"
and "to-<color>" (and optional "via-<color>") classes to define the gradient
colors (e.g., from-... to-...) or remove the "bg-gradient-to-r" class entirely
if a gradient is not desired. Ensure chosen Tailwind color utility names match
your design system and existing palette.
| <PrescriptionDate date={prescription.date} /> | ||
| <Diagnosis diagnosis={prescription.diagnosis} /> | ||
| <Medications medications={prescription.medications} /> | ||
| <Tests tests={prescription.tests} /> | ||
| <Notes notes={prescription.notes} /> | ||
| <FollowUp followUpDate={prescription.followUpDate} /> | ||
|
|
There was a problem hiding this comment.
🧩 Analysis chain
Prevent crash on null props (add guards).
prescription and appointment can be null initially (parent sets them with useState(null)). Directly reading prescription.date and appointment.doctorId.firstName will throw. Guard before render.
Apply this diff near the top of the component (right before the return):
const PrescriptionSection = ({ prescription, appointment }) => {
const [downloadLoading, setDownloadLoading] = useState(false);
const handleDownloadPDF = async () => {
setDownloadLoading(true);
try {
- await generatePrescriptionPDF(prescription, appointment, setDownloadLoading);
+ await generatePrescriptionPDF(prescription, appointment, setDownloadLoading);
} catch (error) {
console.error('Error generating PDF:', error);
} finally {
setDownloadLoading(false);
}
};
+ // Data not ready yet; avoid dereferencing nulls
+ if (!prescription || !appointment || !appointment.doctorId) {
+ return null; // or a lightweight skeleton placeholder
+ }Run to confirm no unguarded renders:
Also applies to: 58-58
🏁 Script executed:
#!/bin/bash
rg -nP -C2 'PrescriptionSection\s*\(' --type=tsx --type=jsxLength of output: 27
🏁 Script executed:
#!/bin/bash
# Search for PrescriptionSection usage without file type restriction
rg -nP -C2 'PrescriptionSection\s*\(' Length of output: 0
🏁 Script executed:
#!/bin/bash
# Find and examine the PrescriptionSection component file
fd 'PrescriptionSection.jsx' --exec cat {}Length of output: 2985
🏁 Script executed:
#!/bin/bash
# Search for imports of PrescriptionSection to find parent component
rg -nP 'import.*PrescriptionSection' Length of output: 136
🏁 Script executed:
#!/bin/bash
# Look for generatePrescriptionPDF to verify util signature
rg -nP 'generatePrescriptionPDF' -C3Length of output: 2153
🏁 Script executed:
#!/bin/bash
# Examine parent component to confirm null initialization
fd 'AppointmentDetailsLayout.jsx' --exec cat {}Length of output: 5358
Guard appointment.doctorId before dereferencing on line 57 to prevent crash.
The parent component conditionally renders PrescriptionSection only when prescription is truthy, so lines 49-55 are safe. However, appointment.doctorId is accessed directly on line 57 without a null check. If doctorId is null or undefined, the component will crash.
Add a guard:
+ // Ensure doctor info exists before rendering
+ if (!appointment?.doctorId) {
+ return null; // or fallback UI
+ }Also:
- Incomplete gradient:
bg-gradient-to-ron line 31 is missing color stops. Addfrom-blue-500 to-indigo-500(or preferred colors). - Anti-pattern in util call: Line 17 passes
setDownloadLoadingstate setter togeneratePrescriptionPDF. Move loading state management into the component; keep the util pure (only acceptprescriptionandappointment).
Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In client/src/components/Patient/AppointmentDetails/PrescriptionSection.jsx
around lines 49-57, guard access to appointment.doctorId before dereferencing
(e.g., check appointment && appointment.doctorId or use optional chaining) to
prevent a runtime crash when doctorId is null/undefined; also update the
gradient utility class on line 31 to include color stops (e.g., add
from-blue-500 to-indigo-500) so bg-gradient-to-r is complete; finally remove the
setDownloadLoading setter from the generatePrescriptionPDF util call on line 17
and instead manage the loading state inside this component (set loading true
before calling the util and false after promise resolves/rejects) while keeping
the util pure and only passing prescription and appointment.
There was a problem hiding this comment.
Actionable comments posted: 0
♻️ Duplicate comments (3)
client/src/components/Patient/AppointmentDetails/PrescriptionSection.jsx (3)
26-34: Add gradient color stops (current bg-gradient-to-r has no effect).Define from/to (or remove the gradient).
- <div className="flex justify-between items-center px-3 sm:px-4 py-2.5 sm:py-3 bg-gradient-to-r rounded-t-lg"> + <div className="flex justify-between items-center px-3 sm:px-4 py-2.5 sm:py-3 bg-gradient-to-r from-white to-gray-100 rounded-t-lg">
49-55: Guard against null prescription before dereferencing.Prevent crashes if data isn’t ready.
- return ( + // Avoid dereferencing until data exists + if (!prescription) return null; // or a lightweight skeleton + + return (
57-63: Guard doctor info before access.appointment.doctorId may be null/undefined; add a guard.
- <p className="text-sm text-gray-500 m-0"> - Dr. {appointment.doctorId.firstName} {appointment.doctorId.lastName} - </p> + {appointment?.doctorId ? ( + <p className="text-sm text-gray-500 m-0"> + Dr. {appointment.doctorId.firstName} {appointment.doctorId.lastName} + </p> + ) : null}
🧹 Nitpick comments (5)
.github/PULL_REQUEST_TEMPLATE/ui-redesign-pr.md (1)
31-36: Clean up stray placeholder dashes.Removes empty list markers around the “New Components Created” header for a cleaner template.
-- - **New Components Created:** +**New Components Created:** @@ -- -client/src/components/Patient/AppointmentDetails/prescription/Tests.jsx (1)
6-16: Use stable keys and avoid 10px text for readability.Prefer a stable key (id/name) and bump the 10px text to Tailwind text‑xs for a11y.
- {tests.map((test, index) => ( - <li key={index} className="bg-green-50 p-2 sm:p-3 rounded-md"> + {tests.map((test, index) => ( + <li key={test?.id ?? `${test?.name ?? 'test'}-${index}`}" + className="bg-green-50 p-2 sm:p-3 rounded-md"> @@ - <p className="text-green-600 text-[10px] sm:text-sm mt-0.5 sm:mt-1"> + <p className="text-green-600 text-xs sm:text-sm mt-0.5 sm:mt-1"> Instructions: {test.instructions} </p>If a unique id isn’t available, confirm name is unique per list or keep the index.
client/src/components/Patient/AppointmentDetails/prescription/Notes.jsx (1)
6-7: Preserve line breaks and long words in notes.Improves readability for multi-line notes and long tokens.
- <p className="text-gray-600 bg-yellow-50 p-2 sm:p-3 rounded-md text-xs sm:text-sm">{notes}</p> + <p className="text-gray-600 bg-yellow-50 p-2 sm:p-3 rounded-md text-xs sm:text-sm whitespace-pre-line break-words"> + {notes} + </p>client/src/components/Patient/AppointmentDetails/PrescriptionSection.jsx (2)
14-18: Keep utility pure; don’t pass state setter into generatePrescriptionPDF.Manage loading locally; have the util accept only data. Safer, testable, and side‑effect free.
- await generatePrescriptionPDF(prescription, appointment, setDownloadLoading); + await generatePrescriptionPDF(prescription, appointment);If you own the util, update its signature accordingly:
- export async function generatePrescriptionPDF(prescription, appointment, setLoading) { ... } + export async function generatePrescriptionPDF(prescription, appointment) { ... }
35-43: Button a11y and disabled behavior.Add type, aria attributes, and neutralize hover on disabled.
- <button + <button + type="button" onClick={handleDownloadPDF} disabled={downloadLoading} - className="flex items-center gap-1.5 px-2.5 sm:px-3 py-1.5 sm:py-2 bg-white text-indigo-600 border-0 rounded-md text-xs sm:text-sm font-medium cursor-pointer hover:-translate-y-0.5 hover:shadow-lg transition-all disabled:opacity-60 disabled:cursor-not-allowed" + aria-label={downloadLoading ? 'Generating prescription PDF' : 'Download prescription PDF'} + aria-busy={downloadLoading} + className="flex items-center gap-1.5 px-2.5 sm:px-3 py-1.5 sm:py-2 bg-white text-indigo-600 border-0 rounded-md text-xs sm:text-sm font-medium cursor-pointer hover:-translate-y-0.5 hover:shadow-lg transition-all disabled:opacity-60 disabled:cursor-not-allowed disabled:pointer-events-none disabled:hover:shadow-none disabled:translate-y-0" >
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
.github/PULL_REQUEST_TEMPLATE/ui-redesign-pr.md(1 hunks)client/src/components/Patient/AppointmentDetails/PrescriptionSection.jsx(1 hunks)client/src/components/Patient/AppointmentDetails/prescription/Medications.jsx(1 hunks)client/src/components/Patient/AppointmentDetails/prescription/Notes.jsx(1 hunks)client/src/components/Patient/AppointmentDetails/prescription/Tests.jsx(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- client/src/components/Patient/AppointmentDetails/prescription/Medications.jsx
🧰 Additional context used
🧬 Code graph analysis (1)
client/src/components/Patient/AppointmentDetails/PrescriptionSection.jsx (7)
client/src/components/Patient/AppointmentDetails/prescription/PrescriptionDate.jsx (1)
PrescriptionDate(3-9)client/src/pages/patient/AppointmentDetails.jsx (2)
prescription(15-15)appointment(13-13)client/src/components/Patient/AppointmentDetails/prescription/Diagnosis.jsx (1)
Diagnosis(1-12)client/src/components/Patient/AppointmentDetails/prescription/Medications.jsx (1)
Medications(1-41)client/src/components/Patient/AppointmentDetails/prescription/Tests.jsx (1)
Tests(1-23)client/src/components/Patient/AppointmentDetails/prescription/Notes.jsx (1)
Notes(1-10)client/src/components/Patient/AppointmentDetails/prescription/FollowUp.jsx (1)
FollowUp(3-12)
Resigned the UI and improved the Responsiveness for patient prescription


#Screenshots of updated UI
#Desktop:
#Mobile
Summary by CodeRabbit
New Features
Style
Chores