Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Doctor notes enhancement #9298

Merged

Conversation

UdaySagar-Git
Copy link
Contributor

@UdaySagar-Git UdaySagar-Git commented Dec 4, 2024

image

Proposed Changes

follow up for #7159
backend pr: ohcnetwork/care#2635

  • Adds file upload support for discussion notes.
  • Adds thread view functionality.
  • Adds mentions support in discussion notes, with hover preview.
  • Fix notification redirect for notes
image image image image

@ohcnetwork/care-fe-code-reviewers

Merge Checklist

  • Add specs that demonstrate bug / test a new feature.
  • Update product documentation.
  • Ensure that UI text is kept in I18n files.
  • Prep screenshot or demo video for changelog entry, and attach it to issue.
  • Request for Peer Reviews
  • Completion of QA

Summary by CodeRabbit

Release Notes

  • New Features

    • Introduced a new endpoint for retrieving specific patient notes by ID.
    • Added a DiscussionNotesEditor component for editing discussion notes with features like mentions and file uploads.
    • Implemented a FilePreviewCard component for displaying uploaded file previews.
    • Added a MentionsDropdown component for user mentions in notes.
    • Introduced a PatientNotesListComponent for managing and displaying patient notes.
    • Added a Textarea component for enhanced text area functionality.
    • Introduced a PatientNotesDetailedView component for displaying detailed patient notes and replies.
  • Enhancements

    • Improved notification handling for mentions in patient notes.
    • Enhanced PatientNoteCard with audio playback functionality.
    • Updated localization entries for improved user interface interactions.
    • Modified the FileUpload component to integrate support for patient notes.
  • Bug Fixes

    • Corrected type errors in various components related to patient notes.
    • Fixed state management issues in the PatientNotes component.
  • Chores

    • Removed deprecated components and streamlined routing for patient notes.
    • Updated internal logic for file uploads and management.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🔭 Outside diff range comments (1)
src/components/Files/FileUpload.tsx (1)

Line range hint 446-446: Update archivable prop to include PATIENT_NOTES

Based on the learnings, PATIENT_NOTES files should be archivable.

-archivable={tab !== "DISCHARGE_SUMMARY"}
+archivable={tab === "PATIENT_NOTES" || (tab !== "DISCHARGE_SUMMARY")}
🧹 Nitpick comments (7)
src/Utils/request/types.ts (1)

39-40: LGTM! Consider adding JSDoc comments.

The type changes to support both string and number types for pathParams and the broader QueryParams type are well-designed and maintain type safety while providing necessary flexibility for the new patient notes functionality.

