@pucp-gidis-hiisc/esm-fua-app 1.0.5 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (118) hide show
  1. package/dist/116.js +1 -0
  2. package/dist/116.js.map +1 -0
  3. package/dist/123.js +2 -0
  4. package/dist/123.js.map +1 -0
  5. package/dist/191.js +1 -0
  6. package/dist/191.js.map +1 -0
  7. package/dist/194.js +1 -0
  8. package/dist/194.js.map +1 -0
  9. package/dist/276.js +2 -0
  10. package/dist/{556.js.LICENSE.txt → 276.js.LICENSE.txt} +1 -11
  11. package/dist/276.js.map +1 -0
  12. package/dist/300.js +1 -1
  13. package/dist/31.js +1 -0
  14. package/dist/31.js.map +1 -0
  15. package/dist/322.js +1 -0
  16. package/dist/322.js.map +1 -0
  17. package/dist/336.js +1 -1
  18. package/dist/336.js.map +1 -1
  19. package/dist/372.js +1 -1
  20. package/dist/372.js.map +1 -1
  21. package/dist/397.js +1 -0
  22. package/dist/397.js.map +1 -0
  23. package/dist/41.js +1 -1
  24. package/dist/41.js.map +1 -1
  25. package/dist/457.js +1 -1
  26. package/dist/457.js.map +1 -1
  27. package/dist/464.js +1 -1
  28. package/dist/464.js.map +1 -1
  29. package/dist/470.js +1 -1
  30. package/dist/470.js.map +1 -1
  31. package/dist/495.js +2 -1
  32. package/dist/495.js.LICENSE.txt +9 -0
  33. package/dist/495.js.map +1 -1
  34. package/dist/51.js +2 -0
  35. package/dist/{main.js.LICENSE.txt → 51.js.LICENSE.txt} +18 -3
  36. package/dist/51.js.map +1 -0
  37. package/dist/661.js +1 -0
  38. package/dist/661.js.map +1 -0
  39. package/dist/69.js +1 -0
  40. package/dist/69.js.map +1 -0
  41. package/dist/745.js +1 -0
  42. package/dist/745.js.map +1 -0
  43. package/dist/794.js +1 -0
  44. package/dist/794.js.map +1 -0
  45. package/dist/810.js +1 -0
  46. package/dist/810.js.map +1 -0
  47. package/dist/876.js +1 -2
  48. package/dist/876.js.map +1 -1
  49. package/dist/89.js +1 -1
  50. package/dist/89.js.map +1 -1
  51. package/dist/913.js +1 -1
  52. package/dist/913.js.LICENSE.txt +3 -3
  53. package/dist/913.js.map +1 -1
  54. package/dist/932.js +1 -0
  55. package/dist/932.js.map +1 -0
  56. package/dist/964.js +1 -0
  57. package/dist/964.js.map +1 -0
  58. package/dist/99.js +1 -1
  59. package/dist/main.js +1 -2
  60. package/dist/main.js.map +1 -1
  61. package/dist/pucp-gidis-hiisc-esm-fua-app.js +1 -1
  62. package/dist/pucp-gidis-hiisc-esm-fua-app.js.buildmanifest.json +368 -101
  63. package/dist/pucp-gidis-hiisc-esm-fua-app.js.map +1 -1
  64. package/dist/routes.json +1 -1
  65. package/package.json +4 -2
  66. package/src/components/fua-html-viewer.component.tsx +81 -0
  67. package/src/components/fua-html-viewer.scss +44 -0
  68. package/src/components/summary-tiles/summary-tile.component.tsx +35 -0
  69. package/src/components/summary-tiles/summary-tiles.scss +64 -0
  70. package/src/config-schema.ts +15 -53
  71. package/src/declarations.d.ts +4 -6
  72. package/src/fua/fua-date-range-picker.component.tsx +38 -0
  73. package/src/fua/fua-date-range-picker.scss +15 -0
  74. package/src/fua/fua-header.scss +68 -0
  75. package/src/fua/{case-management-header.tsx → fua-header.tsx} +6 -6
  76. package/src/fua/{case-management-illustration.tsx → fua-illustration.tsx} +3 -3
  77. package/src/fua/fua-request-table.scss +80 -128
  78. package/src/fua/fuaRequestTable.tsx +148 -101
  79. package/src/fua-dashboard.component.tsx +25 -0
  80. package/src/fua-dashboard.scss +35 -0
  81. package/src/fua-tabs/data-table-extensions/all-fua-requests-table.extension.tsx +8 -0
  82. package/src/fua-tabs/data-table-extensions/completed-fua-requests-table.extension.tsx +8 -0
  83. package/src/fua-tabs/data-table-extensions/declined-fua-requests-table.extension.tsx +8 -0
  84. package/src/fua-tabs/data-table-extensions/in-progress-fua-requests-table.extension.tsx +8 -0
  85. package/src/fua-tabs/fua-tabs.component.tsx +74 -0
  86. package/src/fua-tabs/fua-tabs.scss +65 -0
  87. package/src/fua-tiles/all-fua-requests-tile.component.tsx +20 -0
  88. package/src/fua-tiles/completed-fua-requests-tile.component.tsx +19 -0
  89. package/src/fua-tiles/fua-summary-tiles.component.tsx +46 -0
  90. package/src/fua-tiles/fua-summary-tiles.scss +16 -0
  91. package/src/fua-tiles/in-progress-fua-requests-tile.component.tsx +20 -0
  92. package/src/fua-viewer-page/fua-viewer-page.component.tsx +90 -0
  93. package/src/fua-viewer-page/fua-viewer-page.scss +82 -0
  94. package/src/hooks/useFuaRequests.ts +93 -26
  95. package/src/index.ts +82 -7
  96. package/src/root.component.tsx +8 -0
  97. package/src/routes.json +94 -10
  98. package/src/types/index.ts +4 -0
  99. package/src/workspaces/fua-viewer.workspace.tsx +20 -0
  100. package/translations/en.json +15 -1
  101. package/translations/es.json +15 -1
  102. package/.turbo/turbo-build.log +0 -43
  103. package/.turbo/turbo-extract-translations.log +0 -11
  104. package/.turbo/turbo-lint.log +0 -14
  105. package/dist/144.js +0 -2
  106. package/dist/144.js.LICENSE.txt +0 -19
  107. package/dist/144.js.map +0 -1
  108. package/dist/466.js +0 -1
  109. package/dist/466.js.map +0 -1
  110. package/dist/556.js +0 -2
  111. package/dist/556.js.map +0 -1
  112. package/dist/596.js +0 -2
  113. package/dist/596.js.LICENSE.txt +0 -30
  114. package/dist/596.js.map +0 -1
  115. package/dist/790.js +0 -1
  116. package/dist/790.js.map +0 -1
  117. package/src/root.scss +0 -102
  118. /package/dist/{876.js.LICENSE.txt → 123.js.LICENSE.txt} +0 -0
