diff --git a/e2e/specs/edit-existing-visit.spec.ts b/e2e/specs/edit-existing-visit.spec.ts index 382e90ae9..637c509fb 100644 --- a/e2e/specs/edit-existing-visit.spec.ts +++ b/e2e/specs/edit-existing-visit.spec.ts @@ -1,6 +1,6 @@ import { expect } from '@playwright/test'; import { type Visit } from '@openmrs/esm-framework'; -import { type Patient, generateRandomPatient, deletePatient, startVisit } from '../commands'; +import { deletePatient, generateRandomPatient, type Patient, startVisit } from '../commands'; import { test } from '../core'; import { ChartPage, VisitsPage } from '../pages'; @@ -27,18 +27,24 @@ test('Edit an existing visit', async ({ page }) => { await test.step('Then I should see the `Edit Visit` form launch in the workspace', async () => { await expect(chartPage.page.getByText(/visit start date and time/i)).toBeVisible(); - const datePickerInput = chartPage.page.getByPlaceholder(/dd\/mm\/yyyy/i); - await expect(datePickerInput).toBeVisible(); - const dateValue = await datePickerInput.inputValue(); + + const startDateInput = chartPage.page.locator('input#visitStartDateInput'); + const startTimeInput = chartPage.page.locator('input#visitStartTime'); + + await expect(startDateInput).toBeVisible(); + const dateValue = await startDateInput.inputValue(); expect(dateValue).not.toBe(''); expect(dateValue).toMatch(/^\d{2}\/\d{2}\/\d{4}$/); - await expect(chartPage.page.getByPlaceholder(/hh\:mm/i)).toBeVisible(); + await expect(startTimeInput).toBeVisible(); + const timeValue = await startTimeInput.inputValue(); + expect(timeValue).toMatch(/^(1[0-2]|0?[1-9]):([0-5][0-9])$/); + await expect(chartPage.page.getByRole('combobox', { name: /select a location/i })).toBeVisible(); await expect(chartPage.page.getByRole('combobox', { name: /select a location/i })).toHaveValue('Outpatient Clinic'); await expect(chartPage.page.getByText(/visit type/i)).toBeVisible(); await expect(chartPage.page.getByLabel(/facility visit/i)).toBeChecked(); - await expect(chartPage.page.getByRole('search', { name: /search for a visit type/i })).toBeVisible(); + await expect(chartPage.page.getByRole('search', { name: /visit type/i })).toBeVisible(); await expect(chartPage.page.getByLabel(/facility visit/i)).toBeVisible(); await expect(chartPage.page.getByLabel(/home visit/i)).toBeVisible(); await expect(chartPage.page.getByLabel(/opd visit/i)).toBeVisible(); diff --git a/packages/esm-form-entry-app/translations/ar.json b/packages/esm-form-entry-app/translations/ar.json index c182547d1..6cbc9a193 100644 --- a/packages/esm-form-entry-app/translations/ar.json +++ b/packages/esm-form-entry-app/translations/ar.json @@ -18,13 +18,13 @@ "daysAgo": " أيام مضت", "deleteEntry": "هل أنت متأكد أنك تريد حذف هذا العنصر؟", "discardButton": "تجاهل", - "disallowDecimals": "Decimals are not allowed", + "disallowDecimals": "غير مسموح بالأرقام العشرية", "enterMoreCharacters": "الرجاء إدخال 2 أحرف أو أكثر", "errorFetchingFormData": "حدث خطأ أثناء جلب بيانات النموذج. التفاصيل: {detail}", "errorLoadingForm": "خطأ في تحميل النموذج", "errorWithForm": "هناك خطأ في هذا النموذج", "fix": "إصلاح", - "formSubmissionFailed": "An error occurred while processing your form submission. Kindly notify the system administrator and reference the following error : {error}", + "formSubmissionFailed": "حدث خطأ عند معالجة النموذج. الرجاء اعلام مدير النظام بالخطأ التالي : {error}", "formSubmittedSuccessfully": "تم إرسال النموذج بنجاح.", "from": "من", "futureDateRestriction": "لا يُسمح بتاريخ في المستقبل!", @@ -44,14 +44,14 @@ "minusSecond": "اطرح ثانية", "minutesAgo": " دقائق مضت", "monthsAgo": " أشهر مضت", - "next": "Next", + "next": "التالي", "next21Years": "الـ 21 سنة القادمة", "nextMonth": "الشهر القادم", "nextYear": "السنة القادمة", "patientIdentifierDuplication": "تكرار معرف المريض", "patientIdentifierDuplicationDescription": "المعرف المقدم مرتبط بالفعل بمريض موجود. يرجى التحقق من المعرف والمحاولة مرة أخرى.", - "orderNumber": "Order number", - "previous": "Previous", + "orderNumber": "رقم الأمر", + "previous": "السابق", "previous21Years": "الـ 21 سنة السابقة", "previousMonth": "الشهر السابق", "previousValue": "القيمة السابقة", diff --git a/packages/esm-patient-allergies-app/translations/vi.json b/packages/esm-patient-allergies-app/translations/vi.json index 47fa62681..1dd0551fe 100644 --- a/packages/esm-patient-allergies-app/translations/vi.json +++ b/packages/esm-patient-allergies-app/translations/vi.json @@ -3,45 +3,45 @@ "allergen": "Chất gây dị ứng", "allergies": "Dị ứng", "Allergies": "Dị ứng", - "allergyDeleted": "Allergy deleted", - "allergyIntolerances": "allergy intolerances", - "allergyNowVisible": "It is now visible on the Allergies page", - "allergySaved": "Allergy saved", - "allergySaveError": "Error saving allergy", - "allergyUpdated": "Allergy updated", + "allergyDeleted": "Đã xóa dị ứng", + "allergyIntolerances": "không dung nạp dị ứng", + "allergyNowVisible": "Bây giờ nó có thể nhìn thấy trên trang Dị ứng", + "allergySaved": "Đã lưu dị ứng", + "allergySaveError": "Lỗi khi lưu dị ứng", + "allergyUpdated": "Đã cập nhật dị ứng", "cancel": "Hủy", - "dateOfOnsetAndComments": "Date of onset and comments", + "dateOfOnsetAndComments": "Ngày bắt đầu và bình luận", "delete": "Xóa", - "deleteModalConfirmationText": "Are you sure you want to delete this allergy?", - "deletePatientAllergy": "Delete allergy", + "deleteModalConfirmationText": "Bạn có chắc chắn muốn xóa dị ứng này không?", + "deletePatientAllergy": "Xóa dị ứng", "deleting": "Đang xóa", "discard": "Hủy bỏ", "edit": "Chỉnh sửa", - "editAllergy": "Edit an Allergy", - "editOrDeleteAllergy": "Edit or delete allergy", - "errorDeletingAllergy": "Error deleting allergy", - "invalidComment": "Invalid comment, try again", + "editAllergy": "Sủa dị ứng", + "editOrDeleteAllergy": "Sửa hoặc xóa dự ứng", + "errorDeletingAllergy": "Lỗi xóa dị ứng", + "invalidComment": "Bình luận không hợp lệ, hãy thử lại", "loading": "Đang tải", "mild": "Nhẹ", "moderate": "Vừa phải", "name": "Tên", "nonCodedAllergenWarningDescription": "Việc thêm chất gây dị ứng tùy chỉnh có thể ảnh hưởng đến thông báo dị ứng trên toàn hệ thống. Bạn nên chọn từ danh sách được cung cấp để có cảnh báo chính xác. Các mục tùy chỉnh có thể không kích hoạt thông báo trong mọi bối cảnh có liên quan.", - "nonCodedAllergenWarningTitle": "Warning: Custom Allergen Entry", - "onsetDateAndComments": "Onset date and comments", + "nonCodedAllergenWarningTitle": "Cảnh báo: Mục nhập chất gây dị ứng tùy chỉnh", + "onsetDateAndComments": "Ngày bắt đầu và bình luận", "other": "Khác", - "otherNonCodedAllergen": "Other non-coded allergen", - "otherNonCodedAllergicReaction": "Other non-coded allergic reaction", + "otherNonCodedAllergen": "Chất gây dị ứng khác không được mã hóa", + "otherNonCodedAllergicReaction": "Phản ứng dị ứng khác không được mã hóa", "reaction": "Phản ứng", "reactions": "Phản ứng", - "recordNewAllergy": "Record a new allergy", - "saveAndClose": "Save and close", - "seeAll": "See all", - "selectAllergen": "Select the allergen", - "selectReactions": "Select the reactions", + "recordNewAllergy": "Ghi lại một dị ứng mới", + "saveAndClose": "Lưu và đóng", + "seeAll": "Xem tất cả", + "selectAllergen": "Chọn chất gây dị ứng", + "selectReactions": "Chọn các phản ứng", "severe": "Nghiêm trọng", "severityandReaction": "Mức độ nghiêm trọng", - "severityOfWorstReaction": "Severity of worst reaction", - "typeAdditionalComments": "Type any additional comments here", - "typeAllergenName": "Please type in the name of the allergen", - "typeAllergicReactionName": "Please type in the name of the allergic reaction" + "severityOfWorstReaction": "Mức độ nghiêm trọng của phản ứng tồi tệ nhất", + "typeAdditionalComments": "Nhập bất kỳ bình luận bổ sung nào ở đây", + "typeAllergenName": "Vui lòng nhập tên chất gây dị ứng", + "typeAllergicReactionName": "Vui lòng nhập tên phản ứng dị ứng" } diff --git a/packages/esm-patient-attachments-app/translations/vi.json b/packages/esm-patient-attachments-app/translations/vi.json index 3995317a8..e355b9125 100644 --- a/packages/esm-patient-attachments-app/translations/vi.json +++ b/packages/esm-patient-attachments-app/translations/vi.json @@ -1,56 +1,56 @@ { "add": "Thêm", - "addAnImage": "Add image", - "addAttachment": "Add Attachment", - "addAttachment_title": "Add Attachment", - "addMoreAttachments": "Add more attachments", + "addAnImage": "Thêm hình ảnh", + "addAttachment": "Thêm tệp đính kèm", + "addAttachment_title": "Thêm tệp đính kèm", + "addMoreAttachments": "Thêm nhiều tệp đính kèm hơn", "attachments": "Đính kèm", "Attachments": "Đính kèm", "attachmentsInLowerCase": "đính kèm", "attachmentsInProperFormat": "Đính kèm", - "cameraAccessErrorMessage": "Please enable camera access in your browser settings and try again.", - "cameraError": "Camera Error", + "cameraAccessErrorMessage": "Vui lòng bật quyền truy cập camera trong cài đặt trình duyệt của bạn và thử lại.", + "cameraError": "Lỗi máy ảnh", "cancel": "Hủy", - "chooseAnAllowedFileType": "The file \"{{fileName}}\" cannot be uploaded. Please upload a file with one of the following extensions: {{supportedExtensions}}, or {{ lastExtension }}.", + "chooseAnAllowedFileType": "Không thể tải lên tệp \"{{fileName}}\". Vui lòng tải lên tệp có một trong các phần mở rộng sau: {{supportedExtensions}} hoặc {{lastExtension }}.", "closeModal": "Đóng", - "closePreview": "Close preview", - "dateUploaded": "Date uploaded", + "closePreview": "Đóng bản xem trước", + "dateUploaded": "Ngày tải lên", "delete": "Xóa", - "deleteAttachmentConfirmationText": "Are you sure you want to delete this {{attachmentType}}? This action can't be undone.", - "deleteImage": "Delete image", - "deletePdf": "Delete PDF", + "deleteAttachmentConfirmationText": "Bạn có chắc chắn muốn xóa {{attachmentType}} này không? Không thể hoàn tác hành động này.", + "deleteImage": "Xóa hình ảnh", + "deletePdf": "Xóa PDF", "edit": "Chỉnh sửa", - "enterAttachmentDescription": "Enter attachment description", - "enterAttachmentName": "Enter attachment name", + "enterAttachmentDescription": "Nhập mô tả tệp đính kèm", + "enterAttachmentName": "Nhập tên tệp đính kèm", "error": "Lỗi", "failed": "thất bại", - "failedDeleting": "couldn't be deleted", + "failedDeleting": "không thể xóa được", "file": "Tệp", - "fileDeleted": "File deleted", - "fileName": "File name", - "fileSizeInstructions": "Drag and drop files here or click to upload", - "fileSizeLimitExceeded": "exceeds the size limit of", - "fileSizeLimitExceededText": "File size limit exceeded", - "fileUploadSizeConstraints": "File limit is {{fileSize}}MB", - "gridView": "Grid view", + "fileDeleted": "Tập tin đã xóa", + "fileName": "Tên tệp", + "fileSizeInstructions": "Kéo và thả tập tin vào đây hoặc nhấp để tải lên", + "fileSizeLimitExceeded": "vượt quá giới hạn kích thước của", + "fileSizeLimitExceededText": "Đã vượt quá giới hạn kích thước tệp", + "fileUploadSizeConstraints": "Giới hạn tệp là {{fileSize}}MB", + "gridView": "Chế độ xem lưới", "image": "Hình ảnh", - "imageDescription": "Image description", - "imagePlaceholder": "Image placeholder", - "imagePreview": "Image preview", + "imageDescription": "Mô tả hình ảnh", + "imagePlaceholder": "Giữ chỗ hình ảnh", + "imagePreview": "Xem trước hình ảnh", "name": "tên", - "nameIsRequired": "Name is required", - "noImageToDisplay": "No image to display", + "nameIsRequired": "Tên là bắt buộc", + "noImageToDisplay": "Không có hình ảnh để hiển thị", "options": "Tùy chọn", - "successfullyDeleted": "successfully deleted", - "supportedFiletypes": "Supported files are {{supportedFiles}}", - "tableView": "Table view", + "successfullyDeleted": "đã xóa thành công", + "supportedFiletypes": "Các tập tin được hỗ trợ là {{supportedFiles}}", + "tableView": "Xem bảng", "type": "Loại", - "unsupportedFileType": "Unsupported file type", - "uploadComplete": "Upload complete", - "uploadedSuccessfully": "uploaded successfully", - "uploadError": "Error uploading file", - "uploadFiles": "Upload files", + "unsupportedFileType": "Loại tệp không được hỗ trợ", + "uploadComplete": "Tải lên hoàn tất", + "uploadedSuccessfully": "đã tải lên thành công", + "uploadError": "Lỗi tải tập tin lên", + "uploadFiles": "Tải lên các tập tin", "uploading": "Đang tải lên", - "uploadWillContinueInTheBackground": "Files will be uploaded in the background. You can close this modal.", + "uploadWillContinueInTheBackground": "Các tập tin sẽ được tải lên ở chế độ nền. Bạn có thể đóng hộp thoại này.", "webcam": "Webcam" } diff --git a/packages/esm-patient-banner-app/translations/vi.json b/packages/esm-patient-banner-app/translations/vi.json index 2e8aa4954..c1abe8095 100644 --- a/packages/esm-patient-banner-app/translations/vi.json +++ b/packages/esm-patient-banner-app/translations/vi.json @@ -7,14 +7,14 @@ "countyDistrict": "Huyện", "district": "Huyện", "implementationLogo": "Logo triển khai", - "patientAge": "Age:", - "patientDateOfBirthWithSeparator": "Date of birth:", - "patientGenderWithSeparator": "Gender:", - "patientIdentifierSticker": "Patient identifier sticker", - "patientNameWithSeparator": "Patient name:", - "postalCode": "Postal code", - "printIdentifierSticker": "Print identifier sticker", + "patientAge": "Tuổi\"", + "patientDateOfBirthWithSeparator": "Ngày sinh:", + "patientGenderWithSeparator": "Giới tính:", + "patientIdentifierSticker": "Nhãn dán nhận dạng bệnh nhân", + "patientNameWithSeparator": "Tên bệnh nhân:", + "postalCode": "Mã bưu chính", + "printIdentifierSticker": "In nhãn dán nhận dạng", "state": "State", "stateProvince": "State", - "telephoneNumberWithSeparator": "Telephone number:" + "telephoneNumberWithSeparator": "Số điện thoại:" } diff --git a/packages/esm-patient-chart-app/src/patient-chart/patient-chart.component.tsx b/packages/esm-patient-chart-app/src/patient-chart/patient-chart.component.tsx index 63bba2e81..4443bc0d7 100644 --- a/packages/esm-patient-chart-app/src/patient-chart/patient-chart.component.tsx +++ b/packages/esm-patient-chart-app/src/patient-chart/patient-chart.component.tsx @@ -17,6 +17,7 @@ import Loader from '../loader/loader.component'; import styles from './patient-chart.scss'; import VisitHeader from '../visit-header/visit-header.component'; import SideMenuPanel from '../side-nav/side-menu.component'; +import { getPatientChartStore } from '@openmrs/esm-patient-common-lib'; const PatientChart: React.FC = () => { const { patientUuid, view: encodedView } = useParams(); @@ -41,6 +42,17 @@ const PatientChart: React.FC = () => { }; }, [patientUuid]); + useEffect(() => { + getPatientChartStore().setState({ + patientUuid, + }); + return () => { + getPatientChartStore().setState({ + patientUuid: null, + }); + }; + }, [patientUuid]); + const leftNavBasePath = useMemo(() => spaBasePath.replace(':patientUuid', patientUuid), [patientUuid]); useEffect(() => { setLeftNav({ name: 'patient-chart-dashboard-slot', basePath: leftNavBasePath }); diff --git a/packages/esm-patient-chart-app/src/visit/visit-form/visit-form.component.tsx b/packages/esm-patient-chart-app/src/visit/visit-form/visit-form.component.tsx index 28eb9915b..e29ab38bd 100644 --- a/packages/esm-patient-chart-app/src/visit/visit-form/visit-form.component.tsx +++ b/packages/esm-patient-chart-app/src/visit/visit-form/visit-form.component.tsx @@ -25,6 +25,7 @@ import { zodResolver } from '@hookform/resolvers/zod'; import { ExtensionSlot, formatDatetime, + type NewVisitPayload, openmrsFetch, restBaseUrl, saveVisit, @@ -39,15 +40,14 @@ import { useSession, useVisit, useVisitTypes, - type NewVisitPayload, type Visit, } from '@openmrs/esm-framework'; import { convertTime12to24, createOfflineVisitForPatient, + type DefaultPatientWorkspaceProps, time12HourFormatRegex, useActivePatientEnrollment, - type DefaultPatientWorkspaceProps, } from '@openmrs/esm-patient-common-lib'; import { type ChartConfig } from '../../config-schema'; import { type VisitFormData } from './visit-form.resource'; @@ -121,8 +121,8 @@ const StartVisitForm: React.FC = ({ }); const displayVisitStopDateTimeFields = useMemo( - () => Boolean(visitToEdit?.stopDatetime || showVisitEndDateTimeFields), - [visitToEdit?.stopDatetime, showVisitEndDateTimeFields], + () => Boolean(visitToEdit?.uuid || showVisitEndDateTimeFields), + [visitToEdit?.uuid, showVisitEndDateTimeFields], ); const visitFormSchema = useMemo(() => { @@ -148,6 +148,8 @@ const StartVisitForm: React.FC = ({ return new Date(visitStartDatetime) <= new Date(); }; + const hadPreviousStopDateTime = Boolean(visitToEdit?.stopDatetime); + return z .object({ visitStartDate: z.date().refine( @@ -167,13 +169,18 @@ const StartVisitForm: React.FC = ({ .string() .refine((value) => value.match(time12HourFormatRegex), t('invalidTimeFormat', 'Invalid time format')), visitStartTimeFormat: z.enum(['PM', 'AM']), - visitStopDate: displayVisitStopDateTimeFields ? z.date() : z.date().optional(), - visitStopTime: displayVisitStopDateTimeFields - ? z - .string() - .refine((value) => value.match(time12HourFormatRegex), t('invalidTimeFormat', 'Invalid time format')) - : z.string().optional(), - visitStopTimeFormat: displayVisitStopDateTimeFields ? z.enum(['PM', 'AM']) : z.enum(['PM', 'AM']).optional(), + visitStopDate: displayVisitStopDateTimeFields && hadPreviousStopDateTime ? z.date() : z.date().optional(), + visitStopTime: + displayVisitStopDateTimeFields && hadPreviousStopDateTime + ? z.string().refine((value) => value.match(time12HourFormatRegex), t('invalidTimeFormat')) + : z + .string() + .refine((value) => !value || value.match(time12HourFormatRegex), t('invalidTimeFormat')) + .optional(), + visitStopTimeFormat: + displayVisitStopDateTimeFields && hadPreviousStopDateTime + ? z.enum(['PM', 'AM']) + : z.enum(['PM', 'AM']).optional(), programType: z.string().optional(), visitType: z.string().refine((value) => !!value, t('visitTypeRequired', 'Visit type is required')), visitLocation: z.object({ @@ -186,7 +193,7 @@ const StartVisitForm: React.FC = ({ message: t('futureStartTime', 'Visit start time cannot be in the future'), path: ['visitStartTime'], }); - }, [t, config, displayVisitStopDateTimeFields]); + }, [config.visitAttributeTypes, visitToEdit?.stopDatetime, t, displayVisitStopDateTimeFields]); const defaultValues = useMemo(() => { const visitStartDate = visitToEdit?.startDatetime ? new Date(visitToEdit?.startDatetime) : new Date(); @@ -283,31 +290,33 @@ const StartVisitForm: React.FC = ({ const visitStopTime = getValues('visitStopTime'); const visitStopTimeFormat = getValues('visitStopTimeFormat'); - const [visitStopHours, visitStopMinutes] = convertTime12to24(visitStopTime, visitStopTimeFormat); - - const visitStopDatetime = visitStopDate.setHours(visitStopHours, visitStopMinutes); - - if (minVisitStopDatetime && visitStopDatetime <= minVisitStopDatetime) { - validSubmission = false; - setError('visitStopDate', { - message: t( - 'visitStopDateMustBeAfterMostRecentEncounter', - 'Stop date needs to be on or after {{lastEncounterDatetime}}', - { - lastEncounterDatetime: new Date(minVisitStopDatetime).toLocaleString(), - interpolation: { - escapeValue: false, + if (visitStopDate && visitStopTime && visitStopTimeFormat) { + const [visitStopHours, visitStopMinutes] = convertTime12to24(visitStopTime, visitStopTimeFormat); + + const visitStopDatetime = visitStopDate.setHours(visitStopHours, visitStopMinutes); + + if (minVisitStopDatetime && visitStopDatetime <= minVisitStopDatetime) { + validSubmission = false; + setError('visitStopDate', { + message: t( + 'visitStopDateMustBeAfterMostRecentEncounter', + 'Stop date needs to be on or after {{lastEncounterDatetime}}', + { + lastEncounterDatetime: new Date(minVisitStopDatetime).toLocaleString(), + interpolation: { + escapeValue: false, + }, }, - }, - ), - }); - } + ), + }); + } - if (visitStartDatetime >= visitStopDatetime) { - validSubmission = false; - setError('visitStopDate', { - message: t('invalidVisitStopDate', 'Visit stop date time cannot be on or before visit start date time'), - }); + if (visitStartDatetime >= visitStopDatetime) { + validSubmission = false; + setError('visitStopDate', { + message: t('invalidVisitStopDate', 'Visit stop date time cannot be on or before visit start date time'), + }); + } } return validSubmission; @@ -442,7 +451,7 @@ const StartVisitForm: React.FC = ({ delete payload.patient; } - if (displayVisitStopDateTimeFields) { + if (displayVisitStopDateTimeFields && visitStopDate && visitStopTime && visitStopTimeFormat) { const [visitStopHours, visitStopMinutes] = convertTime12to24(visitStopTime, visitStopTimeFormat); payload.stopDatetime = toDateObjectStrict( diff --git a/packages/esm-patient-chart-app/translations/pt.json b/packages/esm-patient-chart-app/translations/pt.json index bef2c0bf3..52ddbddcb 100644 --- a/packages/esm-patient-chart-app/translations/pt.json +++ b/packages/esm-patient-chart-app/translations/pt.json @@ -1,186 +1,186 @@ { - "addAPastVisit": "Add a past visit", - "addPastVisit": "Add past visit", - "addPastVisitText": "You can add a new past visit or update an old one. Choose from one of the options below to continue.", - "all": "All", - "allEncounters": "All encounters", - "appointmentCheckedIn": "Appointment checked in", - "appointmentMarkedChecked": "Appointment marked as Checked In", - "cancel": "Cancel", - "cancelActiveVisitConfirmation": "Are you sure you want to cancel this active visit?", - "cancellingVisit": "Cancelling visit", - "cancelVisit": "Cancel visit", - "cancelVisitExplainerMessage": "Cancelling this visit will delete its associated encounters", - "causeOfDeath": "Cause of death", - "causeOfDeath_lower": "cause of death concepts configured in the system", - "causeOfDeathIsRequired": "Please select the cause of death", - "checkFilters": "Check the filters above", - "close": "Close", - "confirm": "Confirm", - "confirmDeletingVisitTextWithStartAndEndDate": "Are you sure you want to delete {{visit}} which started {{visitStartDate}} and ended {{visitEndDate}}?", - "confirmModifyingVisitDateToAccomodateEncounter": "The encounter date falls outside the designated visit date range. Would you like to modify the visit date to accommodate the new encounter date?", - "currentVisit": "Current visit", - "date": "Date", - "dateAndTime": "Date & time", - "dateOfDeath": "Date of death", - "deathDateRequired": "Please select the date of death", - "delete": "Delete", - "deleteEncounter": "Delete encounter", - "deleteEncounterConfirmationText": "Are you sure you want to delete this encounter? This action can't be undone.", - "deleteThisEncounter": "Delete this encounter", - "deleteVisit": "Delete visit", - "deleteVisitDialogHeader": "Are you sure you want to delete visit?", - "deletingVisit": "Deleting visit", - "deletingVisitWillDeleteEncounters": "Deleting this visit will delete all associated encounters.", - "diagnoses": "Diagnoses", - "discard": "Discard", + "addAPastVisit": "Adicionar uma visita anterior", + "addPastVisit": "Adicionar visita anterior", + "addPastVisitText": "Você pode adicionar uma nova visita anterior ou actualizar uma antiga. Escolha uma das opções abaixo para continuar.", + "all": "Todos", + "allEncounters": "Todas consultas", + "appointmentCheckedIn": "Consulta marcada Check-in", + "appointmentMarkedChecked": "Consulta marcada como Check-in", + "cancel": "Cancelar", + "cancelActiveVisitConfirmation": "Tem certeza de que deseja cancelar esta visita activa?", + "cancellingVisit": "Cancelando visita", + "cancelVisit": "Cancelar visita", + "cancelVisitExplainerMessage": "Ao cancelar esta visita irá apagar as suas consultas associadas.", + "causeOfDeath": "Causa de óbito", + "causeOfDeath_lower": "conceitos de causa de óbito configurados no sistema", + "causeOfDeathIsRequired": "Por favor selecione a causa de óbito", + "checkFilters": "Verifique os filtros acima", + "close": "Fechar", + "confirm": "Confirmar", + "confirmDeletingVisitTextWithStartAndEndDate": "Tem certeza de que deseja excluir {{visit}} que iniciou em {{visitStartDate}} e terminou em {{visitEndDate}}?", + "confirmModifyingVisitDateToAccomodateEncounter": "A data de consulta está fora do intervalo de datas associada a visita. Gostaria de modificar a data da visita para acomodar a nova data da consulta?", + "currentVisit": "Visita actual", + "date": "Data", + "dateAndTime": "Data e hora", + "dateOfDeath": "Data de óbito", + "deathDateRequired": "Por favor selecione a data de óbito", + "delete": "Apagar", + "deleteEncounter": "Apagar consulta", + "deleteEncounterConfirmationText": "Tem certeza de que deseja apagar esta consulta? Esta ação não pode ser desfeita.", + "deleteThisEncounter": "Apagar esta consulta", + "deleteVisit": "Apagar visita", + "deleteVisitDialogHeader": "Tem certeza de que deseja apagar esta visita?", + "deletingVisit": "Apagando visita", + "deletingVisitWillDeleteEncounters": "Apagando esta visita irá apagar todas as consultas associadas.", + "diagnoses": "Diagnósticos", + "discard": "Descartar", "dose": "Dose", - "editPastVisit": "Edit past visit", - "editThisEncounter": "Edit this encounter", - "editThisVisit": "Edit this visit", - "editVisitDetails": "Edit visit details", - "emptyStateText": "There are no {{displayText}} to display for this patient", - "encounterDeleted": "Encounter deleted", - "encounters": "Encounters", - "encounters__lower": "encounters", - "encounters_title": "Encounters", - "encounterType": "Encounter type", - "end": "End", - "endActiveVisitConfirmation": "Are you sure you want to end this active visit?", - "endDate": "End date", - "endDate_title": "End date", - "endVisit": "End visit", - "endVisit_title": "End Visit", - "endVisitExplainerMessage": "Ending this visit means that you will no longer be able to add encounters to it. If you need to add an encounter, you can create a new visit for this patient or edit a past one.", - "enterNonCodedCauseOfDeath": "Enter non-coded cause of death", - "error": "Error", - "errorCancellingVisit": "Error cancelling active visit", - "errorCopy": "Sorry, there was a problem displaying this information. You can try to reload this page, or contact the site administrator and quote the error code above.", - "errorCreatingVisitAttribute": "Could not delete {{attributeName}} attribute", - "errorDeletingVisit": "Error deleting visit", - "errorDeletingVisitAttribute": "Could not delete {{attributeName}} attribute", - "errorEndingVisit": "Error ending visit", - "errorMarkingPatientAlive": "Error marking patient alive", - "errorMarkingPatientDeceased": "Error marking patient deceased", - "errorOccuredDeletingVisit": "An error occured when deleting visit", - "errorUpdatingVisitAttribute": "Could not update {{attributeName}} attribute", - "errorUpdatingVisitDetails": "Error updating visit details", - "errorWhenRestoringVisit": "Error occured when restoring {{visit}}", - "failedDeleting": "couldn't be deleted", - "failedToLoadCurrentVisit": "Failed loading current visit", - "fieldRequired": "This field is required", - "filterByEncounterType": "Filter by encounter type", - "form": "Form name", - "futureStartTime": "Visit start time cannot be in the future", - "goToThisEncounter": "Go to this encounter", - "indication": "Indication", - "invalidTimeFormat": "Invalid time format", - "invalidVisitStartDate": "Start date needs to be on or before {{firstEncounterDatetime}}", - "invalidVisitStopDate": "Visit stop date time cannot be on or before visit start date time", - "loading": "Loading", - "loadingVisit": "Loading current visit...", - "loadMore": "Load more", - "location": "Location", - "markAliveSuccessfully": "Patient marked alive succesfully", - "markDeceasedWarning": "Marking the patient as deceased will end any active visits for this patient", - "markPatientAlive": "Mark patient alive", - "markPatientAliveConfirmation": "Are you sure you want to mark this patient alive?", - "markPatientDeceased": "Mark patient deceased", - "medications": "Medications", - "medications__lower": "medications", - "missingVisitType": "Missing visit type", - "modifyVisitDate": "Modify visit date", - "movePatient": "Move patient", - "movePatientToNextService": "Move patient to next service", - "name": "Name", - "no": "No", - "noActiveVisit": "No Active Visit", - "noActiveVisitMessage": "active visit", - "noActiveVisitNoRDEText": "You can't add data to the patient chart without an active visit. Would you like to start a new visit?", - "noActiveVisitText": "You can't add data to the patient chart without an active visit. Choose from one of the options below to continue.", - "noDiagnosesFound": "No diagnoses found", - "noEncountersFound": "No encounters found", - "noEncountersToDisplay": "No encounters to display", - "noMatchingCodedCausesOfDeath": "No matching coded causes of death", - "nonCodedCauseOfDeath": "Non-coded cause of death", - "nonCodedCauseOfDeathRequired": "Please enter the non-coded cause of death", - "noObservationsFound": "No observations found", - "notes": "Notes", - "notes__lower": "notes", - "noVisitTypesToDisplay": "No visit types to display", - "optional": "optional", - "orderDurationAndUnit": "for {{duration}} {{durationUnit}}", - "orderIndefiniteDuration": "Indefinite duration", + "editPastVisit": "Editar visita anterior", + "editThisEncounter": "Editar esta consulta", + "editThisVisit": "Editar esta visita", + "editVisitDetails": "Editar detalhes da visita", + "emptyStateText": "Não há {{displayText}} para mostrar para este utente", + "encounterDeleted": "Consulta eliminada", + "encounters": "Consultas", + "encounters__lower": "consultas", + "encounters_title": "Consultas", + "encounterType": "Tipo de consulta", + "end": "E", + "endActiveVisitConfirmation": "Tem certeza de que deseja terminar esta visita activa?", + "endDate": "Data de fim", + "endDate_title": "Data de fim", + "endVisit": "Terminar visita", + "endVisit_title": "Terminar Visita", + "endVisitExplainerMessage": "Ao terminar esta visita significa que você não poderá mais adicionar consultas a ela. Se precisar adicionar uma consulta, você pode criar uma nova visita para este utente ou editar uma visita anterior.", + "enterNonCodedCauseOfDeath": "Insira a causa de óbito não codificada", + "error": "Erro", + "errorCancellingVisit": "Erro ao cancelar visita activa", + "errorCopy": "Desculpe, ocorreu um problema ao visualizar essas informações. Você pode tentar recarregar esta página ou entrar em contato com o administrador do sistema providenciando o código de erro acima.", + "errorCreatingVisitAttribute": "Não foi possível apagar o atributo {{attributeName}}", + "errorDeletingVisit": "Erro ao apagar visita", + "errorDeletingVisitAttribute": "Não foi possível apagar o atributo {{attributeName}}", + "errorEndingVisit": "Erro ao terminar visita", + "errorMarkingPatientAlive": "Erro ao marcar utente como vivo", + "errorMarkingPatientDeceased": "Erro ao marcar utente como óbito", + "errorOccuredDeletingVisit": "Ocorreu um erro ao apagar a visita", + "errorUpdatingVisitAttribute": "Não foi possível actualizar o atributo {{attributeName}}", + "errorUpdatingVisitDetails": "Erro ao actualizar detalhes da visita", + "errorWhenRestoringVisit": "Ocorreu um erro ao restaurar {{visit}}", + "failedDeleting": "Não pode ser apagado", + "failedToLoadCurrentVisit": "Falha ao carregar a visita actual", + "fieldRequired": "Este campo é obrigatório", + "filterByEncounterType": "Filtrar por tipo de consulta", + "form": "Nome do formulário", + "futureStartTime": "Data de início da visita não pode ser no futuro ", + "goToThisEncounter": "Ir para esta consulta", + "indication": "Indicação", + "invalidTimeFormat": "Formato de hora inválido", + "invalidVisitStartDate": "Data de inicio deve ser igual ou antes de {{firstEncounterDatetime}}", + "invalidVisitStopDate": "A data de fim da visita não pode ser igual ou anterior à data de início da visita", + "loading": "Carregando", + "loadingVisit": "Carregando visita actual...", + "loadMore": "Carregar mais", + "location": "Local", + "markAliveSuccessfully": "Utente marcado vivo com sucesso", + "markDeceasedWarning": "Marcar o utente como óbito encerrará todas as visitas activas", + "markPatientAlive": "Marcar utente vivo", + "markPatientAliveConfirmation": "Tem certeza de que deseja marcar este utente como vivo?", + "markPatientDeceased": "Marcar paciente como obitou", + "medications": "Medicamentos", + "medications__lower": "medicamentos", + "missingVisitType": "Falta o tipo de visita", + "modifyVisitDate": "Modifcar data de visita", + "movePatient": "Mover utente", + "movePatientToNextService": "Mover o utente para próximo serviço?", + "name": "Nome", + "no": "Não", + "noActiveVisit": "Sem Visita Ativa", + "noActiveVisitMessage": "visita activa", + "noActiveVisitNoRDEText": "Você não pode adicionar dados ao prontuário do utente sem uma visita activa. Gostaria de iniciar uma nova visita?", + "noActiveVisitText": "Você não pode adicionar dados ao prontuário do utente sem uma visita activa. Escolha uma das opções abaixo para continuar.", + "noDiagnosesFound": "Nenhum diagnóstico encontrado", + "noEncountersFound": "Nenhuma consulta encontrada", + "noEncountersToDisplay": "Nenhuma consulta para mostrar", + "noMatchingCodedCausesOfDeath": "Nenhuma causa de óbito codificada encontrada", + "nonCodedCauseOfDeath": "Causa de óbito não codificada", + "nonCodedCauseOfDeathRequired": "Por favor, insira a causa de óbito não codificada", + "noObservationsFound": "Nenhuma observação encontrada", + "notes": "Notas", + "notes__lower": "notas", + "noVisitTypesToDisplay": "Nenhum tipo de visita para mostrar", + "optional": "opcional", + "orderDurationAndUnit": "para {{duration}} {{durationUnit}}", + "orderIndefiniteDuration": "Duração indefinida", "paginationItemsCount_one": "{{pageItemsCount}} / {{count}} item", - "paginationItemsCount_other": "{{pageItemsCount}} / {{count}} items", - "paginationPageText_one": "of {{count}} page", - "paginationPageText_other": "of {{count}} pages", - "partOfFormDidntLoad": "Part of the form did not load", - "pastVisitErrorText": "Past visit error", - "pastVisits": "Past visits", - "Patient Summary": "Patient summary", - "program": "Program", - "provider": "Provider", - "quantity": "Quantity", - "queueAddedSuccessfully": "Patient has been added to the queue successfully.", - "queueEntryError": "Error adding patient to the queue", - "recommended": "Recommended", - "record": "Record", - "refills": "Refills", - "refreshToTryAgain": "Please refresh to try again", - "required": "Required", - "retrospectiveEntry": "Retrospective entry", - "saveAndClose": "Save and close", - "saving": "Saving", - "searchForAVisitType": "Search for a visit type", - "searchForCauseOfDeath": "Search for a cause of death", - "searchThisList": "Search this list", - "seeAll": "See all", - "selectAnOption": "Select an option", - "selectLocation": "Select a location", - "selectProgramType": "Select program type", - "selectVisitType": "Please select a visit type", - "start": "Start", - "startAVisit": "Start a visit", - "startDate": "Start date", - "startingVisit": "Starting visit", - "startNewVisit": "Start new visit", - "startVisit": "Start visit", - "startVisitError": "Error starting visit", - "successfullyDeleted": "successfully deleted", - "tests": "Tests", - "time": "Time", - "timeFormat ": "Time Format", - "type": "Type", - "undo": "Undo", - "updateError": "Error updating upcoming appointment", - "updateVisit": "Update visit", - "updatingVisit": "Updating visit", - "visit": "Visit", - "visitAttributes": "Visit attributes", - "visitCancelled": "Visit cancelled", - "visitCancelSuccessMessage": "Active {{visit}} cancelled successfully", - "visitDeleted": "{{visit}} deleted", - "visitDeletedSuccessfully": "{{visit}} deleted successfully", - "visitDetailsUpdated": "Visit details updated", - "visitDetailsUpdatedSuccessfully": "{{visit}} updated successfully", - "visitEnded": "Visit ended", - "visitEndSuccessfully": "Ended current visit successfully", - "visitLocation": "Visit location", - "visitNotRestored": "Visit couldn't be restored", - "visitRestored": "Visit restored", - "visitRestoredSuccessfully": "{{visit}} restored successfully", - "visits": "visits", - "Visits": "Visits", - "visitStartDatetime": "Visit start date and time", - "visitStarted": "Visit started", - "visitStartedSuccessfully": "{{visit}} started successfully", - "visitStopDateMustBeAfterMostRecentEncounter": "Stop date needs to be on or after {{lastEncounterDatetime}}", - "visitStopDatetime": "Visit stop date and time", - "visitSummaries": "Visit summaries", - "visitType": "Visit type", - "visitType_title": "Visit Type", - "visitTypeRequired": "Visit type is required", - "warning": "Warning", - "yes": "Yes" + "paginationItemsCount_other": "{{pageItemsCount}} / {{count}} itens", + "paginationPageText_one": "de {{count}} página", + "paginationPageText_other": "de {{count}} páginas", + "partOfFormDidntLoad": "Parte do formulário não foi carregado", + "pastVisitErrorText": "Erro de visita anterior", + "pastVisits": "Visitas anteriores", + "Patient Summary": "Sumário do utente", + "program": "Programa", + "provider": "Provedor", + "quantity": "Quantidade", + "queueAddedSuccessfully": "O paciente foi adicionado à fila com sucesso.", + "queueEntryError": "Erro ao adicionar o utente na fila", + "recommended": "Recomendado", + "record": "Registo", + "refills": "Repor", + "refreshToTryAgain": "Por favor, actualize para tentar novamente", + "required": "Obrigatório", + "retrospectiveEntry": "Digitação retroespectiva", + "saveAndClose": "Salvar e fechar", + "saving": "Gravando", + "searchForAVisitType": "Pesquise um tipo de visita", + "searchForCauseOfDeath": "Pesquise a causa de óbito", + "searchThisList": "Pesquisar esta lista", + "seeAll": "Ver tudo", + "selectAnOption": "Selecione uma opção", + "selectLocation": "Selecione um local", + "selectProgramType": "Selecione tipo de programa", + "selectVisitType": "Favor, selecionar o tipo de visita", + "start": "Iniciar", + "startAVisit": "Iniciar uma visita", + "startDate": "Data inicial", + "startingVisit": "Iniciando visita", + "startNewVisit": "Iniciar nova visita", + "startVisit": "Iniciar visita", + "startVisitError": "Erro ao iniciar visita", + "successfullyDeleted": "apagado com sucesso", + "tests": "Testes", + "time": "Tempo", + "timeFormat ": "Formato de hora", + "type": "Tipo", + "undo": "Desfazer", + "updateError": "Erro ao actualizar a próxima consulta marcada", + "updateVisit": "Actualizar visita", + "updatingVisit": "Actualizando visita", + "visit": "Visita", + "visitAttributes": "Atributos da visita", + "visitCancelled": "Visita cancelada", + "visitCancelSuccessMessage": " {{visit}} activa cancelada com sucesso", + "visitDeleted": "{{visit}} apagada", + "visitDeletedSuccessfully": "{{visit}} apagada com sucesso", + "visitDetailsUpdated": "Detalhes da visita actualizados", + "visitDetailsUpdatedSuccessfully": "{{visit}} actualizado com sucesso", + "visitEnded": "Visita terminada", + "visitEndSuccessfully": "Visita actual terminada com sucesso", + "visitLocation": "Local da Visita", + "visitNotRestored": "Visita não pode ser restaurada", + "visitRestored": "Visita restaurada", + "visitRestoredSuccessfully": "{{visit}} restaurada com sucesso", + "visits": "visitas", + "Visits": "Visitas", + "visitStartDatetime": "Data e hora de início da visita", + "visitStarted": "Visita iniciada", + "visitStartedSuccessfully": "{{visit}} iniciada com sucesso", + "visitStopDateMustBeAfterMostRecentEncounter": "A data de fim precisa ser igual ou posterior a {{lastEncounterDatetime}}", + "visitStopDatetime": "Data e hora de fim da visita", + "visitSummaries": "Resumos de visitas", + "visitType": "Tipo de visita", + "visitType_title": "Tipo de Visita", + "visitTypeRequired": "Tipo de visita é obrigatório", + "warning": "Aviso", + "yes": "Sim" } diff --git a/packages/esm-patient-chart-app/translations/vi.json b/packages/esm-patient-chart-app/translations/vi.json index 7a7aeac73..98cb01648 100644 --- a/packages/esm-patient-chart-app/translations/vi.json +++ b/packages/esm-patient-chart-app/translations/vi.json @@ -31,156 +31,156 @@ "deleteVisit": "Xóa lượt khám", "deleteVisitDialogHeader": "Bạn có chắc chắn muốn xóa lượt khám không?", "deletingVisit": "Đang xóa lượt khám", - "deletingVisitWillDeleteEncounters": "Deleting this visit will delete all associated encounters.", + "deletingVisitWillDeleteEncounters": "Xóa chuyến thăm này sẽ xóa tất cả các cuộc gặp gỡ có liên quan.", "diagnoses": "Chẩn đoán", "discard": "Hủy bỏ", "dose": "Liều lượng", - "editPastVisit": "Edit past visit", - "editThisEncounter": "Edit this encounter", - "editThisVisit": "Edit this visit", - "editVisitDetails": "Edit visit details", - "emptyStateText": "There are no {{displayText}} to display for this patient", - "encounterDeleted": "Encounter deleted", + "editPastVisit": "Chỉnh sửa lượt khám trước đó", + "editThisEncounter": "Chỉnh sửa cuộc gặp gỡ này", + "editThisVisit": "Chỉnh sửa lượt khám này", + "editVisitDetails": "Chỉnh sửa chi tiết lượt khám", + "emptyStateText": "Không có {{displayText}} để hiển thị cho bệnh nhân này", + "encounterDeleted": "Cuộc gặp gỡ đã xóa", "encounters": "Cuộc gặp", "encounters__lower": "cuộc gặp", "encounters_title": "Cuộc gặp", - "encounterType": "Encounter type", + "encounterType": "Loại gặp gỡ", "end": "Kết thúc", - "endActiveVisitConfirmation": "Are you sure you want to end this active visit?", - "endDate": "End date", - "endDate_title": "End date", - "endVisit": "End visit", - "endVisit_title": "End Visit", + "endActiveVisitConfirmation": "Bạn có chắc chắn muốn kết thúc lượt khám hiện tại này không?", + "endDate": "Ngày kết thúc", + "endDate_title": "Ngày kết thúc", + "endVisit": "Kết thúc lượt khám", + "endVisit_title": "Kết thúc lượt khám", "endVisitExplainerMessage": "Kết thúc lượt khám này có nghĩa là bạn sẽ không thể thêm cuộc gặp gỡ vào đó nữa. Nếu bạn cần thêm một cuộc gặp gỡ, bạn có thể tạo một lượt thăm khám mới cho bệnh nhân này hoặc chỉnh sửa một lượt thăm khám trước đó.", - "enterNonCodedCauseOfDeath": "Enter non-coded cause of death", + "enterNonCodedCauseOfDeath": "Nhập nguyên nhân tử vong không được mã hóa", "error": "Lỗi", - "errorCancellingVisit": "Error cancelling active visit", + "errorCancellingVisit": "Lỗi khi hủy chuyến thăm đang hoạt động", "errorCopy": "Xin lỗi, đã xảy ra sự cố khi hiển thị thông tin này. Bạn có thể thử tải lại trang này hoặc liên hệ với quản trị viên trang web và trích dẫn mã lỗi ở trên.", - "errorCreatingVisitAttribute": "Could not delete {{attributeName}} attribute", - "errorDeletingVisit": "Error deleting visit", - "errorDeletingVisitAttribute": "Could not delete {{attributeName}} attribute", - "errorEndingVisit": "Error ending visit", - "errorMarkingPatientAlive": "Error marking patient alive", - "errorMarkingPatientDeceased": "Error marking patient deceased", - "errorOccuredDeletingVisit": "An error occured when deleting visit", - "errorUpdatingVisitAttribute": "Could not update {{attributeName}} attribute", - "errorUpdatingVisitDetails": "Error updating visit details", - "errorWhenRestoringVisit": "Error occured when restoring {{visit}}", - "failedDeleting": "couldn't be deleted", - "failedToLoadCurrentVisit": "Failed loading current visit", - "fieldRequired": "This field is required", - "filterByEncounterType": "Filter by encounter type", - "form": "Form name", - "futureStartTime": "Visit start time cannot be in the future", - "goToThisEncounter": "Go to this encounter", + "errorCreatingVisitAttribute": "Không thể xóa thuộc tính {{attributeName}}", + "errorDeletingVisit": "Lỗi xóa lượt khám", + "errorDeletingVisitAttribute": "Không thể xóa thuộc tính {{attributeName}}", + "errorEndingVisit": "Lỗi kết thúc lượt truy cập", + "errorMarkingPatientAlive": "Lỗi đánh dấu bệnh nhân còn sống", + "errorMarkingPatientDeceased": "Lỗi đánh dấu bệnh nhân đã chết", + "errorOccuredDeletingVisit": "Đã xảy ra lỗi khi xóa lượt khám", + "errorUpdatingVisitAttribute": "Không thể cập nhật thuộc tính {{attributeName}}", + "errorUpdatingVisitDetails": "Lỗi cập nhật chi tiết lượt khám", + "errorWhenRestoringVisit": "Đã xảy ra lỗi khi khôi phục {{visit}}", + "failedDeleting": "không thể xóa được", + "failedToLoadCurrentVisit": "Không tải được lượt khám hiện tại", + "fieldRequired": "Trường này là bắt buộc", + "filterByEncounterType": "Lọc theo loại cuộc gặp gỡ", + "form": "Tên biểu mẫu", + "futureStartTime": "Thời gian bắt đầu khám không thể ở trong tương lai", + "goToThisEncounter": "Đi đến cuộc gặp gỡ này", "indication": "Chỉ định", - "invalidTimeFormat": "Invalid time format", - "invalidVisitStartDate": "Start date needs to be on or before {{firstEncounterDatetime}}", - "invalidVisitStopDate": "Visit stop date time cannot be on or before visit start date time", + "invalidTimeFormat": "Định dạng thời gian không hợp lệ", + "invalidVisitStartDate": "Ngày bắt đầu phải vào hoặc trước {{firstEncounterDatetime}}", + "invalidVisitStopDate": "Ngày giờ kết thúc chuyến thăm khám không được trùng hoặc trước ngày giờ bắt đầu chuyến thăm khám", "loading": "Đang tải", - "loadingVisit": "Loading current visit...", - "loadMore": "Load more", + "loadingVisit": "Đang tải lượt truy cập hiện tại...", + "loadMore": "Tải thêm", "location": "Vị trí", - "markAliveSuccessfully": "Patient marked alive succesfully", - "markDeceasedWarning": "Marking the patient as deceased will end any active visits for this patient", - "markPatientAlive": "Mark patient alive", - "markPatientAliveConfirmation": "Are you sure you want to mark this patient alive?", - "markPatientDeceased": "Mark patient deceased", + "markAliveSuccessfully": "Bệnh nhân được đánh dấu là còn sống thành công", + "markDeceasedWarning": "Đánh dấu bệnh nhân là đã chết sẽ kết thúc mọi cuộc thăm khám đang hoạt động của bệnh nhân này", + "markPatientAlive": "Đánh dấu bệnh nhân còn sống", + "markPatientAliveConfirmation": "Bạn có chắc chắn muốn đánh dấu bệnh nhân này còn sống không?", + "markPatientDeceased": "Đánh dấu bệnh nhân đã chết", "medications": "Thuốc", "medications__lower": "thuốc", - "missingVisitType": "Missing visit type", - "modifyVisitDate": "Modify visit date", - "movePatient": "Move patient", - "movePatientToNextService": "Move patient to next service", + "missingVisitType": "Loại chuyến thăm khám bị thiếu", + "modifyVisitDate": "Sửa đổi ngày thăm khám", + "movePatient": "Di chuyển bệnh nhân", + "movePatientToNextService": "Chuyển bệnh nhân đến dịch vụ tiếp theo", "name": "Tên", "no": "Không", - "noActiveVisit": "No Active Visit", - "noActiveVisitMessage": "active visit", - "noActiveVisitNoRDEText": "You can't add data to the patient chart without an active visit. Would you like to start a new visit?", - "noActiveVisitText": "You can't add data to the patient chart without an active visit. Choose from one of the options below to continue.", - "noDiagnosesFound": "No diagnoses found", - "noEncountersFound": "No encounters found", - "noEncountersToDisplay": "No encounters to display", - "noMatchingCodedCausesOfDeath": "No matching coded causes of death", - "nonCodedCauseOfDeath": "Non-coded cause of death", - "nonCodedCauseOfDeathRequired": "Please enter the non-coded cause of death", - "noObservationsFound": "No observations found", + "noActiveVisit": "Không có chuyến thăm khám nào hoạt động", + "noActiveVisitMessage": "lượt khám hoạt động", + "noActiveVisitNoRDEText": "Bạn không thể thêm dữ liệu vào biểu đồ bệnh nhân nếu không có chuyến thăm khám đang hoạt động. Bạn có muốn bắt đầu một chuyến thăm khám mới không?", + "noActiveVisitText": "Bạn không thể thêm dữ liệu vào biểu đồ bệnh nhân nếu không có chuyến thăm khám đang hoạt động. Chọn một trong các tùy chọn bên dưới để tiếp tục.", + "noDiagnosesFound": "Không tìm thấy chẩn đoán", + "noEncountersFound": "Không tìm thấy cuộc gặp gỡ nào", + "noEncountersToDisplay": "Không có cuộc gặp gỡ nào để hiển thị", + "noMatchingCodedCausesOfDeath": "Không có nguyên nhân tử vong được mã hóa phù hợp", + "nonCodedCauseOfDeath": "Nguyên nhân tử vong không được mã hóa", + "nonCodedCauseOfDeathRequired": "Vui lòng nhập nguyên nhân tử vong không được mã hóa", + "noObservationsFound": "Không tìm thấy quan sát nào", "notes": "Ghi chú", "notes__lower": "ghi chú", - "noVisitTypesToDisplay": "No visit types to display", + "noVisitTypesToDisplay": "Không có loại thăm khám nào để hiển thị", "optional": "tùy chọn", - "orderDurationAndUnit": "for {{duration}} {{durationUnit}}", - "orderIndefiniteDuration": "Indefinite duration", - "paginationItemsCount_one": "{{pageItemsCount}} / {{count}} item", - "paginationItemsCount_other": "{{pageItemsCount}} / {{count}} items", - "paginationPageText_one": "of {{count}} page", - "paginationPageText_other": "of {{count}} pages", - "partOfFormDidntLoad": "Part of the form did not load", - "pastVisitErrorText": "Past visit error", - "pastVisits": "Past visits", - "Patient Summary": "Patient summary", + "orderDurationAndUnit": "cho {{duration}} {{durationUnit}}", + "orderIndefiniteDuration": "Thời hạn không xác định", + "paginationItemsCount_one": "{{pageItemsCount}} / {{count}} mục", + "paginationItemsCount_other": "{{pageItemsCount}} / {{count}} mục", + "paginationPageText_one": "của {{count}} trang", + "paginationPageText_other": "của {{count}} trang", + "partOfFormDidntLoad": "Một phần của biểu mẫu không tải được", + "pastVisitErrorText": "Lỗi lượt khám trước đây", + "pastVisits": "Các chuyến thăm khám trước đây", + "Patient Summary": "Tóm tắt bệnh nhân", "program": "Chương trình", "provider": "Nhà cung cấp", "quantity": "Số lượng", - "queueAddedSuccessfully": "Patient has been added to the queue successfully.", - "queueEntryError": "Error adding patient to the queue", + "queueAddedSuccessfully": "Bệnh nhân đã được thêm vào hàng đợi thành công.", + "queueEntryError": "Lỗi khi thêm bệnh nhân vào hàng đợi", "recommended": "Gợi ý", "record": "Ghi", "refills": "Nạp lại", - "refreshToTryAgain": "Please refresh to try again", + "refreshToTryAgain": "Vui lòng làm mới để thử lại", "required": "Yêu cầu", - "retrospectiveEntry": "Retrospective entry", - "saveAndClose": "Save and close", + "retrospectiveEntry": "Mục nhập hồi tưởng", + "saveAndClose": "Lưu và đóng", "saving": "Đang lưu", - "searchForAVisitType": "Search for a visit type", - "searchForCauseOfDeath": "Search for a cause of death", - "searchThisList": "Search this list", - "seeAll": "See all", - "selectAnOption": "Select an option", - "selectLocation": "Select a location", - "selectProgramType": "Select program type", - "selectVisitType": "Please select a visit type", + "searchForAVisitType": "Tìm kiếm loại chuyến thăm khám", + "searchForCauseOfDeath": "Tìm kiếm nguyên nhân tử vong", + "searchThisList": "Tìm kiếm danh sách này", + "seeAll": "Xem tất cả", + "selectAnOption": "Chọn một tùy chọn", + "selectLocation": "Chọn một vị trí", + "selectProgramType": "Chọn loại chương trình", + "selectVisitType": "Vui lòng chọn loại thăm khám", "start": "Bắt đầu", - "startAVisit": "Start a visit", - "startDate": "Start date", - "startingVisit": "Starting visit", - "startNewVisit": "Start new visit", - "startVisit": "Start visit", - "startVisitError": "Error starting visit", - "successfullyDeleted": "successfully deleted", + "startAVisit": "Bắt đầu một lượt thăm khám", + "startDate": "Ngày bắt đầu", + "startingVisit": "Bắt đầu khám", + "startNewVisit": "Bắt đầu lượt khám mới", + "startVisit": "Bắt đầu lượt khám", + "startVisitError": "Lỗi khi bắt đầu lượt khám", + "successfullyDeleted": "đã xóa thành công", "tests": "Kiểm tra", "time": "Thời gian", - "timeFormat ": "Time Format", + "timeFormat ": "Định dạng thời gian", "type": "Kiểu", "undo": "Hoàn tác", - "updateError": "Error updating upcoming appointment", - "updateVisit": "Update visit", - "updatingVisit": "Updating visit", + "updateError": "Lỗi khi cập nhật cuộc hẹn sắp tới", + "updateVisit": "Cập nhật lượt thăm khám", + "updatingVisit": "Đang cập nhật lượt thăm khám", "visit": "Lượt khám", - "visitAttributes": "Visit attributes", - "visitCancelled": "Visit cancelled", - "visitCancelSuccessMessage": "Active {{visit}} cancelled successfully", - "visitDeleted": "{{visit}} deleted", - "visitDeletedSuccessfully": "{{visit}} deleted successfully", - "visitDetailsUpdated": "Visit details updated", - "visitDetailsUpdatedSuccessfully": "{{visit}} updated successfully", - "visitEnded": "Visit ended", - "visitEndSuccessfully": "Ended current visit successfully", - "visitLocation": "Visit location", - "visitNotRestored": "Visit couldn't be restored", - "visitRestored": "Visit restored", - "visitRestoredSuccessfully": "{{visit}} restored successfully", + "visitAttributes": "Thuộc tính thăm khám", + "visitCancelled": "Hủy lượt khám", + "visitCancelSuccessMessage": "{{visit}} đang hoạt động đã bị hủy thành công", + "visitDeleted": "{{ghé thăm}} đã bị xóa", + "visitDeletedSuccessfully": "{{visit}} đã xóa thành công", + "visitDetailsUpdated": "Đã cập nhật chi tiết chuyến thăm khám", + "visitDetailsUpdatedSuccessfully": "{{visit}} đã cập nhật thành công", + "visitEnded": "Chuyến thăm khám đã kết thúc", + "visitEndSuccessfully": "Đã kết thúc chuyến thăm khám hiện tại thành công", + "visitLocation": "Địa điểm khám", + "visitNotRestored": "Không thể khôi phục lại chuyến thăm khám", + "visitRestored": "Đã khôi phục lượt khám", + "visitRestoredSuccessfully": "{{visit}} đã được khôi phục thành công", "visits": "lượt khám", "Visits": "Lượt khám", - "visitStartDatetime": "Visit start date and time", - "visitStarted": "Visit started", - "visitStartedSuccessfully": "{{visit}} started successfully", - "visitStopDateMustBeAfterMostRecentEncounter": "Stop date needs to be on or after {{lastEncounterDatetime}}", - "visitStopDatetime": "Visit stop date and time", - "visitSummaries": "Visit summaries", - "visitType": "Visit type", - "visitType_title": "Visit Type", - "visitTypeRequired": "Visit type is required", + "visitStartDatetime": "Ngày và giờ bắt đầu thăm khám", + "visitStarted": "Đã bắt đầu chuyến thăm khám", + "visitStartedSuccessfully": "{{visit}} đã bắt đầu thành công", + "visitStopDateMustBeAfterMostRecentEncounter": "Ngày dừng phải vào hoặc sau {{lastEncounterDatetime}}", + "visitStopDatetime": "Ngày và giờ dừng thăm khám", + "visitSummaries": "Tóm tắt lượt thăm khám", + "visitType": "Loại thăm khám", + "visitType_title": "Loại thăm khám", + "visitTypeRequired": "Loại thăm khám là bắt buộc", "warning": "Cảnh báo", "yes": "Có" } diff --git a/packages/esm-patient-common-lib/src/get-patient-uuid-from-url.ts b/packages/esm-patient-common-lib/src/get-patient-uuid-from-url.ts index 12c1357f8..be4c1399b 100644 --- a/packages/esm-patient-common-lib/src/get-patient-uuid-from-url.ts +++ b/packages/esm-patient-common-lib/src/get-patient-uuid-from-url.ts @@ -1,4 +1,11 @@ +import { getPatientUuidFromStore } from './store/patient-chart-store'; + +/** + * @deprecated This function is now replaced with `getPatientUuidFromStore`. This function will be removed in upcoming releases. + * @returns {string} patientUuid + */ export function getPatientUuidFromUrl(): string { const match = /\/patient\/([a-zA-Z0-9\-]+)\/?/.exec(location.pathname); - return match && match[1]; + const patientUuidFromUrl = match && match[1]; + return patientUuidFromUrl || getPatientUuidFromStore(); } diff --git a/packages/esm-patient-common-lib/src/index.ts b/packages/esm-patient-common-lib/src/index.ts index 76537159b..e35a3031c 100644 --- a/packages/esm-patient-common-lib/src/index.ts +++ b/packages/esm-patient-common-lib/src/index.ts @@ -20,3 +20,4 @@ export * from './types'; export * from './useAllowedFileExtensions'; export * from './useSystemVisitSetting'; export * from './workspaces'; +export * from './store/patient-chart-store'; diff --git a/packages/esm-patient-common-lib/src/orders/postOrders.ts b/packages/esm-patient-common-lib/src/orders/postOrders.ts index 2bbe92944..992886176 100644 --- a/packages/esm-patient-common-lib/src/orders/postOrders.ts +++ b/packages/esm-patient-common-lib/src/orders/postOrders.ts @@ -1,5 +1,5 @@ import { openmrsFetch, type OpenmrsResource, parseDate, restBaseUrl, type Visit } from '@openmrs/esm-framework'; -import { getPatientUuidFromUrl } from '../get-patient-uuid-from-url'; +import { getPatientUuidFromStore } from '../store/patient-chart-store'; import { type OrderBasketStore, orderBasketStore } from './store'; import { type ExtractedOrderErrorObject, type OrderBasketItem, type OrderErrorObject, type OrderPost } from './types'; @@ -55,7 +55,7 @@ export async function postOrdersOnNewEncounter( } export async function postOrders(encounterUuid: string, abortController: AbortController) { - const patientUuid = getPatientUuidFromUrl(); + const patientUuid = getPatientUuidFromStore(); const { items, postDataPrepFunctions }: OrderBasketStore = orderBasketStore.getState(); const patientItems = items[patientUuid]; diff --git a/packages/esm-patient-common-lib/src/orders/useOrderBasket.ts b/packages/esm-patient-common-lib/src/orders/useOrderBasket.ts index 625afb2c7..843035e98 100644 --- a/packages/esm-patient-common-lib/src/orders/useOrderBasket.ts +++ b/packages/esm-patient-common-lib/src/orders/useOrderBasket.ts @@ -1,6 +1,6 @@ import { useStoreWithActions } from '@openmrs/esm-framework'; import type { OrderBasketItem, PostDataPrepFunction } from './types'; -import { getPatientUuidFromUrl } from '../get-patient-uuid-from-url'; +import { getPatientUuidFromStore } from '../store/patient-chart-store'; import { useEffect } from 'react'; import { type OrderBasketStore, orderBasketStore } from './store'; @@ -10,7 +10,7 @@ const orderBasketStoreActions = { grouping: string, value: Array | (() => Array), ) { - const patientUuid = getPatientUuidFromUrl(); + const patientUuid = getPatientUuidFromStore(); if (!Object.keys(state.postDataPrepFunctions).includes(grouping)) { console.warn(`Programming error: You must register a postDataPrepFunction for grouping ${grouping} `); } @@ -35,7 +35,7 @@ const orderBasketStoreActions = { }; function getOrderItems(items: OrderBasketStore['items'], grouping?: string | null): Array { - const patientUuid = getPatientUuidFromUrl(); + const patientUuid = getPatientUuidFromStore(); const patientItems = items?.[patientUuid] ?? {}; return grouping ? patientItems[grouping] ?? [] : Object.values(patientItems).flat(); } @@ -46,7 +46,7 @@ export interface ClearOrdersOptions { function clearOrders(options?: ClearOrdersOptions) { const exceptThoseMatchingFcn = options?.exceptThoseMatching ?? (() => false); - const patientUuid = getPatientUuidFromUrl(); + const patientUuid = getPatientUuidFromStore(); const items = orderBasketStore.getState().items; const patientItems = items[patientUuid] ?? {}; const newPatientItems = Object.fromEntries( diff --git a/packages/esm-patient-common-lib/src/store/patient-chart-store.ts b/packages/esm-patient-common-lib/src/store/patient-chart-store.ts new file mode 100644 index 000000000..1b9f401e1 --- /dev/null +++ b/packages/esm-patient-common-lib/src/store/patient-chart-store.ts @@ -0,0 +1,33 @@ +import { createGlobalStore, useStore } from '@openmrs/esm-framework'; + +export interface PatientChartStore { + patientUuid: string; +} + +const patientChartStoreName = 'patient-chart-global-store'; + +const patientChartStore = createGlobalStore(patientChartStoreName, { + patientUuid: '', +}); + +/** + * This function returns the patient chart store. + * + * The patient chart store is used to store all global variables used in the patient chart. + * In the recent requirements, patient chart is now not only bound with `/patient/{patientUuid}/` path. + */ +export function getPatientChartStore() { + return patientChartStore; +} + +export function usePatientChartStore() { + return useStore(patientChartStore); +} + +/** + * This function will get the patient UUID from either URL, or will look into the patient chart store. + * @returns {string} patientUuid + */ +export function getPatientUuidFromStore(): string { + return patientChartStore.getState()?.patientUuid; +} diff --git a/packages/esm-patient-common-lib/src/workspaces.ts b/packages/esm-patient-common-lib/src/workspaces.ts index c202a6363..50ffb1dfd 100644 --- a/packages/esm-patient-common-lib/src/workspaces.ts +++ b/packages/esm-patient-common-lib/src/workspaces.ts @@ -4,18 +4,19 @@ import { navigateAndLaunchWorkspace, usePatient, } from '@openmrs/esm-framework'; -import { getPatientUuidFromUrl } from './get-patient-uuid-from-url'; +import { getPatientUuidFromStore } from './store/patient-chart-store'; import { useSystemVisitSetting } from './useSystemVisitSetting'; import { useVisitOrOfflineVisit } from './offline/visit'; import { useCallback } from 'react'; import { launchStartVisitPrompt } from './launchStartVisitPrompt'; +import { usePatientChartStore } from './store/patient-chart-store'; export interface DefaultPatientWorkspaceProps extends DefaultWorkspaceProps { patientUuid: string; } export function launchPatientWorkspace(workspaceName: string, additionalProps?: object) { - const patientUuid = getPatientUuidFromUrl(); + const patientUuid = getPatientUuidFromStore(); launchWorkspace(workspaceName, { patientUuid: patientUuid, ...additionalProps, @@ -42,7 +43,7 @@ export function launchPatientChartWithWorkspaceOpen({ } export function useLaunchWorkspaceRequiringVisit(workspaceName: string) { - const { patientUuid } = usePatient(); + const { patientUuid } = usePatientChartStore(); const { systemVisitEnabled } = useSystemVisitSetting(); const { currentVisit } = useVisitOrOfflineVisit(patientUuid); diff --git a/packages/esm-patient-medications-app/src/add-drug-order/drug-order-form.component.tsx b/packages/esm-patient-medications-app/src/add-drug-order/drug-order-form.component.tsx index 3480dc3d4..3226682fb 100644 --- a/packages/esm-patient-medications-app/src/add-drug-order/drug-order-form.component.tsx +++ b/packages/esm-patient-medications-app/src/add-drug-order/drug-order-form.component.tsx @@ -51,6 +51,7 @@ import type { } from '../types'; import { useRequireOutpatientQuantity } from '../api'; import styles from './drug-order-form.scss'; +import { usePatientChartStore } from '@openmrs/esm-patient-common-lib'; export interface DrugOrderFormProps { initialOrderBasketItem: DrugOrderBasketItem; @@ -354,7 +355,8 @@ export function DrugOrderForm({ initialOrderBasketItem, onSave, onCancel, prompt }, []); const [showStickyMedicationHeader, setShowMedicationHeader] = useState(false); - const { patient, isLoading: isLoadingPatientDetails } = usePatient(); + const { patientUuid } = usePatientChartStore(); + const { patient, isLoading: isLoadingPatientDetails } = usePatient(patientUuid); const patientName = patient ? getPatientName(patient) : ''; const { maxDispenseDurationInDays } = useConfig(); diff --git a/packages/esm-patient-medications-app/src/add-drug-order/drug-search/order-basket-search-results.component.tsx b/packages/esm-patient-medications-app/src/add-drug-order/drug-search/order-basket-search-results.component.tsx index b0664dd89..7264d85b4 100644 --- a/packages/esm-patient-medications-app/src/add-drug-order/drug-search/order-basket-search-results.component.tsx +++ b/packages/esm-patient-medications-app/src/add-drug-order/drug-search/order-basket-search-results.component.tsx @@ -24,6 +24,7 @@ import { } from './drug-search.resource'; import type { DrugOrderBasketItem } from '../../types'; import styles from './order-basket-search-results.scss'; +import { usePatientChartStore } from '@openmrs/esm-patient-common-lib'; export interface OrderBasketSearchResultsProps { searchTerm: string; @@ -114,8 +115,8 @@ export default function OrderBasketSearchResults({ const DrugSearchResultItem: React.FC = ({ drug, openOrderForm }) => { const isTablet = useLayoutType() === 'tablet'; const { orders, setOrders } = useOrderBasket('medications', prepMedicationOrderPostData); - const patient = usePatient(); - const { data: activeOrders, isLoading: isLoadingActiveOrders } = usePatientOrders(patient.patientUuid); + const { patientUuid } = usePatientChartStore(); + const { data: activeOrders, isLoading: isLoadingActiveOrders } = usePatientOrders(patientUuid); const drugAlreadyInBasket = useMemo( () => orders?.some((order) => ordersEqual(order, getTemplateOrderBasketItem(drug))), [orders, drug], diff --git a/packages/esm-patient-medications-app/translations/am.json b/packages/esm-patient-medications-app/translations/am.json index 3e0e07ff7..2a200aea4 100644 --- a/packages/esm-patient-medications-app/translations/am.json +++ b/packages/esm-patient-medications-app/translations/am.json @@ -11,7 +11,7 @@ "directlyAddToBasket": "Add to basket", "discard": "Discard", "discontinue": "Discontinue", - "discontinuedDate": "Discontinued date", + "discontinued": "Discontinued", "dispensingInformation": "3. Dispensing instructions", "dosageInstructions": "1. Dosage instructions", "dosageRequiredErrorMessage": "Dosage is required", diff --git a/packages/esm-patient-medications-app/translations/ar.json b/packages/esm-patient-medications-app/translations/ar.json index 0a427399b..673b2cc0e 100644 --- a/packages/esm-patient-medications-app/translations/ar.json +++ b/packages/esm-patient-medications-app/translations/ar.json @@ -11,7 +11,7 @@ "directlyAddToBasket": "أضف إلى السلة", "discard": "تجاهل", "discontinue": "إيقاف", - "discontinuedDate": "Discontinued date", + "discontinued": "Discontinued", "dispensingInformation": "3. تعليمات الصرف", "dosageInstructions": "1. تعليمات الجرعة", "dosageRequiredErrorMessage": "Dosage is required", diff --git a/packages/esm-patient-medications-app/translations/de.json b/packages/esm-patient-medications-app/translations/de.json index 3e0e07ff7..2a200aea4 100644 --- a/packages/esm-patient-medications-app/translations/de.json +++ b/packages/esm-patient-medications-app/translations/de.json @@ -11,7 +11,7 @@ "directlyAddToBasket": "Add to basket", "discard": "Discard", "discontinue": "Discontinue", - "discontinuedDate": "Discontinued date", + "discontinued": "Discontinued", "dispensingInformation": "3. Dispensing instructions", "dosageInstructions": "1. Dosage instructions", "dosageRequiredErrorMessage": "Dosage is required", diff --git a/packages/esm-patient-medications-app/translations/es.json b/packages/esm-patient-medications-app/translations/es.json index 257885b9f..088ef1fbf 100644 --- a/packages/esm-patient-medications-app/translations/es.json +++ b/packages/esm-patient-medications-app/translations/es.json @@ -11,7 +11,7 @@ "directlyAddToBasket": "Añadir a la cesta", "discard": "Descartar", "discontinue": "Descontinuar", - "discontinuedDate": "Fecha de descontinuación", + "discontinued": "Discontinued", "dispensingInformation": "3. Instrucciones de suministro", "dosageInstructions": "1. Instrucciones de dosificación", "dosageRequiredErrorMessage": "La dosificación es obligatoria", diff --git a/packages/esm-patient-medications-app/translations/fr.json b/packages/esm-patient-medications-app/translations/fr.json index fff080a5a..85a6a136a 100644 --- a/packages/esm-patient-medications-app/translations/fr.json +++ b/packages/esm-patient-medications-app/translations/fr.json @@ -11,7 +11,7 @@ "directlyAddToBasket": "Ajouter au panier", "discard": "Rejeter", "discontinue": "Interrompre", - "discontinuedDate": "Date d'arrêt", + "discontinued": "Discontinued", "dispensingInformation": "3. Instructions de distribution", "dosageInstructions": "1. Instructions de dosage", "dosageRequiredErrorMessage": "Le dosage est requis", diff --git a/packages/esm-patient-medications-app/translations/he.json b/packages/esm-patient-medications-app/translations/he.json index 3e26e516f..2f874c70c 100644 --- a/packages/esm-patient-medications-app/translations/he.json +++ b/packages/esm-patient-medications-app/translations/he.json @@ -11,7 +11,7 @@ "directlyAddToBasket": "הוסף לסל מיד", "discard": "בטל", "discontinue": "הפסק", - "discontinuedDate": "Discontinued date", + "discontinued": "Discontinued", "dispensingInformation": "3. הוראות חליפה", "dosageInstructions": "1. הוראות מינון", "dosageRequiredErrorMessage": "Dosage is required", diff --git a/packages/esm-patient-medications-app/translations/hi.json b/packages/esm-patient-medications-app/translations/hi.json index 3e0e07ff7..2a200aea4 100644 --- a/packages/esm-patient-medications-app/translations/hi.json +++ b/packages/esm-patient-medications-app/translations/hi.json @@ -11,7 +11,7 @@ "directlyAddToBasket": "Add to basket", "discard": "Discard", "discontinue": "Discontinue", - "discontinuedDate": "Discontinued date", + "discontinued": "Discontinued", "dispensingInformation": "3. Dispensing instructions", "dosageInstructions": "1. Dosage instructions", "dosageRequiredErrorMessage": "Dosage is required", diff --git a/packages/esm-patient-medications-app/translations/hi_IN.json b/packages/esm-patient-medications-app/translations/hi_IN.json index 3e0e07ff7..2a200aea4 100644 --- a/packages/esm-patient-medications-app/translations/hi_IN.json +++ b/packages/esm-patient-medications-app/translations/hi_IN.json @@ -11,7 +11,7 @@ "directlyAddToBasket": "Add to basket", "discard": "Discard", "discontinue": "Discontinue", - "discontinuedDate": "Discontinued date", + "discontinued": "Discontinued", "dispensingInformation": "3. Dispensing instructions", "dosageInstructions": "1. Dosage instructions", "dosageRequiredErrorMessage": "Dosage is required", diff --git a/packages/esm-patient-medications-app/translations/id.json b/packages/esm-patient-medications-app/translations/id.json index 3e0e07ff7..2a200aea4 100644 --- a/packages/esm-patient-medications-app/translations/id.json +++ b/packages/esm-patient-medications-app/translations/id.json @@ -11,7 +11,7 @@ "directlyAddToBasket": "Add to basket", "discard": "Discard", "discontinue": "Discontinue", - "discontinuedDate": "Discontinued date", + "discontinued": "Discontinued", "dispensingInformation": "3. Dispensing instructions", "dosageInstructions": "1. Dosage instructions", "dosageRequiredErrorMessage": "Dosage is required", diff --git a/packages/esm-patient-medications-app/translations/it.json b/packages/esm-patient-medications-app/translations/it.json index 3e0e07ff7..2a200aea4 100644 --- a/packages/esm-patient-medications-app/translations/it.json +++ b/packages/esm-patient-medications-app/translations/it.json @@ -11,7 +11,7 @@ "directlyAddToBasket": "Add to basket", "discard": "Discard", "discontinue": "Discontinue", - "discontinuedDate": "Discontinued date", + "discontinued": "Discontinued", "dispensingInformation": "3. Dispensing instructions", "dosageInstructions": "1. Dosage instructions", "dosageRequiredErrorMessage": "Dosage is required", diff --git a/packages/esm-patient-medications-app/translations/km.json b/packages/esm-patient-medications-app/translations/km.json index 5f01bd151..df7446117 100644 --- a/packages/esm-patient-medications-app/translations/km.json +++ b/packages/esm-patient-medications-app/translations/km.json @@ -11,7 +11,7 @@ "directlyAddToBasket": "បញ្ចូលទៅក្នុង(ប្រអប់)កញ្ចប់ភ្លាមៗ", "discard": "បោះបង់", "discontinue": "បញ្ឈប់", - "discontinuedDate": "Discontinued date", + "discontinued": "Discontinued", "dispensingInformation": "3. ការណែនាំអំពីការផ្តល់ឱសថ", "dosageInstructions": "1. ការណែនាំអំពីកំរិតប្រើប្រាស់", "dosageRequiredErrorMessage": "Dosage is required", diff --git a/packages/esm-patient-medications-app/translations/pt.json b/packages/esm-patient-medications-app/translations/pt.json index 3e0e07ff7..e4d692d99 100644 --- a/packages/esm-patient-medications-app/translations/pt.json +++ b/packages/esm-patient-medications-app/translations/pt.json @@ -1,95 +1,95 @@ { - "activeMedicationsDisplayText": "Active medications", - "activeMedicationsHeaderTitle": "active medications", - "activeMedicationsTableTitle": "Active Medications", - "add": "Add", - "addDrugOrderWorkspaceTitle": "Add drug order", - "backToOrderBasket": "Back to order basket", - "clearSearchResults": "Clear Results", - "decrement": "Decrement", - "details": "Details", - "directlyAddToBasket": "Add to basket", - "discard": "Discard", - "discontinue": "Discontinue", - "discontinuedDate": "Discontinued date", - "dispensingInformation": "3. Dispensing instructions", - "dosageInstructions": "1. Dosage instructions", - "dosageRequiredErrorMessage": "Dosage is required", + "activeMedicationsDisplayText": "Medicamentos activos", + "activeMedicationsHeaderTitle": "medicamentos activos", + "activeMedicationsTableTitle": "Medicamentos Activos", + "add": "Adicionar", + "addDrugOrderWorkspaceTitle": "Adicionar prescrição", + "backToOrderBasket": "Voltar ao carinho de pedidos", + "clearSearchResults": "Limpar Resultados", + "decrement": "Diminuir", + "details": "Detalhes", + "directlyAddToBasket": "Adicionar ao carrinho", + "discard": "Descartar", + "discontinue": "Discontinuar", + "discontinued": "Discontinuar", + "dispensingInformation": "3. Instruções de dispensa", + "dosageInstructions": "1. Instruções de dosagem", + "dosageRequiredErrorMessage": "Dosagem é obrigatório", "dose": "Dose", - "drugAlreadyPrescribed": "Already prescribed", - "drugOrders": "Drug orders", - "duration": "Duration", - "durationUnit": "Duration unit", - "durationUnitPlaceholder": "Duration Unit", - "editDispensingUnit": "Quantity unit", - "editDosageUnitsPlaceholder": "Unit", - "editDosageUnitsTitle": "Dose unit", + "drugAlreadyPrescribed": "Já prescrito", + "drugOrders": "Prescrição de medicamentos", + "duration": "Duração", + "durationUnit": "Unidade de duração", + "durationUnitPlaceholder": "Unidade de Duração", + "editDispensingUnit": "Unidade de quantidade", + "editDosageUnitsPlaceholder": "Unidade", + "editDosageUnitsTitle": "Unidade de dosagem", "editDoseComboBoxPlaceholder": "Dose", "editDoseComboBoxTitle": "Dose", - "editFrequencyComboBoxTitle": "Frequency", - "editRouteComboBoxTitle": "Route", - "error": "Error", - "errorFetchingDrugOrderTemplates": "Error fetching drug order templates", - "errorFetchingDrugResults": "Error fetching results for \"{{searchTerm}}\"", - "errorFetchingOrderConfig": "Error occured when fetching Order config", - "female": "Female", - "freeDosageErrorMessage": "Add free dosage note", - "freeTextDosage": "Free text dosage", - "goToDrugOrderForm": "Order form", - "increment": "Increment", - "indication": "Indication", - "indicationErrorMessage": "Indication is required", - "indicationPlaceholder": "e.g. \"Hypertension\"", - "male": "Male", - "medicationDurationAndUnit": "for {{duration}} {{durationUnit}}", - "medicationIndefiniteDuration": "Indefinite duration", - "medications": "Medications", - "modify": "Modify", - "none": "None", - "noResultsForDrugSearch": "No results to display for \"{{searchTerm}}\"", - "numRefillsErrorMessage": "Number of refills is required", - "onDate": "on", - "or": "or", - "orderActionDiscontinue": "Discontinue", - "orderActionIncomplete": "Incomplete", - "orderActionNew": "New", - "orderActionRenew": "Renew", - "orderActionRevise": "Modify", - "orderForm": "Order Form", - "other": "Other", - "pastMedicationsDisplayText": "Past medications", - "pastMedicationsHeaderTitle": "past medications", - "pastMedicationsTableTitle": "Past Medications", - "patientInstructions": "Patient instructions", - "patientInstructionsPlaceholder": "Additional dosing instructions (e.g. \"Take after eating\")", - "pillDispensedErrorMessage": "Quantity to dispense is required", - "prescriptionDuration": "2. Prescription duration", - "prescriptionRefills": "Prescription refills", - "print": "Print", - "printedBy": "Printed by", + "editFrequencyComboBoxTitle": "Frequência", + "editRouteComboBoxTitle": "Rota", + "error": "Erro", + "errorFetchingDrugOrderTemplates": "Erro ao buscar modelos de prescrição de medicamentos", + "errorFetchingDrugResults": "Erro ao buscar resultados para \"{{searchTerm}}\"", + "errorFetchingOrderConfig": "Ocorreu um erro ao buscar a configuração da prescrição", + "female": "Feminino", + "freeDosageErrorMessage": "Adicionar nota livre de dosagem", + "freeTextDosage": "Dosagem texto livre", + "goToDrugOrderForm": "Formulário de prescrição", + "increment": "Incremento", + "indication": "Indicação", + "indicationErrorMessage": "Indicação é obrigatório", + "indicationPlaceholder": "Ex: \"Hipertensão\"", + "male": "Masculino", + "medicationDurationAndUnit": "para {{duration}} {{durationUnit}}", + "medicationIndefiniteDuration": "Duração indefinida", + "medications": "Medicamentos", + "modify": "Modificar", + "none": "Nenhum", + "noResultsForDrugSearch": "Não há resultados a mostrar para \"{{searchTerm}}\"", + "numRefillsErrorMessage": "Número de reabastecimento é obrigatório", + "onDate": "no", + "or": "ou", + "orderActionDiscontinue": "Discontinuar", + "orderActionIncomplete": "Incompleto", + "orderActionNew": "Novo", + "orderActionRenew": "Renovar", + "orderActionRevise": "Modificar", + "orderForm": "Formulário de prescrição", + "other": "Outro", + "pastMedicationsDisplayText": "Medicamentos anteriores", + "pastMedicationsHeaderTitle": "medicamentos anteriores", + "pastMedicationsTableTitle": "Medicamentos Anteriores", + "patientInstructions": "Instruções do utente", + "patientInstructionsPlaceholder": "Instruções adicionais de dosagem (Ex: \"Tomar depois de comer\")", + "pillDispensedErrorMessage": "Quantidade para dispensar é obrigatória", + "prescriptionDuration": "2. Duração da prescrição", + "prescriptionRefills": "Repor prescrição", + "print": "Imprimir", + "printedBy": "Impresso por", "prn": "P.R.N.", - "prnReason": "P.R.N. reason", - "prnReasonPlaceholder": "Reason to take medicine", - "quantity": "Quantity", - "quantityToDispense": "Quantity to dispense", - "refills": "Refills", - "removeFromBasket": "Remove from basket", - "reorder": "Reorder", - "returnToOrderBasket": "Return to order basket", - "saveOrder": "Save order", - "searchAgain": "search again", - "searchFieldPlaceholder": "Search for a drug or orderset (e.g. \"Aspirin\")", - "searchResultsMatchesForTerm_one": "{{count}} result for \"{{searchTerm}}\"", - "searchResultsMatchesForTerm_other": "{{count}} results for \"{{searchTerm}}\"", - "selectFrequencyErrorMessage": "Frequency is required", - "selectQuantityUnitsErrorMessage": "Quantity unit is required", - "selectRouteErrorMessage": "Route is required", - "selectUnitErrorMessage": "Dose unit is required", - "startDate": "Start date", - "takeAsNeeded": "Take as needed", - "tryReopeningTheForm": "Please try launching the form again", - "trySearchingAgain": "Please try searching again", - "tryTo": "Try to", - "unknown": "Unknown", - "usingADifferentTerm": "using a different term" + "prnReason": "Razão P.R.N.", + "prnReasonPlaceholder": "Motivo para tomar remédio", + "quantity": "Quantidade", + "quantityToDispense": "Quantidade a dispensar", + "refills": "Repor", + "removeFromBasket": "Remover do carinho", + "reorder": "Reordenar", + "returnToOrderBasket": "Retornar à carinho de pedidos", + "saveOrder": "Gravar prescrição", + "searchAgain": "Pesquisar novamente", + "searchFieldPlaceholder": "Pesquise um medicamento ou conjunto de pedidos (Ex: \"Aspirina\")", + "searchResultsMatchesForTerm_one": "{{count}} resultado para \"{{searchTerm}}\"", + "searchResultsMatchesForTerm_other": "{{count}} resultados para \"{{searchTerm}}\"", + "selectFrequencyErrorMessage": "Frequência é obrigatória", + "selectQuantityUnitsErrorMessage": "A unidade da quantidade é obrigatória", + "selectRouteErrorMessage": "Rota é obrigatória", + "selectUnitErrorMessage": "Unidade da dose é obrigatória", + "startDate": "Data inicial", + "takeAsNeeded": "Tome conforme necessário", + "tryReopeningTheForm": "Por favor, tente iniciar o formulário novamente", + "trySearchingAgain": "Por favor, tente pesquisar novamente", + "tryTo": "Tente para", + "unknown": "Desconhecido", + "usingADifferentTerm": "usando um termo diferente" } diff --git a/packages/esm-patient-medications-app/translations/qu.json b/packages/esm-patient-medications-app/translations/qu.json index 3e0e07ff7..2a200aea4 100644 --- a/packages/esm-patient-medications-app/translations/qu.json +++ b/packages/esm-patient-medications-app/translations/qu.json @@ -11,7 +11,7 @@ "directlyAddToBasket": "Add to basket", "discard": "Discard", "discontinue": "Discontinue", - "discontinuedDate": "Discontinued date", + "discontinued": "Discontinued", "dispensingInformation": "3. Dispensing instructions", "dosageInstructions": "1. Dosage instructions", "dosageRequiredErrorMessage": "Dosage is required", diff --git a/packages/esm-patient-medications-app/translations/si.json b/packages/esm-patient-medications-app/translations/si.json index 3e0e07ff7..2a200aea4 100644 --- a/packages/esm-patient-medications-app/translations/si.json +++ b/packages/esm-patient-medications-app/translations/si.json @@ -11,7 +11,7 @@ "directlyAddToBasket": "Add to basket", "discard": "Discard", "discontinue": "Discontinue", - "discontinuedDate": "Discontinued date", + "discontinued": "Discontinued", "dispensingInformation": "3. Dispensing instructions", "dosageInstructions": "1. Dosage instructions", "dosageRequiredErrorMessage": "Dosage is required", diff --git a/packages/esm-patient-medications-app/translations/sw.json b/packages/esm-patient-medications-app/translations/sw.json index 3e0e07ff7..2a200aea4 100644 --- a/packages/esm-patient-medications-app/translations/sw.json +++ b/packages/esm-patient-medications-app/translations/sw.json @@ -11,7 +11,7 @@ "directlyAddToBasket": "Add to basket", "discard": "Discard", "discontinue": "Discontinue", - "discontinuedDate": "Discontinued date", + "discontinued": "Discontinued", "dispensingInformation": "3. Dispensing instructions", "dosageInstructions": "1. Dosage instructions", "dosageRequiredErrorMessage": "Dosage is required", diff --git a/packages/esm-patient-medications-app/translations/sw_KE.json b/packages/esm-patient-medications-app/translations/sw_KE.json index 3e0e07ff7..2a200aea4 100644 --- a/packages/esm-patient-medications-app/translations/sw_KE.json +++ b/packages/esm-patient-medications-app/translations/sw_KE.json @@ -11,7 +11,7 @@ "directlyAddToBasket": "Add to basket", "discard": "Discard", "discontinue": "Discontinue", - "discontinuedDate": "Discontinued date", + "discontinued": "Discontinued", "dispensingInformation": "3. Dispensing instructions", "dosageInstructions": "1. Dosage instructions", "dosageRequiredErrorMessage": "Dosage is required", diff --git a/packages/esm-patient-medications-app/translations/tr.json b/packages/esm-patient-medications-app/translations/tr.json index 3e0e07ff7..2a200aea4 100644 --- a/packages/esm-patient-medications-app/translations/tr.json +++ b/packages/esm-patient-medications-app/translations/tr.json @@ -11,7 +11,7 @@ "directlyAddToBasket": "Add to basket", "discard": "Discard", "discontinue": "Discontinue", - "discontinuedDate": "Discontinued date", + "discontinued": "Discontinued", "dispensingInformation": "3. Dispensing instructions", "dosageInstructions": "1. Dosage instructions", "dosageRequiredErrorMessage": "Dosage is required", diff --git a/packages/esm-patient-medications-app/translations/tr_TR.json b/packages/esm-patient-medications-app/translations/tr_TR.json index 3e0e07ff7..2a200aea4 100644 --- a/packages/esm-patient-medications-app/translations/tr_TR.json +++ b/packages/esm-patient-medications-app/translations/tr_TR.json @@ -11,7 +11,7 @@ "directlyAddToBasket": "Add to basket", "discard": "Discard", "discontinue": "Discontinue", - "discontinuedDate": "Discontinued date", + "discontinued": "Discontinued", "dispensingInformation": "3. Dispensing instructions", "dosageInstructions": "1. Dosage instructions", "dosageRequiredErrorMessage": "Dosage is required", diff --git a/packages/esm-patient-medications-app/translations/uk.json b/packages/esm-patient-medications-app/translations/uk.json index 3e0e07ff7..2a200aea4 100644 --- a/packages/esm-patient-medications-app/translations/uk.json +++ b/packages/esm-patient-medications-app/translations/uk.json @@ -11,7 +11,7 @@ "directlyAddToBasket": "Add to basket", "discard": "Discard", "discontinue": "Discontinue", - "discontinuedDate": "Discontinued date", + "discontinued": "Discontinued", "dispensingInformation": "3. Dispensing instructions", "dosageInstructions": "1. Dosage instructions", "dosageRequiredErrorMessage": "Dosage is required", diff --git a/packages/esm-patient-medications-app/translations/vi.json b/packages/esm-patient-medications-app/translations/vi.json index b36cfdd4c..7f30af984 100644 --- a/packages/esm-patient-medications-app/translations/vi.json +++ b/packages/esm-patient-medications-app/translations/vi.json @@ -11,7 +11,7 @@ "directlyAddToBasket": "Add to basket", "discard": "Hủy bỏ", "discontinue": "Ngừng lại", - "discontinuedDate": "Discontinued date", + "discontinued": "Discontinued", "dispensingInformation": "3. Dispensing instructions", "dosageInstructions": "1. Dosage instructions", "dosageRequiredErrorMessage": "Dosage is required", diff --git a/packages/esm-patient-medications-app/translations/zh.json b/packages/esm-patient-medications-app/translations/zh.json index 383276e13..4b689a19e 100644 --- a/packages/esm-patient-medications-app/translations/zh.json +++ b/packages/esm-patient-medications-app/translations/zh.json @@ -11,7 +11,7 @@ "directlyAddToBasket": "添加到医嘱篮", "discard": "放弃", "discontinue": "停止使用", - "discontinuedDate": "Discontinued date", + "discontinued": "Discontinued", "dispensingInformation": "3. 配药说明", "dosageInstructions": "1. 用药剂量指导", "dosageRequiredErrorMessage": "Dosage is required", diff --git a/packages/esm-patient-medications-app/translations/zh_CN.json b/packages/esm-patient-medications-app/translations/zh_CN.json index 383276e13..4b689a19e 100644 --- a/packages/esm-patient-medications-app/translations/zh_CN.json +++ b/packages/esm-patient-medications-app/translations/zh_CN.json @@ -11,7 +11,7 @@ "directlyAddToBasket": "添加到医嘱篮", "discard": "放弃", "discontinue": "停止使用", - "discontinuedDate": "Discontinued date", + "discontinued": "Discontinued", "dispensingInformation": "3. 配药说明", "dosageInstructions": "1. 用药剂量指导", "dosageRequiredErrorMessage": "Dosage is required", diff --git a/packages/esm-patient-orders-app/src/components/order-details-table.scss b/packages/esm-patient-orders-app/src/components/order-details-table.scss index cea68c18c..7c4ef3007 100644 --- a/packages/esm-patient-orders-app/src/components/order-details-table.scss +++ b/packages/esm-patient-orders-app/src/components/order-details-table.scss @@ -161,3 +161,18 @@ .helperText { @include type.type-style('helper-text-02'); } + +.printButton { + margin-left: 1.25rem; +} + +@media print { + html, + body { + margin: 0 !important; + width: fit-content; + padding: 0 !important; + overflow: hidden; + page-break-inside: avoid; + } +} diff --git a/packages/esm-patient-orders-app/src/components/orders-details-table.component.tsx b/packages/esm-patient-orders-app/src/components/orders-details-table.component.tsx index 80df0067a..7d19f57e0 100644 --- a/packages/esm-patient-orders-app/src/components/orders-details-table.component.tsx +++ b/packages/esm-patient-orders-app/src/components/orders-details-table.component.tsx @@ -177,6 +177,14 @@ const OrderDetailsTable: React.FC = ({ patientUuid, showAddBu }, ]; + if (isPrinting) { + tableHeaders.push({ + key: 'dosage', + header: t('dosage', 'Dosage'), + isSortable: true, + }); + } + const tableRows = useMemo( () => allOrders?.map((order) => ({ @@ -184,7 +192,15 @@ const OrderDetailsTable: React.FC = ({ patientUuid, showAddBu dateActivated: order.dateActivated, orderNumber: order.orderNumber, dateOfOrder:
{formatDate(new Date(order.dateActivated))}
, - orderType: capitalize(order.orderType?.display ?? '--'), + orderType: capitalize(order.orderType?.display ?? '-'), + dosage: + order.type === 'drugorder' ? ( +
{`${t('indication', 'Indication').toUpperCase()} + ${order.orderReasonNonCoded} ${'-'} ${t('quantity', 'Quantity').toUpperCase()} ${order.quantity} ${order + ?.quantityUnits?.display} `}
+ ) : ( + '--' + ), order: order.display, priority: (
@@ -255,15 +271,15 @@ const OrderDetailsTable: React.FC = ({ patientUuid, showAddBu if (isPrinting && onBeforeGetContentResolve.current) { onBeforeGetContentResolve.current(); } - }, [isPrinting, onBeforeGetContentResolve]); + }, [isPrinting]); const handlePrint = useReactToPrint({ content: () => contentToPrintRef.current, documentTitle: `OpenMRS - ${patientDetails.name} - ${title}`, - onBeforeGetContent: () => + onBeforeGetContent: (): Promise => new Promise((resolve) => { - if (patient && patient?.patient && title) { - onBeforeGetContentResolve.current = resolve; + if (patient && title) { + onBeforeGetContentResolve.current = resolve(); setIsPrinting(true); } }), @@ -347,8 +363,8 @@ const OrderDetailsTable: React.FC = ({ patientUuid, showAddBu {showPrintButton && (