Consider adding JSDoc comments to document the purpose and expected usage of these parameters:

 export interface QueryOptions<TBody = unknown> {
+  /** Path parameters for the request URL. Supports both string and numeric values (e.g., IDs) */
   pathParams?: Record<string, string | number>;
+  /** Query string parameters. Supports various types including string, number, boolean, null, undefined */
   queryParams?: QueryParams;
src/components/Files/FileUpload.tsx (2)

198-217: Improve type safety for queries object

Consider adding explicit TypeScript types for the queries object to improve type safety and maintainability.

+interface QueryState {
+  data: typeof activeFilesData;
+  isLoading: boolean;
+  refetch: () => void;
+}

+type QueryTypes = 'UNARCHIVED' | 'ARCHIVED' | 'DISCHARGE_SUMMARY' | 'PATIENT_NOTES';

-const queries = {
+const queries: Record<QueryTypes, QueryState> = {
   UNARCHIVED: {
     data: activeFilesData,
     isLoading: isLoadingActiveFiles,
     refetch: refetchActiveFiles,
   },
   // ... rest of the queries
 };

434-440: Simplify file manager selection logic

The current implementation could be simplified for better maintainability.

-fileManager={
-  {
-    DISCHARGE_SUMMARY: dischargeSummaryFileManager,
-    PATIENT_NOTES: patientNotesFileManager,
-  }[tab] || fileManager
-}
-associating_id={
-  tab === "PATIENT_NOTES" ? item.associating_id! : associatedId
-}
+fileManager={getFileManager(tab)}
+associating_id={getAssociatingId(tab, item)}

// Add these utility functions:
+const getFileManager = (tab: string) => {
+  const managers = {
+    DISCHARGE_SUMMARY: dischargeSummaryFileManager,
+    PATIENT_NOTES: patientNotesFileManager,
+  };
+  return managers[tab as keyof typeof managers] || fileManager;
+};
+
+const getAssociatingId = (tab: string, item: FileUploadModel) => 
+  tab === "PATIENT_NOTES" ? item.associating_id! : associatedId;
src/components/Patient/PatientNotes.tsx (1)

30-40: Consider using useEffect for state updates

The state updates within the if conditions could lead to unnecessary renders. Consider moving these updates to a useEffect hook.

-  if (patientData) {
-    if (patientData.name && patientData.name !== patientName) {
-      setPatientName(patientData.name);
-    }
-    if (
-      patientData.facility_object?.name &&
-      patientData.facility_object.name !== facilityName
-    ) {
-      setFacilityName(patientData.facility_object.name);
-    }
-  }
+  useEffect(() => {
+    if (patientData?.name && patientData.name !== patientName) {
+      setPatientName(patientData.name);
+    }
+    if (
+      patientData?.facility_object?.name &&
+      patientData.facility_object.name !== facilityName
+    ) {
+      setFacilityName(patientData.facility_object.name);
+    }
+  }, [patientData, patientName, facilityName]);
src/components/Facility/PatientNotesListComponent.tsx (2)

128-163: Enhance error handling in onAddNote function

The error handling could be more specific to help users better understand what went wrong.

 } catch (error) {
-  Notification.Error({ msg: "An error occurred while adding the note." });
+  Notification.Error({
+    msg: error instanceof Error
+      ? `Failed to add note: ${error.message}`
+      : "An unexpected error occurred while adding the note."
+  });
   return undefined;
 }

165-175: Consider debouncing the refetch operation

The real-time update mechanism might trigger too many refetches if multiple updates occur in quick succession.

+ import { debounce } from 'lodash';
+
+ const debouncedRefetch = debounce(() => {
+   refetchNotes();
+ }, 500);
+
  useMessageListener((data) => {
    const message = data?.message;
    if (
      (message?.from == "patient/doctor_notes/create" ||
        message?.from == "patient/doctor_notes/edit") &&
      message?.facility_id == facilityId &&
      message?.patient_id == patientId
    ) {
-     refetchNotes();
+     debouncedRefetch();
    }
  });
src/components/Facility/PatientNotesSlideover.tsx (1)

174-177: Add cleanup for local storage

Consider cleaning up the local storage when the component unmounts to prevent stale data.

  useEffect(() => {
    localStorage.setItem(localStorageKey, noteField);
+   return () => {
+     localStorage.removeItem(localStorageKey);
+   };
  }, [noteField, localStorageKey]);
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 25a4bbe and b58cfad.

📒 Files selected for processing (7)
  • src/Utils/request/types.ts (1 hunks)
  • src/components/Common/MentionDropdown.tsx (1 hunks)
  • src/components/Facility/PatientNotesDetailedView.tsx (1 hunks)
  • src/components/Facility/PatientNotesListComponent.tsx (1 hunks)
  • src/components/Facility/PatientNotesSlideover.tsx (7 hunks)
  • src/components/Files/FileUpload.tsx (7 hunks)
  • src/components/Patient/PatientNotes.tsx (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/components/Facility/PatientNotesDetailedView.tsx
  • src/components/Common/MentionDropdown.tsx
🧰 Additional context used
📓 Learnings (2)
src/components/Patient/PatientNotes.tsx (1)
Learnt from: UdaySagar-Git
PR: ohcnetwork/care_fe#9298
File: src/components/Facility/PatientNotesDetailedView.tsx:147-188
Timestamp: 2024-12-05T22:41:24.173Z
Learning: In the `PatientNotesDetailedView` component, child notes (`state.child_notes`) are fetched along with the parent note in a single query, so a separate loading state for child notes is not required.
src/components/Files/FileUpload.tsx (1)
Learnt from: UdaySagar-Git
PR: ohcnetwork/care_fe#9298
File: src/components/Files/FileUpload.tsx:392-393
Timestamp: 2024-12-17T05:44:33.531Z
Learning: In the `FileUpload` component (`src/components/Files/FileUpload.tsx`), `PATIENT_NOTES` files should be archivable; therefore, the `archivable` prop should include `PATIENT_NOTES`.
🔇 Additional comments (4)
src/components/Files/FileUpload.tsx (2)

235-242: LGTM! Well-implemented tab management

The implementation follows best practices with proper internationalization and conditional rendering based on data availability.


295-298: LGTM! File manager implementation is correct

The implementation correctly follows the pattern and includes proper callback handling for state updates.

src/components/Patient/PatientNotes.tsx (1)

Line range hint 1-61: LGTM! Well-structured component with proper separation of concerns

The component is well-organized with proper type definitions, efficient data fetching using react-query, and good state management practices.

src/components/Facility/PatientNotesListComponent.tsx (1)

97-108: ⚠️ Potential issue

Fix potential state inconsistency in useEffect

The dependency array is missing state.cPage, which could lead to stale state references.

  useEffect(() => {
    if (notesData) {
      setState((prevState) => ({
        ...prevState,
        notes:
-         state.cPage === 1
+         prevState.cPage === 1
          ? notesData.results
          : [...prevState.notes, ...notesData.results],
        totalPages: Math.ceil(notesData.count / RESULTS_PER_PAGE_LIMIT),
      }));
    }
-  }, [notesData]);
+  }, [notesData, state.cPage]);