@@ -0,0 +1,74 @@
1
+ import React, { useState } from 'react';
2
+ import { useTranslation } from 'react-i18next';
3
+ import { type AssignedExtension, Extension, useAssignedExtensions } from '@openmrs/esm-framework';
4
+ import { ComponentContext } from '@openmrs/esm-framework/src/internal';
5
+ import styles from './fua-tabs.scss';
6
+
7
+ const fuaPanelSlot = 'fua-panels-slot';
8
+
9
+ const FuaOrdersTabs: React.FC = () => {
10
+ const { t } = useTranslation();
11
+ const [selectedTab, setSelectedTab] = useState(0);
12
+ const tabExtensions = useAssignedExtensions(fuaPanelSlot) as AssignedExtension[];
13
+
14
+ const filteredExtensions = tabExtensions.filter((extension) => Object.keys(extension.meta).length > 0);
15
+
16
+ if (filteredExtensions.length === 0) {
17
+ return (
18
+ <div style={{ padding: '20px' }}>
19
+ <p>No tab extensions found</p>
20
+ </div>
21
+ );
22
+ }
23
+
24
+ return (
25
+ <div className={styles.customTabsContainer}>
26
+ {/* Tab buttons */}
27
+ <div className={styles.customTabList}>
28
+ {filteredExtensions.map((extension, index) => {
29
+ const { name, title } = extension.meta;
30
+ return (
31
+ <button
32
+ key={index}
33
+ className={`${styles.customTab} ${selectedTab === index ? styles.customTabActive : ''}`}
34
+ onClick={() => setSelectedTab(index)}
35
+ aria-selected={selectedTab === index}
36
+ >
37
+ {t(title, {
38
+ ns: extension.moduleName,
39
+ defaultValue: title,
40
+ })}
41
+ </button>
42
+ );
43
+ })}
44
+ </div>
45
+
46
+ {/* Tab panels */}
47
+ <div className={styles.customTabPanels}>
48
+ {filteredExtensions.map((extension, index) => {
49
+ if (selectedTab !== index) return null;
50
+
51
+ return (
52
+ <div key={index} className={styles.customTabPanel}>
53
+ <ComponentContext.Provider
54
+ value={{
55
+ moduleName: extension.moduleName,
56
+ featureName: 'fua',
57
+ extension: {
58
+ extensionId: extension.id,
59
+ extensionSlotName: fuaPanelSlot,
60
+ extensionSlotModuleName: extension.moduleName,
61
+ },
62
+ }}
63
+ >
64
+ <Extension />
65
+ </ComponentContext.Provider>
66
+ </div>
67
+ );
68
+ })}
69
+ </div>
70
+ </div>
71
+ );
72
+ };
73
+
74
+ export default FuaOrdersTabs;
@@ -0,0 +1,65 @@
1
+ @use '@carbon/styles/scss/spacing';
2
+ @use '@carbon/styles/scss/type';
3
+
4
+ .customTabsContainer {
5
+ background-color: var(--cds-layer-01);
6
+ margin: 0;
7
+ }
8
+
9
+ .customTabList {
10
+ display: flex;
11
+ border-bottom: 1px solid var(--cds-border-subtle-01);
12
+ padding-left: spacing.$spacing-05;
13
+ background-color: var(--cds-layer-01);
14
+ }
15
+
16
+ .customTab {
17
+ @include type.type-style('body-compact-01');
18
+
19
+ padding: spacing.$spacing-04 spacing.$spacing-05;
20
+ min-width: 8.875rem;
21
+ background: transparent;
22
+ border: none;
23
+ border-bottom: 2px solid transparent;
24
+ color: var(--cds-text-secondary);
25
+ cursor: pointer;
26
+ transition: all 0.11s cubic-bezier(0.2, 0, 0.38, 0.9);
27
+
28
+ &:hover {
29
+ background-color: var(--cds-layer-hover-01);
30
+ color: var(--cds-text-primary);
31
+ }
32
+
33
+ &:focus {
34
+ outline: 2px solid var(--cds-focus);
35
+ outline-offset: -2px;
36
+ }
37
+ }
38
+
39
+ .customTabActive {
40
+ color: var(--cds-text-primary);
41
+ border-bottom-color: var(--cds-border-interactive);
42
+ font-weight: 600;
43
+
44
+ &:hover {
45
+ border-bottom-color: var(--cds-border-interactive);
46
+ }
47
+ }
48
+
49
+ .customTabPanels {
50
+ padding: spacing.$spacing-05;
51
+ background-color: var(--cds-layer-01);
52
+ }
53
+
54
+ .customTabPanel {
55
+ animation: fadeIn 0.15s ease-in;
56
+ }
57
+
58
+ @keyframes fadeIn {
59
+ from {
60
+ opacity: 0;
61
+ }
62
+ to {
63
+ opacity: 1;
64
+ }
65
+ }
@@ -0,0 +1,20 @@
1
+ import React from 'react';
2
+ import { useTranslation } from 'react-i18next';
3
+ import { useFuaRequests } from '../hooks/useFuaRequests';
4
+ import FuaSummaryTile from '../components/summary-tiles/summary-tile.component';
5
+
6
+ const AllFuaRequestsTile = () => {
7
+ const { t } = useTranslation();
8
+
9
+ const { fuaOrders } = useFuaRequests({ newOrdersOnly: true });
10
+
11
+ return (
12
+ <FuaSummaryTile
13
+ label={t('orders', 'Orders')}
14
+ value={fuaOrders?.length}
15
+ headerLabel={t('testsOrdered', 'Tests ordered')}
16
+ />
17
+ );
18
+ };
19
+
20
+ export default AllFuaRequestsTile;
@@ -0,0 +1,19 @@
1
+ import React from 'react';
2
+ import { useTranslation } from 'react-i18next';
3
+ import { useFuaRequests } from '../hooks/useFuaRequests';
4
+ import FuaSummaryTile from '../components/summary-tiles/summary-tile.component';
5
+
6
+ const CompletedFuaRequestsTile = () => {
7
+ const { t } = useTranslation();
8
+ const { fuaOrders } = useFuaRequests({ status: 'COMPLETED', excludeCanceled: false });
9
+
10
+ return (
11
+ <FuaSummaryTile
12
+ label={t('completed', 'Completed')}
13
+ value={fuaOrders?.length}
14
+ headerLabel={t('results', 'Results')}
15
+ />
16
+ );
17
+ };
18
+
19
+ export default CompletedFuaRequestsTile;
@@ -0,0 +1,46 @@
1
+ import React from 'react';
2
+ import { useTranslation } from 'react-i18next';
3
+ import { type AssignedExtension, useAssignedExtensions, Extension, useConfig } from '@openmrs/esm-framework';
4
+ import { ComponentContext } from '@openmrs/esm-framework/src/internal';
5
+ import styles from './fua-summary-tiles.scss';
6
+ import { type Config } from '../config-schema';
7
+
8
+ const FuaSummaryTiles: React.FC = () => {
9
+ const { t } = useTranslation();
10
+ const { enableReviewingLabResultsBeforeApproval } = useConfig<Config>();
11
+ const fuaTileSlot = 'fua-tiles-slot';
12
+ const tilesExtensions = useAssignedExtensions(fuaTileSlot) as AssignedExtension[];
13
+
14
+ const filteredExtensions = tilesExtensions
15
+ .filter((extension) => Object.keys(extension.meta).length > 0)
16
+ .filter((extension) => {
17
+ if (extension.name === 'pending-review-list-tile-component') {
18
+ return enableReviewingLabResultsBeforeApproval === true;
19
+ }
20
+ return true;
21
+ });
22
+ return (
23
+ <div className={styles.cardContainer}>
24
+ {filteredExtensions.map((extension, index) => {
25
+ return (
26
+ <ComponentContext.Provider
27
+ key={extension.id}
28
+ value={{
29
+ moduleName: extension.moduleName,
30
+ featureName: 'fua',
31
+ extension: {
32
+ extensionId: extension.id,
33
+ extensionSlotName: fuaTileSlot,
34
+ extensionSlotModuleName: extension.moduleName,
35
+ },
36
+ }}
37
+ >
38
+ <Extension />
39
+ </ComponentContext.Provider>
40
+ );
41
+ })}
42
+ </div>
43
+ );
44
+ };
45
+
46
+ export default FuaSummaryTiles;
@@ -0,0 +1,16 @@
1
+ @use '@carbon/layout';
2
+ @use '@carbon/type';
3
+ @use '@openmrs/esm-styleguide/src/vars' as *;
4
+
5
+ .cardContainer {
6
+ background-color: $ui-02;
7
+ display: flex;
8
+ flex-wrap: wrap;
9
+ padding: layout.$spacing-03;
10
+ gap: 0 layout.$spacing-01;
11
+ }
12
+
13
+ .cardContainer>div {
14
+ flex: 1 1 300px;
15
+ box-sizing: border-box;
16
+ }
@@ -0,0 +1,20 @@
1
+ import React from 'react';
2
+ import { useTranslation } from 'react-i18next';
3
+ import { useFuaRequests } from '../hooks/useFuaRequests';
4
+ import FuaSummaryTile from '../components/summary-tiles/summary-tile.component';
5
+
6
+
7
+ const InProgressFuaRequestsTile = () => {
8
+ const { t } = useTranslation();
9
+ const { fuaOrders } = useFuaRequests({ status: 'IN_PROGRESS' });
10
+
11
+ return (
12
+ <FuaSummaryTile
13
+ label={t('inProgress', 'In progress')}
14
+ value={fuaOrders?.length}
15
+ headerLabel={t('worklist', 'Ex-Worklist')}
16
+ />
17
+ );
18
+ };
19
+
20
+ export default InProgressFuaRequestsTile;
@@ -0,0 +1,90 @@
1
+ import React, { useState, useEffect } from 'react';
2
+ import { useConfig, showSnackbar } from '@openmrs/esm-framework';
3
+ import { InlineLoading } from '@carbon/react';
4
+ import type { Config } from '../config-schema';
5
+ import styles from './fua-viewer-page.scss';
6
+
7
+ const FuaViewerPage: React.FC = () => {
8
+ const config = useConfig<Config>();
9
+ const endpoint = config.fuaGeneratorEndpoint;
10
+ const [htmlContent, setHtmlContent] = useState<string>('');
11
+ const [isLoading, setIsLoading] = useState(true);
12
+ const [error, setError] = useState<string | null>(null);
13
+
14
+ useEffect(() => {
15
+ const fetchHtml = async () => {
16
+ try {
17
+ setIsLoading(true);
18
+ setError(null);
19
+
20
+ const response = await fetch(endpoint);
21
+
22
+ if (!response.ok) {
23
+ throw new Error(`Error al cargar el contenido: ${response.status} ${response.statusText}`);
24
+ }
25
+
26
+ const html = await response.text();
27
+ setHtmlContent(html);
28
+ } catch (err) {
29
+ const errorMessage = err instanceof Error ? err.message : 'Error desconocido al cargar el contenido';
30
+ setError(errorMessage);
31
+ console.error('Error fetching FUA HTML:', err);
32
+ showSnackbar({
33
+ title: 'Error al cargar FUA',
34
+ subtitle: errorMessage,
35
+ kind: 'error',
36
+ });
37
+ } finally {
38
+ setIsLoading(false);
39
+ }
40
+ };
41
+
42
+ fetchHtml();
43
+ }, [endpoint]);
44
+
45
+ if (isLoading) {
46
+ return (
47
+ <div className={styles.loadingContainer}>
48
+ <InlineLoading description="Cargando visor de FUA..." />
49
+ </div>
50
+ );
51
+ }
52
+
53
+ if (error) {
54
+ return (
55
+ <div className={styles.errorContainer}>
56
+ <h3>⚠️ Error al cargar el visor de FUA</h3>
57
+ <p>{error}</p>
58
+ <details>
59
+ <summary>Información técnica</summary>
60
+ <p><strong>Endpoint:</strong> {endpoint}</p>
61
+ <p><strong>Posibles causas:</strong></p>
62
+ <ul>
63
+ <li>El servidor no está respondiendo</li>
64
+ <li>Políticas CORS bloqueando la conexión</li>
65
+ <li>El endpoint configurado es incorrecto</li>
66
+ </ul>
67
+ <p><strong>Soluciones:</strong></p>
68
+ <ul>
69
+ <li>Verifica que el servidor esté funcionando</li>
70
+ <li>Prueba el endpoint directamente en tu navegador</li>
71
+ <li>Contacta al administrador del sistema</li>
72
+ </ul>
73
+ </details>
74
+ </div>
75
+ );
76
+ }
77
+
78
+ return (
79
+ <div className={styles.pageContainer}>
80
+ <iframe
81
+ srcDoc={htmlContent}
82
+ title="Visor de FUA"
83
+ className={styles.fullIframe}
84
+ sandbox="allow-scripts allow-same-origin allow-popups allow-popups-to-escape-sandbox allow-forms"
85
+ />
86
+ </div>
87
+ );
88
+ };
89
+
90
+ export default FuaViewerPage;
@@ -0,0 +1,82 @@
1
+ @use '@carbon/styles/scss/spacing';
2
+ @use '@carbon/styles/scss/type';
3
+
4
+ .pageContainer {
5
+ width: 100%;
6
+ height: 100vh;
7
+ margin: 0;
8
+ padding: 0;
9
+ overflow: hidden;
10
+ }
11
+
12
+ .fullIframe {
13
+ width: 100%;
14
+ height: 100%;
15
+ border: none;
16
+ margin: 0;
17
+ padding: 0;
18
+ display: block;
19
+ }
20
+
21
+ .loadingContainer {
22
+ display: flex;
23
+ justify-content: center;
24
+ align-items: center;
25
+ height: 100vh;
26
+ padding: spacing.$spacing-05;
27
+ }
28
+
29
+ .errorContainer {
30
+ display: flex;
31
+ flex-direction: column;
32
+ justify-content: center;
33
+ align-items: center;
34
+ height: 100vh;
35
+ padding: spacing.$spacing-07;
36
+ text-align: center;
37
+ max-width: 800px;
38
+ margin: 0 auto;
39
+
40
+ h3 {
41
+ @include type.type-style('heading-03');
42
+ color: #da1e28;
43
+ margin-bottom: spacing.$spacing-05;
44
+ }
45
+
46
+ p {
47
+ @include type.type-style('body-01');
48
+ color: #525252;
49
+ margin-bottom: spacing.$spacing-03;
50
+ }
51
+
52
+ details {
53
+ margin-top: spacing.$spacing-05;
54
+ text-align: left;
55
+ width: 100%;
56
+ background-color: #f4f4f4;
57
+ padding: spacing.$spacing-05;
58
+ border-radius: 4px;
59
+ border-left: 3px solid #da1e28;
60
+
61
+ summary {
62
+ @include type.type-style('label-01');
63
+ cursor: pointer;
64
+ font-weight: 600;
65
+ margin-bottom: spacing.$spacing-03;
66
+
67
+ &:hover {
68
+ color: #0f62fe;
69
+ }
70
+ }
71
+
72
+ ul {
73
+ margin-left: spacing.$spacing-05;
74
+ margin-top: spacing.$spacing-03;
75
+
76
+ li {
77
+ @include type.type-style('body-compact-01');
78
+ margin-bottom: spacing.$spacing-02;
79
+ }
80
+ }
81
+ }
82
+ }
@@ -1,5 +1,6 @@
1
- import { useEffect, useState } from 'react';
2
- import { openmrsFetch } from '@openmrs/esm-framework';
1
+ import dayjs from 'dayjs';
2
+ import useSWR from 'swr';
3
+ import { openmrsFetch, useAppContext } from '@openmrs/esm-framework';
3
4
  import { ModuleFuaRestURL } from '../constant';
