import React, { useCallback, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { z } from 'zod'; import { zodResolver } from '@hookform/resolvers/zod'; import { Controller, useForm } from 'react-hook-form'; import { Button, Column, Form, InlineLoading, InlineNotification, Row, Stack, TextArea } from '@carbon/react'; import { closeWorkspaceGroup2, getCoreTranslation, ResponsiveWrapper, showSnackbar, translateFrom, useConfig, useSession, Workspace2, } from '@openmrs/esm-framework'; import { moduleName } from '../../constant'; import { createPatientNote, usePatientNotes } from './notes.resource'; import useEmrConfiguration from '../../hooks/useEmrConfiguration'; import styles from './notes.scss'; import { type WardPatientWorkspaceDefinition, type EncounterPayload } from '../../types'; import { type WardConfigObject } from '../../config-schema'; import WardPatientWorkspaceBanner from '../patient-banner/patient-banner.component'; import PatientNotesHistory from './history/notes-container.component'; type NotesFormData = z.infer; const noteFormSchema = z.object({ wardClinicalNote: z.string().refine((val) => val.trim().length > 0, { //t('clinicalNoteErrorMessage','Clinical note is required') message: translateFrom(moduleName, 'clinicalNoteErrorMessage', 'Clinical note is required'), }), }); const WardPatientNotesWorkspace: React.FC = ({ groupProps: { wardPatient }, closeWorkspace, }) => { const patientUuid = wardPatient.patient.uuid; const visitUuid = wardPatient?.visit?.uuid; const { emrConfiguration, isLoadingEmrConfiguration, errorFetchingEmrConfiguration } = useEmrConfiguration(); const config = useConfig(); const { t } = useTranslation(); const session = useSession(); const { patientNotes, mutatePatientNotes, isLoadingPatientNotes, errorFetchingPatientNotes } = usePatientNotes( patientUuid, visitUuid, [emrConfiguration?.consultFreeTextCommentsConcept?.uuid, ...config.additionalInpatientNotesConceptUuids], ); const [isSubmitting, setIsSubmitting] = useState(false); const [hasEditChanges, setHasEditChanges] = useState(false); const { control, handleSubmit, formState: { errors, isDirty }, } = useForm({ mode: 'onSubmit', resolver: zodResolver(noteFormSchema), defaultValues: { wardClinicalNote: '', }, }); const locationUuid = session?.sessionLocation?.uuid; const providerUuid = session?.currentProvider?.uuid; const onSubmit = useCallback( (data: NotesFormData) => { const { wardClinicalNote } = data; setIsSubmitting(true); const notePayload: EncounterPayload = { patient: patientUuid, location: locationUuid, visit: visitUuid, encounterType: emrConfiguration?.inpatientNoteEncounterType?.uuid, encounterProviders: [ { encounterRole: emrConfiguration?.clinicianEncounterRole?.uuid, provider: providerUuid, }, ], obs: wardClinicalNote ? [ { concept: { uuid: emrConfiguration?.consultFreeTextCommentsConcept.uuid, display: '' }, value: wardClinicalNote, }, ] : [], }; const abortController = new AbortController(); createPatientNote(notePayload, abortController) .then(async () => { showSnackbar({ isLowContrast: true, kind: 'success', subtitle: t('patientNoteNowVisible', 'It should be now visible in the notes history'), title: t('visitNoteSaved', 'Patient note saved'), }); mutatePatientNotes(); await closeWorkspace({ discardUnsavedChanges: true }); closeWorkspaceGroup2(); }) .catch((err) => { showSnackbar({ isLowContrast: false, kind: 'error', subtitle: err?.message, title: t('patientNoteSaveError', 'Error saving patient note'), }); }) .finally(() => setIsSubmitting(false)); }, [ emrConfiguration?.clinicianEncounterRole?.uuid, emrConfiguration?.consultFreeTextCommentsConcept?.uuid, emrConfiguration?.inpatientNoteEncounterType?.uuid, locationUuid, mutatePatientNotes, patientUuid, providerUuid, t, closeWorkspace, visitUuid, ], ); const onError = (errors) => console.error(errors); return (
{errorFetchingEmrConfiguration && (
)} {t('note', 'Note')} (