Likely invalid or redundant comment.

src/components/Files/FileUpload.tsx Show resolved Hide resolved
src/components/Facility/PatientNotesSlideover.tsx Outdated Show resolved Hide resolved
@UdaySagar-Git
Copy link
Contributor Author

@nihal467
image

cypress tests regarding fileuploads are passing in my local , can you please look into it (it is passing some times and failing completely sometime in github actions)

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (2)
src/components/Files/FileUpload.tsx (1)

295-298: Consider adding type annotations for callback handlers

While the implementation is correct, adding TypeScript type annotations would improve type safety.

 const patientNotesFileManager = useFileManager({
   type: "PATIENT_NOTES",
-  onArchive: () => refetchDiscussionNotes(),
-  onEdit: () => refetchDiscussionNotes(),
+  onArchive: (): Promise<void> => refetchDiscussionNotes(),
+  onEdit: (): Promise<void> => refetchDiscussionNotes(),
 });
src/components/Facility/PatientNotesSlideover.tsx (1)

Line range hint 42-47: Consider extracting thread initialization logic

The thread initialization logic could be moved to a separate function or constant to improve readability and maintainability.

+ const getInitialThread = (userType: string) =>
+   userType === "Nurse"
+     ? PATIENT_NOTES_THREADS.Nurses
+     : PATIENT_NOTES_THREADS.Doctors;

  const [thread, setThread] = useState(
-   authUser.user_type === "Nurse"
-     ? PATIENT_NOTES_THREADS.Nurses
-     : PATIENT_NOTES_THREADS.Doctors,
+   getInitialThread(authUser.user_type)
  );
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 59625d2 and ab45147.

📒 Files selected for processing (2)
  • src/components/Facility/PatientNotesSlideover.tsx (7 hunks)
  • src/components/Files/FileUpload.tsx (7 hunks)
🧰 Additional context used
📓 Learnings (1)
src/components/Files/FileUpload.tsx (1)
Learnt from: UdaySagar-Git
PR: ohcnetwork/care_fe#9298
File: src/components/Files/FileUpload.tsx:392-393
Timestamp: 2024-12-17T05:44:33.531Z
Learning: In the `FileUpload` component (`src/components/Files/FileUpload.tsx`), `PATIENT_NOTES` files should be archivable; therefore, the `archivable` prop should include `PATIENT_NOTES`.
🔇 Additional comments (6)
src/components/Files/FileUpload.tsx (3)