4
5
 
5
6
  export interface FuaEstado {
@@ -19,30 +20,96 @@ export interface FuaRequest {
19
20
  fechaActualizacion: number;
20
21
  }
21
22
 
22
- function useFuaRequests() {
23
- const [data, setData] = useState<FuaRequest[]>([]);
24
- const [isLoading, setIsLoading] = useState<boolean>(false);
25
- const [error, setError] = useState<Error | null>(null);
26
-
27
- useEffect(() => {
28
- const fetchData = async () => {
29
- setIsLoading(true);
30
- setError(null);
31
- try {
32
- const { data: response } = await openmrsFetch(`${ModuleFuaRestURL}/list`);
33
- setData(response as FuaRequest[]);
34
- } catch (err: any) {
35
- console.error('Error fetching FUA list:', err);
36
- setError(err);
37
- } finally {
38
- setIsLoading(false);
39
- }
40
- };
41
-
42
- fetchData();
43
- }, []);
44
-
45
- return { data, isLoading, error };
23
+ export interface DateFilterContext {
24
+ dateRange: [Date, Date];
25
+ }
26
+
27
+ const useFuaRequestsDefaultParams: UseFuaRequestsParams = {
28
+ status: null,
29
+ newOrdersOnly: false,
30
+ excludeCanceled: true,
31
+ };
32
+
33
+ export interface UseFuaRequestsParams {
34
+ status: string | null;
35
+ newOrdersOnly: boolean;
36
+ excludeCanceled: boolean;
37
+ }
38
+
39
+ /**
40
+ * Custom hook for retrieving FUA requests based on the specified status.
41
+ *
42
+ * @param status - The status of the requests to retrieve
43
+ * @param excludeCanceled - Whether to exclude canceled requests
44
+ * @param newOrdersOnly - Whether to retrieve only new orders
45
+ */
46
+ export function useFuaRequests(params: Partial<UseFuaRequestsParams> = useFuaRequestsDefaultParams) {
47
+ const { status, newOrdersOnly, excludeCanceled } = { ...useFuaRequestsDefaultParams, ...params };
48
+ const { dateRange } = useAppContext<DateFilterContext>('fua-date-filter') ?? {
49
+ dateRange: [dayjs().startOf('day').toDate(), new Date()],
50
+ };
51
+
52
+ let url = `${ModuleFuaRestURL}/list`;
53
+ const queryParams: string[] = [];
54
+
55
+ if (status) {
56
+ queryParams.push(`status=${status}`);
57
+ }
58
+
59
+ if (excludeCanceled) {
60
+ queryParams.push('excludeCanceled=true');
61
+ }
62
+
63
+ if (dateRange) {
64
+ queryParams.push(`startDate=${dateRange.at(0).toISOString()}`);
65
+ queryParams.push(`endDate=${dateRange.at(1).toISOString()}`);
66
+ }
67
+
68
+ if (queryParams.length > 0) {
69
+ url = `${url}?${queryParams.join('&')}`;
70
+ }
71
+
72
+ const { data, error, mutate, isLoading, isValidating } = useSWR<{ data: Array<FuaRequest> }>(
73
+ url,
74
+ openmrsFetch,
75
+ );
76
+
77
+ // openmrsFetch returns { data: T }, so we access data.data to get the array
78
+ const allOrders = data?.data ?? [];
79
+
80
+ const filteredOrders = allOrders.filter(
81
+ (order) => !newOrdersOnly || (order?.fuaEstado === null || order?.fuaEstado === undefined),
82
+ );
83
+
84
+ return {
85
+ fuaOrders: filteredOrders,
86
+ isLoading,
87
+ isError: error,
88
+ mutate,
89
+ isValidating,
90
+ };
91
+ }
92
+
93
+ export function setFuaEstado(fuaRequestId: string, estadoId: number, abortController: AbortController) {
94
+ return openmrsFetch(`${ModuleFuaRestURL}/${fuaRequestId}/estado`, {
95
+ method: 'POST',
96
+ headers: {
97
+ 'Content-Type': 'application/json',
98
+ },
99
+ signal: abortController.signal,
100
+ body: { estadoId },
101
+ });
102
+ }
103
+
104
+ export function cancelFuaRequest(fuaRequestId: string, comment: string, abortController: AbortController) {
105
+ return openmrsFetch(`${ModuleFuaRestURL}/${fuaRequestId}/cancel`, {
106
+ method: 'POST',
107
+ headers: {
108
+ 'Content-Type': 'application/json',
109
+ },
110
+ signal: abortController.signal,
111
+ body: { comment },
112
+ });
46
113
  }
47
114
 
48
115
  export default useFuaRequests;
package/src/index.ts CHANGED
@@ -1,15 +1,14 @@
1
1
  import { defineConfigSchema, getAsyncLifecycle, getSyncLifecycle } from '@openmrs/esm-framework';
2
- import { createDashboardLink } from '@openmrs/esm-patient-common-lib';
3
2
  import { configSchema } from './config-schema';
4
3
  import { createLeftPanelLink } from './left-panel-link.component';
5
- import FuaRequestTable from './fua/fuaRequestTable';
6
- import { FuaRequestDashboardMeta } from './dashboard.meta';
4
+ import rootComponent from './root.component';
7
5
 
8
6
  export const importTranslation = require.context('../translations', false, /.json$/, 'lazy');
9
7
 
10
8
  const moduleName = '@pucp-gidis-hiisc/esm-fua-app';
9
+
11
10
  const options = {
12
- featureName: 'patient-clinical-view-app',
11
+ featureName: 'fua',
13
12
  moduleName,
14
13
  };
15
14
 
@@ -21,7 +20,83 @@ export function startupApp(): void {
21
20
  }
22
21
 
23
22
  // ================================================================================
24
- // FUA REQUEST EXPORTS
23
+ // ROOT COMPONENT
24
+ // ================================================================================
25
+ export const root = getSyncLifecycle(rootComponent, options);
26
+
27
+ // ================================================================================
28
+ // DASHBOARD LINK
29
+ // ================================================================================
30
+ export const fuaDashboardLink = getSyncLifecycle(
31
+ createLeftPanelLink({
32
+ name: 'fua-request',
33
+ title: 'Formato Único de Atención',
34
+ }),
35
+ options,
36
+ );
37
+
38
+
39
+ // ================================================================================
40
+ // TILES
41
+ // ================================================================================
42
+ export const allFuaRequestsTile = getAsyncLifecycle(
43
+ () => import('./fua-tiles/all-fua-requests-tile.component'),
44
+ options,
45
+ );
46
+
47
+ export const inProgressFuaRequestsTile = getAsyncLifecycle(
48
+ () => import('./fua-tiles/in-progress-fua-requests-tile.component'),
49
+ options,
50
+ );
51
+
52
+ export const completedFuaRequestsTile = getAsyncLifecycle(
53
+ () => import('./fua-tiles/completed-fua-requests-tile.component'),
54
+ options,
55
+ );
56
+
57
+ // ================================================================================
58
+ // TABLES/TABS
59
+ // ================================================================================
60
+ export const allFuaRequestsTable = getAsyncLifecycle(
61
+ () => import('./fua-tabs/data-table-extensions/all-fua-requests-table.extension'),
62
+ options,
63
+ );
64
+
65
+ export const inProgressFuaRequestsTable = getAsyncLifecycle(
66
+ () => import('./fua-tabs/data-table-extensions/in-progress-fua-requests-table.extension'),
67
+ options,
68
+ );
69
+
70
+ export const completedFuaRequestsTable = getAsyncLifecycle(
71
+ () => import('./fua-tabs/data-table-extensions/completed-fua-requests-table.extension'),
72
+ options,
73
+ );
74
+
75
+ export const declinedFuaRequestsTable = getAsyncLifecycle(
76
+ () => import('./fua-tabs/data-table-extensions/declined-fua-requests-table.extension'),
77
+ options,
78
+ );
79
+
80
+ // ================================================================================
81
+ // HTML VIEWER
82
+ // ================================================================================
83
+ export const fuaHtmlViewer = getAsyncLifecycle(
84
+ () => import('./components/fua-html-viewer.component'),
85
+ options,
86
+ );
87
+
88
+ // ================================================================================
89
+ // WORKSPACES
90
+ // ================================================================================
91
+ export const fuaViewerWorkspace = getAsyncLifecycle(
92
+ () => import('./workspaces/fua-viewer.workspace'),
93
+ options,
94
+ );
95
+
96
+ // ================================================================================
97
+ // FUA VIEWER PAGE
25
98
  // ================================================================================
26
- export const fuaRequestDashboardLink = getSyncLifecycle(createLeftPanelLink(FuaRequestDashboardMeta), options);
27
- export const fuaRequestTable = getSyncLifecycle(FuaRequestTable, options);
99
+ export const fuaViewerPage = getAsyncLifecycle(
100
+ () => import('./fua-viewer-page/fua-viewer-page.component'),
101
+ options,
102
+ );
@@ -0,0 +1,8 @@
1
+ import React from 'react';
2
+ import FuaDashboard from './fua-dashboard.component';
3
+
4
+ const Root: React.FC = () => {
5
+ return <FuaDashboard />;
6
+ };
7
+
8
+ export default Root;