diff --git a/package.json b/package.json index 966adb1d..d5e65a0b 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ "@ant-design/colors": "^7.0.0", "@ant-design/icons": "^5.1.4", "@beda.software/emr-config": "*", - "@beda.software/fhir-react": "^1.8.6", + "@beda.software/fhir-react": "^1.8.7", "@beda.software/remote-data": "^1.1.3", "@fullcalendar/core": "^6.1.15", "@fullcalendar/daygrid": "^6.1.8", diff --git a/src/components/BaseLayout/Footer/Footer.styles.ts b/src/components/BaseLayout/Footer/Footer.styles.ts index d7ab0967..b9444af2 100644 --- a/src/components/BaseLayout/Footer/Footer.styles.ts +++ b/src/components/BaseLayout/Footer/Footer.styles.ts @@ -1,5 +1,7 @@ import styled from 'styled-components'; +import { Text } from 'src/components/Typography'; + export const S = { Footer: styled.footer` position: absolute; @@ -34,4 +36,9 @@ export const S = { text-decoration: underline; } `, + Text: styled(Text)` + color: var(--footer-text); + font-size: 14px; + line-height: 22px; + `, }; diff --git a/src/components/BaseLayout/Footer/index.tsx b/src/components/BaseLayout/Footer/index.tsx index 43bc610d..daf44cf6 100644 --- a/src/components/BaseLayout/Footer/index.tsx +++ b/src/components/BaseLayout/Footer/index.tsx @@ -1,3 +1,5 @@ +import { t } from '@lingui/macro'; + import { S } from './Footer.styles'; interface Props { @@ -10,7 +12,9 @@ export function AppFooter(props: Props) { return ( - Made with ❤️ by{' '} + + {t`Made with`} ❤️ {t`by`}{' '} + Beda Software diff --git a/src/components/BaseQuestionnaireResponseForm/ReadonlyQuestionnaireResponseForm.tsx b/src/components/BaseQuestionnaireResponseForm/ReadonlyQuestionnaireResponseForm.tsx index a0140bcc..d664613e 100644 --- a/src/components/BaseQuestionnaireResponseForm/ReadonlyQuestionnaireResponseForm.tsx +++ b/src/components/BaseQuestionnaireResponseForm/ReadonlyQuestionnaireResponseForm.tsx @@ -1,3 +1,4 @@ +import { useContext } from 'react'; import { FormProvider, useForm } from 'react-hook-form'; import { calcInitialContext, @@ -8,6 +9,13 @@ import { QuestionnaireResponseFormProvider, } from 'sdc-qrf'; +import { + ItemControlGroupItemReadonlyWidgetsContext, + ItemControlQuestionItemReadonlyWidgetsContext, +} from 'src/components/BaseQuestionnaireResponseForm/context'; +import { MarkdownRenderControl } from 'src/components/BaseQuestionnaireResponseForm/readonly-widgets/MarkdownRender'; + +import { AudioAttachment } from './readonly-widgets/AudioAttachment'; import { QuestionBoolean } from './readonly-widgets/boolean'; import { QuestionChoice } from './readonly-widgets/choice'; import { QuestionDateTime } from './readonly-widgets/date'; @@ -19,7 +27,6 @@ import { AnxietyScore, DepressionScore } from './readonly-widgets/score'; import { QuestionText, TextWithInput } from './readonly-widgets/string'; import { TimeRangePickerControl } from './readonly-widgets/TimeRangePickerControl'; import { UploadFile } from './readonly-widgets/UploadFile'; -import { AudioAttachment } from './readonly-widgets/AudioAttachment'; interface Props extends Partial { formData: QuestionnaireResponseFormData; @@ -40,6 +47,9 @@ export function ReadonlyQuestionnaireResponseForm(props: Props) { const formValues = watch(); + const ItemControlQuestionItemReadonlyWidgetsFromContext = useContext(ItemControlQuestionItemReadonlyWidgetsContext); + const ItemControlGroupItemReadonlyWidgetsFromContext = useContext(ItemControlGroupItemReadonlyWidgetsContext); + return (
@@ -54,6 +64,7 @@ export function ReadonlyQuestionnaireResponseForm(props: Props) { row: Row, 'time-range-picker': TimeRangePickerControl, ...itemControlGroupItemComponents, + ...ItemControlGroupItemReadonlyWidgetsFromContext, }} questionItemComponents={{ text: QuestionText, @@ -76,7 +87,9 @@ export function ReadonlyQuestionnaireResponseForm(props: Props) { 'depression-score': DepressionScore, 'input-inside-text': TextWithInput, 'audio-recorder-uploader': AudioAttachment, + 'markdown-editor': MarkdownRenderControl, ...itemControlQuestionItemComponents, + ...ItemControlQuestionItemReadonlyWidgetsFromContext, }} > <> diff --git a/src/components/BaseQuestionnaireResponseForm/context.ts b/src/components/BaseQuestionnaireResponseForm/context.ts index ffed68c6..93013e4a 100644 --- a/src/components/BaseQuestionnaireResponseForm/context.ts +++ b/src/components/BaseQuestionnaireResponseForm/context.ts @@ -7,6 +7,9 @@ import { BaseQuestionnaireResponseFormProps } from '.'; export const ItemControlQuestionItemWidgetsContext = createContext({}); export const ItemControlGroupItemWidgetsContext = createContext({}); +export const ItemControlQuestionItemReadonlyWidgetsContext = createContext({}); +export const ItemControlGroupItemReadonlyWidgetsContext = createContext({}); + interface BaseQuestionnaireResponseFormPropsContextProps extends BaseQuestionnaireResponseFormProps { submitting: boolean; debouncedSaveDraft?: DebouncedFunc<(currentFormValues: FormItems) => Promise>; diff --git a/src/components/BaseQuestionnaireResponseForm/readonly-widgets/MarkdownRender/index.tsx b/src/components/BaseQuestionnaireResponseForm/readonly-widgets/MarkdownRender/index.tsx new file mode 100644 index 00000000..90d881c3 --- /dev/null +++ b/src/components/BaseQuestionnaireResponseForm/readonly-widgets/MarkdownRender/index.tsx @@ -0,0 +1,21 @@ +import classNames from 'classnames'; +import Markdown from 'react-markdown'; +import { QuestionItemProps } from 'sdc-qrf'; + +import { useFieldController } from 'src/components/BaseQuestionnaireResponseForm/hooks'; + +import s from '../ReadonlyWidgets.module.scss'; +import { S } from '../ReadonlyWidgets.styles'; + +export function MarkdownRenderControl({ parentPath, questionItem }: QuestionItemProps) { + const { linkId, text } = questionItem; + const fieldName = [...parentPath, linkId, 0, 'value', 'string']; + const { value } = useFieldController(fieldName, questionItem); + + return ( + + {text} + {value || '-'} + + ); +} diff --git a/src/components/BaseQuestionnaireResponseForm/widgets/QuestionDateTime.stories.tsx b/src/components/BaseQuestionnaireResponseForm/widgets/QuestionDateTime.stories.tsx index 5b6f39df..d4597400 100644 --- a/src/components/BaseQuestionnaireResponseForm/widgets/QuestionDateTime.stories.tsx +++ b/src/components/BaseQuestionnaireResponseForm/widgets/QuestionDateTime.stories.tsx @@ -1,3 +1,4 @@ +import { t } from '@lingui/macro'; import { Meta, StoryObj } from '@storybook/react'; import { ItemContext } from 'sdc-qrf/lib/types'; @@ -19,7 +20,7 @@ export const DateTime: Story = { _.toInteger(displayValue)} /> ); diff --git a/src/components/LinkToEdit/__tests__/LinkToEdit.test.ts b/src/components/LinkToEdit/__tests__/LinkToEdit.test.ts new file mode 100644 index 00000000..22fd3efe --- /dev/null +++ b/src/components/LinkToEdit/__tests__/LinkToEdit.test.ts @@ -0,0 +1,66 @@ +import { Provenance } from 'fhir/r4b'; +import { describe } from 'vitest'; + +import { getLinkToEditUrl } from 'src/components/LinkToEdit/utils'; + +describe('getSourceFromProvenance', () => { + test('getSourceFromProvenance for empty Provenance', () => { + const provenance = {} as Provenance; + const pathname = '/patients/patient1/resources'; + + expect(getLinkToEditUrl({ provenance, pathname })).toBeUndefined(); + }); + + test('getSourceFromProvenance for undefined Provenance', () => { + expect(getLinkToEditUrl({})).toBeUndefined(); + }); + + test('getSourceFromProvenance for Provenance with source reference', () => { + const provenance: Provenance = { + resourceType: 'Provenance', + entity: [ + { + role: 'source', + what: { + reference: 'QuestionnaireResponse/getme', + }, + }, + ], + agent: [ + { + who: {}, + }, + ], + target: [{}], + recorded: '', + }; + const pathname = '/patients/patient1/resources'; + + expect(getLinkToEditUrl({ provenance, pathname })).toEqual('/patients/patient1/documents/getme'); + }); + + test('getSourceFromProvenance for Provenance with source reference and custom to', () => { + const provenance: Provenance = { + resourceType: 'Provenance', + entity: [ + { + role: 'source', + what: { + reference: 'QuestionnaireResponse/getme', + }, + }, + ], + agent: [ + { + who: {}, + }, + ], + target: [{}], + recorded: '', + }; + const pathname = '/patients/patient1/resources'; + const to = '/custom'; + + expect(getLinkToEditUrl({ provenance, pathname, to })).toEqual('/custom/getme'); + }); +}); diff --git a/src/components/LinkToEdit/context.ts b/src/components/LinkToEdit/context.ts new file mode 100644 index 00000000..1e1dbefe --- /dev/null +++ b/src/components/LinkToEdit/context.ts @@ -0,0 +1,11 @@ +import { createContext } from 'react'; + +import { getLinkToEditUrl, GetLinkToEditUrlProps } from 'src/components/LinkToEdit/utils'; + +export type LinkToEditContextType = { + getLinkToEditUrl: (props: GetLinkToEditUrlProps) => string | undefined; +}; + +export const LinkToEditContext = createContext({ + getLinkToEditUrl, +}); diff --git a/src/components/LinkToEdit/index.tsx b/src/components/LinkToEdit/index.tsx new file mode 100644 index 00000000..586e83e2 --- /dev/null +++ b/src/components/LinkToEdit/index.tsx @@ -0,0 +1,38 @@ +import { Resource, Provenance } from 'fhir/r4b'; +import { useContext } from 'react'; +import { Link, useLocation } from 'react-router-dom'; +import { fromFHIRReference } from 'sdc-qrf'; + +import { LinkToEditContext } from 'src/components/LinkToEdit/context'; + +interface LinkToEditProps { + name?: string; + resource: Resource; + provenanceList: Provenance[]; + to?: string; +} + +export function LinkToEdit(props: LinkToEditProps) { + const { name, resource, provenanceList, to } = props; + + const location = useLocation(); + const provenance = provenanceList + .filter((provenance) => + provenance.target.find( + (target) => + fromFHIRReference(target)?.id === resource.id && + fromFHIRReference(target)?.resourceType === resource.resourceType, + ), + ) + .sort((a, b) => new Date(b.recorded).getTime() - new Date(a.recorded).getTime())[0]; + + const { getLinkToEditUrl } = useContext(LinkToEditContext); + + const customPathTo = getLinkToEditUrl({ provenance, pathname: location.pathname, to }); + + if (!customPathTo) { + return <>{name}; + } + + return {name}; +} diff --git a/src/components/LinkToEdit/utils.ts b/src/components/LinkToEdit/utils.ts new file mode 100644 index 00000000..d37a9f04 --- /dev/null +++ b/src/components/LinkToEdit/utils.ts @@ -0,0 +1,30 @@ +import { Provenance } from 'fhir/r4b'; +import { fromFHIRReference } from 'sdc-qrf'; + +export type GetLinkToEditUrlProps = { + provenance?: Provenance; + pathname?: string; + to?: string; +}; + +export function getLinkToEditUrl(props: GetLinkToEditUrlProps): string | undefined { + const { provenance, pathname, to } = props; + + const entity = provenance?.entity?.[0]?.what; + const qrId = fromFHIRReference(entity)?.id; + const baseUrl = pathname?.split('/').slice(0, 3).join('/'); + + if (!qrId) { + return undefined; + } + + if (to) { + return `${to}/${qrId}`; + } + + if (!baseUrl) { + return undefined; + } + + return `${baseUrl}/documents/${qrId}`; +} diff --git a/src/components/ResourceTable/index.tsx b/src/components/ResourceTable/index.tsx index a5aa4130..957a6413 100644 --- a/src/components/ResourceTable/index.tsx +++ b/src/components/ResourceTable/index.tsx @@ -3,8 +3,6 @@ import { Empty } from 'antd'; import { ColumnsType } from 'antd/lib/table'; import { Provenance, Resource } from 'fhir/r4b'; import { ReactNode } from 'react'; -import { Link, useLocation } from 'react-router-dom'; -import { fromFHIRReference } from 'sdc-qrf'; import { RenderRemoteData, SearchParams, extractBundleResources, ResourcesMap } from '@beda.software/fhir-react'; @@ -77,22 +75,3 @@ export function ResourceTable(props: ResourceTableProps) ); } - -export function LinkToEdit(props: { name?: string; resource: Resource; provenanceList: Provenance[] }) { - const { name, resource, provenanceList } = props; - const location = useLocation(); - const provenance = provenanceList.find( - (p) => - fromFHIRReference(p.target[0])?.id === resource.id && - fromFHIRReference(p.target[0])?.resourceType === resource.resourceType, - ); - const entity = provenance?.entity?.[0]?.what; - const qrId = fromFHIRReference(entity)?.id; - const pathname = location.pathname.split('/').slice(0, 3).join('/'); - - if (qrId) { - return {name}; - } - - return <>{name}; -} diff --git a/src/components/SearchBar/index.tsx b/src/components/SearchBar/index.tsx index 3046f51c..1bc5ca45 100644 --- a/src/components/SearchBar/index.tsx +++ b/src/components/SearchBar/index.tsx @@ -1,12 +1,12 @@ import { Trans } from '@lingui/macro'; import { Button } from 'antd'; +import { useMemo } from 'react'; import { SearchBarColumn } from './SearchBarColumn'; +import { SearchBarMobile } from './SearchBarMobile'; import { S } from './styles'; import { SearchBarData } from './types'; -import { SearchBarMobile } from './SearchBarMobile'; import { isSearchBarFilter } from './utils'; -import { useMemo } from 'react'; interface SearchBarProps extends SearchBarData { showInDrawerOnMobile?: boolean; @@ -33,9 +33,11 @@ export function SearchBar(props: SearchBarProps) { ))} - + {searchBarFilterValues.length > 1 ? ( + + ) : null} diff --git a/src/components/index.ts b/src/components/index.ts index fa495c91..906aba0c 100644 --- a/src/components/index.ts +++ b/src/components/index.ts @@ -11,6 +11,7 @@ export * from './DatePicker'; export * from './Empty'; export * from './EncounterStatusBadge'; export * from './EncountersTable'; +export * from './LinkToEdit'; export * from './Modal'; export * from './ModalChangeActiveHealthcareService'; export * from './ModalEditHealthcareService'; diff --git a/src/containers/EncounterDetails/AIScribe/index.tsx b/src/containers/EncounterDetails/AIScribe/index.tsx index 4c1825c2..9a84c3d6 100644 --- a/src/containers/EncounterDetails/AIScribe/index.tsx +++ b/src/containers/EncounterDetails/AIScribe/index.tsx @@ -309,7 +309,7 @@ function Extract(props: ExtractProps) { return ( Loading...} + renderLoading={() => ${t`Loading...`}} renderFailure={(error) => {formatError(error)}} > {() => <>} diff --git a/src/containers/HealthcareServiceList/index.tsx b/src/containers/HealthcareServiceList/index.tsx index c4c4feb5..bc9d895b 100644 --- a/src/containers/HealthcareServiceList/index.tsx +++ b/src/containers/HealthcareServiceList/index.tsx @@ -1,4 +1,4 @@ -import { Trans } from '@lingui/macro'; +import { t, Trans } from '@lingui/macro'; import { Col, Empty, Row } from 'antd'; import { isLoading, isSuccess } from '@beda.software/remote-data'; @@ -71,7 +71,7 @@ export function HealthcareServiceList() { dataIndex: 'active', key: 'active', width: '20%', - render: (_text, resource) => (resource.active ? 'Active' : 'Inactive'), + render: (_text, resource) => (resource.active ? t`Active` : t`Inactive`), }, { title: Actions, diff --git a/src/containers/InvoiceList/components/InvoiceListSearchBar/hooks.ts b/src/containers/InvoiceList/components/InvoiceListSearchBar/hooks.ts index 55849e53..c47d5d20 100644 --- a/src/containers/InvoiceList/components/InvoiceListSearchBar/hooks.ts +++ b/src/containers/InvoiceList/components/InvoiceListSearchBar/hooks.ts @@ -1,3 +1,4 @@ +import { t } from '@lingui/macro'; import { Patient, Practitioner, PractitionerRole } from 'fhir/r4b'; import { useCallback, useState } from 'react'; @@ -93,23 +94,23 @@ export function useInvoiceSearchBarSelect() { const statusOptions = useCallback(async (search: string) => { const invoiceStatusOptions = [ { - label: 'Balanced', + label: t`Balanced`, value: 'balanced', }, { - label: 'Cancelled', + label: t`Cancelled`, value: 'cancelled', }, { - label: 'Issued', + label: t`Issued`, value: 'issued', }, { - label: 'Draft', + label: t`Draft`, value: 'draft', }, { - label: 'Entered in error', + label: t`Entered in error`, value: 'entered-in-error', }, ]; diff --git a/src/containers/InvoiceList/tableUtils.tsx b/src/containers/InvoiceList/tableUtils.tsx index d428f8a8..3c12806c 100644 --- a/src/containers/InvoiceList/tableUtils.tsx +++ b/src/containers/InvoiceList/tableUtils.tsx @@ -100,7 +100,7 @@ export function getInvoiceTableColumns( practitioners: Practitioner[], practitionerRoles: PractitionerRole[], patients: Patient[], - pagerManager: PagerManager, + pagerManager: PagerManager, ) { const excludeColumnKeys = matchCurrentUserRole({ [Role.Admin]: () => ['patientActions'], diff --git a/src/containers/InvoiceList/types.ts b/src/containers/InvoiceList/types.ts index cc9605d5..3d8092b7 100644 --- a/src/containers/InvoiceList/types.ts +++ b/src/containers/InvoiceList/types.ts @@ -1,4 +1,4 @@ -import { Invoice } from 'fhir/r4b'; +import { Invoice, Patient, Practitioner, PractitionerRole } from 'fhir/r4b'; import { PagerManager } from '@beda.software/fhir-react'; @@ -22,7 +22,7 @@ export interface InvoiceListSearchBarSelectProps { } export interface InvoiceActionsProps { - manager: PagerManager; + manager: PagerManager; invoice: Invoice; simplified?: boolean; } diff --git a/src/containers/PatientDetails/PatientOrders/index.tsx b/src/containers/PatientDetails/PatientOrders/index.tsx index 924e675c..793b1e6e 100644 --- a/src/containers/PatientDetails/PatientOrders/index.tsx +++ b/src/containers/PatientDetails/PatientOrders/index.tsx @@ -8,9 +8,10 @@ import styled from 'styled-components'; import { WithId } from '@beda.software/fhir-react'; +import { LinkToEdit } from 'src/components/LinkToEdit'; import { Modal } from 'src/components/Modal'; import { QuestionnaireResponseForm } from 'src/components/QuestionnaireResponseForm'; -import { ResourceTable, LinkToEdit } from 'src/components/ResourceTable'; +import { ResourceTable } from 'src/components/ResourceTable'; import { questionnaireIdLoader } from 'src/hooks/questionnaire-response-form-data'; import { formatHumanDate } from 'src/utils/date'; import { selectCurrentUserRoleResource } from 'src/utils/role'; diff --git a/src/containers/PatientDetails/PatientOverviewDynamic/components/LinkToEdit/index.tsx b/src/containers/PatientDetails/PatientOverviewDynamic/components/LinkToEdit/index.tsx deleted file mode 100644 index 4c49d494..00000000 --- a/src/containers/PatientDetails/PatientOverviewDynamic/components/LinkToEdit/index.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import { Resource, Provenance } from 'fhir/r4b'; -import { Link, useLocation } from 'react-router-dom'; -import { fromFHIRReference } from 'sdc-qrf'; - -interface LinkToEditProps { - name?: string; - resource: Resource; - provenanceList: Provenance[]; - to?: string; -} -export function LinkToEdit(props: LinkToEditProps) { - const { name, resource, provenanceList, to } = props; - const location = useLocation(); - const provenance = provenanceList.find((provenance) => { - const targets = provenance.target || []; - - return targets.find((target) => { - return ( - fromFHIRReference(target)?.id === resource.id && - fromFHIRReference(target)?.resourceType === resource.resourceType - ); - }); - }); - const entity = provenance?.entity?.[0]?.what; - const qrId = fromFHIRReference(entity)?.id; - - if (qrId) { - return {name}; - } - - return <>{name}; -} diff --git a/src/containers/PatientDetails/PatientOverviewDynamic/components/StandardCard/prepare.tsx b/src/containers/PatientDetails/PatientOverviewDynamic/components/StandardCard/prepare.tsx index 97364812..f69c4162 100644 --- a/src/containers/PatientDetails/PatientOverviewDynamic/components/StandardCard/prepare.tsx +++ b/src/containers/PatientDetails/PatientOverviewDynamic/components/StandardCard/prepare.tsx @@ -19,15 +19,15 @@ import { extractExtension } from 'sdc-qrf'; import { WithId, extractBundleResources, formatFHIRDate, parseFHIRDateTime } from '@beda.software/fhir-react'; +import { LinkToEdit } from 'src/components/LinkToEdit'; import { PatientActivitySummary } from 'src/containers/PatientDetails/PatientActivitySummary'; -import { LinkToEdit } from 'src/containers/PatientDetails/PatientOverviewDynamic/components/LinkToEdit'; import { OverviewCard } from 'src/containers/PatientDetails/PatientOverviewDynamic/components/StandardCard/types'; import medicationIcon from 'src/containers/PatientDetails/PatientOverviewDynamic/images/medication.svg'; import { formatHumanDate } from 'src/utils/date'; export function prepareAllergies( allergies: AllergyIntolerance[], - bundle: Bundle, + bundle: Bundle, ): OverviewCard { return { title: t`Allergies`, @@ -42,7 +42,7 @@ export function prepareAllergies( key: 'name', render: (resource: AllergyIntolerance) => ( @@ -64,7 +64,7 @@ export function prepareAllergies( export function prepareConditions( conditions: Condition[], - bundle: Bundle, + bundle: Bundle, ): OverviewCard { return { title: t`Conditions`, @@ -99,10 +99,7 @@ export function prepareConditions( }; } -export function prepareConsents( - consents: Consent[], - bundle: Bundle, -): OverviewCard { +export function prepareConsents(consents: Consent[], bundle: Bundle): OverviewCard { return { title: t`Consents`, key: 'consents', @@ -179,7 +176,7 @@ export function prepareActivitySummary(activitySummary: Observation[]): Overview export function prepareImmunizations( observations: Immunization[], - bundle: Bundle, + bundle: Bundle, ): OverviewCard { return { title: t`Immunization`, @@ -194,7 +191,7 @@ export function prepareImmunizations( key: 'name', render: (resource: Immunization) => ( @@ -212,7 +209,7 @@ export function prepareImmunizations( export function prepareMedications( observations: MedicationStatement[], - bundle: Bundle, + bundle: Bundle, ): OverviewCard { return { title: t`Active Medications`, @@ -227,7 +224,10 @@ export function prepareMedications( key: 'name', render: (resource: MedicationStatement) => ( diff --git a/src/containers/PatientDetails/PatientResources/utils.tsx b/src/containers/PatientDetails/PatientResources/utils.tsx index e5c9458b..51e15df2 100644 --- a/src/containers/PatientDetails/PatientResources/utils.tsx +++ b/src/containers/PatientDetails/PatientResources/utils.tsx @@ -15,7 +15,8 @@ import { extractExtension } from 'sdc-qrf'; import { WithId } from '@beda.software/fhir-react'; -import { ResourceTable, Option, LinkToEdit } from 'src/components/ResourceTable'; +import { LinkToEdit } from 'src/components/LinkToEdit'; +import { ResourceTable, Option } from 'src/components/ResourceTable'; import { compileAsArray } from 'src/utils'; import { formatHumanDate, formatHumanDateTime } from 'src/utils/date'; diff --git a/src/containers/PatientQuestionnaire/index.tsx b/src/containers/PatientQuestionnaire/index.tsx index c79a32e5..8ecfe425 100644 --- a/src/containers/PatientQuestionnaire/index.tsx +++ b/src/containers/PatientQuestionnaire/index.tsx @@ -68,9 +68,7 @@ export function PatientQuestionnaire({ onSuccess }: { onSuccess?: () => void }) return ( Questionnaire}> -
- {isLoading ? : } -
+ {isLoading ? : }
); } diff --git a/src/containers/PatientResourceListExample/index.tsx b/src/containers/PatientResourceListExample/index.tsx index 23f310bd..52ee0f40 100644 --- a/src/containers/PatientResourceListExample/index.tsx +++ b/src/containers/PatientResourceListExample/index.tsx @@ -9,8 +9,8 @@ import { formatHumanDate } from 'src/utils/date'; import { renderHumanName } from 'src/utils/fhir'; import { matchCurrentUserRole, Role } from 'src/utils/role'; -import { getPatientSearchParamsForPractitioner } from './utils'; import { S } from './styles'; +import { getPatientSearchParamsForPractitioner } from './utils'; export function PatientResourceListExample() { /* @@ -18,7 +18,7 @@ export function PatientResourceListExample() { */ const searchParams = matchCurrentUserRole({ [Role.Admin]: () => { - return {}; + return { _count: 33 }; }, [Role.Practitioner]: (practitioner) => { return getPatientSearchParamsForPractitioner(practitioner.id); diff --git a/src/locale/en/messages.po b/src/locale/en/messages.po index 878d14f9..dd42132a 100644 --- a/src/locale/en/messages.po +++ b/src/locale/en/messages.po @@ -43,6 +43,7 @@ msgstr "" msgid "Activate healthcare service" msgstr "" +#: src/containers/HealthcareServiceList/index.tsx:74 #: src/containers/Prescriptions/components/PrescriptionsSearchBar/hooks.ts:97 #: src/containers/Prescriptions/index.tsx:185 #: src/containers/QuestionnaireBuilder/QuestionnaireSaveForm/index.tsx:82 @@ -198,6 +199,7 @@ msgstr "" msgid "Available units" msgstr "" +#: src/containers/InvoiceList/components/InvoiceListSearchBar/hooks.ts:97 #: src/containers/InvoiceList/tableUtils.tsx:27 msgid "Balanced" msgstr "" @@ -211,6 +213,7 @@ msgstr "" msgid "Batch Number" msgstr "" +#: src/components/BaseQuestionnaireResponseForm/widgets/QuestionDateTime.stories.tsx:37 #: src/containers/PatientDetails/PatientOverviewDynamic/containers/GeneralIInformationDashboardContainer/hooks.ts:31 #: src/containers/PatientList/index.tsx:85 #: src/containers/PatientResourceListExample/index.tsx:48 @@ -230,6 +233,10 @@ msgstr "" msgid "Build your form" msgstr "" +#: src/components/BaseLayout/Footer/index.tsx:15 +msgid "by" +msgstr "" + #: src/containers/PatientDetails/PatientWearables/index.tsx:46 msgid "Calories" msgstr "" @@ -250,6 +257,7 @@ msgstr "" msgid "Cancel Medication Request" msgstr "" +#: src/containers/InvoiceList/components/InvoiceListSearchBar/hooks.ts:101 #: src/containers/InvoiceList/tableUtils.tsx:28 #: src/containers/Prescriptions/components/PrescriptionsSearchBar/hooks.ts:101 #: src/containers/Prescriptions/index.tsx:187 @@ -386,6 +394,10 @@ msgstr "" msgid "CRP" msgstr "" +#: src/utils/relative-date.ts:25 +msgid "d.o." +msgstr "" + #: src/components/PatientEncounter/index.tsx:39 #: src/containers/EncounterList/index.tsx:63 #: src/containers/InvoiceDetails/components/InvoiceDetailsHeader/index.tsx:23 @@ -491,6 +503,7 @@ msgstr "" msgid "Download audio" msgstr "" +#: src/containers/InvoiceList/components/InvoiceListSearchBar/hooks.ts:109 #: src/containers/InvoiceList/tableUtils.tsx:30 #: src/containers/Prescriptions/components/PrescriptionsSearchBar/hooks.ts:121 #: src/containers/Prescriptions/index.tsx:191 @@ -582,6 +595,7 @@ msgstr "" msgid "End date" msgstr "" +#: src/containers/InvoiceList/components/InvoiceListSearchBar/hooks.ts:113 #: src/containers/InvoiceList/tableUtils.tsx:31 #: src/containers/Prescriptions/components/PrescriptionsSearchBar/hooks.ts:113 #: src/containers/Prescriptions/index.tsx:189 @@ -726,6 +740,10 @@ msgstr "" msgid "in progress" msgstr "" +#: src/containers/HealthcareServiceList/index.tsx:74 +msgid "Inactive" +msgstr "" + #: src/containers/QuestionnaireBuilder/QuestionnaireItemSettings/controls.tsx:40 msgid "Inline choice" msgstr "" @@ -753,6 +771,7 @@ msgstr "" msgid "Invoices" msgstr "" +#: src/containers/InvoiceList/components/InvoiceListSearchBar/hooks.ts:105 #: src/containers/InvoiceList/tableUtils.tsx:29 msgid "Issued" msgstr "" @@ -781,6 +800,10 @@ msgstr "" msgid "Listen to the audio" msgstr "" +#: src/containers/EncounterDetails/AIScribe/index.tsx:312 +msgid "Loading..." +msgstr "" + #: src/containers/SignIn/index.tsx:89 msgid "Log in" msgstr "" @@ -797,10 +820,18 @@ msgstr "" msgid "Log out" msgstr "" +#: src/utils/relative-date.ts:22 +msgid "m.o." +msgstr "" + #: src/containers/QuestionnaireBuilder/QuestionnaireItemSettings/controls.tsx:101 msgid "Macro text" msgstr "" +#: src/components/BaseLayout/Footer/index.tsx:15 +msgid "Made with" +msgstr "" + #: src/components/DashboardCard/creatinine.tsx:91 msgid "Max" msgstr "" @@ -1236,6 +1267,14 @@ msgstr "" msgid "Select all" msgstr "" +#: src/components/BaseQuestionnaireResponseForm/widgets/QuestionDateTime.stories.tsx:23 +msgid "Select date" +msgstr "" + +#: src/components/BaseQuestionnaireResponseForm/widgets/QuestionDateTime.stories.tsx:51 +msgid "Select time" +msgstr "" + #: src/components/BaseQuestionnaireResponseForm/widgets/choice/index.tsx:30 #: src/components/BaseQuestionnaireResponseForm/widgets/choice/index.tsx:55 msgid "Select..." @@ -1455,6 +1494,10 @@ msgstr "" msgid "Time" msgstr "" +#: src/components/BaseQuestionnaireResponseForm/widgets/QuestionDateTime.stories.tsx:65 +msgid "Time with no seconds" +msgstr "" + #: src/containers/PatientDetails/PatientOrders/index.tsx:27 #: src/containers/PatientDetails/PatientOverviewDynamic/components/PatientNoteListCard/NoteList/index.tsx:33 #: src/containers/PatientDetails/PatientResources/utils.tsx:246 @@ -1562,6 +1605,10 @@ msgstr "" msgid "Welcome to" msgstr "" +#: src/utils/relative-date.ts:18 +msgid "y.o." +msgstr "" + #: src/containers/PatientDetails/PatientDocumentDetails/index.tsx:147 #: src/containers/PatientDetails/PatientDocumentDetails/index.tsx:172 #: src/containers/QuestionnaireBuilder/QuestionnaireItemSettings/index.tsx:136 diff --git a/src/locale/es/messages.po b/src/locale/es/messages.po index f9ae02ef..5f1b4080 100644 --- a/src/locale/es/messages.po +++ b/src/locale/es/messages.po @@ -43,6 +43,7 @@ msgstr "Activar" msgid "Activate healthcare service" msgstr "Activar servicio clínico" +#: src/containers/HealthcareServiceList/index.tsx:74 #: src/containers/Prescriptions/components/PrescriptionsSearchBar/hooks.ts:97 #: src/containers/Prescriptions/index.tsx:185 #: src/containers/QuestionnaireBuilder/QuestionnaireSaveForm/index.tsx:82 @@ -198,9 +199,10 @@ msgstr "Servicios disponibles" msgid "Available units" msgstr "Unidades disponibles" +#: src/containers/InvoiceList/components/InvoiceListSearchBar/hooks.ts:97 #: src/containers/InvoiceList/tableUtils.tsx:27 msgid "Balanced" -msgstr "Balanceado" +msgstr "Saldada" #: src/containers/MedicationManagement/index.tsx:118 #: src/containers/MedicationManagement/ModalNewMedicationBatch.tsx:23 @@ -211,6 +213,7 @@ msgstr "Lote" msgid "Batch Number" msgstr "Número de lote" +#: src/components/BaseQuestionnaireResponseForm/widgets/QuestionDateTime.stories.tsx:37 #: src/containers/PatientDetails/PatientOverviewDynamic/containers/GeneralIInformationDashboardContainer/hooks.ts:31 #: src/containers/PatientList/index.tsx:85 #: src/containers/PatientResourceListExample/index.tsx:48 @@ -230,6 +233,10 @@ msgstr "Pausa" msgid "Build your form" msgstr "Construye tu formulario" +#: src/components/BaseLayout/Footer/index.tsx:15 +msgid "by" +msgstr "por" + #: src/containers/PatientDetails/PatientWearables/index.tsx:46 msgid "Calories" msgstr "Calorías" @@ -250,11 +257,12 @@ msgstr "Cancelar recibo" msgid "Cancel Medication Request" msgstr "Cancelar solicitud de medicamento" +#: src/containers/InvoiceList/components/InvoiceListSearchBar/hooks.ts:101 #: src/containers/InvoiceList/tableUtils.tsx:28 #: src/containers/Prescriptions/components/PrescriptionsSearchBar/hooks.ts:101 #: src/containers/Prescriptions/index.tsx:187 msgid "Cancelled" -msgstr "Cancelado" +msgstr "Cancelada" #: src/components/AudioRecorder/index.tsx:39 #: src/containers/EncounterDetails/AIScribe/index.tsx:93 @@ -267,16 +275,16 @@ msgstr "Características" #: src/containers/PatientResourceListExample/index.tsx:89 msgid "Choose gender" -msgstr "" +msgstr "Elegir género" #: src/components/SearchBar/index.tsx:36 #: src/components/SearchBar/SearchBarMobile/index.tsx:51 msgid "Clear filters" -msgstr "" +msgstr "Limpiar filtros" #: src/components/BaseQuestionnaireResponseForm/widgets/UploadFileControl/index.tsx:29 msgid "Click or drag file to this area to upload" -msgstr "" +msgstr "Haz click o arrastra el archivo hasta esta área para cargar" #: src/containers/PractitionerDetails/PractitionerOverview/index.tsx:92 msgid "Clinician successfully updated" @@ -384,7 +392,11 @@ msgstr "Fecha de creación" #: src/containers/PatientDetails/PatientOrders/index.tsx:156 msgid "CRP" -msgstr "" +msgstr "PCR" + +#: src/utils/relative-date.ts:25 +msgid "d.o." +msgstr "días" #: src/components/PatientEncounter/index.tsx:39 #: src/containers/EncounterList/index.tsx:63 @@ -443,7 +455,7 @@ msgstr "Eliminar" #: src/containers/PatientResourceListExample/index.tsx:119 msgid "Delete patients" -msgstr "" +msgstr "Eliminar pacientes" #: src/containers/QuestionnaireBuilder/QuestionnaireItemSettings/index.tsx:133 msgid "Delete Questionnaire Item" @@ -485,8 +497,9 @@ msgstr "Forma de dosificación" #: src/components/AudioRecorder/index.tsx:124 msgid "Download audio" -msgstr "" +msgstr "Descargar audio" +#: src/containers/InvoiceList/components/InvoiceListSearchBar/hooks.ts:109 #: src/containers/InvoiceList/tableUtils.tsx:30 #: src/containers/Prescriptions/components/PrescriptionsSearchBar/hooks.ts:121 #: src/containers/Prescriptions/index.tsx:191 @@ -578,6 +591,7 @@ msgstr "Fin" msgid "End date" msgstr "Fecha de finalización" +#: src/containers/InvoiceList/components/InvoiceListSearchBar/hooks.ts:113 #: src/containers/InvoiceList/tableUtils.tsx:31 #: src/containers/Prescriptions/components/PrescriptionsSearchBar/hooks.ts:113 #: src/containers/Prescriptions/index.tsx:189 @@ -627,7 +641,7 @@ msgstr "Rellenar" #: src/components/SearchBar/SearchBarMobile/index.tsx:33 msgid "Filters" -msgstr "" +msgstr "Filtros" #: src/containers/PatientList/searchBarUtils.ts:10 #: src/containers/PatientResourceListExample/index.tsx:75 @@ -652,7 +666,7 @@ msgstr "Viernes" #: src/containers/PatientResourceListExample/index.tsx:55 msgid "Gender" -msgstr "" +msgstr "Género" #: src/containers/PatientDetails/PatientOverviewDynamic/components/GeneralInformationDashboard/index.tsx:20 #: src/containers/PractitionerDetails/PractitionerOverview/index.tsx:61 @@ -722,6 +736,10 @@ msgstr "Inmunización" msgid "in progress" msgstr "En progreso" +#: src/containers/HealthcareServiceList/index.tsx:74 +msgid "Inactive" +msgstr "Inactivo" + #: src/containers/QuestionnaireBuilder/QuestionnaireItemSettings/controls.tsx:40 msgid "Inline choice" msgstr "Elección en línea" @@ -749,6 +767,7 @@ msgstr "La factura fue pagada con éxito" msgid "Invoices" msgstr "Facturas" +#: src/containers/InvoiceList/components/InvoiceListSearchBar/hooks.ts:105 #: src/containers/InvoiceList/tableUtils.tsx:29 msgid "Issued" msgstr "Agendado" @@ -775,7 +794,11 @@ msgstr "Apellido" #: src/components/AudioRecorder/index.tsx:68 msgid "Listen to the audio" -msgstr "" +msgstr "Escuchar el audio" + +#: src/containers/EncounterDetails/AIScribe/index.tsx:312 +msgid "Loading..." +msgstr "Cargando..." #: src/containers/SignIn/index.tsx:89 msgid "Log in" @@ -789,10 +812,18 @@ msgstr "Iniciar sesión como paciente demo" msgid "Log out" msgstr "Cerrar sesión" +#: src/utils/relative-date.ts:22 +msgid "m.o." +msgstr "meses" + #: src/containers/QuestionnaireBuilder/QuestionnaireItemSettings/controls.tsx:101 msgid "Macro text" msgstr "Texto macro" +#: src/components/BaseLayout/Footer/index.tsx:15 +msgid "Made with" +msgstr "Hecho con" + #: src/components/DashboardCard/creatinine.tsx:91 msgid "Max" msgstr "Máximo" @@ -909,7 +940,7 @@ msgstr "Número (predeterminado)" #: src/containers/PatientResourceListExample/index.tsx:122 msgid "Number of Patients" -msgstr "" +msgstr "Número de pacientes" #: src/containers/PatientDetails/PatientResources/utils.tsx:230 msgid "Observations" @@ -1017,7 +1048,7 @@ msgstr "Pago" #: src/containers/PatientDetails/PatientOrders/index.tsx:164 msgid "PCT" -msgstr "" +msgstr "PCT" #: src/containers/App/DefaultUserWithNoRoles.tsx:31 #: src/containers/PatientDetails/PatientOverviewDynamic/containers/GeneralIInformationDashboardContainer/hooks.ts:45 @@ -1030,7 +1061,7 @@ msgstr "Widget de teléfono" #: src/containers/App/DefaultUserWithNoRoles.tsx:20 msgid "Please ask administrator to add a role for your user" -msgstr "" +msgstr "Por favor contactarse con el administrador para agregar un rol a su usuario" #: src/components/PatientEncounter/index.tsx:25 #: src/containers/EncounterList/index.tsx:51 @@ -1122,7 +1153,7 @@ msgstr "Restablecer" #: src/uberComponents/ResourceListPage/BatchActions.tsx:48 msgid "Reset selection" -msgstr "" +msgstr "Limpiar selección" #: src/containers/PatientDetails/PatientDetailsTabs/index.tsx:24 #: src/containers/PatientDetails/PatientHeader/index.tsx:96 @@ -1148,7 +1179,7 @@ msgstr "Guardar" #: src/components/BaseQuestionnaireResponseForm/FormFooter.tsx:77 msgid "Save as draft" -msgstr "" +msgstr "Guardar borrador" #: src/containers/QuestionnaireBuilder/index.tsx:49 #: src/containers/QuestionnaireBuilder/index.tsx:50 @@ -1157,11 +1188,11 @@ msgstr "Guardar cuestionario" #: src/components/BaseQuestionnaireResponseForm/FormFooter.tsx:94 msgid "Saved as draft" -msgstr "" +msgstr "Guardado como borrador" #: src/components/BaseQuestionnaireResponseForm/FormFooter.tsx:85 msgid "Saving draft" -msgstr "" +msgstr "Guardando borrador" #: src/containers/Scheduling/ScheduleCalendar/index.tsx:41 msgid "Schedule calendar" @@ -1214,7 +1245,15 @@ msgstr "Seleccionar (predeterminado)" #: src/uberComponents/ResourceListPage/BatchActions.tsx:69 msgid "Select all" -msgstr "" +msgstr "Seleccionar todos" + +#: src/components/BaseQuestionnaireResponseForm/widgets/QuestionDateTime.stories.tsx:23 +msgid "Select date" +msgstr "Seleccionar fecha" + +#: src/components/BaseQuestionnaireResponseForm/widgets/QuestionDateTime.stories.tsx:51 +msgid "Select time" +msgstr "Selecciona hora" #: src/components/BaseQuestionnaireResponseForm/widgets/choice/index.tsx:30 #: src/components/BaseQuestionnaireResponseForm/widgets/choice/index.tsx:55 @@ -1251,7 +1290,7 @@ msgstr "Compartir enlace" #: src/components/SearchBar/SearchBarMobile/index.tsx:48 msgid "Show results" -msgstr "" +msgstr "Mostrar resultados" #: src/containers/QuestionnaireBuilder/QuestionnaireItemSettings/controls.tsx:53 msgid "Slider" @@ -1352,13 +1391,13 @@ msgstr "Enviar" #: src/uberComponents/ResourceListPage/actions.tsx:105 #: src/uberComponents/ResourceListPage/actions.tsx:146 #~ msgid "Successfully saved" -#~ msgstr "" +#~ msgstr "Guardado exitosamente" #: src/uberComponents/ResourceListPage/actions.tsx:91 #: src/uberComponents/ResourceListPage/actions.tsx:126 #: src/uberComponents/ResourceListPage/actions.tsx:173 msgid "Successfully submitted" -msgstr "" +msgstr "Enviado exitosamente" #: src/containers/Scheduling/Availability/index.tsx:43 msgid "Successfully updated" @@ -1424,7 +1463,7 @@ msgstr "Aún no hay documentos" #: src/components/AudioRecorder/index.tsx:94 msgid "This audio cannot be played in Safari, please download the audio or use the Chrome browser" -msgstr "" +msgstr "Este audio no se puede reproducir en Safari, por favor descarga el audio o usa el navegador Chrome" #: src/containers/Scheduling/available-time.ts:16 msgid "Thursday" @@ -1435,6 +1474,10 @@ msgstr "Jueves" msgid "Time" msgstr "Hora" +#: src/components/BaseQuestionnaireResponseForm/widgets/QuestionDateTime.stories.tsx:65 +msgid "Time with no seconds" +msgstr "Hora sin segundos" + #: src/containers/PatientDetails/PatientOrders/index.tsx:27 #: src/containers/PatientDetails/PatientOverviewDynamic/components/PatientNoteListCard/NoteList/index.tsx:33 #: src/containers/PatientDetails/PatientResources/utils.tsx:246 @@ -1499,7 +1542,7 @@ msgstr "URL:" #: src/containers/App/DefaultUserWithNoRoles.tsx:15 msgid "User with no roles in the system" -msgstr "" +msgstr "Usuario sin rol en el sistema" #: src/containers/SignIn/index.tsx:49 #: src/containers/SignIn/index.tsx:98 @@ -1542,6 +1585,10 @@ msgstr "Semana" msgid "Welcome to" msgstr "Bienvenido a" +#: src/utils/relative-date.ts:18 +msgid "y.o." +msgstr "años" + #: src/containers/PatientDetails/PatientDocumentDetails/index.tsx:147 #: src/containers/PatientDetails/PatientDocumentDetails/index.tsx:172 #: src/containers/QuestionnaireBuilder/QuestionnaireItemSettings/index.tsx:136 @@ -1555,4 +1602,4 @@ msgstr "Actualmente no tienes acceso a los datos del paciente. Para obtenerlos, #: src/components/AudioRecorder/index.tsx:102 msgid "Your browser does not support the audio element" -msgstr "" +msgstr "Tu navegador no sorporta reproducción de audio" diff --git a/src/locale/ru/messages.po b/src/locale/ru/messages.po index 535e8bf0..ea3f2680 100644 --- a/src/locale/ru/messages.po +++ b/src/locale/ru/messages.po @@ -43,6 +43,7 @@ msgstr "" msgid "Activate healthcare service" msgstr "" +#: src/containers/HealthcareServiceList/index.tsx:74 #: src/containers/Prescriptions/components/PrescriptionsSearchBar/hooks.ts:97 #: src/containers/Prescriptions/index.tsx:185 #: src/containers/QuestionnaireBuilder/QuestionnaireSaveForm/index.tsx:82 @@ -198,6 +199,7 @@ msgstr "" msgid "Available units" msgstr "" +#: src/containers/InvoiceList/components/InvoiceListSearchBar/hooks.ts:97 #: src/containers/InvoiceList/tableUtils.tsx:27 msgid "Balanced" msgstr "" @@ -211,6 +213,7 @@ msgstr "" msgid "Batch Number" msgstr "" +#: src/components/BaseQuestionnaireResponseForm/widgets/QuestionDateTime.stories.tsx:37 #: src/containers/PatientDetails/PatientOverviewDynamic/containers/GeneralIInformationDashboardContainer/hooks.ts:31 #: src/containers/PatientList/index.tsx:85 #: src/containers/PatientResourceListExample/index.tsx:48 @@ -230,6 +233,10 @@ msgstr "" msgid "Build your form" msgstr "" +#: src/components/BaseLayout/Footer/index.tsx:15 +msgid "by" +msgstr "" + #: src/containers/PatientDetails/PatientWearables/index.tsx:46 msgid "Calories" msgstr "" @@ -250,6 +257,7 @@ msgstr "" msgid "Cancel Medication Request" msgstr "" +#: src/containers/InvoiceList/components/InvoiceListSearchBar/hooks.ts:101 #: src/containers/InvoiceList/tableUtils.tsx:28 #: src/containers/Prescriptions/components/PrescriptionsSearchBar/hooks.ts:101 #: src/containers/Prescriptions/index.tsx:187 @@ -386,6 +394,10 @@ msgstr "" msgid "CRP" msgstr "" +#: src/utils/relative-date.ts:25 +msgid "d.o." +msgstr "" + #: src/components/PatientEncounter/index.tsx:39 #: src/containers/EncounterList/index.tsx:63 #: src/containers/InvoiceDetails/components/InvoiceDetailsHeader/index.tsx:23 @@ -491,6 +503,7 @@ msgstr "" msgid "Download audio" msgstr "" +#: src/containers/InvoiceList/components/InvoiceListSearchBar/hooks.ts:109 #: src/containers/InvoiceList/tableUtils.tsx:30 #: src/containers/Prescriptions/components/PrescriptionsSearchBar/hooks.ts:121 #: src/containers/Prescriptions/index.tsx:191 @@ -582,6 +595,7 @@ msgstr "" msgid "End date" msgstr "Конец периода" +#: src/containers/InvoiceList/components/InvoiceListSearchBar/hooks.ts:113 #: src/containers/InvoiceList/tableUtils.tsx:31 #: src/containers/Prescriptions/components/PrescriptionsSearchBar/hooks.ts:113 #: src/containers/Prescriptions/index.tsx:189 @@ -726,6 +740,10 @@ msgstr "" msgid "in progress" msgstr "" +#: src/containers/HealthcareServiceList/index.tsx:74 +msgid "Inactive" +msgstr "" + #: src/containers/QuestionnaireBuilder/QuestionnaireItemSettings/controls.tsx:40 msgid "Inline choice" msgstr "" @@ -753,6 +771,7 @@ msgstr "" msgid "Invoices" msgstr "" +#: src/containers/InvoiceList/components/InvoiceListSearchBar/hooks.ts:105 #: src/containers/InvoiceList/tableUtils.tsx:29 msgid "Issued" msgstr "" @@ -781,6 +800,10 @@ msgstr "" msgid "Listen to the audio" msgstr "" +#: src/containers/EncounterDetails/AIScribe/index.tsx:312 +msgid "Loading..." +msgstr "" + #: src/containers/SignIn/index.tsx:89 msgid "Log in" msgstr "" @@ -797,10 +820,18 @@ msgstr "" msgid "Log out" msgstr "Выйти" +#: src/utils/relative-date.ts:22 +msgid "m.o." +msgstr "" + #: src/containers/QuestionnaireBuilder/QuestionnaireItemSettings/controls.tsx:101 msgid "Macro text" msgstr "" +#: src/components/BaseLayout/Footer/index.tsx:15 +msgid "Made with" +msgstr "" + #: src/components/DashboardCard/creatinine.tsx:91 msgid "Max" msgstr "" @@ -1236,6 +1267,14 @@ msgstr "" msgid "Select all" msgstr "" +#: src/components/BaseQuestionnaireResponseForm/widgets/QuestionDateTime.stories.tsx:23 +msgid "Select date" +msgstr "" + +#: src/components/BaseQuestionnaireResponseForm/widgets/QuestionDateTime.stories.tsx:51 +msgid "Select time" +msgstr "" + #: src/components/BaseQuestionnaireResponseForm/widgets/choice/index.tsx:30 #: src/components/BaseQuestionnaireResponseForm/widgets/choice/index.tsx:55 msgid "Select..." @@ -1455,6 +1494,10 @@ msgstr "" msgid "Time" msgstr "" +#: src/components/BaseQuestionnaireResponseForm/widgets/QuestionDateTime.stories.tsx:65 +msgid "Time with no seconds" +msgstr "" + #: src/containers/PatientDetails/PatientOrders/index.tsx:27 #: src/containers/PatientDetails/PatientOverviewDynamic/components/PatientNoteListCard/NoteList/index.tsx:33 #: src/containers/PatientDetails/PatientResources/utils.tsx:246 @@ -1562,6 +1605,10 @@ msgstr "" msgid "Welcome to" msgstr "" +#: src/utils/relative-date.ts:18 +msgid "y.o." +msgstr "" + #: src/containers/PatientDetails/PatientDocumentDetails/index.tsx:147 #: src/containers/PatientDetails/PatientDocumentDetails/index.tsx:172 #: src/containers/QuestionnaireBuilder/QuestionnaireItemSettings/index.tsx:136 diff --git a/src/services/i18n.ts b/src/services/i18n.ts index 67d168e1..d325b6e5 100644 --- a/src/services/i18n.ts +++ b/src/services/i18n.ts @@ -1,4 +1,8 @@ import { i18n } from '@lingui/core'; +import type { Locale } from 'antd/es/locale'; +import enAntdLocale from 'antd/es/locale/en_US'; +import esAntdLocale from 'antd/es/locale/es_ES'; +import ruAntdLocale from 'antd/es/locale/ru_RU'; import { en, es, ru } from 'make-plural/plurals'; import { messages as enMessages } from 'src/locale/en/messages'; @@ -42,3 +46,9 @@ export function dynamicActivate(locale: LocaleCode) { i18n.activate(locale); } + +export const antdLocaleMap: { [localeCode in LocaleCode]: Locale } = { + en: enAntdLocale, + es: esAntdLocale, + ru: ruAntdLocale, +}; diff --git a/src/theme/ThemeProvider.tsx b/src/theme/ThemeProvider.tsx index 7be1ff61..86453ebc 100644 --- a/src/theme/ThemeProvider.tsx +++ b/src/theme/ThemeProvider.tsx @@ -2,6 +2,8 @@ import { ConfigProvider as ANTDConfigProvider } from 'antd'; import { ReactNode } from 'react'; import { ThemeProvider as StyledComponentsThemeProvider, createGlobalStyle } from 'styled-components'; +import { antdLocaleMap, getCurrentLocale } from 'src/services/i18n'; + import { getAppTheme, getANTDTheme } from './'; import { useTheme } from '../utils/theme'; @@ -36,7 +38,7 @@ export function ThemeProvider(props: Props) { }; return ( - + {children} diff --git a/src/uberComponents/ResourceListPage/hooks.ts b/src/uberComponents/ResourceListPage/hooks.ts index 29d75484..f5f7729f 100644 --- a/src/uberComponents/ResourceListPage/hooks.ts +++ b/src/uberComponents/ResourceListPage/hooks.ts @@ -1,13 +1,12 @@ -import { TablePaginationConfig } from 'antd'; import { Bundle, Resource } from 'fhir/r4b'; import { useEffect, useMemo, useState } from 'react'; -import { SearchParams } from '@beda.software/fhir-react'; +import { SearchParams, usePager } from '@beda.software/fhir-react'; import { isSuccess, mapSuccess } from '@beda.software/remote-data'; import { ColumnFilterValue } from 'src/components/SearchBar/types'; import { getSearchBarColumnFilterValue } from 'src/components/SearchBar/utils'; -import { usePagerExtended } from 'src/hooks/pager'; +import { service } from 'src/services'; import { useDebounce } from 'src/utils/debounce'; export function useResourceListPage( @@ -30,22 +29,31 @@ export function useResourceListPage( }; const searchParams = { _sort: '-_lastUpdated', ...defaultSearchParams, ...searchBarSearchParams }; - const { - resourceResponse, - pagerManager, - handleTableChange: pagerHandleTableChange, - pagination, - } = usePagerExtended(resourceType, searchParams); + const defaultPageSize = defaultSearchParams._count; - const handleTableChange = async (pagination: TablePaginationConfig) => { - // Handle pagination only - if (typeof pagination.current !== 'number') { - return; - } + const [pageSize, setPageSize] = useState(typeof defaultPageSize === 'number' ? defaultPageSize : 10); - pagerHandleTableChange(pagination); - setSelectedRowKeys([]); - }; + const [resourceResponse, pagerManager] = usePager({ + resourceType, + requestService: service, + resourcesOnPage: pageSize, + initialSearchParams: searchParams, + }); + + const total = isSuccess(resourceResponse) ? resourceResponse.data.total : 0; + + const pagination = useMemo( + () => ({ + ...pagerManager, + updatePageSize: (pageSize: number) => { + pagerManager.reload(); + setPageSize(pageSize); + }, + pageSize, + total, + }), + [pagerManager, pageSize, total, setPageSize], + ); useEffect(() => { setSelectedRowKeys([]); @@ -82,7 +90,6 @@ export function useResourceListPage( return { pagination, recordResponse, - handleTableChange, selectedRowKeys, setSelectedRowKeys, selectedResourcesBundle, diff --git a/src/uberComponents/ResourceListPage/index.tsx b/src/uberComponents/ResourceListPage/index.tsx index 5a0790e2..7e295d3c 100644 --- a/src/uberComponents/ResourceListPage/index.tsx +++ b/src/uberComponents/ResourceListPage/index.tsx @@ -1,13 +1,14 @@ import { Trans } from '@lingui/macro'; import { Empty } from 'antd'; -import { ColumnsType } from 'antd/lib/table'; +import { ColumnsType, TablePaginationConfig } from 'antd/lib/table'; import { Bundle, ParametersParameter, Resource } from 'fhir/r4b'; -import React, { useMemo } from 'react'; +import React, { useCallback, useMemo } from 'react'; -import { formatError, SearchParams } from '@beda.software/fhir-react'; +import { formatError } from '@beda.software/fhir-react'; import { isFailure, isLoading, isSuccess, RemoteData } from '@beda.software/remote-data'; import { PageContainer } from 'src/components/BaseLayout/PageContainer'; +import { Report } from 'src/components/Report'; import { SearchBar } from 'src/components/SearchBar'; import { useSearchBar } from 'src/components/SearchBar/hooks'; import { isTableFilter } from 'src/components/SearchBar/utils'; @@ -28,91 +29,23 @@ import { isCustomAction, } from './actions'; export { navigationAction, customAction, questionnaireAction } from './actions'; +import { BatchActions } from './BatchActions'; import { useResourceListPage } from './hooks'; -import { SearchBarColumn } from '../../components/SearchBar/types'; import { S } from './styles'; -import { Report } from 'src/components/Report'; -import { BatchActions } from './BatchActions'; +import { ResourceListProps, ReportColumn, TableManager } from './types'; type RecordType = { resource: R; bundle: Bundle }; -interface TableManager { - reload: () => void; -} - -interface ReportColumn { - title: React.ReactNode; - value: React.ReactNode; -} - -export interface ResourceListPageProps { +type ResourceListPageProps = ResourceListProps & { /* Page header title (for example, Organizations) */ headerTitle: string; /* Page content max width */ maxWidth?: number | string; - /* Primary resource type (for example, Organization) */ - resourceType: R['resourceType']; - - /** - * Custom primary resources extractor, might be used when the same resource type included - * e.g. Organizations included via part-of - * - * Default - extract all resources matching `resourceType` - */ - extractPrimaryResources?: (bundle: Bundle) => R[]; - - /* Default search params */ - searchParams?: SearchParams; - - /* Filter that are displayed in the search bar and inside table columns */ - getFilters?: () => SearchBarColumn[]; - /* Table columns without action column - action column is generated based on `getRecordActions` */ getTableColumns: (manager: TableManager) => ColumnsType>; - - /** - * Record actions list that is displayed in the table per record - * (for example, edit organization) - */ - getRecordActions?: ( - record: RecordType, - manager: TableManager, - ) => Array; - - /** - * Header actions (for example, new organization) - * - * NOTE: Theoretically getHeaderActions can accept all resources Bundle - */ - getHeaderActions?: () => Array; - - /** - * Batch actions that are available when rows are selected - * (for example, delete multiple organizations) - * - * NOTE: Theoretically getHeaderActions can accept selected resources Bundle - */ - getBatchActions?: () => Array; - - /** - * Default launch context that will be added to all questionnaires - */ - defaultLaunchContext?: ParametersParameter[]; - - /** - * EXPERIMENTAL FEATURE. The interface might be changed - * TODO: https://github.com/beda-software/fhir-emr/issues/414 - */ - // loadReportBundle?: (searchParams: SearchParams) => Promise> - - /** - * EXPERIMENTAL FEATURE. The interface might be changed - * TODO: https://github.com/beda-software/fhir-emr/issues/414 - */ - getReportColumns?: (bundle: Bundle, reportBundle?: Bundle) => Array; -} +}; export function ResourceListPage({ headerTitle: title, @@ -138,15 +71,26 @@ export function ResourceListPage({ [JSON.stringify(columnsFilterValues)], ); - const { - recordResponse, - reload, - pagination, - handleTableChange, - selectedRowKeys, - setSelectedRowKeys, - selectedResourcesBundle, - } = useResourceListPage(resourceType, extractPrimaryResources, columnsFilterValues, searchParams ?? {}); + const { recordResponse, reload, pagination, selectedRowKeys, setSelectedRowKeys, selectedResourcesBundle } = + useResourceListPage(resourceType, extractPrimaryResources, columnsFilterValues, searchParams ?? {}); + + const handleTableChange = useCallback( + (event: TablePaginationConfig) => { + if (typeof event.current !== 'number') { + return; + } + if (event.pageSize && event.pageSize !== pagination.pageSize) { + pagination.reload(); + pagination.updatePageSize(event.pageSize); + } else { + pagination.loadPage(event.current, { + _page: event.current, + }); + } + setSelectedRowKeys([]); + }, + [pagination], + ); // TODO: move to hooks const initialTableColumns = getTableColumns({ reload }); @@ -198,7 +142,7 @@ export function ResourceListPage({ ) : null} > - pagination={pagination} + pagination={{ total: pagination.total, pageSize: pagination.pageSize }} onChange={handleTableChange} rowSelection={batchActions.length ? { selectedRowKeys, onChange: setSelectedRowKeys } : undefined} locale={{ diff --git a/src/uberComponents/ResourceListPage/types.ts b/src/uberComponents/ResourceListPage/types.ts new file mode 100644 index 00000000..fb467f8d --- /dev/null +++ b/src/uberComponents/ResourceListPage/types.ts @@ -0,0 +1,77 @@ +import { Bundle, ParametersParameter, Resource } from 'fhir/r4b'; + +import { SearchParams } from '@beda.software/fhir-react'; + +import { NavigationActionType, CustomActionType, QuestionnaireActionType } from './actions'; +import { SearchBarColumn } from '../../components/SearchBar/types'; + +export type RecordType = { resource: R; bundle: Bundle }; + +export interface ReportColumn { + title: React.ReactNode; + value: React.ReactNode; +} + +export interface TableManager { + reload: () => void; +} + +export interface ResourceListProps { + /* Primary resource type (for example, Organization) */ + resourceType: R['resourceType']; + + /** + * Custom primary resources extractor, might be used when the same resource type included + * e.g. Organizations included via part-of + * + * Default - extract all resources matching `resourceType` + */ + extractPrimaryResources?: (bundle: Bundle) => R[]; + + /* Default search params */ + searchParams?: SearchParams; + + /* Filter that are displayed in the search bar and inside table columns */ + getFilters?: () => SearchBarColumn[]; + + /** + * Record actions list that is displayed in the table per record + * (for example, edit organization) + */ + getRecordActions?: ( + record: RecordType, + manager: TableManager, + ) => Array; + + /** + * Header actions (for example, new organization) + * + * NOTE: Theoretically getHeaderActions can accept all resources Bundle + */ + getHeaderActions?: () => Array; + + /** + * Batch actions that are available when rows are selected + * (for example, delete multiple organizations) + * + * NOTE: Theoretically getHeaderActions can accept selected resources Bundle + */ + getBatchActions?: () => Array; + + /** + * Default launch context that will be added to all questionnaires + */ + defaultLaunchContext?: ParametersParameter[]; + + /** + * EXPERIMENTAL FEATURE. The interface might be changed + * TODO: https://github.com/beda-software/fhir-emr/issues/414 + */ + // loadReportBundle?: (searchParams: SearchParams) => Promise> + + /** + * EXPERIMENTAL FEATURE. The interface might be changed + * TODO: https://github.com/beda-software/fhir-emr/issues/414 + */ + getReportColumns?: (bundle: Bundle, reportBundle?: Bundle) => Array; +} diff --git a/src/utils/debounce.ts b/src/utils/debounce.ts index f2c315e3..6a176cb7 100644 --- a/src/utils/debounce.ts +++ b/src/utils/debounce.ts @@ -11,7 +11,7 @@ export function useDebounce(value: T, delay: number) { return () => { clearTimeout(timeoutId); }; - }, [value, delay]); + }, [JSON.stringify(value), delay]); return debouncedValue; } diff --git a/src/utils/questionnaire.ts b/src/utils/questionnaire.ts index c4e69044..c1d16ae2 100644 --- a/src/utils/questionnaire.ts +++ b/src/utils/questionnaire.ts @@ -72,7 +72,10 @@ export function getDisplay( return ''; } -export function getArrayDisplay(options?: QuestionnaireResponseItemAnswer[], choiceColumn?: QuestionnaireItemChoiceColumn[]): string | null { +export function getArrayDisplay( + options?: QuestionnaireResponseItemAnswer[], + choiceColumn?: QuestionnaireItemChoiceColumn[], +): string | null { if (!options) { return null; } @@ -91,13 +94,21 @@ export function questionnaireItemsToValidationSchema(questionnaireItems: Questio if (item.maxLength && item.maxLength > 0) schema = (schema as yup.StringSchema).max(item.maxLength); schema = createSchemaArrayOfValues(yup.object({ string: schema })).required(); } else if (item.type === 'integer') { - schema = yup.number(); + schema = yup.number().integer(); if (item.required) schema = schema.required(); schema = createSchemaArrayOfValues(yup.object({ integer: schema })).required(); } else if (item.type === 'date') { schema = yup.date(); if (item.required) schema = schema.required(); schema = createSchemaArrayOfValues(yup.object({ date: schema })).required(); + } else if (item.item) { + schema = yup + .object({ + items: item.repeats + ? yup.array().of(questionnaireItemsToValidationSchema(item.item)) + : questionnaireItemsToValidationSchema(item.item), + }) + .required(); } else { schema = item.required ? yup.array().of(yup.mixed()).min(1).required() : yup.mixed().nullable(); } @@ -110,12 +121,6 @@ export function questionnaireItemsToValidationSchema(questionnaireItems: Questio }); } else { validationSchema[item.linkId] = schema; - - if (item.item && !item.repeats) { - validationSchema[item.linkId] = yup - .object({ items: questionnaireItemsToValidationSchema(item.item) }) - .required(); - } } }); diff --git a/src/utils/relative-date.ts b/src/utils/relative-date.ts index d93aa9a6..d023d613 100644 --- a/src/utils/relative-date.ts +++ b/src/utils/relative-date.ts @@ -1,3 +1,4 @@ +import { t } from '@lingui/macro'; import { differenceInDays, differenceInMonths, differenceInYears, parseISO } from 'date-fns'; export function getYears(date: string) { @@ -14,12 +15,12 @@ export function getDays(date: string) { export function getPersonAge(date: string) { if (getYears(date) > 0) { - return `${getYears(date)} y.o.`; + return `${getYears(date)} ${t`y.o.`}`; } if (getMonths(date) > 0) { - return `${getMonths(date)} m.o.`; + return `${getMonths(date)} ${t`m.o.`}`; } - return `${getDays(date)} d.o.`; + return `${getDays(date)} ${t`d.o.`}`; } diff --git a/yarn.lock b/yarn.lock index 8e470978..0796ba0f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -772,10 +772,10 @@ resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== -"@beda.software/fhir-react@^1.8.6": - version "1.8.6" - resolved "https://registry.yarnpkg.com/@beda.software/fhir-react/-/fhir-react-1.8.6.tgz#d996c28a47edb776786fa033f415b22d90e00f21" - integrity sha512-ip+TLFp1BN2/NlxPMzIsVisGhb8GM5EvZXm6o/9+06tggBetIgaYk/Ye+nLmAc1l83DtdqQMfJkyhBnSCJ9Avw== +"@beda.software/fhir-react@^1.8.7": + version "1.8.7" + resolved "https://registry.yarnpkg.com/@beda.software/fhir-react/-/fhir-react-1.8.7.tgz#5f15d2baf770245fcc5c7faca6dd78b3b1cea4e4" + integrity sha512-j2JfdgYGCK2MuIqEurM8j3MMkOYtOEqkaHrBLZfZYgGQv2WJno+nG9PCsey17hVFC4MZ8kbm5IG4u7QRAZqdGQ== dependencies: "@beda.software/remote-data" "^1.1.3" axios "^1.6.2"