213-217: LGTM: Patient notes query integration

The integration of patient notes query follows the established pattern and maintains consistency with other query implementations.


235-242: LGTM: Well-implemented tab management

The patient notes tab implementation follows best practices:

  • Uses internationalization
  • Conditionally renders based on data availability
  • Maintains consistency with existing tab structure

179-194: 🛠️ Refactor suggestion

Add error handling for discussion notes query

The query implementation looks good, but it's missing error handling for API failures.

 const {
   data: discussionNotesData,
   isLoading: isLoadingDiscussionNotes,
+  error: discussionNotesError,
   refetch: refetchDiscussionNotes,
 } = useQuery({
   queryKey: [routes.viewUpload.path, "PATIENT_NOTES", consultationId, offset],
   queryFn: query(routes.viewUpload, {
     queryParams: {
       file_type: "PATIENT_NOTES",
       consultation_id: consultationId || "",
       is_archived: false,
       limit: RESULTS_PER_PAGE_LIMIT,
       offset,
     },
   }),
   enabled: !!consultationId,
+  onError: (error) => {
+    console.error('Failed to fetch discussion notes:', error);
+    // TODO: Add user-friendly error notification
+  },
 });

Likely invalid or redundant comment.

src/components/Facility/PatientNotesSlideover.tsx (3)

1-31: LGTM! Clean import organization

The imports are well-structured and properly organized, with clear separation between external libraries, internal components, and utilities.


237-243: 🛠️ Refactor suggestion

Enhance accessibility for the slideover panel

The slideover panel should have proper ARIA attributes for better screen reader support.

  <div
    ref={slideoverRef}
+   role="dialog"
+   aria-modal="true"
+   aria-labelledby="discussion-notes-title"
    className={classNames(
      "fixed bottom-0 z-20 sm:right-8",
      show
        ? "right-0 h-screen w-screen sm:h-fit sm:w-[430px]"
        : "right-8 w-[250px]",
    )}
  >

Also add a corresponding ID to the title:

-   <span className="font-semibold">Discussion Notes</span>
+   <span id="discussion-notes-title" className="font-semibold">Discussion Notes</span>

Likely invalid or redundant comment.


298-307: Verify DiscussionNotesEditor usage across the codebase

Let's ensure consistent usage of the DiscussionNotesEditor component across different features.

✅ Verification successful

DiscussionNotesEditor usage is consistent across the codebase

The component is used in three locations (PatientNotesSlideover, PatientNotesListComponent, and PatientNotesDetailedView) with consistent prop usage:

  • All implementations properly provide the required props: initialNote, onChange, onAddNote
  • Optional props like isAuthorized, onRefetch, and maxRows are used appropriately
  • The implementation in PatientNotesSlideover matches the component's interface definition
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for all usages of DiscussionNotesEditor to verify consistent prop usage
ast-grep --pattern 'DiscussionNotesEditor $$$'

# Search for any TODO comments related to the editor
rg -i "todo.*editor|editor.*todo"

Length of output: 84


Script:

#!/bin/bash
# Let's try a different approach to find DiscussionNotesEditor usages
# First, find the file containing the component definition
fd "DiscussionNotesEditor" --type f

# Then search for JSX/TSX imports and usage
rg "DiscussionNotesEditor" --type=tsx --type=jsx -B 2 -A 2

Length of output: 170


Script:

#!/bin/bash
# Now that we found the component file, let's try a different ripgrep approach
# Search for imports and usages of DiscussionNotesEditor
rg "DiscussionNotesEditor" -t ts -t tsx -t jsx -B 2 -A 2

# Also check the component definition to verify required props
cat src/components/Common/DiscussionNotesEditor.tsx

Length of output: 9961


Script:

