@openmrs/esm-patient-programs-app 8.2.1-pre.5464 → 8.2.1-pre.5474
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.
- package/.turbo/turbo-build.log +5 -5
- package/dist/300.js +1 -1
- package/dist/38.js +1 -1
- package/dist/38.js.map +1 -1
- package/dist/414.js +1 -1
- package/dist/414.js.map +1 -1
- package/dist/683.js +1 -1
- package/dist/683.js.map +1 -1
- package/dist/main.js +1 -1
- package/dist/main.js.map +1 -1
- package/dist/openmrs-esm-patient-programs-app.js +1 -1
- package/dist/openmrs-esm-patient-programs-app.js.buildmanifest.json +14 -14
- package/dist/routes.json +1 -1
- package/package.json +3 -3
- package/src/config-schema.ts +7 -0
- package/src/programs/programs-detailed-summary.component.tsx +26 -16
- package/src/programs/programs-detailed-summary.test.tsx +20 -1
- package/src/programs/programs-form.test.tsx +21 -1
- package/src/programs/programs-form.workspace.tsx +61 -4
- package/src/programs/programs-overview.component.tsx +18 -10
- package/src/programs/programs.resource.tsx +17 -6
- package/src/types/index.ts +21 -17
- package/translations/en.json +3 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
var _openmrs_esm_patient_programs_app;(()=>{"use strict";var e,r,t,n,o,a,i,s,l,p,u,f,d,h,c,m={3864:(e,r,t)=>{var n={"./start":()=>Promise.all([t.e(917),t.e(899),t.e(343),t.e(112),t.e(853),t.e(414)]).then((()=>()=>t(8414)))},o=(e,r)=>(t.R=r,r=t.o(n,e)?n[e]():Promise.resolve().then((()=>{throw new Error('Module "'+e+'" does not exist in container.')})),t.R=void 0,r),a=(e,r)=>{if(t.S){var n="default",o=t.S[n];if(o&&o!==e)throw new Error("Container initialization failed as it has already been initialized with a different share scope");return t.S[n]=e,t.I(n,r)}};t.d(r,{get:()=>o,init:()=>a})}},v={};function g(e){var r=v[e];if(void 0!==r)return r.exports;var t=v[e]={id:e,loaded:!1,exports:{}};return m[e].call(t.exports,t,t.exports,g),t.loaded=!0,t.exports}g.m=m,g.c=v,g.n=e=>{var r=e&&e.__esModule?()=>e.default:()=>e;return g.d(r,{a:r}),r},g.d=(e,r)=>{for(var t in r)g.o(r,t)&&!g.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:r[t]})},g.f={},g.e=e=>Promise.all(Object.keys(g.f).reduce(((r,t)=>(g.f[t](e,r),r)),[])),g.u=e=>e+".js",g.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),g.o=(e,r)=>Object.prototype.hasOwnProperty.call(e,r),e={},r="@openmrs/esm-patient-programs-app:",g.l=(t,n,o,a)=>{if(e[t])e[t].push(n);else{var i,s;if(void 0!==o)for(var l=document.getElementsByTagName("script"),p=0;p<l.length;p++){var u=l[p];if(u.getAttribute("src")==t||u.getAttribute("data-webpack")==r+o){i=u;break}}i||(s=!0,(i=document.createElement("script")).charset="utf-8",i.timeout=120,g.nc&&i.setAttribute("nonce",g.nc),i.setAttribute("data-webpack",r+o),i.src=t),e[t]=[n];var f=(r,n)=>{i.onerror=i.onload=null,clearTimeout(d);var o=e[t];if(delete e[t],i.parentNode&&i.parentNode.removeChild(i),o&&o.forEach((e=>e(n))),r)return r(n)},d=setTimeout(f.bind(null,void 0,{type:"timeout",target:i}),12e4);i.onerror=f.bind(null,i.onerror),i.onload=f.bind(null,i.onload),s&&document.head.appendChild(i)}},g.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},g.nmd=e=>(e.paths=[],e.children||(e.children=[]),e),(()=>{g.S={};var e={},r={};g.I=(t,n)=>{n||(n=[]);var o=r[t];if(o||(o=r[t]={}),!(n.indexOf(o)>=0)){if(n.push(o),e[t])return e[t];g.o(g.S,t)||(g.S[t]={});var a=g.S[t],i="@openmrs/esm-patient-programs-app",s=(e,r,t,n)=>{var o=a[e]=a[e]||{},s=o[r];(!s||!s.loaded&&(!n!=!s.eager?n:i>s.from))&&(o[r]={get:t,from:i,eager:!!n})},l=[];return"default"===t&&(s("@openmrs/esm-framework","5.8.2-pre.2301",(()=>Promise.all([g.e(367),g.e(343)]).then((()=>()=>g(367))))),s("@openmrs/esm-patient-common-lib","8.2.1-pre.
|
|
1
|
+
var _openmrs_esm_patient_programs_app;(()=>{"use strict";var e,r,t,n,o,a,i,s,l,p,u,f,d,h,c,m={3864:(e,r,t)=>{var n={"./start":()=>Promise.all([t.e(917),t.e(899),t.e(343),t.e(112),t.e(853),t.e(414)]).then((()=>()=>t(8414)))},o=(e,r)=>(t.R=r,r=t.o(n,e)?n[e]():Promise.resolve().then((()=>{throw new Error('Module "'+e+'" does not exist in container.')})),t.R=void 0,r),a=(e,r)=>{if(t.S){var n="default",o=t.S[n];if(o&&o!==e)throw new Error("Container initialization failed as it has already been initialized with a different share scope");return t.S[n]=e,t.I(n,r)}};t.d(r,{get:()=>o,init:()=>a})}},v={};function g(e){var r=v[e];if(void 0!==r)return r.exports;var t=v[e]={id:e,loaded:!1,exports:{}};return m[e].call(t.exports,t,t.exports,g),t.loaded=!0,t.exports}g.m=m,g.c=v,g.n=e=>{var r=e&&e.__esModule?()=>e.default:()=>e;return g.d(r,{a:r}),r},g.d=(e,r)=>{for(var t in r)g.o(r,t)&&!g.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:r[t]})},g.f={},g.e=e=>Promise.all(Object.keys(g.f).reduce(((r,t)=>(g.f[t](e,r),r)),[])),g.u=e=>e+".js",g.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),g.o=(e,r)=>Object.prototype.hasOwnProperty.call(e,r),e={},r="@openmrs/esm-patient-programs-app:",g.l=(t,n,o,a)=>{if(e[t])e[t].push(n);else{var i,s;if(void 0!==o)for(var l=document.getElementsByTagName("script"),p=0;p<l.length;p++){var u=l[p];if(u.getAttribute("src")==t||u.getAttribute("data-webpack")==r+o){i=u;break}}i||(s=!0,(i=document.createElement("script")).charset="utf-8",i.timeout=120,g.nc&&i.setAttribute("nonce",g.nc),i.setAttribute("data-webpack",r+o),i.src=t),e[t]=[n];var f=(r,n)=>{i.onerror=i.onload=null,clearTimeout(d);var o=e[t];if(delete e[t],i.parentNode&&i.parentNode.removeChild(i),o&&o.forEach((e=>e(n))),r)return r(n)},d=setTimeout(f.bind(null,void 0,{type:"timeout",target:i}),12e4);i.onerror=f.bind(null,i.onerror),i.onload=f.bind(null,i.onload),s&&document.head.appendChild(i)}},g.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},g.nmd=e=>(e.paths=[],e.children||(e.children=[]),e),(()=>{g.S={};var e={},r={};g.I=(t,n)=>{n||(n=[]);var o=r[t];if(o||(o=r[t]={}),!(n.indexOf(o)>=0)){if(n.push(o),e[t])return e[t];g.o(g.S,t)||(g.S[t]={});var a=g.S[t],i="@openmrs/esm-patient-programs-app",s=(e,r,t,n)=>{var o=a[e]=a[e]||{},s=o[r];(!s||!s.loaded&&(!n!=!s.eager?n:i>s.from))&&(o[r]={get:t,from:i,eager:!!n})},l=[];return"default"===t&&(s("@openmrs/esm-framework","5.8.2-pre.2301",(()=>Promise.all([g.e(367),g.e(343)]).then((()=>()=>g(367))))),s("@openmrs/esm-patient-common-lib","8.2.1-pre.5474",(()=>Promise.all([g.e(917),g.e(899),g.e(343),g.e(112),g.e(923),g.e(853)]).then((()=>()=>g(8923))))),s("dayjs","1.11.11",(()=>g.e(464).then((()=>()=>g(3464))))),s("react-i18next","11.18.6",(()=>Promise.all([g.e(641),g.e(343)]).then((()=>()=>g(4641))))),s("react-router-dom","6.16.0",(()=>Promise.all([g.e(913),g.e(343)]).then((()=>()=>g(2913))))),s("react","18.3.1",(()=>g.e(41).then((()=>()=>g(4041))))),s("swr/_internal","2.2.4",(()=>Promise.all([g.e(74),g.e(343)]).then((()=>()=>g(9074))))),s("swr/immutable","2.2.4",(()=>Promise.all([g.e(917),g.e(343),g.e(112),g.e(610)]).then((()=>()=>g(2610)))))),e[t]=l.length?Promise.all(l).then((()=>e[t]=1)):1}}})(),(()=>{var e;g.g.importScripts&&(e=g.g.location+"");var r=g.g.document;if(!e&&r&&(r.currentScript&&"SCRIPT"===r.currentScript.tagName.toUpperCase()&&(e=r.currentScript.src),!e)){var t=r.getElementsByTagName("script");if(t.length)for(var n=t.length-1;n>-1&&(!e||!/^http(s?):/.test(e));)e=t[n--].src}if(!e)throw new Error("Automatic publicPath is not supported in this browser");e=e.replace(/#.*$/,"").replace(/\?.*$/,"").replace(/\/[^\/]+$/,"/"),g.p=e})(),t=e=>{var r=e=>e.split(".").map((e=>+e==e?+e:e)),t=/^([^-+]+)?(?:-([^+]+))?(?:\+(.+))?$/.exec(e),n=t[1]?r(t[1]):[];return t[2]&&(n.length++,n.push.apply(n,r(t[2]))),t[3]&&(n.push([]),n.push.apply(n,r(t[3]))),n},n=(e,r)=>{e=t(e),r=t(r);for(var n=0;;){if(n>=e.length)return n<r.length&&"u"!=(typeof r[n])[0];var o=e[n],a=(typeof o)[0];if(n>=r.length)return"u"==a;var i=r[n],s=(typeof i)[0];if(a!=s)return"o"==a&&"n"==s||"s"==s||"u"==a;if("o"!=a&&"u"!=a&&o!=i)return o<i;n++}},o=e=>{var r=e[0],t="";if(1===e.length)return"*";if(r+.5){t+=0==r?">=":-1==r?"<":1==r?"^":2==r?"~":r>0?"=":"!=";for(var n=1,a=1;a<e.length;a++)n--,t+="u"==(typeof(s=e[a]))[0]?"-":(n>0?".":"")+(n=2,s);return t}var i=[];for(a=1;a<e.length;a++){var s=e[a];i.push(0===s?"not("+l()+")":1===s?"("+l()+" || "+l()+")":2===s?i.pop()+" "+i.pop():o(s))}return l();function l(){return i.pop().replace(/^\((.+)\)$/,"$1")}},a=(e,r)=>{if(0 in e){r=t(r);var n=e[0],o=n<0;o&&(n=-n-1);for(var i=0,s=1,l=!0;;s++,i++){var p,u,f=s<e.length?(typeof e[s])[0]:"";if(i>=r.length||"o"==(u=(typeof(p=r[i]))[0]))return!l||("u"==f?s>n&&!o:""==f!=o);if("u"==u){if(!l||"u"!=f)return!1}else if(l)if(f==u)if(s<=n){if(p!=e[s])return!1}else{if(o?p>e[s]:p<e[s])return!1;p!=e[s]&&(l=!1)}else if("s"!=f&&"n"!=f){if(o||s<=n)return!1;l=!1,s--}else{if(s<=n||u<f!=o)return!1;l=!1}else"s"!=f&&"n"!=f&&(l=!1,s--)}}var d=[],h=d.pop.bind(d);for(i=1;i<e.length;i++){var c=e[i];d.push(1==c?h()|h():2==c?h()&h():c?a(c,r):!h())}return!!h()},i=(e,r)=>{var t=e[r];return Object.keys(t).reduce(((e,r)=>!e||!t[e].loaded&&n(e,r)?r:e),0)},s=(e,r,t,n)=>"Unsatisfied version "+t+" from "+(t&&e[r][t].from)+" of shared singleton module "+r+" (required "+o(n)+")",l=(e,r,t,n)=>{var o=i(e,t);return a(n,o)||p(s(e,t,o,n)),u(e[t][o])},p=e=>{"undefined"!=typeof console&&console.warn&&console.warn(e)},u=e=>(e.loaded=1,e.get()),f=(e=>function(r,t,n,o){var a=g.I(r);return a&&a.then?a.then(e.bind(e,r,g.S[r],t,n,o)):e(0,g.S[r],t,n,o)})(((e,r,t,n,o)=>r&&g.o(r,t)?l(r,0,t,n):o())),d={},h={1343:()=>f("default","react",[1,18],(()=>g.e(41).then((()=>()=>g(4041))))),6112:()=>f("default","swr/_internal",[1,2],(()=>g.e(74).then((()=>()=>g(9074))))),5260:()=>f("default","swr/immutable",[1,2],(()=>g.e(229).then((()=>()=>g(2610))))),8877:()=>f("default","react-router-dom",[1,6],(()=>g.e(913).then((()=>()=>g(2913))))),1083:()=>f("default","@openmrs/esm-framework",[1,5],(()=>g.e(367).then((()=>()=>g(367))))),3150:()=>f("default","react-i18next",[1,11],(()=>g.e(641).then((()=>()=>g(4641))))),6966:()=>f("default","@openmrs/esm-patient-common-lib",[1,8],(()=>g.e(923).then((()=>()=>g(8923))))),6372:()=>f("default","dayjs",[1,1],(()=>g.e(464).then((()=>()=>g(3464)))))},c={112:[6112],343:[1343],683:[6372],853:[1083,3150,6966],923:[5260,8877]},g.f.consumes=(e,r)=>{g.o(c,e)&&c[e].forEach((e=>{if(g.o(d,e))return r.push(d[e]);var t=r=>{d[e]=0,g.m[e]=t=>{delete g.c[e],t.exports=r()}},n=r=>{delete d[e],g.m[e]=t=>{throw delete g.c[e],r}};try{var o=h[e]();o.then?r.push(d[e]=o.then(t).catch(n)):t(o)}catch(e){n(e)}}))},(()=>{var e={453:0};g.f.j=(r,t)=>{var n=g.o(e,r)?e[r]:void 0;if(0!==n)if(n)t.push(n[2]);else if(/^(112|343|853)$/.test(r))e[r]=0;else{var o=new Promise(((t,o)=>n=e[r]=[t,o]));t.push(n[2]=o);var a=g.p+g.u(r),i=new Error;g.l(a,(t=>{if(g.o(e,r)&&(0!==(n=e[r])&&(e[r]=void 0),n)){var o=t&&("load"===t.type?"missing":t.type),a=t&&t.target&&t.target.src;i.message="Loading chunk "+r+" failed.\n("+o+": "+a+")",i.name="ChunkLoadError",i.type=o,i.request=a,n[1](i)}}),"chunk-"+r,r)}};var r=(r,t)=>{var n,o,[a,i,s]=t,l=0;if(a.some((r=>0!==e[r]))){for(n in i)g.o(i,n)&&(g.m[n]=i[n]);s&&s(g)}for(r&&r(t);l<a.length;l++)o=a[l],g.o(e,o)&&e[o]&&e[o][0](),e[o]=0},t=globalThis.webpackChunk_openmrs_esm_patient_programs_app=globalThis.webpackChunk_openmrs_esm_patient_programs_app||[];t.forEach(r.bind(null,0)),t.push=r.bind(null,t.push.bind(t))})(),g.nc=void 0;var b=g(3864);_openmrs_esm_patient_programs_app=b})();
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"auxiliaryFiles": [
|
|
25
25
|
"38.js.map"
|
|
26
26
|
],
|
|
27
|
-
"hash": "
|
|
27
|
+
"hash": "92eeb45ccf522630",
|
|
28
28
|
"childrenByOrder": {}
|
|
29
29
|
},
|
|
30
30
|
{
|
|
@@ -216,9 +216,9 @@
|
|
|
216
216
|
"initial": false,
|
|
217
217
|
"entry": false,
|
|
218
218
|
"recorded": false,
|
|
219
|
-
"size":
|
|
219
|
+
"size": 1353,
|
|
220
220
|
"sizes": {
|
|
221
|
-
"javascript":
|
|
221
|
+
"javascript": 1353
|
|
222
222
|
},
|
|
223
223
|
"names": [],
|
|
224
224
|
"idHints": [],
|
|
@@ -230,7 +230,7 @@
|
|
|
230
230
|
"300.js"
|
|
231
231
|
],
|
|
232
232
|
"auxiliaryFiles": [],
|
|
233
|
-
"hash": "
|
|
233
|
+
"hash": "156fb5ceb756e00c",
|
|
234
234
|
"childrenByOrder": {}
|
|
235
235
|
},
|
|
236
236
|
{
|
|
@@ -308,9 +308,9 @@
|
|
|
308
308
|
"initial": false,
|
|
309
309
|
"entry": false,
|
|
310
310
|
"recorded": false,
|
|
311
|
-
"size":
|
|
311
|
+
"size": 52324,
|
|
312
312
|
"sizes": {
|
|
313
|
-
"javascript":
|
|
313
|
+
"javascript": 52324
|
|
314
314
|
},
|
|
315
315
|
"names": [],
|
|
316
316
|
"idHints": [],
|
|
@@ -323,7 +323,7 @@
|
|
|
323
323
|
"auxiliaryFiles": [
|
|
324
324
|
"414.js.map"
|
|
325
325
|
],
|
|
326
|
-
"hash": "
|
|
326
|
+
"hash": "4a9f9d004a7c6567",
|
|
327
327
|
"childrenByOrder": {}
|
|
328
328
|
},
|
|
329
329
|
{
|
|
@@ -350,7 +350,7 @@
|
|
|
350
350
|
"auxiliaryFiles": [
|
|
351
351
|
"openmrs-esm-patient-programs-app.js.map"
|
|
352
352
|
],
|
|
353
|
-
"hash": "
|
|
353
|
+
"hash": "89f9fb5b9db68a44",
|
|
354
354
|
"childrenByOrder": {}
|
|
355
355
|
},
|
|
356
356
|
{
|
|
@@ -477,9 +477,9 @@
|
|
|
477
477
|
"initial": false,
|
|
478
478
|
"entry": false,
|
|
479
479
|
"recorded": false,
|
|
480
|
-
"size":
|
|
480
|
+
"size": 60234,
|
|
481
481
|
"sizes": {
|
|
482
|
-
"javascript":
|
|
482
|
+
"javascript": 60192,
|
|
483
483
|
"consume-shared": 42
|
|
484
484
|
},
|
|
485
485
|
"names": [],
|
|
@@ -494,7 +494,7 @@
|
|
|
494
494
|
"auxiliaryFiles": [
|
|
495
495
|
"683.js.map"
|
|
496
496
|
],
|
|
497
|
-
"hash": "
|
|
497
|
+
"hash": "0118719c9ef03e19",
|
|
498
498
|
"childrenByOrder": {}
|
|
499
499
|
},
|
|
500
500
|
{
|
|
@@ -502,10 +502,10 @@
|
|
|
502
502
|
"initial": true,
|
|
503
503
|
"entry": true,
|
|
504
504
|
"recorded": false,
|
|
505
|
-
"size":
|
|
505
|
+
"size": 2211239,
|
|
506
506
|
"sizes": {
|
|
507
507
|
"consume-shared": 210,
|
|
508
|
-
"javascript":
|
|
508
|
+
"javascript": 2189295,
|
|
509
509
|
"share-init": 336,
|
|
510
510
|
"runtime": 21398
|
|
511
511
|
},
|
|
@@ -522,7 +522,7 @@
|
|
|
522
522
|
"auxiliaryFiles": [
|
|
523
523
|
"main.js.map"
|
|
524
524
|
],
|
|
525
|
-
"hash": "
|
|
525
|
+
"hash": "9603c33df0c5a159",
|
|
526
526
|
"childrenByOrder": {}
|
|
527
527
|
},
|
|
528
528
|
{
|
package/dist/routes.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"$schema":"https://json.openmrs.org/routes.schema.json","backendDependencies":{"webservices.rest":"^2.2.0"},"extensions":[{"name":"programs-overview-widget","component":"programsOverview","meta":{"fullWidth":false},"order":6},{"name":"programs-details-widget","slot":"patient-chart-programs-dashboard-slot","component":"programsDetailedSummary","order":6},{"name":"programs-summary-dashboard","slot":"patient-chart-dashboard-slot","component":"programsDashboardLink","meta":{"slot":"patient-chart-programs-dashboard-slot","path":"Programs"},"order":10}],"pages":[],"workspaces":[{"name":"programs-form-workspace","title":"programEnrollmentWorkspaceTitle","component":"programsFormWorkspace"}],"version":"8.2.1-pre.
|
|
1
|
+
{"$schema":"https://json.openmrs.org/routes.schema.json","backendDependencies":{"webservices.rest":"^2.2.0"},"extensions":[{"name":"programs-overview-widget","component":"programsOverview","meta":{"fullWidth":false},"order":6},{"name":"programs-details-widget","slot":"patient-chart-programs-dashboard-slot","component":"programsDetailedSummary","order":6},{"name":"programs-summary-dashboard","slot":"patient-chart-dashboard-slot","component":"programsDashboardLink","meta":{"slot":"patient-chart-programs-dashboard-slot","path":"Programs"},"order":10}],"pages":[],"workspaces":[{"name":"programs-form-workspace","title":"programEnrollmentWorkspaceTitle","component":"programsFormWorkspace"}],"version":"8.2.1-pre.5474"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openmrs/esm-patient-programs-app",
|
|
3
|
-
"version": "8.2.1-pre.
|
|
3
|
+
"version": "8.2.1-pre.5474",
|
|
4
4
|
"license": "MPL-2.0",
|
|
5
5
|
"description": "Patient programs microfrontend for the OpenMRS SPA",
|
|
6
6
|
"browser": "dist/openmrs-esm-patient-programs-app.js",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
40
|
"@carbon/react": "^1.12.0",
|
|
41
|
-
"@openmrs/esm-patient-common-lib": "^8.2.1-pre.
|
|
41
|
+
"@openmrs/esm-patient-common-lib": "^8.2.1-pre.5474",
|
|
42
42
|
"lodash-es": "^4.17.21"
|
|
43
43
|
},
|
|
44
44
|
"peerDependencies": {
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
"swr": "2.x"
|
|
53
53
|
},
|
|
54
54
|
"devDependencies": {
|
|
55
|
-
"@openmrs/esm-patient-common-lib": "8.2.1-pre.
|
|
55
|
+
"@openmrs/esm-patient-common-lib": "8.2.1-pre.5474",
|
|
56
56
|
"webpack": "^5.94.0"
|
|
57
57
|
},
|
|
58
58
|
"stableVersion": "8.2.0"
|
package/src/config-schema.ts
CHANGED
|
@@ -5,8 +5,15 @@ export const configSchema = {
|
|
|
5
5
|
_type: Type.Boolean,
|
|
6
6
|
_default: false,
|
|
7
7
|
},
|
|
8
|
+
showProgramStatusField: {
|
|
9
|
+
_type: Type.Boolean,
|
|
10
|
+
_description:
|
|
11
|
+
'Whether to show the Program status field in the Record program enrollment and Edit program enrollment forms. If set to true, the `Program status` field is displayed in the Programs datatable',
|
|
12
|
+
_default: false,
|
|
13
|
+
},
|
|
8
14
|
};
|
|
9
15
|
|
|
10
16
|
export interface ConfigObject {
|
|
11
17
|
hideAddProgramButton: boolean;
|
|
18
|
+
showProgramStatusField: boolean;
|
|
12
19
|
}
|
|
@@ -26,7 +26,7 @@ import {
|
|
|
26
26
|
isDesktop as desktopLayout,
|
|
27
27
|
} from '@openmrs/esm-framework';
|
|
28
28
|
import { CardHeader, EmptyState, ErrorState, launchPatientWorkspace } from '@openmrs/esm-patient-common-lib';
|
|
29
|
-
import { usePrograms } from './programs.resource';
|
|
29
|
+
import { findLastState, usePrograms } from './programs.resource';
|
|
30
30
|
import styles from './programs-detailed-summary.scss';
|
|
31
31
|
|
|
32
32
|
interface ProgramsDetailedSummaryProps {
|
|
@@ -40,7 +40,7 @@ interface ProgramEditButtonProps {
|
|
|
40
40
|
|
|
41
41
|
const ProgramsDetailedSummary: React.FC<ProgramsDetailedSummaryProps> = ({ patientUuid }) => {
|
|
42
42
|
const { t } = useTranslation();
|
|
43
|
-
const { hideAddProgramButton } = useConfig<ConfigObject>();
|
|
43
|
+
const { hideAddProgramButton, showProgramStatusField } = useConfig<ConfigObject>();
|
|
44
44
|
const layout = useLayoutType();
|
|
45
45
|
const isTablet = layout === 'tablet';
|
|
46
46
|
const isDesktop = desktopLayout(layout);
|
|
@@ -49,8 +49,8 @@ const ProgramsDetailedSummary: React.FC<ProgramsDetailedSummaryProps> = ({ patie
|
|
|
49
49
|
|
|
50
50
|
const { enrollments, isLoading, error, isValidating, availablePrograms } = usePrograms(patientUuid);
|
|
51
51
|
|
|
52
|
-
const tableHeaders: Array<typeof DataTableHeader> = useMemo(
|
|
53
|
-
|
|
52
|
+
const tableHeaders: Array<typeof DataTableHeader> = useMemo(() => {
|
|
53
|
+
const headers = [
|
|
54
54
|
{
|
|
55
55
|
key: 'display',
|
|
56
56
|
header: t('activePrograms', 'Active programs'),
|
|
@@ -67,21 +67,31 @@ const ProgramsDetailedSummary: React.FC<ProgramsDetailedSummaryProps> = ({ patie
|
|
|
67
67
|
key: 'status',
|
|
68
68
|
header: t('status', 'Status'),
|
|
69
69
|
},
|
|
70
|
-
]
|
|
71
|
-
|
|
72
|
-
|
|
70
|
+
];
|
|
71
|
+
if (showProgramStatusField) {
|
|
72
|
+
headers.push({
|
|
73
|
+
key: 'state',
|
|
74
|
+
header: t('programStatus', 'Program status'),
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
return headers;
|
|
78
|
+
}, [t, showProgramStatusField]);
|
|
73
79
|
|
|
74
80
|
const tableRows = useMemo(
|
|
75
81
|
() =>
|
|
76
|
-
enrollments?.map((program) =>
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
:
|
|
84
|
-
|
|
82
|
+
enrollments?.map((program) => {
|
|
83
|
+
const state = program ? findLastState(program.states) : null;
|
|
84
|
+
return {
|
|
85
|
+
id: program.uuid,
|
|
86
|
+
display: program.display,
|
|
87
|
+
location: program.location?.display ?? '--',
|
|
88
|
+
dateEnrolled: formatDatetime(new Date(program.dateEnrolled)),
|
|
89
|
+
status: program.dateCompleted
|
|
90
|
+
? `${t('completedOn', 'Completed On')} ${formatDate(new Date(program.dateCompleted))}`
|
|
91
|
+
: t('active', 'Active'),
|
|
92
|
+
state: state ? state.state.concept.display : '--',
|
|
93
|
+
};
|
|
94
|
+
}),
|
|
85
95
|
[enrollments, t],
|
|
86
96
|
);
|
|
87
97
|
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import userEvent from '@testing-library/user-event';
|
|
3
3
|
import { screen, within } from '@testing-library/react';
|
|
4
|
-
import { openmrsFetch } from '@openmrs/esm-framework';
|
|
4
|
+
import { getDefaultsFromConfigSchema, openmrsFetch, useConfig } from '@openmrs/esm-framework';
|
|
5
5
|
import { launchPatientWorkspace } from '@openmrs/esm-patient-common-lib';
|
|
6
6
|
import { mockCareProgramsResponse, mockEnrolledInAllProgramsResponse, mockEnrolledProgramsResponse } from '__mocks__';
|
|
7
7
|
import { mockPatient, renderWithSwr, waitForLoadingToFinish } from 'tools';
|
|
8
|
+
import { type ConfigObject, configSchema } from '../config-schema';
|
|
8
9
|
import ProgramsDetailedSummary from './programs-detailed-summary.component';
|
|
9
10
|
|
|
10
11
|
const mockOpenmrsFetch = openmrsFetch as jest.Mock;
|
|
12
|
+
const mockUseConfig = jest.mocked(useConfig<ConfigObject>);
|
|
11
13
|
|
|
12
14
|
jest.mock('@openmrs/esm-patient-common-lib', () => {
|
|
13
15
|
const originalModule = jest.requireActual('@openmrs/esm-patient-common-lib');
|
|
@@ -107,4 +109,21 @@ describe('ProgramsDetailedSummary', () => {
|
|
|
107
109
|
expect(screen.getByText(/enrolled in all programs/i)).toBeInTheDocument();
|
|
108
110
|
expect(screen.getByText(/there are no more programs left to enroll this patient in/i)).toBeInTheDocument();
|
|
109
111
|
});
|
|
112
|
+
|
|
113
|
+
it('renders the programs status field', async () => {
|
|
114
|
+
const user = userEvent.setup();
|
|
115
|
+
|
|
116
|
+
mockOpenmrsFetch.mockReturnValueOnce({ data: { results: mockEnrolledProgramsResponse } });
|
|
117
|
+
|
|
118
|
+
mockUseConfig.mockReturnValue({
|
|
119
|
+
...getDefaultsFromConfigSchema(configSchema),
|
|
120
|
+
showProgramStatusField: true,
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
renderWithSwr(<ProgramsDetailedSummary patientUuid={mockPatient.id} />);
|
|
124
|
+
|
|
125
|
+
await waitForLoadingToFinish();
|
|
126
|
+
|
|
127
|
+
expect(screen.getByRole('columnheader', { name: /program status/i })).toBeInTheDocument();
|
|
128
|
+
});
|
|
110
129
|
});
|
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import userEvent from '@testing-library/user-event';
|
|
3
3
|
import { render, screen } from '@testing-library/react';
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
type FetchResponse,
|
|
6
|
+
showSnackbar,
|
|
7
|
+
useLocations,
|
|
8
|
+
useConfig,
|
|
9
|
+
getDefaultsFromConfigSchema,
|
|
10
|
+
} from '@openmrs/esm-framework';
|
|
5
11
|
import { mockCareProgramsResponse, mockEnrolledProgramsResponse, mockLocationsResponse } from '__mocks__';
|
|
6
12
|
import { mockPatient } from 'tools';
|
|
7
13
|
import {
|
|
@@ -11,6 +17,7 @@ import {
|
|
|
11
17
|
useEnrollments,
|
|
12
18
|
} from './programs.resource';
|
|
13
19
|
import ProgramsForm from './programs-form.workspace';
|
|
20
|
+
import { type ConfigObject, configSchema } from '../config-schema';
|
|
14
21
|
|
|
15
22
|
const mockUseAvailablePrograms = jest.mocked(useAvailablePrograms);
|
|
16
23
|
const mockUseEnrollments = jest.mocked(useEnrollments);
|
|
@@ -21,6 +28,7 @@ const mockUseLocations = jest.mocked(useLocations);
|
|
|
21
28
|
const mockCloseWorkspace = jest.fn();
|
|
22
29
|
const mockCloseWorkspaceWithSavedChanges = jest.fn();
|
|
23
30
|
const mockPromptBeforeClosing = jest.fn();
|
|
31
|
+
const mockUseConfig = jest.mocked(useConfig<ConfigObject>);
|
|
24
32
|
|
|
25
33
|
const testProps = {
|
|
26
34
|
closeWorkspace: mockCloseWorkspace,
|
|
@@ -38,6 +46,7 @@ jest.mock('./programs.resource', () => ({
|
|
|
38
46
|
updateProgramEnrollment: jest.fn(),
|
|
39
47
|
useAvailablePrograms: jest.fn(),
|
|
40
48
|
useEnrollments: jest.fn(),
|
|
49
|
+
findLastState: jest.fn(),
|
|
41
50
|
}));
|
|
42
51
|
|
|
43
52
|
mockUseLocations.mockReturnValue(mockLocationsResponse);
|
|
@@ -145,6 +154,17 @@ describe('ProgramsForm', () => {
|
|
|
145
154
|
}),
|
|
146
155
|
);
|
|
147
156
|
});
|
|
157
|
+
|
|
158
|
+
it('renders the programs status field if the config property is set to true', async () => {
|
|
159
|
+
mockUseConfig.mockReturnValue({
|
|
160
|
+
...getDefaultsFromConfigSchema(configSchema),
|
|
161
|
+
showProgramStatusField: true,
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
renderProgramsForm();
|
|
165
|
+
|
|
166
|
+
expect(screen.getByLabelText(/program status/i)).toBeInTheDocument();
|
|
167
|
+
});
|
|
148
168
|
});
|
|
149
169
|
|
|
150
170
|
function renderProgramsForm(programEnrollmentUuidToEdit?: string) {
|
|
@@ -16,15 +16,16 @@ import {
|
|
|
16
16
|
Stack,
|
|
17
17
|
} from '@carbon/react';
|
|
18
18
|
import { z } from 'zod';
|
|
19
|
-
import { useForm, Controller } from 'react-hook-form';
|
|
19
|
+
import { useForm, Controller, useWatch } from 'react-hook-form';
|
|
20
20
|
import { zodResolver } from '@hookform/resolvers/zod';
|
|
21
|
-
import { parseDate, showSnackbar, useLayoutType, useLocations, useSession } from '@openmrs/esm-framework';
|
|
21
|
+
import { parseDate, showSnackbar, useConfig, useLayoutType, useLocations, useSession } from '@openmrs/esm-framework';
|
|
22
22
|
import { type DefaultPatientWorkspaceProps } from '@openmrs/esm-patient-common-lib';
|
|
23
23
|
import {
|
|
24
24
|
createProgramEnrollment,
|
|
25
25
|
useAvailablePrograms,
|
|
26
26
|
useEnrollments,
|
|
27
27
|
updateProgramEnrollment,
|
|
28
|
+
findLastState,
|
|
28
29
|
} from './programs.resource';
|
|
29
30
|
import styles from './programs-form.scss';
|
|
30
31
|
|
|
@@ -38,6 +39,7 @@ const createProgramsFormSchema = (t: TFunction) =>
|
|
|
38
39
|
enrollmentDate: z.date(),
|
|
39
40
|
completionDate: z.date().nullable(),
|
|
40
41
|
enrollmentLocation: z.string(),
|
|
42
|
+
selectedProgramStatus: z.string(),
|
|
41
43
|
});
|
|
42
44
|
|
|
43
45
|
export type ProgramsFormData = z.infer<ReturnType<typeof createProgramsFormSchema>>;
|
|
@@ -56,6 +58,7 @@ const ProgramsForm: React.FC<ProgramsFormProps> = ({
|
|
|
56
58
|
const { data: availablePrograms } = useAvailablePrograms();
|
|
57
59
|
const { data: enrollments, mutateEnrollments } = useEnrollments(patientUuid);
|
|
58
60
|
const [isSubmittingForm, setIsSubmittingForm] = useState(false);
|
|
61
|
+
const { showProgramStatusField } = useConfig();
|
|
59
62
|
|
|
60
63
|
const programsFormSchema = useMemo(() => createProgramsFormSchema(t), [t]);
|
|
61
64
|
|
|
@@ -81,6 +84,8 @@ const ProgramsForm: React.FC<ProgramsFormProps> = ({
|
|
|
81
84
|
return currentEnrollment?.location.uuid ?? null;
|
|
82
85
|
};
|
|
83
86
|
|
|
87
|
+
const currentState = currentEnrollment ? findLastState(currentEnrollment.states) : null;
|
|
88
|
+
|
|
84
89
|
const {
|
|
85
90
|
control,
|
|
86
91
|
handleSubmit,
|
|
@@ -94,16 +99,19 @@ const ProgramsForm: React.FC<ProgramsFormProps> = ({
|
|
|
94
99
|
enrollmentDate: currentEnrollment?.dateEnrolled ? parseDate(currentEnrollment.dateEnrolled) : new Date(),
|
|
95
100
|
completionDate: currentEnrollment?.dateCompleted ? parseDate(currentEnrollment.dateCompleted) : null,
|
|
96
101
|
enrollmentLocation: getLocationUuid() ?? '',
|
|
102
|
+
selectedProgramStatus: currentState?.state.uuid ?? '',
|
|
97
103
|
},
|
|
98
104
|
});
|
|
99
105
|
|
|
106
|
+
const selectedProgram = useWatch({ control, name: 'selectedProgram' });
|
|
107
|
+
|
|
100
108
|
useEffect(() => {
|
|
101
109
|
promptBeforeClosing(() => isDirty);
|
|
102
110
|
}, [isDirty, promptBeforeClosing]);
|
|
103
111
|
|
|
104
112
|
const onSubmit = useCallback(
|
|
105
113
|
async (data: ProgramsFormData) => {
|
|
106
|
-
const { selectedProgram, enrollmentDate, completionDate, enrollmentLocation } = data;
|
|
114
|
+
const { selectedProgram, enrollmentDate, completionDate, enrollmentLocation, selectedProgramStatus } = data;
|
|
107
115
|
|
|
108
116
|
const payload = {
|
|
109
117
|
patient: patientUuid,
|
|
@@ -111,9 +119,15 @@ const ProgramsForm: React.FC<ProgramsFormProps> = ({
|
|
|
111
119
|
dateEnrolled: enrollmentDate ? dayjs(enrollmentDate).format() : null,
|
|
112
120
|
dateCompleted: completionDate ? dayjs(completionDate).format() : null,
|
|
113
121
|
location: enrollmentLocation,
|
|
122
|
+
states:
|
|
123
|
+
!!selectedProgramStatus && selectedProgramStatus != currentState?.state.uuid
|
|
124
|
+
? [{ state: { uuid: selectedProgramStatus } }]
|
|
125
|
+
: [],
|
|
114
126
|
};
|
|
115
127
|
|
|
116
128
|
try {
|
|
129
|
+
setIsSubmittingForm(true);
|
|
130
|
+
|
|
117
131
|
const abortController = new AbortController();
|
|
118
132
|
|
|
119
133
|
if (currentEnrollment) {
|
|
@@ -144,7 +158,7 @@ const ProgramsForm: React.FC<ProgramsFormProps> = ({
|
|
|
144
158
|
|
|
145
159
|
setIsSubmittingForm(false);
|
|
146
160
|
},
|
|
147
|
-
[closeWorkspaceWithSavedChanges, currentEnrollment, mutateEnrollments, patientUuid, t],
|
|
161
|
+
[closeWorkspaceWithSavedChanges, currentEnrollment, currentState, mutateEnrollments, patientUuid, t],
|
|
148
162
|
);
|
|
149
163
|
|
|
150
164
|
const programSelect = (
|
|
@@ -241,6 +255,41 @@ const ProgramsForm: React.FC<ProgramsFormProps> = ({
|
|
|
241
255
|
/>
|
|
242
256
|
);
|
|
243
257
|
|
|
258
|
+
let workflowStates = [];
|
|
259
|
+
if (!currentProgram && !!selectedProgram) {
|
|
260
|
+
const program = eligiblePrograms.find((p) => p.uuid === selectedProgram);
|
|
261
|
+
if (program?.allWorkflows.length > 0) workflowStates = program.allWorkflows[0].states;
|
|
262
|
+
} else if (currentProgram?.allWorkflows.length > 0) {
|
|
263
|
+
workflowStates = currentProgram.allWorkflows[0].states;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
const programStatusDropdown = (
|
|
267
|
+
<Controller
|
|
268
|
+
name="selectedProgramStatus"
|
|
269
|
+
control={control}
|
|
270
|
+
render={({ fieldState, field: { onChange, value } }) => (
|
|
271
|
+
<>
|
|
272
|
+
<Select
|
|
273
|
+
aria-label={t('programStatus', 'Program status')}
|
|
274
|
+
id="programStatus"
|
|
275
|
+
invalid={!!fieldState?.error}
|
|
276
|
+
labelText={t('programStatus', 'Program status')}
|
|
277
|
+
onChange={(event) => onChange(event.target.value)}
|
|
278
|
+
value={value}
|
|
279
|
+
>
|
|
280
|
+
<SelectItem text={t('chooseStatus', 'Choose a program status')} value="" />
|
|
281
|
+
{workflowStates.map((state) => (
|
|
282
|
+
<SelectItem key={state.uuid} text={state.concept.display} value={state.uuid}>
|
|
283
|
+
{state.concept.display}
|
|
284
|
+
</SelectItem>
|
|
285
|
+
))}
|
|
286
|
+
</Select>
|
|
287
|
+
<p className={styles.errorMessage}>{fieldState?.error?.message}</p>
|
|
288
|
+
</>
|
|
289
|
+
)}
|
|
290
|
+
/>
|
|
291
|
+
);
|
|
292
|
+
|
|
244
293
|
const formGroups = [
|
|
245
294
|
{
|
|
246
295
|
style: { maxWidth: isTablet && '50%' },
|
|
@@ -264,6 +313,14 @@ const ProgramsForm: React.FC<ProgramsFormProps> = ({
|
|
|
264
313
|
},
|
|
265
314
|
];
|
|
266
315
|
|
|
316
|
+
if (showProgramStatusField) {
|
|
317
|
+
formGroups.push({
|
|
318
|
+
style: { width: '50%' },
|
|
319
|
+
legendText: '',
|
|
320
|
+
value: programStatusDropdown,
|
|
321
|
+
});
|
|
322
|
+
}
|
|
323
|
+
|
|
267
324
|
return (
|
|
268
325
|
<Form className={styles.form} onSubmit={handleSubmit(onSubmit)}>
|
|
269
326
|
<Stack className={styles.formContainer} gap={7}>
|
|
@@ -32,7 +32,7 @@ import {
|
|
|
32
32
|
usePagination,
|
|
33
33
|
isDesktop as desktopLayout,
|
|
34
34
|
} from '@openmrs/esm-framework';
|
|
35
|
-
import { usePrograms } from './programs.resource';
|
|
35
|
+
import { findLastState, usePrograms } from './programs.resource';
|
|
36
36
|
import { type ConfigurableProgram } from '../types';
|
|
37
37
|
import styles from './programs-overview.scss';
|
|
38
38
|
|
|
@@ -77,6 +77,10 @@ const ProgramsOverview: React.FC<ProgramsOverviewProps> = ({ basePath, patientUu
|
|
|
77
77
|
key: 'status',
|
|
78
78
|
header: t('status', 'Status'),
|
|
79
79
|
},
|
|
80
|
+
{
|
|
81
|
+
key: 'state',
|
|
82
|
+
header: t('state', 'State'),
|
|
83
|
+
},
|
|
80
84
|
{
|
|
81
85
|
key: 'actions',
|
|
82
86
|
header: t('actions', 'Actions'),
|
|
@@ -84,15 +88,19 @@ const ProgramsOverview: React.FC<ProgramsOverviewProps> = ({ basePath, patientUu
|
|
|
84
88
|
];
|
|
85
89
|
|
|
86
90
|
const tableRows = React.useMemo(() => {
|
|
87
|
-
return paginatedEnrollments?.map((enrollment: ConfigurableProgram) =>
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
:
|
|
95
|
-
|
|
91
|
+
return paginatedEnrollments?.map((enrollment: ConfigurableProgram) => {
|
|
92
|
+
const state = enrollment ? findLastState(enrollment.states) : null;
|
|
93
|
+
return {
|
|
94
|
+
id: enrollment.uuid,
|
|
95
|
+
display: enrollment.display,
|
|
96
|
+
location: enrollment.location?.display ?? '--',
|
|
97
|
+
dateEnrolled: enrollment.dateEnrolled ? formatDatetime(new Date(enrollment.dateEnrolled)) : '--',
|
|
98
|
+
status: enrollment.dateCompleted
|
|
99
|
+
? `${t('completedOn', 'Completed On')} ${formatDate(new Date(enrollment.dateCompleted))}`
|
|
100
|
+
: t('active', 'Active'),
|
|
101
|
+
state: state ? state.state.concept.display : '--',
|
|
102
|
+
};
|
|
103
|
+
});
|
|
96
104
|
}, [paginatedEnrollments, t]);
|
|
97
105
|
|
|
98
106
|
if (isLoading) return <DataTableSkeleton role="progressbar" compact={isDesktop} zebra />;
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import useSWR from 'swr';
|
|
2
2
|
import { openmrsFetch, restBaseUrl } from '@openmrs/esm-framework';
|
|
3
|
-
import { type PatientProgram, type Program, type ProgramsFetchResponse } from '../types';
|
|
3
|
+
import { type ProgramWorkflowState, type PatientProgram, type Program, type ProgramsFetchResponse } from '../types';
|
|
4
4
|
import uniqBy from 'lodash-es/uniqBy';
|
|
5
5
|
import filter from 'lodash-es/filter';
|
|
6
6
|
import includes from 'lodash-es/includes';
|
|
7
7
|
import map from 'lodash-es/map';
|
|
8
8
|
|
|
9
|
-
export const customRepresentation = `custom:(uuid,display,program,dateEnrolled,dateCompleted,location:(uuid,display))`;
|
|
9
|
+
export const customRepresentation = `custom:(uuid,display,program,dateEnrolled,dateCompleted,location:(uuid,display),states:(startDate,endDate,voided,state:(uuid,concept:(display))))`;
|
|
10
10
|
|
|
11
11
|
export function useEnrollments(patientUuid: string) {
|
|
12
12
|
const enrollmentsUrl = `${restBaseUrl}/programenrollment?patient=${patientUuid}&v=${customRepresentation}`;
|
|
@@ -57,13 +57,13 @@ export function createProgramEnrollment(payload, abortController) {
|
|
|
57
57
|
if (!payload) {
|
|
58
58
|
return null;
|
|
59
59
|
}
|
|
60
|
-
const { program, patient, dateEnrolled, dateCompleted, location } = payload;
|
|
60
|
+
const { program, patient, dateEnrolled, dateCompleted, location, states } = payload;
|
|
61
61
|
return openmrsFetch(`${restBaseUrl}/programenrollment`, {
|
|
62
62
|
method: 'POST',
|
|
63
63
|
headers: {
|
|
64
64
|
'Content-Type': 'application/json',
|
|
65
65
|
},
|
|
66
|
-
body: { program, patient, dateEnrolled, dateCompleted, location },
|
|
66
|
+
body: { program, patient, dateEnrolled, dateCompleted, location, states },
|
|
67
67
|
signal: abortController.signal,
|
|
68
68
|
});
|
|
69
69
|
}
|
|
@@ -72,13 +72,13 @@ export function updateProgramEnrollment(programEnrollmentUuid: string, payload,
|
|
|
72
72
|
if (!payload && !payload.program) {
|
|
73
73
|
return null;
|
|
74
74
|
}
|
|
75
|
-
const { dateEnrolled, dateCompleted, location } = payload;
|
|
75
|
+
const { dateEnrolled, dateCompleted, location, states } = payload;
|
|
76
76
|
return openmrsFetch(`${restBaseUrl}/programenrollment/${programEnrollmentUuid}`, {
|
|
77
77
|
method: 'POST',
|
|
78
78
|
headers: {
|
|
79
79
|
'Content-Type': 'application/json',
|
|
80
80
|
},
|
|
81
|
-
body: { dateEnrolled, dateCompleted, location },
|
|
81
|
+
body: { dateEnrolled, dateCompleted, location, states },
|
|
82
82
|
signal: abortController.signal,
|
|
83
83
|
});
|
|
84
84
|
}
|
|
@@ -103,3 +103,14 @@ export const usePrograms = (patientUuid: string) => {
|
|
|
103
103
|
eligiblePrograms,
|
|
104
104
|
};
|
|
105
105
|
};
|
|
106
|
+
|
|
107
|
+
export const findLastState = (states: ProgramWorkflowState[]): ProgramWorkflowState => {
|
|
108
|
+
const activeStates = states.filter((state) => !state.voided);
|
|
109
|
+
const ongoingState = activeStates.find((state) => !state.endDate);
|
|
110
|
+
|
|
111
|
+
if (ongoingState) {
|
|
112
|
+
return ongoingState;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
return activeStates.sort((a, b) => new Date(b.endDate).getTime() - new Date(a.endDate).getTime())[0];
|
|
116
|
+
};
|