#!/bin/bash
# Let's try one more time with a simpler ripgrep pattern to find usages
rg -l "import.*DiscussionNotesEditor|from.*DiscussionNotesEditor"

# And search for direct component usage
rg "<DiscussionNotesEditor"

Length of output: 653


Script:

#!/bin/bash
# Let's check the props usage in all three files
cat src/components/Facility/PatientNotesDetailedView.tsx | grep -A 5 "<DiscussionNotesEditor"
cat src/components/Facility/PatientNotesListComponent.tsx | grep -A 5 "<DiscussionNotesEditor"
cat src/components/Facility/PatientNotesSlideover.tsx | grep -A 5 "<DiscussionNotesEditor"

Length of output: 1082

src/components/Files/FileUpload.tsx Show resolved Hide resolved
src/components/Facility/PatientNotesSlideover.tsx Outdated Show resolved Hide resolved
@github-actions github-actions bot removed the merge conflict pull requests with merge conflict label Dec 17, 2024
@rithviknishad rithviknishad added changes required and removed Deploy-Failed Deplyment is not showing preview labels Dec 18, 2024
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
public/locale/en.json (1)

1449-1449: Consider standardizing message input placeholders.

For consistency with other input placeholders in the file, consider ending the message placeholder with an ellipsis.

-  "type_your_message": "Type your message here...",
+  "type_your_message": "Type your message...",
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ab45147 and 5bb768f.

📒 Files selected for processing (1)
  • public/locale/en.json (8 hunks)
🔇 Additional comments (1)
public/locale/en.json (1)

358-358: LGTM! New localization entries align with feature requirements.

The added entries support the new doctor notes features including file attachments, user mentions, thread view, and messaging functionality.

Also applies to: 968-968, 1024-1024, 1046-1046, 1123-1123, 1253-1253, 1449-1449, 1515-1515

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (4)
src/components/Facility/PatientNotesListComponent.tsx (2)

149-155: Enhance note field validation.

The current validation only checks for non-whitespace characters. Consider adding more robust validation:

  1. Maximum length check
  2. Trim whitespace before validation

Apply this diff:

  const onAddNote = async () => {
-   if (!/\S+/.test(noteField)) {
+   const trimmedNote = noteField.trim();
+   const MAX_NOTE_LENGTH = 1000; // Adjust as needed
+   
+   if (!trimmedNote) {
      Notification.Error({
        msg: "Note Should Contain At Least 1 Character",
      });
      return;
    }
+   
+   if (trimmedNote.length > MAX_NOTE_LENGTH) {
+     Notification.Error({
+       msg: `Note exceeds maximum length of ${MAX_NOTE_LENGTH} characters`,
+     });
+     return;
+   }

61-64: Consider persisting thread view mode.

The thread view mode state is reset on component remount. Consider persisting it in localStorage for a better user experience.

Apply this diff:

+ const THREAD_VIEW_MODE_KEY = 'threadViewMode';
+ 
  const [mode, setMode] = useState<"thread-view" | "default-view">(
-   "default-view",
+   (localStorage.getItem(THREAD_VIEW_MODE_KEY) as "thread-view" | "default-view") || "default-view"
  );
  const [threadViewNote, setThreadViewNote] = useState("");

+ useEffect(() => {
+   localStorage.setItem(THREAD_VIEW_MODE_KEY, mode);
+ }, [mode]);
src/components/Facility/models.tsx (2)

564-565: Consider using a more specific type for ThreadCategory.

The current type allows any value from PATIENT_NOTES_THREADS. Consider using a union type of specific string literals for better type safety.

Apply this diff:

- export type ThreadCategory =
-   (typeof PATIENT_NOTES_THREADS)[keyof typeof PATIENT_NOTES_THREADS];
+ export type ThreadCategory = 'DOCTORS' | 'NURSES' | 'SPECIALISTS';

585-589: Add validation constraints to PatientNotesRequest interface.

Consider adding validation constraints using TypeScript utility types to enforce data validation at the type level.

Apply this diff:

+ type NonEmptyString = string & { __brand: 'NonEmptyString' };
+ 
  export interface PatientNotesRequest {
-   note: string;
+   note: NonEmptyString;
    thread: ThreadCategory;
    consultation?: string;
    reply_to?: string;
  }
+
+ // Validation function
+ export function createPatientNotesRequest(
+   note: string,
+   thread: ThreadCategory,
+   consultation?: string,
+   reply_to?: string
+ ): PatientNotesRequest | null {
+   if (!note.trim()) return null;
+   return {
+     note: note as NonEmptyString,
+     thread,
+     consultation,
+     reply_to,
+   };
+ }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5bb768f and 542a615.

📒 Files selected for processing (5)
  • src/Utils/request/api.tsx (3 hunks)
  • src/components/Facility/PatientNotesDetailedView.tsx (1 hunks)
  • src/components/Facility/PatientNotesListComponent.tsx (1 hunks)
  • src/components/Facility/PatientNotesSlideover.tsx (7 hunks)
  • src/components/Facility/models.tsx (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/components/Facility/PatientNotesDetailedView.tsx
🧰 Additional context used
📓 Learnings (1)
src/components/Facility/PatientNotesListComponent.tsx (1)
Learnt from: UdaySagar-Git
PR: ohcnetwork/care_fe#9298
File: src/components/Facility/PatientNotesDetailedView.tsx:147-188
Timestamp: 2024-12-05T22:41:24.173Z
Learning: In the `PatientNotesDetailedView` component, child notes (`state.child_notes`) are fetched along with the parent note in a single query, so a separate loading state for child notes is not required.
🔇 Additional comments (3)
src/components/Facility/PatientNotesSlideover.tsx (1)

118-128: 🛠️ Refactor suggestion

Add cleanup for notification subscription effect.

The notification warning effect should be cleaned up when the component unmounts to prevent memory leaks.

Apply this diff:

  useEffect(() => {
+   let mounted = true;
    if (notificationSubscriptionState === "unsubscribed") {
-     Notification.Warn({
+     mounted && Notification.Warn({
        msg: "Please subscribe to notifications to get live updates on discussion notes.",
      });
    } else if (notificationSubscriptionState === "subscribed_on_other_device") {
-     Notification.Warn({
+     mounted && Notification.Warn({
        msg: "Please subscribe to notifications on this device to get live updates on discussion notes.",
      });
    }
+   return () => {
+     mounted = false;
+   };
  }, [notificationSubscriptionState]);

Likely invalid or redundant comment.

src/Utils/request/api.tsx (2)

669-673: LGTM! New endpoint follows RESTful conventions.

The new getPatientNote endpoint is well-structured and maintains consistency with the existing API patterns.


662-662: LGTM! Type safety improvement.

The update to use PatientNotesRequest type enhances type safety for the request body.

@github-actions github-actions bot added stale merge conflict pull requests with merge conflict labels Dec 28, 2024
Copy link

👋 Hi, @UdaySagar-Git,
Conflicts have been detected against the base branch. Please rebase your branch against the base branch.


This message is automatically generated by prince-chrismc/label-merge-conflicts-action so don't hesitate to report issues/improvements there.

@github-actions github-actions bot removed the stale label Dec 30, 2024
@rithviknishad rithviknishad changed the base branch from develop to develop-v2 December 31, 2024 06:54
@rithviknishad rithviknishad removed test failed changes required merge conflict pull requests with merge conflict labels Dec 31, 2024
Copy link
Member

@rithviknishad rithviknishad left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@nihal467 nihal467 added tested reviewed reviewed by a core member labels Dec 31, 2024
@rithviknishad rithviknishad merged commit 04cc72a into ohcnetwork:develop-v2 Dec 31, 2024
27 checks passed
Copy link

@UdaySagar-Git Your efforts have helped advance digital healthcare and TeleICU systems. 🚀 Thank you for taking the time out to make CARE better. We hope you continue to innovate and contribute; your impact is immense! 🙌

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
reviewed reviewed by a core member tested
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants