@ampath/esm-dha-workflow-app 4.0.0-next.33 → 4.0.0-next.331

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 (758) hide show
  1. package/README.md +19 -0
  2. package/dist/1149.js +1 -0
  3. package/dist/1149.js.map +1 -0
  4. package/dist/1197.js +1 -0
  5. package/dist/1362.js +1 -0
  6. package/dist/1362.js.map +1 -0
  7. package/dist/1551.js +1 -0
  8. package/dist/1551.js.map +1 -0
  9. package/dist/1925.js +1 -0
  10. package/dist/1925.js.map +1 -0
  11. package/dist/1927.js +1 -0
  12. package/dist/1927.js.map +1 -0
  13. package/dist/203.js +1 -0
  14. package/dist/203.js.map +1 -0
  15. package/dist/2054.js +1 -0
  16. package/dist/2054.js.map +1 -0
  17. package/dist/2093.js +1 -0
  18. package/dist/2093.js.map +1 -0
  19. package/dist/2177.js +2 -0
  20. package/dist/2177.js.map +1 -0
  21. package/dist/2200.js +1 -0
  22. package/dist/2200.js.map +1 -0
  23. package/dist/2230.js +1 -0
  24. package/dist/2230.js.map +1 -0
  25. package/dist/2493.js +1 -0
  26. package/dist/2493.js.map +1 -0
  27. package/dist/262.js +2 -0
  28. package/dist/262.js.map +1 -0
  29. package/dist/2914.js +1 -0
  30. package/dist/2914.js.map +1 -0
  31. package/dist/2936.js +1 -0
  32. package/dist/2936.js.map +1 -0
  33. package/dist/2988.js +1 -0
  34. package/dist/2988.js.map +1 -0
  35. package/dist/3041.js +1 -0
  36. package/dist/3041.js.map +1 -0
  37. package/dist/307.js +1 -0
  38. package/dist/307.js.map +1 -0
  39. package/dist/3099.js +1 -0
  40. package/dist/3184.js +2 -0
  41. package/dist/3184.js.map +1 -0
  42. package/dist/3202.js +1 -0
  43. package/dist/3202.js.map +1 -0
  44. package/dist/3222.js +1 -0
  45. package/dist/3222.js.map +1 -0
  46. package/dist/3406.js +1 -0
  47. package/dist/3406.js.map +1 -0
  48. package/dist/347.js +1 -0
  49. package/dist/347.js.map +1 -0
  50. package/dist/3654.js +1 -0
  51. package/dist/3654.js.map +1 -0
  52. package/dist/4003.js +1 -0
  53. package/dist/4003.js.map +1 -0
  54. package/dist/4008.js +1 -0
  55. package/dist/4008.js.map +1 -0
  56. package/dist/4055.js +1 -0
  57. package/dist/4205.js +1 -0
  58. package/dist/4205.js.map +1 -0
  59. package/dist/4225.js +1 -0
  60. package/dist/4225.js.map +1 -0
  61. package/dist/4231.js +1 -0
  62. package/dist/4231.js.map +1 -0
  63. package/dist/4300.js +1 -0
  64. package/dist/4335.js +1 -0
  65. package/dist/4353.js +1 -0
  66. package/dist/4353.js.map +1 -0
  67. package/dist/4431.js +1 -0
  68. package/dist/4431.js.map +1 -0
  69. package/dist/4454.js +1 -0
  70. package/dist/4454.js.map +1 -0
  71. package/dist/4457.js +2 -0
  72. package/dist/4457.js.LICENSE.txt +282 -0
  73. package/dist/4457.js.map +1 -0
  74. package/dist/446.js +1 -0
  75. package/dist/446.js.map +1 -0
  76. package/dist/4611.js +1 -0
  77. package/dist/4611.js.map +1 -0
  78. package/dist/4652.js +1 -0
  79. package/dist/4674.js +1 -0
  80. package/dist/4674.js.map +1 -0
  81. package/dist/4755.js +1 -0
  82. package/dist/4755.js.map +1 -0
  83. package/dist/4986.js +1 -0
  84. package/dist/4986.js.map +1 -0
  85. package/dist/5097.js +1 -0
  86. package/dist/5097.js.map +1 -0
  87. package/dist/5119.js +1 -0
  88. package/dist/5119.js.map +1 -0
  89. package/dist/5167.js +1 -0
  90. package/dist/5167.js.map +1 -0
  91. package/dist/5380.js +1 -0
  92. package/dist/5380.js.map +1 -0
  93. package/dist/5422.js +1 -0
  94. package/dist/5422.js.map +1 -0
  95. package/dist/5576.js +1 -0
  96. package/dist/5576.js.map +1 -0
  97. package/dist/5851.js +1 -0
  98. package/dist/5851.js.map +1 -0
  99. package/dist/5961.js +1 -0
  100. package/dist/5961.js.map +1 -0
  101. package/dist/6264.js +1 -0
  102. package/dist/6264.js.map +1 -0
  103. package/dist/6540.js +2 -0
  104. package/dist/6540.js.map +1 -0
  105. package/dist/6606.js +1 -0
  106. package/dist/6606.js.map +1 -0
  107. package/dist/6720.js +1 -0
  108. package/dist/6720.js.map +1 -0
  109. package/dist/6824.js +1 -0
  110. package/dist/6824.js.map +1 -0
  111. package/dist/6942.js +1 -0
  112. package/dist/6942.js.map +1 -0
  113. package/dist/71.js +1 -0
  114. package/dist/71.js.map +1 -0
  115. package/dist/7207.js +1 -0
  116. package/dist/7207.js.map +1 -0
  117. package/dist/7240.js +1 -0
  118. package/dist/7240.js.map +1 -0
  119. package/dist/7255.js +1 -0
  120. package/dist/7255.js.map +1 -0
  121. package/dist/7271.js +1 -0
  122. package/dist/7271.js.map +1 -0
  123. package/dist/7420.js +1 -0
  124. package/dist/7420.js.map +1 -0
  125. package/dist/7521.js +1 -0
  126. package/dist/7521.js.map +1 -0
  127. package/dist/7557.js +1 -0
  128. package/dist/7557.js.map +1 -0
  129. package/dist/7717.js +1 -0
  130. package/dist/7717.js.map +1 -0
  131. package/dist/7830.js +2 -0
  132. package/dist/7830.js.map +1 -0
  133. package/dist/7879.js +1 -0
  134. package/dist/7879.js.map +1 -0
  135. package/dist/7941.js +1 -0
  136. package/dist/7941.js.map +1 -0
  137. package/dist/8091.js +1 -0
  138. package/dist/8091.js.map +1 -0
  139. package/dist/810.js +1 -2
  140. package/dist/810.js.map +1 -1
  141. package/dist/8558.js +1 -0
  142. package/dist/8558.js.map +1 -0
  143. package/dist/8733.js +1 -0
  144. package/dist/8733.js.map +1 -0
  145. package/dist/874.js +1 -0
  146. package/dist/874.js.map +1 -0
  147. package/dist/8895.js +1 -0
  148. package/dist/8895.js.map +1 -0
  149. package/dist/9070.js +1 -0
  150. package/dist/9070.js.map +1 -0
  151. package/dist/9091.js +1 -0
  152. package/dist/9091.js.map +1 -0
  153. package/dist/9093.js +1 -0
  154. package/dist/9093.js.map +1 -0
  155. package/dist/9249.js +1 -0
  156. package/dist/9249.js.map +1 -0
  157. package/dist/9338.js +1 -0
  158. package/dist/9338.js.map +1 -0
  159. package/dist/9418.js +2 -0
  160. package/dist/9418.js.LICENSE.txt +1 -0
  161. package/dist/9418.js.map +1 -0
  162. package/dist/9428.js +1 -0
  163. package/dist/9428.js.map +1 -0
  164. package/dist/9721.js +1 -0
  165. package/dist/9721.js.map +1 -0
  166. package/dist/esm-dha-workflow-app.js +1 -1
  167. package/dist/esm-dha-workflow-app.js.buildmanifest.json +1675 -210
  168. package/dist/esm-dha-workflow-app.js.map +1 -1
  169. package/dist/main.js +1 -1
  170. package/dist/main.js.map +1 -1
  171. package/dist/routes.json +1 -1
  172. package/local-config.json +5 -0
  173. package/package.json +16 -6
  174. package/src/admissions/admission-request-list/admission-request-list.scss +0 -0
  175. package/src/admissions/admission-request-list/admission-request-list.tsx +263 -0
  176. package/src/admissions/admissions-dashboard.component.scss +15 -0
  177. package/src/admissions/admissions-dashboard.component.tsx +277 -0
  178. package/src/admissions/admissions.resource.ts +233 -0
  179. package/src/admissions/admitted-list/admitted-patients-list.tsx +206 -0
  180. package/src/admissions/awaiting-discharge-list/awaiting-discharge-list.tsx +197 -0
  181. package/src/admissions/bed-assigment-request/bed-assignment-request-list.tsx +134 -0
  182. package/src/admissions/constants/index.ts +33 -0
  183. package/src/admissions/discharged-list/discharged-list.scss +0 -0
  184. package/src/admissions/discharged-list/discharged-list.tsx +67 -0
  185. package/src/admissions/form-entry-workspace/form-entry-workspace.tsx +62 -0
  186. package/src/admissions/inpatient/admission-history/patient-admission-history.tsx +76 -0
  187. package/src/admissions/inpatient/admission-requests/patient-admission-requests.scss +19 -0
  188. package/src/admissions/inpatient/admission-requests/patient-admission-requests.tsx +72 -0
  189. package/src/admissions/inpatient/inpatient-admissions.component.scss +7 -0
  190. package/src/admissions/inpatient/inpatient-admissions.component.tsx +46 -0
  191. package/src/admissions/modal/add-bill-items/add-bill-items.modal.scss +17 -0
  192. package/src/admissions/modal/add-bill-items/add-bill-items.modal.tsx +233 -0
  193. package/src/admissions/modal/admit-elsewhere/admit-elsewhere.modal.scss +23 -0
  194. package/src/admissions/modal/admit-elsewhere/admit-elsewhere.modal.tsx +156 -0
  195. package/src/admissions/modal/admit-patient/admit-patient.modal.scss +0 -0
  196. package/src/admissions/modal/admit-patient/admit-patient.modal.tsx +111 -0
  197. package/src/admissions/modal/bed-swap/bed-swap.modal.scss +0 -0
  198. package/src/admissions/modal/bed-swap/bed-swap.modal.tsx +102 -0
  199. package/src/admissions/modal/cancel-admission-request/cancel-admission-request.scss +11 -0
  200. package/src/admissions/modal/cancel-admission-request/cancel-admission-request.tsx +105 -0
  201. package/src/admissions/modal/discharge/discharge-patient.modal.scss +13 -0
  202. package/src/admissions/modal/discharge/discharge-patient.modal.tsx +86 -0
  203. package/src/admissions/types/index.ts +263 -0
  204. package/src/appointments/appointments.component.scss +6 -0
  205. package/src/appointments/appointments.component.tsx +8 -1
  206. package/src/billing/api/billing.api.ts +139 -0
  207. package/src/billing/billing-claims.resource.ts +900 -0
  208. package/src/billing/billing-dashboard-link.component.tsx +31 -0
  209. package/src/billing/billing-dashboard-reset.ts +27 -0
  210. package/src/billing/billing-root.tsx +42 -0
  211. package/src/billing/dashboard/billingDashboard.component.scss +0 -0
  212. package/src/billing/dashboard/billingDashboard.component.tsx +25 -0
  213. package/src/billing/dashboard/v2/active-visits/active-visits.component.tsx +257 -0
  214. package/src/billing/dashboard/v2/active-visits/active-visits.resource.ts +85 -0
  215. package/src/billing/dashboard/v2/active-visits/active-visits.scss +15 -0
  216. package/src/billing/dashboard/v2/active-visits.component.tsx +102 -0
  217. package/src/billing/dashboard/v2/admissions/admission-requests-tab.component.tsx +79 -0
  218. package/src/billing/dashboard/v2/billing-claims-dashboard.component.scss +209 -0
  219. package/src/billing/dashboard/v2/billing-claims-dashboard.component.tsx +347 -0
  220. package/src/billing/dashboard/v2/cash-checklist/bill-document.component.scss +90 -0
  221. package/src/billing/dashboard/v2/cash-checklist/bill-document.component.tsx +101 -0
  222. package/src/billing/dashboard/v2/cash-checklist/cash-checklist.component.scss +199 -0
  223. package/src/billing/dashboard/v2/cash-checklist/cash-checklist.component.tsx +361 -0
  224. package/src/billing/dashboard/v2/cash-checklist/cash-checklist.resource.ts +239 -0
  225. package/src/billing/dashboard/v2/cash-checklist/payment-drawer.component.scss +246 -0
  226. package/src/billing/dashboard/v2/cash-checklist/payment-drawer.component.tsx +182 -0
  227. package/src/billing/dashboard/v2/claim-statuses.ts +143 -0
  228. package/src/billing/dashboard/v2/claim-visits/claim-diagnosis-details/claim-diagnosis-details.component.scss +0 -0
  229. package/src/billing/dashboard/v2/claim-visits/claim-diagnosis-details/claim-diagnosis-details.component.tsx +35 -0
  230. package/src/billing/dashboard/v2/claim-visits/claim-diagnosis-details/claim-diagnosis-panel.component.scss +67 -0
  231. package/src/billing/dashboard/v2/claim-visits/claim-diagnosis-details/claim-diagnosis-panel.component.tsx +90 -0
  232. package/src/billing/dashboard/v2/claim-visits/claim-doctors/claim-doctors.scss +28 -0
  233. package/src/billing/dashboard/v2/claim-visits/claim-doctors/claim-doctors.tsx +36 -0
  234. package/src/billing/dashboard/v2/claim-visits/claim-history/claim-history.component.scss +119 -0
  235. package/src/billing/dashboard/v2/claim-visits/claim-history/claim-history.component.tsx +198 -0
  236. package/src/billing/dashboard/v2/claim-visits/claim-intervention-details/claim-intervention-details.component.scss +5 -0
  237. package/src/billing/dashboard/v2/claim-visits/claim-intervention-details/claim-intervention-details.component.tsx +160 -0
  238. package/src/billing/dashboard/v2/claim-visits/claim-intervention-details/claim-intervention-panel.component.scss +105 -0
  239. package/src/billing/dashboard/v2/claim-visits/claim-intervention-details/claim-intervention-panel.component.tsx +184 -0
  240. package/src/billing/dashboard/v2/claim-visits/claim-intervention-details/intervention-attachments.component.scss +161 -0
  241. package/src/billing/dashboard/v2/claim-visits/claim-intervention-details/intervention-attachments.component.tsx +328 -0
  242. package/src/billing/dashboard/v2/claim-visits/claim-invoice-details/claim-invoice-details.component.tsx +96 -0
  243. package/src/billing/dashboard/v2/claim-visits/claim-invoice-details/claim-invoice-document.component.tsx +236 -0
  244. package/src/billing/dashboard/v2/claim-visits/claim-invoice-details/claim-invoice-panel.component.scss +98 -0
  245. package/src/billing/dashboard/v2/claim-visits/claim-invoice-details/claim-invoice-panel.component.tsx +292 -0
  246. package/src/billing/dashboard/v2/claim-visits/claim-invoice-line-details/claim-invoice-line-details.component.scss +133 -0
  247. package/src/billing/dashboard/v2/claim-visits/claim-invoice-line-details/claim-invoice-line-details.component.tsx +217 -0
  248. package/src/billing/dashboard/v2/claim-visits/claim-visit-details/claim-details-by-token.component.tsx +150 -0
  249. package/src/billing/dashboard/v2/claim-visits/claim-visit-details/claim-details-page.component.scss +13 -0
  250. package/src/billing/dashboard/v2/claim-visits/claim-visit-details/claim-details-page.component.tsx +116 -0
  251. package/src/billing/dashboard/v2/claim-visits/claim-visit-details/claim-visit-details.component.scss +338 -0
  252. package/src/billing/dashboard/v2/claim-visits/claim-visit-details/claim-visit-details.component.tsx +616 -0
  253. package/src/billing/dashboard/v2/claim-visits/claim-visits.component.scss +5 -0
  254. package/src/billing/dashboard/v2/claim-visits/claim-visits.component.tsx +133 -0
  255. package/src/billing/dashboard/v2/claim-visits/modal/claim-doctors/add-claim-doctor/add-claim-doctor.modal.scss +5 -0
  256. package/src/billing/dashboard/v2/claim-visits/modal/claim-doctors/add-claim-doctor/add-claim-doctor.modal.tsx +49 -0
  257. package/src/billing/dashboard/v2/claim-visits/modal/claim-visit-details/claim-visit-details.modal.scss +17 -0
  258. package/src/billing/dashboard/v2/claim-visits/modal/claim-visit-details/claim-visit-details.modal.tsx +56 -0
  259. package/src/billing/dashboard/v2/claim-visits/modal/close-claim/close-claim.modal.scss +0 -0
  260. package/src/billing/dashboard/v2/claim-visits/modal/close-claim/close-claim.modal.tsx +129 -0
  261. package/src/billing/dashboard/v2/claim-visits/modal/submit-claim/submit-claim.modal.tsx +204 -0
  262. package/src/billing/dashboard/v2/claim-visits/shared/_empty-state.scss +28 -0
  263. package/src/billing/dashboard/v2/claim-visits/shared/record-cards.component.scss +298 -0
  264. package/src/billing/dashboard/v2/claim-visits/shared/record-cards.component.tsx +252 -0
  265. package/src/billing/dashboard/v2/claim-visits/shared/record-details.workspace.scss +42 -0
  266. package/src/billing/dashboard/v2/claim-visits/shared/record-details.workspace.tsx +54 -0
  267. package/src/billing/dashboard/v2/claim-visits/shared/record-table.component.scss +61 -0
  268. package/src/billing/dashboard/v2/claim-visits/shared/record-table.component.tsx +150 -0
  269. package/src/billing/dashboard/v2/claim-visits/switch-intervention/switch-intervention.resource.ts +51 -0
  270. package/src/billing/dashboard/v2/claim-visits/switch-intervention/switch-intervention.workspace.scss +191 -0
  271. package/src/billing/dashboard/v2/claim-visits/switch-intervention/switch-intervention.workspace.tsx +648 -0
  272. package/src/billing/dashboard/v2/claim-workspace/claim-workspace.component.scss +595 -0
  273. package/src/billing/dashboard/v2/claim-workspace/claim-workspace.component.tsx +810 -0
  274. package/src/billing/dashboard/v2/claim-workspace/claim-workspace.resource.ts +282 -0
  275. package/src/billing/dashboard/v2/claims-accounting/bill-utils.ts +134 -0
  276. package/src/billing/dashboard/v2/claims-accounting/claim-detail.component.tsx +346 -0
  277. package/src/billing/dashboard/v2/claims-accounting/claims-accounting.component.scss +546 -0
  278. package/src/billing/dashboard/v2/claims-accounting/claims-accounting.component.tsx +206 -0
  279. package/src/billing/dashboard/v2/claims-accounting/claims-accounting.resource.ts +337 -0
  280. package/src/billing/dashboard/v2/claims-accounting/invoice-document.component.scss +90 -0
  281. package/src/billing/dashboard/v2/claims-accounting/invoice-document.component.tsx +90 -0
  282. package/src/billing/dashboard/v2/claims-accounting/remittances.component.tsx +169 -0
  283. package/src/billing/dashboard/v2/claims-accounting/remittances.resource.ts +46 -0
  284. package/src/billing/dashboard/v2/claims-accounting/status-meta.ts +25 -0
  285. package/src/billing/dashboard/v2/clearance/cash-patients.scss +18 -0
  286. package/src/billing/dashboard/v2/clearance/cash.component.tsx +149 -0
  287. package/src/billing/dashboard/v2/clearance/clearance.component.scss +84 -0
  288. package/src/billing/dashboard/v2/clearance/clearance.component.tsx +225 -0
  289. package/src/billing/dashboard/v2/clearance/pay-cash.component.tsx +176 -0
  290. package/src/billing/dashboard/v2/clearance/pay-cash.scss +28 -0
  291. package/src/billing/dashboard/v2/clearance/prepaid-services.component.tsx +112 -0
  292. package/src/billing/dashboard/v2/facility-bills/claim-status.ts +249 -0
  293. package/src/billing/dashboard/v2/facility-bills/facility-bills.component.scss +140 -0
  294. package/src/billing/dashboard/v2/facility-bills/facility-bills.component.tsx +687 -0
  295. package/src/billing/dashboard/v2/facility-bills/preauths-datatables/pending-preauths.component.tsx +132 -0
  296. package/src/billing/dashboard/v2/facility-bills/preauths-datatables/preauth-preview-table.component.tsx +267 -0
  297. package/src/billing/dashboard/v2/facility-bills/preauths.component.tsx +124 -0
  298. package/src/billing/dashboard/v2/inpatient-requests/inpatient-requests.component.scss +22 -0
  299. package/src/billing/dashboard/v2/inpatient-requests/inpatient-requests.component.tsx +389 -0
  300. package/src/billing/dashboard/v2/inpatient-requests/modal/start-inpatient-claim/start-inpatient-claim.component.scss +0 -0
  301. package/src/billing/dashboard/v2/inpatient-requests/modal/start-inpatient-claim/start-inpatient-claim.component.tsx +0 -0
  302. package/src/billing/dashboard/v2/new-facility-bills/bills-table.component.tsx +78 -0
  303. package/src/billing/dashboard/v2/new-facility-bills/bills-table.scss +18 -0
  304. package/src/billing/dashboard/v2/new-facility-bills/new-facility-bills.component.tsx +64 -0
  305. package/src/billing/dashboard/v2/new-facility-bills/new-facility-bills.scss +146 -0
  306. package/src/billing/dashboard/v2/patient-bill-details/attachments/add-attachments.component.tsx +223 -0
  307. package/src/billing/dashboard/v2/patient-bill-details/attachments/attachment.component.tsx +157 -0
  308. package/src/billing/dashboard/v2/patient-bill-details/attachments/attachments.scss +92 -0
  309. package/src/billing/dashboard/v2/patient-bill-details/attachments/case-summary/case-summary.scss +295 -0
  310. package/src/billing/dashboard/v2/patient-bill-details/attachments/case-summary/case-summary.tsx +326 -0
  311. package/src/billing/dashboard/v2/patient-bill-details/attachments/dialysis/dialysis-chart.scss +238 -0
  312. package/src/billing/dashboard/v2/patient-bill-details/attachments/dialysis/dialysis-chart.tsx +269 -0
  313. package/src/billing/dashboard/v2/patient-bill-details/attachments/discharge-summary/discharge-summary.scss +96 -0
  314. package/src/billing/dashboard/v2/patient-bill-details/attachments/discharge-summary/discharge-summary.tsx +124 -0
  315. package/src/billing/dashboard/v2/patient-bill-details/attachments/final-bill.component.tsx +152 -0
  316. package/src/billing/dashboard/v2/patient-bill-details/attachments/final-bill.scss +225 -0
  317. package/src/billing/dashboard/v2/patient-bill-details/attachments/general-discharge-summary/general-discharge-summary.scss +182 -0
  318. package/src/billing/dashboard/v2/patient-bill-details/attachments/general-discharge-summary/general-discharge-summary.tsx +173 -0
  319. package/src/billing/dashboard/v2/patient-bill-details/attachments/generate-attachments.component.tsx +360 -0
  320. package/src/billing/dashboard/v2/patient-bill-details/attachments/invoice.component.tsx +151 -0
  321. package/src/billing/dashboard/v2/patient-bill-details/attachments/invoice.scss +225 -0
  322. package/src/billing/dashboard/v2/patient-bill-details/attachments/type.ts +44 -0
  323. package/src/billing/dashboard/v2/patient-bill-details/bill-details/bill-details.scss +107 -0
  324. package/src/billing/dashboard/v2/patient-bill-details/bill-details/bill-details.tsx +508 -0
  325. package/src/billing/dashboard/v2/patient-bill-details/bill-details-page.component.scss +30 -0
  326. package/src/billing/dashboard/v2/patient-bill-details/bill-details-page.component.tsx +94 -0
  327. package/src/billing/dashboard/v2/patient-bill-details/claim-details/claim-details-skeleton.component.scss +89 -0
  328. package/src/billing/dashboard/v2/patient-bill-details/claim-details/claim-details-skeleton.component.tsx +53 -0
  329. package/src/billing/dashboard/v2/patient-bill-details/claim-details/patient-claim-details.component.scss +32 -0
  330. package/src/billing/dashboard/v2/patient-bill-details/claim-details/patient-claim-details.component.tsx +215 -0
  331. package/src/billing/dashboard/v2/patient-bill-details/modals/add-claim-diagnosis/add-claim-diagnosis.modal.scss +0 -0
  332. package/src/billing/dashboard/v2/patient-bill-details/modals/add-claim-diagnosis/add-claim-diagnosis.modal.tsx +99 -0
  333. package/src/billing/dashboard/v2/patient-bill-details/modals/add-claim-line/add-claim-line.modal.tsx +186 -0
  334. package/src/billing/dashboard/v2/patient-bill-details/patient-bill-details.scss +153 -0
  335. package/src/billing/dashboard/v2/patient-bill-details/patient-bill-details.tsx +458 -0
  336. package/src/billing/dashboard/v2/patient-bill-details/payment-mode.ts +124 -0
  337. package/src/billing/dashboard/v2/patient-bill-details/workspaces/add-claim-line/add-claim-line.workspace.scss +27 -0
  338. package/src/billing/dashboard/v2/patient-bill-details/workspaces/add-claim-line/add-claim-line.workspace.tsx +222 -0
  339. package/src/billing/dashboard/v2/patient-bill-details/workspaces/bill-item-payment/bill-item-payment.workspace.scss +27 -0
  340. package/src/billing/dashboard/v2/patient-bill-details/workspaces/bill-item-payment/bill-item-payment.workspace.tsx +109 -0
  341. package/src/billing/dashboard/v2/preauth/preauth-attachments.component.tsx +389 -0
  342. package/src/billing/dashboard/v2/preauth/preauth-list.component.scss +38 -0
  343. package/src/billing/dashboard/v2/preauth/preauth-list.component.tsx +226 -0
  344. package/src/billing/dashboard/v2/preauth/preauth-status-tag.component.tsx +75 -0
  345. package/src/billing/dashboard/v2/preauth/preauth-typed-fields.md +125 -0
  346. package/src/billing/dashboard/v2/preauth/preauth.resource.ts +1067 -0
  347. package/src/billing/dashboard/v2/preauth/preauth.workspace.scss +91 -0
  348. package/src/billing/dashboard/v2/preauth/preauth.workspace.tsx +1802 -0
  349. package/src/billing/dashboard/v2/preauth/preauthorizations-tab.component.tsx +45 -0
  350. package/src/billing/dashboard/v2/sha-claims/sha-claims-table.component.tsx +36 -0
  351. package/src/billing/dashboard/v2/sha-claims/sha-claims.component.tsx +60 -0
  352. package/src/billing/dashboard/v2/sha-claims/sha-claims.scss +8 -0
  353. package/src/billing/dashboard/v2/shared/dash-board-card/dash-board-card.component.scss +17 -0
  354. package/src/billing/dashboard/v2/shared/dash-board-card/dash-board-card.component.tsx +15 -0
  355. package/src/billing/dashboard/v2/shared/empty-state.component.scss +24 -0
  356. package/src/billing/dashboard/v2/shared/empty-state.component.tsx +13 -0
  357. package/src/billing/dashboard/v2/shared/scroll-to-top.component.scss +54 -0
  358. package/src/billing/dashboard/v2/shared/scroll-to-top.component.tsx +54 -0
  359. package/src/billing/dashboard/v2/shared/table-toolbar.component.scss +77 -0
  360. package/src/billing/dashboard/v2/shared/table-toolbar.component.tsx +48 -0
  361. package/src/billing/dashboard/v2/types/index.ts +507 -0
  362. package/src/billing/dashboard/v3/active-visits/active-visits.component.tsx +256 -0
  363. package/src/billing/dashboard/v3/active-visits/active-visits.resource.ts +57 -0
  364. package/src/billing/dashboard/v3/active-visits/active-visits.scss +15 -0
  365. package/src/billing/dashboard/v3/cash-checklist/bill-document.component.scss +90 -0
  366. package/src/billing/dashboard/v3/cash-checklist/bill-document.component.tsx +101 -0
  367. package/src/billing/dashboard/v3/cash-checklist/cash-checklist.component.scss +199 -0
  368. package/src/billing/dashboard/v3/cash-checklist/cash-checklist.component.tsx +361 -0
  369. package/src/billing/dashboard/v3/cash-checklist/cash-checklist.resource.ts +240 -0
  370. package/src/billing/dashboard/v3/cash-checklist/payment-drawer.component.scss +246 -0
  371. package/src/billing/dashboard/v3/cash-checklist/payment-drawer.component.tsx +182 -0
  372. package/src/billing/dashboard/v3/claim-visits/claim-diagnosis-details/claim-diagnosis-details.component.scss +0 -0
  373. package/src/billing/dashboard/v3/claim-visits/claim-diagnosis-details/claim-diagnosis-details.component.tsx +44 -0
  374. package/src/billing/dashboard/v3/claim-visits/claim-doctors/claim-doctors.scss +5 -0
  375. package/src/billing/dashboard/v3/claim-visits/claim-doctors/claim-doctors.tsx +42 -0
  376. package/src/billing/dashboard/v3/claim-visits/claim-documents/claim-documents.scss +10 -0
  377. package/src/billing/dashboard/v3/claim-visits/claim-documents/claim-documents.tsx +25 -0
  378. package/src/billing/dashboard/v3/claim-visits/claim-intervention-details/claim-intervention-details.component.tsx +223 -0
  379. package/src/billing/dashboard/v3/claim-visits/claim-invoice-details/claim-invoice-details.component.scss +6 -0
  380. package/src/billing/dashboard/v3/claim-visits/claim-invoice-details/claim-invoice-details.component.tsx +85 -0
  381. package/src/billing/dashboard/v3/claim-visits/claim-invoice-line-details/claim-invoice-line-details.component.scss +0 -0
  382. package/src/billing/dashboard/v3/claim-visits/claim-invoice-line-details/claim-invoice-line-details.component.tsx +109 -0
  383. package/src/billing/dashboard/v3/claim-visits/claim-visit-details/claim-visit-details.component.scss +104 -0
  384. package/src/billing/dashboard/v3/claim-visits/claim-visit-details/claim-visit-details.component.tsx +336 -0
  385. package/src/billing/dashboard/v3/claim-visits/claim-visits.component.scss +5 -0
  386. package/src/billing/dashboard/v3/claim-visits/claim-visits.component.tsx +139 -0
  387. package/src/billing/dashboard/v3/claim-visits/modal/claim-doctors/add-claim-doctor/add-claim-doctor.modal.scss +5 -0
  388. package/src/billing/dashboard/v3/claim-visits/modal/claim-doctors/add-claim-doctor/add-claim-doctor.modal.tsx +49 -0
  389. package/src/billing/dashboard/v3/claim-visits/modal/claim-invoice-lines/claim-invoice-lines.modal.scss +7 -0
  390. package/src/billing/dashboard/v3/claim-visits/modal/claim-invoice-lines/claim-invoice-lines.modal.tsx +35 -0
  391. package/src/billing/dashboard/v3/claim-visits/modal/claim-visit-details/claim-visit-details.modal.scss +6 -0
  392. package/src/billing/dashboard/v3/claim-visits/modal/claim-visit-details/claim-visit-details.modal.tsx +33 -0
  393. package/src/billing/dashboard/v3/claim-visits/modal/close-claim/close-claim.modal.scss +0 -0
  394. package/src/billing/dashboard/v3/claim-visits/modal/close-claim/close-claim.modal.tsx +129 -0
  395. package/src/billing/dashboard/v3/claim-visits/modal/submit-claim/submit-claim.modal.tsx +204 -0
  396. package/src/billing/dashboard/v3/claim-visits/payer-preview/index.scss +140 -0
  397. package/src/billing/dashboard/v3/claim-visits/payer-preview/payer-preview-tile.component.tsx +55 -0
  398. package/src/billing/dashboard/v3/claim-visits/payer-preview/payer-preview-workspace.component.tsx +157 -0
  399. package/src/billing/dashboard/v3/claim-visits/payer-preview/tables/payer-claim-doctors.component.tsx +54 -0
  400. package/src/billing/dashboard/v3/claim-visits/payer-preview/tables/payer-claim-lines.component.tsx +48 -0
  401. package/src/billing/dashboard/v3/claim-visits/payer-preview/tables/payer-claim-notes.component.tsx +47 -0
  402. package/src/billing/dashboard/v3/claim-visits/payer-preview/tables/payer-diagnoses.component.tsx +44 -0
  403. package/src/billing/dashboard/v3/claim-visits/payer-preview/tables/payer-interventions.component.tsx +44 -0
  404. package/src/billing/dashboard/v3/claim-visits/switch-intervention/switch-intervention.resource.ts +51 -0
  405. package/src/billing/dashboard/v3/claim-visits/switch-intervention/switch-intervention.workspace.scss +191 -0
  406. package/src/billing/dashboard/v3/claim-visits/switch-intervention/switch-intervention.workspace.tsx +648 -0
  407. package/src/billing/dashboard/v3/claim-workspace/claim-workspace.component.scss +595 -0
  408. package/src/billing/dashboard/v3/claim-workspace/claim-workspace.component.tsx +810 -0
  409. package/src/billing/dashboard/v3/claim-workspace/claim-workspace.resource.ts +282 -0
  410. package/src/billing/dashboard/v3/claims-accounting/bill-utils.ts +134 -0
  411. package/src/billing/dashboard/v3/claims-accounting/claim-detail.component.tsx +346 -0
  412. package/src/billing/dashboard/v3/claims-accounting/claims-accounting.component.scss +546 -0
  413. package/src/billing/dashboard/v3/claims-accounting/claims-accounting.component.tsx +206 -0
  414. package/src/billing/dashboard/v3/claims-accounting/claims-accounting.resource.ts +337 -0
  415. package/src/billing/dashboard/v3/claims-accounting/invoice-document.component.scss +90 -0
  416. package/src/billing/dashboard/v3/claims-accounting/invoice-document.component.tsx +90 -0
  417. package/src/billing/dashboard/v3/claims-accounting/remittances.component.tsx +169 -0
  418. package/src/billing/dashboard/v3/claims-accounting/remittances.resource.ts +46 -0
  419. package/src/billing/dashboard/v3/claims-accounting/status-meta.ts +25 -0
  420. package/src/billing/dashboard/v3/clearance/clearance.component.scss +100 -0
  421. package/src/billing/dashboard/v3/clearance/clearance.component.tsx +0 -0
  422. package/src/billing/dashboard/v3/clearance/prepaid-services.component.tsx +112 -0
  423. package/src/billing/dashboard/v3/facility-bills/claim-status.ts +243 -0
  424. package/src/billing/dashboard/v3/facility-bills/facility-bills.component.scss +9 -0
  425. package/src/billing/dashboard/v3/facility-bills/facility-bills.component.tsx +172 -0
  426. package/src/billing/dashboard/v3/facility-bills/preauths-datatables/pending-preauths.component.tsx +132 -0
  427. package/src/billing/dashboard/v3/facility-bills/preauths-datatables/preauth-preview-table.component.tsx +232 -0
  428. package/src/billing/dashboard/v3/facility-bills/preauths.component.tsx +124 -0
  429. package/src/billing/dashboard/v3/patient-bill-details/attachments/add-attachments.component.tsx +223 -0
  430. package/src/billing/dashboard/v3/patient-bill-details/attachments/attachment.component.tsx +157 -0
  431. package/src/billing/dashboard/v3/patient-bill-details/attachments/attachments.scss +92 -0
  432. package/src/billing/dashboard/v3/patient-bill-details/attachments/case-summary/case-summary-helper.ts +58 -0
  433. package/src/billing/dashboard/v3/patient-bill-details/attachments/case-summary/case-summary.scss +295 -0
  434. package/src/billing/dashboard/v3/patient-bill-details/attachments/case-summary/case-summary.tsx +273 -0
  435. package/src/billing/dashboard/v3/patient-bill-details/attachments/dialysis/dialysis-chart.scss +238 -0
  436. package/src/billing/dashboard/v3/patient-bill-details/attachments/dialysis/dialysis-chart.tsx +314 -0
  437. package/src/billing/dashboard/v3/patient-bill-details/attachments/discharge-summary/discharge-summary.scss +96 -0
  438. package/src/billing/dashboard/v3/patient-bill-details/attachments/discharge-summary/discharge-summary.tsx +126 -0
  439. package/src/billing/dashboard/v3/patient-bill-details/attachments/final-bill.component.tsx +75 -0
  440. package/src/billing/dashboard/v3/patient-bill-details/attachments/general-discharge-summary/general-discharge-summary.scss +182 -0
  441. package/src/billing/dashboard/v3/patient-bill-details/attachments/general-discharge-summary/general-discharge-summary.tsx +253 -0
  442. package/src/billing/dashboard/v3/patient-bill-details/attachments/generate-attachments.component.tsx +343 -0
  443. package/src/billing/dashboard/v3/patient-bill-details/attachments/invoice.component.tsx +150 -0
  444. package/src/billing/dashboard/v3/patient-bill-details/attachments/invoice.scss +225 -0
  445. package/src/billing/dashboard/v3/patient-bill-details/attachments/type.ts +259 -0
  446. package/src/billing/dashboard/v3/patient-bill-details/bill-details/bill-details.scss +13 -0
  447. package/src/billing/dashboard/v3/patient-bill-details/bill-details/bill-details.tsx +205 -0
  448. package/src/billing/dashboard/v3/patient-bill-details/claim-details/patient-claim-details.component.scss +0 -0
  449. package/src/billing/dashboard/v3/patient-bill-details/claim-details/patient-claim-details.component.tsx +61 -0
  450. package/src/billing/dashboard/v3/patient-bill-details/modals/add-claim-diagnosis/add-claim-diagnosis.modal.scss +0 -0
  451. package/src/billing/dashboard/v3/patient-bill-details/modals/add-claim-diagnosis/add-claim-diagnosis.modal.tsx +99 -0
  452. package/src/billing/dashboard/v3/patient-bill-details/modals/add-claim-line/add-claim-line.modal.scss +14 -0
  453. package/src/billing/dashboard/v3/patient-bill-details/modals/add-claim-line/add-claim-line.modal.tsx +111 -0
  454. package/src/billing/dashboard/v3/patient-bill-details/modals/bill-item-payment/bill-item-payment.modal.scss +6 -0
  455. package/src/billing/dashboard/v3/patient-bill-details/modals/bill-item-payment/bill-item-payment.modal.tsx +139 -0
  456. package/src/billing/dashboard/v3/patient-bill-details/patient-bill-details.scss +20 -0
  457. package/src/billing/dashboard/v3/patient-bill-details/patient-bill-details.tsx +254 -0
  458. package/src/billing/dashboard/v3/patient-bill-details/visit-diagnosis-details/visit-diagnosis-details.component.scss +0 -0
  459. package/src/billing/dashboard/v3/patient-bill-details/visit-diagnosis-details/visit-diagnosis-details.component.tsx +80 -0
  460. package/src/billing/dashboard/v3/preauth/preauth-attachments.component.tsx +389 -0
  461. package/src/billing/dashboard/v3/preauth/preauth-list.component.scss +34 -0
  462. package/src/billing/dashboard/v3/preauth/preauth-list.component.tsx +281 -0
  463. package/src/billing/dashboard/v3/preauth/preauth-status-tag.component.tsx +75 -0
  464. package/src/billing/dashboard/v3/preauth/preauth-typed-fields.md +125 -0
  465. package/src/billing/dashboard/v3/preauth/preauth.resource.ts +1072 -0
  466. package/src/billing/dashboard/v3/preauth/preauth.workspace.scss +91 -0
  467. package/src/billing/dashboard/v3/preauth/preauth.workspace.tsx +1806 -0
  468. package/src/billing/dashboard/v3/preauth/preauthorizations-tab.component.tsx +45 -0
  469. package/src/billing/dashboard/v3/shared/empty-state.component.scss +25 -0
  470. package/src/billing/dashboard/v3/shared/empty-state.component.tsx +13 -0
  471. package/src/billing/dashboard/v3/shared/table-toolbar.component.scss +64 -0
  472. package/src/billing/dashboard/v3/shared/table-toolbar.component.tsx +48 -0
  473. package/src/billing/dashboard/v3/types/index.ts +381 -0
  474. package/src/billing/extensions/generate-order-bill-button/generate-order-bill-button.extension.tsx +55 -0
  475. package/src/billing/extensions/generate-order-bill-button/generate-order-bill-button.scss +16 -0
  476. package/src/billing/extensions/visit-billing/visit-billing.extension.scss +0 -0
  477. package/src/billing/extensions/visit-billing/visit-billing.extension.tsx +509 -0
  478. package/src/billing/invoice/bill.resource.ts +47 -0
  479. package/src/billing/invoice/invoice-header/header-card/header-card.scss +17 -0
  480. package/src/billing/invoice/invoice-header/header-card/header-card.tsx +21 -0
  481. package/src/billing/invoice/invoice.scss +113 -0
  482. package/src/billing/invoice/invoice.tsx +1441 -0
  483. package/src/billing/invoice/line-items/line-items.scss +0 -0
  484. package/src/billing/invoice/line-items/line-items.tsx +120 -0
  485. package/src/billing/invoice/modal/delete-bill-item/delete-bill-item.modal.scss +23 -0
  486. package/src/billing/invoice/modal/delete-bill-item/delete-bill-item.modal.tsx +114 -0
  487. package/src/billing/invoice/modal/edit-bill-item/edit-bill-item.modal.scss +0 -0
  488. package/src/billing/invoice/modal/edit-bill-item/edit-bill-item.modal.tsx +122 -0
  489. package/src/billing/invoice/payment-details/payment-details.scss +0 -0
  490. package/src/billing/invoice/payment-details/payment-details.tsx +43 -0
  491. package/src/billing/invoice/print-invoice/print-receipt.component.tsx +44 -0
  492. package/src/billing/invoice/print-invoice/print-receipt.scss +14 -0
  493. package/src/billing/maternity-discharge.resource.ts +21 -0
  494. package/src/billing/types/index.ts +354 -0
  495. package/src/billing/utils/index.ts +17 -0
  496. package/src/billing/widgets/billingTotalsRow.component.scss +0 -0
  497. package/src/billing/widgets/billingTotalsRow.component.tsx +712 -0
  498. package/src/billing/workspaces/create-order-bill-form-workspace/create-order-bill-form.resource.ts +130 -0
  499. package/src/billing/workspaces/create-order-bill-form-workspace/create-order-bill-form.scss +58 -0
  500. package/src/billing/workspaces/create-order-bill-form-workspace/create-order-bill-form.workspace.tsx +645 -0
  501. package/src/billing/workspaces/create-order-bill-form-workspace/schema.ts +12 -0
  502. package/src/bookings/bookings.component.scss +7 -0
  503. package/src/bookings/bookings.component.tsx +35 -0
  504. package/src/bookings/daily/daily-bookings.resource.ts +2 -1
  505. package/src/case-summary/case-summary.extension.scss +13 -0
  506. package/src/case-summary/case-summary.extension.tsx +40 -0
  507. package/src/case-summary/case-summary.resource.test.ts +69 -0
  508. package/src/case-summary/case-summary.resource.ts +52 -0
  509. package/src/case-summary/components/case-summary-printable.component.scss +174 -0
  510. package/src/case-summary/components/case-summary-printable.component.tsx +288 -0
  511. package/src/case-summary/components/case-summary-printable.utils.ts +51 -0
  512. package/src/case-summary/types/case-summary.types.ts +152 -0
  513. package/src/claims/claims.component.scss +70 -0
  514. package/src/claims/claims.component.tsx +713 -0
  515. package/src/claims/claims.resource.ts +1274 -0
  516. package/src/claims/index.ts +340 -0
  517. package/src/claims/interventions.resource.ts +131 -0
  518. package/src/claims/utils.ts +64 -0
  519. package/src/config-schema.ts +114 -1
  520. package/src/context/patient-context.tsx +27 -0
  521. package/src/createDashboardLink.tsx +9 -0
  522. package/src/dashboard/charts/chart.component.scss +24 -0
  523. package/src/dashboard/charts/chart.component.tsx +56 -0
  524. package/src/dashboard/dashboard.component.scss +48 -3
  525. package/src/dashboard/dashboard.component.tsx +26 -36
  526. package/src/dashboard/overview/overview.component.scss +40 -59
  527. package/src/dashboard/overview/overview.component.tsx +53 -41
  528. package/src/dashboard-meta/accounting-dashboard.meta.ts +6 -0
  529. package/src/dashboard-meta/admissions-dashboard.meta.ts +6 -0
  530. package/src/dashboard-meta/billing-dashboard.meta.ts +6 -0
  531. package/src/dashboard-meta/bookings-dashboard.meta.ts +6 -0
  532. package/src/dashboard-meta/case-summary.meta.ts +6 -0
  533. package/src/dashboard-meta/consultation-dashboard.meta.ts +6 -0
  534. package/src/dashboard-meta/dha-workflow-dashboard.meta.ts +6 -0
  535. package/src/dashboard-meta/inpatient-admissions.meta.ts +6 -0
  536. package/src/dashboard-meta/maternity-dashboard.meta.ts +6 -0
  537. package/src/dashboard-meta/mch-dashboard.meta.ts +6 -0
  538. package/src/dashboard-meta/pharmacy-dashboard.meta.ts +6 -0
  539. package/src/dashboard-meta/queue-dashboard.meta.ts +6 -0
  540. package/src/dashboard-meta/registers-dashboard.meta.ts +6 -0
  541. package/src/dashboard-meta/registry-dashboard.meta.ts +6 -0
  542. package/src/dashboard-meta/service-queue-admin.meta.ts +6 -0
  543. package/src/dashboard-meta/specialized-clinics-dashboard.meta.ts +6 -0
  544. package/src/dashboard-meta/triage-dashboard.meta.ts +6 -0
  545. package/src/index.ts +177 -6
  546. package/src/mnch/maternity/maternity-queues.component.scss +7 -0
  547. package/src/mnch/maternity/maternity-queues.component.tsx +32 -0
  548. package/src/mnch/maternity/queues/triage/maternity-triage.tsx +15 -0
  549. package/src/mnch/mch/mch-queues.component.scss +10 -0
  550. package/src/mnch/mch/mch-queues.component.tsx +36 -0
  551. package/src/mnch/mch/queues/consultation/mch-consultation.tsx +18 -0
  552. package/src/mnch/mch/queues/triage/mch-triage.tsx +15 -0
  553. package/src/mnch/mnch-root.tsx +17 -0
  554. package/src/mortuary/mortuary.component.tsx +13 -0
  555. package/src/pharmacy/pharmacy.component.scss +16 -0
  556. package/src/pharmacy/pharmacy.component.tsx +11 -6
  557. package/src/registers/registers.component.tsx +8 -0
  558. package/src/registry/drawer/emr-compare.component.scss +263 -0
  559. package/src/registry/drawer/emr-compare.component.tsx +302 -0
  560. package/src/registry/drawer/emr-compare.resource.ts +181 -0
  561. package/src/registry/drawer/emr-create-preview.component.tsx +123 -0
  562. package/src/registry/drawer/otp-verification-step.component.tsx +398 -0
  563. package/src/registry/drawer/pomsf-balance.util.test.ts +177 -0
  564. package/src/registry/drawer/pomsf-balance.util.ts +79 -0
  565. package/src/registry/drawer/verification.resource.ts +60 -0
  566. package/src/registry/drawer/workflow-drawer.component.scss +1242 -0
  567. package/src/registry/drawer/workflow-drawer.component.tsx +1476 -0
  568. package/src/registry/eligibility/eligibility-details/eligibility-details.scss +38 -0
  569. package/src/registry/eligibility/eligibility-details/eligibility-details.tsx +101 -0
  570. package/src/registry/eligibility/eliigibility-tags/eligibility-tags.scss +16 -0
  571. package/src/registry/eligibility/eliigibility-tags/eligibility-tags.tsx +120 -0
  572. package/src/registry/eligibility/modal/eligibility-details.modal.scss +0 -0
  573. package/src/registry/eligibility/modal/eligibility-details.modal.tsx +45 -0
  574. package/src/registry/hie.resource.ts +408 -0
  575. package/src/registry/hie.types.ts +57 -0
  576. package/src/registry/modal/biometrics-verification-modal/biometrics-verification-modal.scss +277 -0
  577. package/src/registry/modal/biometrics-verification-modal/biometrics-verification-modal.tsx +218 -0
  578. package/src/registry/modal/biometrics-verification-modal/type.ts +39 -0
  579. package/src/registry/modal/client-details-modal/client-details-modal.tsx +65 -29
  580. package/src/registry/modal/otp-modal/otp-whitlisting-modal.component.tsx +815 -0
  581. package/src/registry/modal/otp-modal/otp-whitlisting-modal.scss +354 -0
  582. package/src/registry/modal/otp-modal/otp-whitlisting.scss +0 -0
  583. package/src/registry/modal/otp-verification-modal/claims-consent.scss +72 -0
  584. package/src/registry/modal/otp-verification-modal/claims-consent.tsx +135 -0
  585. package/src/registry/modal/otp-verification-modal/extension/claims-consent.extension.tsx +124 -0
  586. package/src/registry/modal/otp-verification-modal/otp-verification-modal.scss +30 -0
  587. package/src/registry/modal/otp-verification-modal/otp-verification-modal.tsx +154 -54
  588. package/src/registry/modal/send-to-triage/payment-details.tsx +120 -0
  589. package/src/registry/modal/send-to-triage/payment-method.component.tsx +54 -0
  590. package/src/registry/modal/send-to-triage/send-to-queue.modal.tsx +980 -0
  591. package/src/registry/modal/send-to-triage/send-to-triage.modal.scss +156 -3
  592. package/src/registry/modal/send-to-triage/send-to-triage.modal.tsx +1101 -131
  593. package/src/registry/modal/start-patient-visit/start-patient-visit.modal.scss +34 -0
  594. package/src/registry/modal/start-patient-visit/start-patient-visit.modal.tsx +231 -0
  595. package/src/registry/payment-details/payment-options/payment-options.scss +13 -0
  596. package/src/registry/payment-details/payment-options/payment-options.tsx +61 -14
  597. package/src/registry/registration-list/registration-list.component.scss +32 -0
  598. package/src/registry/registration-list/registration-list.component.tsx +103 -0
  599. package/src/registry/registry-entry.tsx +11 -0
  600. package/src/registry/registry.component.scss +402 -78
  601. package/src/registry/registry.component.tsx +547 -221
  602. package/src/registry/registry.resource.ts +22 -3
  603. package/src/registry/types/index.ts +117 -8
  604. package/src/registry/utils/error-handler.ts +54 -0
  605. package/src/registry/utils/format-dependant-display-data.ts +1 -1
  606. package/src/registry/utils/hie-client-adapter.ts +6 -3
  607. package/src/registry/utils/mask-data.ts +40 -0
  608. package/src/registry/utils/phone-number-formatter.ts +11 -0
  609. package/src/resources/dashboard.resource.ts +20 -0
  610. package/src/resources/identifier-types.ts +2 -0
  611. package/src/resources/patient-resource.ts +6 -1
  612. package/src/resources/queue.resource.ts +24 -1
  613. package/src/resources/superset.resource.ts +21 -0
  614. package/src/resources/visit.resource.ts +19 -1
  615. package/src/root.component.tsx +8 -5
  616. package/src/routes.json +417 -23
  617. package/src/service-queues/admin/queue/modal/create-queue/create-queue.modal.scss +31 -0
  618. package/src/service-queues/admin/queue/modal/create-queue/create-queue.modal.tsx +153 -0
  619. package/src/service-queues/admin/queue/modal/edit-queue/edit-queue.modal.scss +0 -0
  620. package/src/service-queues/admin/queue/modal/edit-queue/edit-queue.modal.tsx +182 -0
  621. package/src/service-queues/admin/queue/queue-list/queue-list.scss +33 -0
  622. package/src/service-queues/admin/queue/queue-list/queue-list.tsx +113 -0
  623. package/src/service-queues/admin/queue-entry/queue-entry-list.component.scss +6 -0
  624. package/src/service-queues/admin/queue-entry/queue-entry-list.component.tsx +137 -0
  625. package/src/service-queues/admin/queue-room/modal/create-queue-room/create-queue-room.modal.scss +31 -0
  626. package/src/service-queues/admin/queue-room/modal/create-queue-room/create-queue-room.modal.tsx +137 -0
  627. package/src/service-queues/admin/queue-room/modal/edit-queue-room/edit-queue-room.modal.scss +0 -0
  628. package/src/service-queues/admin/queue-room/modal/edit-queue-room/edit-queue-room.modal.tsx +146 -0
  629. package/src/service-queues/admin/queue-room/queue-room-list/queue-room-list.scss +22 -0
  630. package/src/service-queues/admin/queue-room/queue-room-list/queue-room-list.tsx +120 -0
  631. package/src/service-queues/admin/service-queue-admin-dashboard.component.scss +6 -0
  632. package/src/service-queues/admin/service-queue-admin-dashboard.component.tsx +34 -0
  633. package/src/service-queues/consultation/consultation.component.tsx +9 -0
  634. package/src/service-queues/extensions/service-queue-patient-banner/service-queue-patient-banner.scss +30 -0
  635. package/src/service-queues/extensions/service-queue-patient-banner/service-queue-patient-banner.tsx +108 -0
  636. package/src/service-queues/modals/daily-report-patient-list/daily-report-patient-list.scss +26 -0
  637. package/src/service-queues/modals/daily-report-patient-list/daily-report-patient-list.tsx +110 -0
  638. package/src/service-queues/modals/move/move-patient.component.scss +1 -1
  639. package/src/service-queues/modals/move/move-patient.component.tsx +31 -17
  640. package/src/service-queues/queue-list/check-in.service.ts +26 -0
  641. package/src/service-queues/queue-list/queue-list.component.scss +37 -0
  642. package/src/service-queues/queue-list/queue-list.component.tsx +256 -56
  643. package/src/service-queues/service-queue/service-queue.component.tsx +151 -8
  644. package/src/service-queues/service-queue/stats/stat-details/stat-details.component.scss +5 -0
  645. package/src/service-queues/service-queue/stats/stat-details/stat-details.component.tsx +36 -7
  646. package/src/service-queues/service-queue.tsx +22 -16
  647. package/src/service-queues/service-queues.resource.ts +197 -1
  648. package/src/service-queues/service.resource.ts +1 -1
  649. package/src/shared/constants/concepts.ts +50 -0
  650. package/src/shared/constants/patient-category.ts +6 -0
  651. package/src/shared/constants/patient-type.ts +10 -0
  652. package/src/shared/constants/visit-types.ts +7 -0
  653. package/src/shared/services/billing.resource.ts +75 -0
  654. package/src/shared/services/claims.resource.ts +47 -0
  655. package/src/shared/services/client-payment-mode.resource.ts +27 -0
  656. package/src/shared/services/client-payment.resource.ts +17 -0
  657. package/src/shared/services/consultation-clearance.resource.ts +210 -0
  658. package/src/shared/services/eligibility.resource.ts +20 -0
  659. package/src/shared/services/encounters.resource.ts +33 -0
  660. package/src/shared/services/location.resource.ts +9 -0
  661. package/src/shared/types/index.ts +156 -0
  662. package/src/shared/ui/aggregate-stat-card/aggregate-stat-card.scss +42 -0
  663. package/src/shared/ui/aggregate-stat-card/aggregate-stat-card.tsx +42 -0
  664. package/src/shared/ui/confirm-modal/confirm.modal.scss +18 -0
  665. package/src/shared/ui/confirm-modal/confirm.modal.tsx +38 -0
  666. package/src/shared/ui/facility-worker-slot/facility-worker.component-slot.component.scss +39 -0
  667. package/src/shared/ui/facility-worker-slot/facility-worker.component-slot.component.tsx +19 -0
  668. package/src/shared/ui/otp-input/otp-input.component.scss +14 -0
  669. package/src/shared/ui/otp-input/otp-input.component.tsx +97 -0
  670. package/src/{service-queues/service-queue/stats → shared/ui}/stat-card/stat-card.component.tsx +6 -3
  671. package/src/shared/ui/timer/timer.component.scss +5 -0
  672. package/src/shared/ui/timer/timer.component.tsx +40 -0
  673. package/src/shared/utils/get-base-url.ts +10 -0
  674. package/src/shared/utils/get-tag-type.ts +75 -0
  675. package/src/side-nav-menu/mnch-nav-link-config.ts +16 -0
  676. package/src/side-nav-menu/mnch-nav-links.tsx +42 -0
  677. package/src/side-nav-menu/nav-link-config.ts +1 -5
  678. package/src/side-nav-menu/specialized-clinics-nav-link-config.ts +36 -0
  679. package/src/side-nav-menu/specialized-clinics-nav-links.tsx +42 -0
  680. package/src/specialized-clinics/critital-care-unit/critical-care-unit-queues.component.scss +7 -0
  681. package/src/specialized-clinics/critital-care-unit/critical-care-unit-queues.component.tsx +36 -0
  682. package/src/specialized-clinics/critital-care-unit/queues/consultation/critical-care-unit-consultation.tsx +15 -0
  683. package/src/specialized-clinics/critital-care-unit/queues/triage/critical-care-unit-triage.tsx +15 -0
  684. package/src/specialized-clinics/dental/dental-queues.component.scss +7 -0
  685. package/src/specialized-clinics/dental/dental-queues.component.tsx +36 -0
  686. package/src/specialized-clinics/dental/queues/consultation/dental-consultation.tsx +15 -0
  687. package/src/specialized-clinics/dental/queues/triage/dental-triage.tsx +15 -0
  688. package/src/specialized-clinics/diagnostic-and-imaging/diagnostic-and-imaging.component.scss +7 -0
  689. package/src/specialized-clinics/diagnostic-and-imaging/diagnostic-and-imaging.component.tsx +36 -0
  690. package/src/specialized-clinics/diagnostic-and-imaging/queues/consultation/diagnosis-and-imaging-consultation.tsx +15 -0
  691. package/src/specialized-clinics/diagnostic-and-imaging/queues/triage/diagnosis-and-imaging-triage.tsx +15 -0
  692. package/src/specialized-clinics/oncology/oncology-queues.component.scss +7 -0
  693. package/src/specialized-clinics/oncology/oncology-queues.component.tsx +36 -0
  694. package/src/specialized-clinics/oncology/queues/consultation/oncology-consultation.tsx +15 -0
  695. package/src/specialized-clinics/oncology/queues/triage/oncology-triage.tsx +15 -0
  696. package/src/specialized-clinics/ophthalmology/ophthalmology-queues.component.scss +7 -0
  697. package/src/specialized-clinics/ophthalmology/ophthalmology-queues.component.tsx +36 -0
  698. package/src/specialized-clinics/ophthalmology/queues/consultation/ophthalmology-consultation.tsx +15 -0
  699. package/src/specialized-clinics/ophthalmology/queues/triage/ophthalmology-triage.tsx +15 -0
  700. package/src/specialized-clinics/psychiatry/psychiatry-queues.component.scss +7 -0
  701. package/src/specialized-clinics/psychiatry/psychiatry-queues.component.tsx +36 -0
  702. package/src/specialized-clinics/psychiatry/queues/consultation/psychiatry-consultation.tsx +15 -0
  703. package/src/specialized-clinics/psychiatry/queues/triage/psychiatry-triage.tsx +15 -0
  704. package/src/specialized-clinics/renal/queues/consultation/dialysis-consultation.tsx +15 -0
  705. package/src/specialized-clinics/renal/queues/triage/renal-triage.tsx +15 -0
  706. package/src/specialized-clinics/renal/renal-queues.component.scss +7 -0
  707. package/src/specialized-clinics/renal/renal-queues.component.tsx +36 -0
  708. package/src/specialized-clinics/specialized-clinics-root.tsx +27 -0
  709. package/src/triage/triage.component.scss +6 -0
  710. package/src/triage/triage.component.tsx +4 -0
  711. package/src/types/types.ts +56 -1
  712. package/webpack.config.js +54 -1
  713. package/dist/104.js +0 -2
  714. package/dist/104.js.map +0 -1
  715. package/dist/15.js +0 -1
  716. package/dist/15.js.map +0 -1
  717. package/dist/184.js +0 -2
  718. package/dist/184.js.map +0 -1
  719. package/dist/197.js +0 -1
  720. package/dist/255.js +0 -1
  721. package/dist/255.js.map +0 -1
  722. package/dist/300.js +0 -1
  723. package/dist/335.js +0 -1
  724. package/dist/339.js +0 -1
  725. package/dist/339.js.map +0 -1
  726. package/dist/353.js +0 -1
  727. package/dist/353.js.map +0 -1
  728. package/dist/420.js +0 -1
  729. package/dist/420.js.map +0 -1
  730. package/dist/540.js +0 -2
  731. package/dist/540.js.map +0 -1
  732. package/dist/55.js +0 -1
  733. package/dist/652.js +0 -1
  734. package/dist/709.js +0 -1
  735. package/dist/709.js.map +0 -1
  736. package/dist/710.js +0 -2
  737. package/dist/710.js.map +0 -1
  738. package/dist/729.js +0 -1
  739. package/dist/729.js.map +0 -1
  740. package/dist/752.js +0 -1
  741. package/dist/752.js.map +0 -1
  742. package/dist/833.js +0 -1
  743. package/dist/833.js.map +0 -1
  744. package/dist/907.js +0 -1
  745. package/dist/907.js.map +0 -1
  746. package/dist/91.js +0 -1
  747. package/dist/91.js.map +0 -1
  748. package/dist/93.js +0 -1
  749. package/dist/93.js.map +0 -1
  750. package/dist/943.js +0 -1
  751. package/dist/943.js.map +0 -1
  752. package/dist/99.js +0 -1
  753. /package/dist/{104.js.LICENSE.txt → 2177.js.LICENSE.txt} +0 -0
  754. /package/dist/{810.js.LICENSE.txt → 262.js.LICENSE.txt} +0 -0
  755. /package/dist/{184.js.LICENSE.txt → 3184.js.LICENSE.txt} +0 -0
  756. /package/dist/{540.js.LICENSE.txt → 6540.js.LICENSE.txt} +0 -0
  757. /package/dist/{710.js.LICENSE.txt → 7830.js.LICENSE.txt} +0 -0
  758. /package/src/{service-queues/service-queue/stats → shared/ui}/stat-card/stat-card.component.scss +0 -0
@@ -0,0 +1,1476 @@
1
+ import React, { useEffect, useRef, useState } from 'react';
2
+ import {
3
+ Button,
4
+ ComboBox,
5
+ Dropdown,
6
+ FileUploaderItem,
7
+ FormLabel,
8
+ InlineLoading,
9
+ Modal,
10
+ ProgressIndicator,
11
+ ProgressStep,
12
+ RadioButton,
13
+ RadioButtonGroup,
14
+ Table,
15
+ TableBody,
16
+ TableCell,
17
+ TableHead,
18
+ TableHeader,
19
+ TableRow,
20
+ Tag,
21
+ } from '@carbon/react';
22
+ import {
23
+ ArrowRight,
24
+ CheckboxCheckedFilled,
25
+ CheckmarkOutline,
26
+ CloudUpload,
27
+ Close,
28
+ FingerprintRecognition,
29
+ Information,
30
+ PendingFilled,
31
+ Renew,
32
+ ScanDisabled,
33
+ WarningAltFilled,
34
+ } from '@carbon/react/icons';
35
+ import { type Patient, showSnackbar } from '@openmrs/esm-framework';
36
+ import styles from './workflow-drawer.component.scss';
37
+ import { type HieClient, type RequestCustomOtpDto, type Scheme } from '../types';
38
+ import { getClientEligibityStatus } from '../../shared/services/eligibility.resource';
39
+ import { maskCrNumber, maskExceptFirstAndLast } from '../utils/mask-data';
40
+ import OtpVerificationStep from './otp-verification-step.component';
41
+ import EmrCompare from './emr-compare.component';
42
+ import EmrCreatePreview from './emr-create-preview.component';
43
+ import {
44
+ getBiometricCaptureUrl,
45
+ getOtpWhitelistStatus,
46
+ isBiometricConfigured,
47
+ requestOtpWhitelist,
48
+ } from './verification.resource';
49
+ import { fetchServiceQueuesByLocationUuid } from '../../resources/queue.resource';
50
+ import { fetchCashPoints, fetchPaymentModes } from '../../shared/services/billing.resource';
51
+ import { getReadableErrorMessage } from '../utils/error-handler';
52
+ import { fetchPomsfBalance } from '../../claims/claims.resource';
53
+ import { type PomsfBalance } from '../../claims';
54
+ import { formatKes, getAllPomsfBenefitBalances, getPomsfDisplayBalance, isPomsfActive } from './pomsf-balance.util';
55
+
56
+ type Phase =
57
+ | 'biometric'
58
+ | 'biometric-not-setup'
59
+ | 'otp-gate'
60
+ | 'whitelist-request'
61
+ | 'whitelist-pending'
62
+ | 'otp'
63
+ | 'consent'
64
+ | 'visit';
65
+
66
+ type Method = 'cash' | 'insurance';
67
+
68
+ type RequiredField = 'visitType' | 'room' | 'insurance';
69
+
70
+ const STEPS = ['Verify & consent', 'Start visit'];
71
+ const BIOMETRIC_MAX_ATTEMPTS = 3;
72
+
73
+ // Decode HTML entities in backend-provided names (e.g. "Accident & Emergency").
74
+ function decodeHtmlEntities(value: string): string {
75
+ if (!value || typeof document === 'undefined') {
76
+ return value;
77
+ }
78
+ const el = document.createElement('textarea');
79
+ el.innerHTML = value;
80
+ return el.value;
81
+ }
82
+ const OTP_EXPIRY_SECONDS = 300; // 5 minutes
83
+
84
+ // Where the patient is sent first, and the rooms available for each category.
85
+ const PATIENT_CATEGORIES = ['Triage', 'Walk-in'];
86
+ const WALK_IN_ROOMS = [];
87
+
88
+ // Payment modes that are direct payment (not insurance schemes) — excluded from
89
+ // the insurance-scheme list.
90
+ const NON_INSURANCE_PAYMENT_MODES = /cash|mpesa|m-pesa|waiver/i;
91
+
92
+ // OpenMRS visit types (searchable).
93
+ const VISIT_TYPE_OPTIONS = ['Outpatient', 'Inpatient'];
94
+
95
+ // Keys that still have to work while an option is selected: menu navigation, commit
96
+ // and dismiss. Everything else that would mutate the text is blocked below.
97
+ const SELECTION_NAV_KEYS = new Set([
98
+ 'Tab',
99
+ 'Enter',
100
+ 'Escape',
101
+ 'ArrowUp',
102
+ 'ArrowDown',
103
+ 'ArrowLeft',
104
+ 'ArrowRight',
105
+ 'Home',
106
+ 'End',
107
+ 'Shift',
108
+ 'Control',
109
+ 'Alt',
110
+ 'Meta',
111
+ ]);
112
+
113
+ // A picked option behaves as a single locked token: while one is selected the field
114
+ // can't be typed into, pasted into, or erased from the keyboard, so it can never hold
115
+ // a half-edited label that still reads as a valid selection. Clearing is deliberate —
116
+ // only the combo box's ✕ button removes a selection. Bound on the wrapper in the
117
+ // capture phase so these run before Carbon's own handlers.
118
+ function lockSelection(hasSelection: boolean) {
119
+ const block = (event: React.SyntheticEvent) => {
120
+ event.preventDefault();
121
+ event.stopPropagation();
122
+ };
123
+ return {
124
+ onKeyDownCapture: (event: React.KeyboardEvent) => {
125
+ if (!hasSelection) {
126
+ return;
127
+ }
128
+ // Backspace/Delete included: use the ✕ button to change a selection.
129
+ if (event.key === 'Backspace' || event.key === 'Delete') {
130
+ block(event);
131
+ return;
132
+ }
133
+ // Let shortcuts through — an actual paste is stopped by onPasteCapture.
134
+ if (SELECTION_NAV_KEYS.has(event.key) || event.ctrlKey || event.metaKey) {
135
+ return;
136
+ }
137
+ // Any single-character key would append to the locked label.
138
+ if (event.key.length === 1) {
139
+ block(event);
140
+ }
141
+ },
142
+ onPasteCapture: (event: React.ClipboardEvent) => {
143
+ if (hasSelection) {
144
+ block(event);
145
+ }
146
+ },
147
+ };
148
+ }
149
+
150
+ // Carbon's ComboBox shows every item unless it's given a shouldFilterItem, so each
151
+ // searchable dropdown gets one of these. Once an item is picked Carbon puts its label
152
+ // in the input, which would otherwise filter the reopened menu down to that one item —
153
+ // hence treating "input equals the current selection" as an empty query.
154
+ function filterByLabel<T>(toLabel: (item: T) => string, selectedLabel: string) {
155
+ return ({ item, inputValue }: { item: T; inputValue: string | null }) => {
156
+ const query = (inputValue ?? '').trim().toLowerCase();
157
+ if (!query || query === (selectedLabel ?? '').trim().toLowerCase()) {
158
+ return true;
159
+ }
160
+ return toLabel(item).toLowerCase().includes(query);
161
+ };
162
+ }
163
+
164
+ // Reasons biometric identification could not be used (option set for the request).
165
+ const WHITELIST_REASONS = [
166
+ 'Biometric device not working',
167
+ 'Patient fingerprints not readable',
168
+ 'Patient has no usable fingerprints',
169
+ 'Fingerprint repeatedly not matching',
170
+ 'Other',
171
+ ];
172
+
173
+ const phaseToIndex: Record<Phase, number> = {
174
+ biometric: 0,
175
+ 'biometric-not-setup': 0,
176
+ 'otp-gate': 0,
177
+ 'whitelist-request': 0,
178
+ 'whitelist-pending': 0,
179
+ otp: 0,
180
+ consent: 0,
181
+ visit: 1,
182
+ };
183
+
184
+ interface WorkflowDrawerProps {
185
+ open: boolean;
186
+ client?: HieClient;
187
+ clientType?: string;
188
+ locationUuid?: string;
189
+ requestCustomOtpDto?: RequestCustomOtpDto;
190
+ phoneNumber?: string;
191
+ // EMR lookup result for the client, so the user can create or sync the record.
192
+ amrsPatient?: Patient | null;
193
+ amrsChecked?: boolean;
194
+ syncingAmrs?: boolean;
195
+ onCreatePatient?: () => void;
196
+ onSyncPatient?: () => void;
197
+ onClose: () => void;
198
+ onStartVisit: (details: {
199
+ patientCategory: string;
200
+ room: string;
201
+ roomUuid: string;
202
+ visitType: string;
203
+ method?: Method;
204
+ insurance?: string;
205
+ }) => void;
206
+ }
207
+
208
+ const WorkflowDrawer: React.FC<WorkflowDrawerProps> = ({
209
+ open,
210
+ client,
211
+ clientType,
212
+ locationUuid,
213
+ requestCustomOtpDto,
214
+ phoneNumber,
215
+ amrsPatient,
216
+ amrsChecked,
217
+ syncingAmrs,
218
+ onCreatePatient,
219
+ onSyncPatient,
220
+ onClose,
221
+ onStartVisit,
222
+ }) => {
223
+ const [phase, setPhase] = useState<Phase>('biometric');
224
+ const [pendingEmrAction, setPendingEmrAction] = useState<'create' | 'sync' | null>(null);
225
+ const [isOtpWhitelisted, setIsOtpWhitelisted] = useState(false);
226
+ const [consent, setConsent] = useState(false);
227
+ const [launchingBiometric, setLaunchingBiometric] = useState(false);
228
+ const [biometricUrl, setBiometricUrl] = useState<string | null>(null);
229
+ const [failCount, setFailCount] = useState(0);
230
+ const [checkingWhitelist, setCheckingWhitelist] = useState(false);
231
+ const [submittingWhitelist, setSubmittingWhitelist] = useState(false);
232
+ const [showWhitelistForm, setShowWhitelistForm] = useState(false);
233
+ const [reason, setReason] = useState('');
234
+ const [failedImage, setFailedImage] = useState<File | null>(null);
235
+ const [reasonError, setReasonError] = useState('');
236
+ const [imageError, setImageError] = useState('');
237
+ const [dragOver, setDragOver] = useState(false);
238
+ const fileInputRef = useRef<HTMLInputElement>(null);
239
+ const [method, setMethod] = useState<Method>('cash');
240
+ const [patientCategory, setPatientCategory] = useState<string>(PATIENT_CATEGORIES[0]);
241
+ const [room, setRoom] = useState<string>('');
242
+ const [insurance, setInsurance] = useState<string>('');
243
+ const [visitType, setVisitType] = useState<string>('');
244
+ const [triageRooms, setTriageRooms] = useState<string[]>([]);
245
+ // Maps each triage room label to its service-queue uuid, needed to enqueue the patient.
246
+ const [triageQueueByRoom, setTriageQueueByRoom] = useState<Record<string, string>>({});
247
+ const [loadingRooms, setLoadingRooms] = useState(false);
248
+ const [insuranceSchemes, setInsuranceSchemes] = useState<string[]>([]);
249
+ const [loadingSchemes, setLoadingSchemes] = useState(false);
250
+ const [hasCashPoint, setHasCashPoint] = useState<boolean | null>(null);
251
+ const [hasCashMode, setHasCashMode] = useState<boolean | null>(null);
252
+ const [schemes, setSchemes] = useState<Scheme[]>([]);
253
+ const [loadingEligibility, setLoadingEligibility] = useState(false);
254
+ const [eligibilityChecked, setEligibilityChecked] = useState(false);
255
+ const [pomsfBalance, setPomsfBalance] = useState<PomsfBalance | null>(null);
256
+ const [insuranceError, setInsuranceError] = useState('');
257
+ // Required fields only flag once the user has actually been in them, so the step
258
+ // doesn't open pre-painted red. Each clears the moment its field has a value.
259
+ const [touched, setTouched] = useState<Record<RequiredField, boolean>>({
260
+ visitType: false,
261
+ room: false,
262
+ insurance: false,
263
+ });
264
+ const markTouched = (field: RequiredField) => () =>
265
+ setTouched((prev) => (prev[field] ? prev : { ...prev, [field]: true }));
266
+
267
+ useEffect(() => {
268
+ if (open) {
269
+ setPhase(isBiometricConfigured() ? 'biometric' : 'biometric-not-setup');
270
+ setPendingEmrAction(null);
271
+ setIsOtpWhitelisted(false);
272
+ setConsent(false);
273
+ setLaunchingBiometric(false);
274
+ setBiometricUrl(null);
275
+ setFailCount(0);
276
+ setReason('');
277
+ setFailedImage(null);
278
+ setReasonError('');
279
+ setImageError('');
280
+ setShowWhitelistForm(false);
281
+ setMethod('cash');
282
+ setPatientCategory(PATIENT_CATEGORIES[0]);
283
+ setRoom('');
284
+ setInsurance('');
285
+ setVisitType('');
286
+ setInsuranceError('');
287
+ setTriageRooms([]);
288
+ setTriageQueueByRoom({});
289
+ setInsuranceSchemes([]);
290
+ setHasCashPoint(null);
291
+ setHasCashMode(null);
292
+ setEligibilityChecked(false);
293
+ setTouched({ visitType: false, room: false, insurance: false });
294
+ }
295
+ }, [open]);
296
+
297
+ // Load the patient's eligibility schemes up front so the eligible schemes and
298
+ // SHA eligibility can be shown on the consent summary and appended to the SHA
299
+ // payment option.
300
+ useEffect(() => {
301
+ if (!open || !client?.id || !locationUuid) {
302
+ return;
303
+ }
304
+ let active = true;
305
+ setLoadingEligibility(true);
306
+ setSchemes([]);
307
+ setEligibilityChecked(false);
308
+ getClientEligibityStatus({ requestIdNumber: client.id, requestIdType: '3', locationUuid })
309
+ .then((resp) => {
310
+ if (!active) {
311
+ return;
312
+ }
313
+ setSchemes(resp?.schemes ?? []);
314
+ setEligibilityChecked(true);
315
+ })
316
+ .catch(() => {
317
+ if (active) {
318
+ setSchemes([]);
319
+ setEligibilityChecked(false);
320
+ }
321
+ })
322
+ .finally(() => {
323
+ if (active) {
324
+ setLoadingEligibility(false);
325
+ }
326
+ });
327
+ return () => {
328
+ active = false;
329
+ };
330
+ }, [open, client?.id, locationUuid]);
331
+
332
+ // POMSF's balance lives behind a separate HIE endpoint (/pomsf-balance) from
333
+ // the /eligibility call above, so it's fetched independently — gated only on
334
+ // POMSF being Active (regardless of which scheme is selected in the dropdown,
335
+ // since the Eligibility row below lists every active scheme unconditionally),
336
+ // and never on Visit type. That means switching Visit type afterwards just
337
+ // re-picks a benefit line out of the response already in state (see
338
+ // pomsf-balance.util.ts) rather than re-fetching. Uses a plain fetch rather
339
+ // than the usePomsfBalance hook, which pulls in useConfig({ externalModuleName
340
+ // }) and has been observed to throw here.
341
+ const pomsfActive = isPomsfActive(schemes);
342
+ useEffect(() => {
343
+ if (!open || !pomsfActive || !client?.id || !locationUuid) {
344
+ setPomsfBalance(null);
345
+ return;
346
+ }
347
+ let active = true;
348
+ fetchPomsfBalance(client.id, locationUuid)
349
+ .then((balance) => {
350
+ if (active) {
351
+ setPomsfBalance(balance);
352
+ }
353
+ })
354
+ .catch(() => {
355
+ if (active) {
356
+ setPomsfBalance(null);
357
+ }
358
+ });
359
+ return () => {
360
+ active = false;
361
+ };
362
+ }, [open, pomsfActive, client?.id, locationUuid]);
363
+
364
+ // Load triage service queues for the LOGGED-IN location only (queues whose
365
+ // name contains "triage"), so rooms from other locations aren't shown.
366
+ useEffect(() => {
367
+ if (!open || !locationUuid) {
368
+ return;
369
+ }
370
+ let active = true;
371
+ setLoadingRooms(true);
372
+ fetchServiceQueuesByLocationUuid(locationUuid)
373
+ .then((resp) => {
374
+ if (!active) {
375
+ return;
376
+ }
377
+ const triageQueues = (resp?.results ?? [])
378
+ // Strictly this location — never queues from sibling/child locations.
379
+ .filter((q) => q.location?.uuid === locationUuid)
380
+ .filter((q) => /triage/i.test(q.name ?? q.display ?? ''))
381
+ .map((q) => ({ label: decodeHtmlEntities(q.display || q.name), uuid: q.uuid }))
382
+ .filter((q) => q.label && q.uuid);
383
+ const byRoom: Record<string, string> = {};
384
+ for (const q of triageQueues) {
385
+ // First queue wins for a given label (deduped below for the dropdown).
386
+ if (!byRoom[q.label]) {
387
+ byRoom[q.label] = q.uuid;
388
+ }
389
+ }
390
+ setTriageQueueByRoom(byRoom);
391
+ setTriageRooms(Array.from(new Set(triageQueues.map((q) => q.label))));
392
+ })
393
+ .catch((err) => {
394
+ if (active) {
395
+ showSnackbar({
396
+ kind: 'error',
397
+ title: 'Couldn’t load triage rooms',
398
+ subtitle: getReadableErrorMessage(err, 'Please try again.'),
399
+ });
400
+ }
401
+ })
402
+ .finally(() => {
403
+ if (active) {
404
+ setLoadingRooms(false);
405
+ }
406
+ });
407
+ return () => {
408
+ active = false;
409
+ };
410
+ }, [open, locationUuid]);
411
+
412
+ // Payment modes are global; cash points are what's tied to a location. So we
413
+ // (1) check the logged-in location has a cash point (can it collect payment),
414
+ // and (2) load the global insurance schemes for the dropdown.
415
+ useEffect(() => {
416
+ if (!open || !locationUuid) {
417
+ return;
418
+ }
419
+ let active = true;
420
+ setLoadingSchemes(true);
421
+ Promise.all([fetchCashPoints(), fetchPaymentModes()])
422
+ .then(([cashPoints, modes]) => {
423
+ if (!active) {
424
+ return;
425
+ }
426
+ const facilityCashPoints = (cashPoints ?? []).filter((cp) => !cp.retired && cp.location?.uuid === locationUuid);
427
+ setHasCashPoint(facilityCashPoints.length > 0);
428
+
429
+ // Whether a "cash" payment mode is configured on the backend.
430
+ setHasCashMode((modes ?? []).some((m) => !m.retired && /cash/i.test(m.name ?? '')));
431
+
432
+ const schemes = (modes ?? [])
433
+ .filter((m) => !m.retired && m.name && !NON_INSURANCE_PAYMENT_MODES.test(m.name))
434
+ .map((m) => decodeHtmlEntities(m.name));
435
+ setInsuranceSchemes(Array.from(new Set(schemes)));
436
+ })
437
+ .catch((err) => {
438
+ if (active) {
439
+ showSnackbar({
440
+ kind: 'error',
441
+ title: 'Couldn’t load payment options',
442
+ subtitle: getReadableErrorMessage(err, 'Please try again.'),
443
+ });
444
+ }
445
+ })
446
+ .finally(() => {
447
+ if (active) {
448
+ setLoadingSchemes(false);
449
+ }
450
+ });
451
+ return () => {
452
+ active = false;
453
+ };
454
+ }, [open, locationUuid]);
455
+
456
+ // Check upfront whether OTP is already whitelisted for this client, so that
457
+ // when biometrics fail we can go straight to sending the OTP.
458
+ useEffect(() => {
459
+ if (!open || !client) {
460
+ return;
461
+ }
462
+ let active = true;
463
+ getOtpWhitelistStatus(client.id).then((status) => {
464
+ if (active) {
465
+ setIsOtpWhitelisted(status === 'approved');
466
+ }
467
+ });
468
+ return () => {
469
+ active = false;
470
+ };
471
+ // eslint-disable-next-line react-hooks/exhaustive-deps
472
+ }, [open]);
473
+
474
+ // When we reach the OTP gate, resolve the whitelist status and route accordingly.
475
+ useEffect(() => {
476
+ if (phase !== 'otp-gate' || !client) {
477
+ return;
478
+ }
479
+ let active = true;
480
+ setCheckingWhitelist(true);
481
+ getOtpWhitelistStatus(client.id)
482
+ .then((status) => {
483
+ if (!active) return;
484
+ if (status === 'approved') {
485
+ setPhase('otp');
486
+ } else if (status === 'pending') {
487
+ setPhase('whitelist-pending');
488
+ } else {
489
+ setPhase('whitelist-request');
490
+ }
491
+ })
492
+ .finally(() => active && setCheckingWhitelist(false));
493
+ return () => {
494
+ active = false;
495
+ };
496
+ // eslint-disable-next-line react-hooks/exhaustive-deps
497
+ }, [phase]);
498
+
499
+ if (!open || !client) {
500
+ return null;
501
+ }
502
+
503
+ const fullName = `${client.first_name} ${maskExceptFirstAndLast(client.middle_name)} ${maskExceptFirstAndLast(
504
+ client.last_name,
505
+ )}`;
506
+
507
+ // Selected person shown as a patient header: initials avatar (colour-coded by
508
+ // type) + name and type on one line, CR number on a subtle second line.
509
+ const isPrincipal = clientType === 'Principal';
510
+ const initials = `${client.first_name?.[0] ?? ''}${client.last_name?.[0] ?? ''}`.toUpperCase();
511
+ const clientStrip = (
512
+ <div className={styles.patientStrip}>
513
+ <span className={`${styles.patientAvatar} ${isPrincipal ? styles.avatarPrincipal : styles.avatarDependant}`}>
514
+ {initials}
515
+ </span>
516
+ <div className={styles.patientInfo}>
517
+ <div className={styles.patientLine1}>
518
+ <span className={styles.patientName}>{fullName}</span>
519
+ {clientType ? (
520
+ <Tag type={isPrincipal ? 'blue' : 'teal'} size="sm">
521
+ {clientType}
522
+ </Tag>
523
+ ) : null}
524
+ </div>
525
+ <span className={styles.patientCr}>CR · {maskCrNumber(client.id)}</span>
526
+ </div>
527
+ </div>
528
+ );
529
+
530
+ // The single action button on the EMR status card. Clicking it opens a focused
531
+ // confirmation dialog (emrConfirmModal) rather than expanding the card inline.
532
+ const emrActionArea = (kind: 'create' | 'sync') => {
533
+ const handler = kind === 'create' ? onCreatePatient : onSyncPatient;
534
+ if (!handler) {
535
+ return null;
536
+ }
537
+ return kind === 'create' ? (
538
+ <Button kind="primary" size="sm" onClick={() => setPendingEmrAction('create')}>
539
+ Create in EMR
540
+ </Button>
541
+ ) : (
542
+ <Button
543
+ kind="tertiary"
544
+ size="sm"
545
+ renderIcon={Renew}
546
+ disabled={syncingAmrs}
547
+ onClick={() => setPendingEmrAction('sync')}
548
+ >
549
+ {syncingAmrs ? 'Syncing…' : 'Sync'}
550
+ </Button>
551
+ );
552
+ };
553
+
554
+ // Focused confirmation dialog for the create / sync EMR actions.
555
+ const emrConfirmModal = (
556
+ <Modal
557
+ open={pendingEmrAction !== null}
558
+ size="sm"
559
+ modalHeading={pendingEmrAction === 'create' ? 'Create patient in the EMR?' : 'Sync EMR record?'}
560
+ primaryButtonText={pendingEmrAction === 'create' ? 'Yes, create' : 'Yes, sync'}
561
+ secondaryButtonText="Cancel"
562
+ primaryButtonDisabled={syncingAmrs}
563
+ onRequestClose={() => setPendingEmrAction(null)}
564
+ onSecondarySubmit={() => setPendingEmrAction(null)}
565
+ onRequestSubmit={() => {
566
+ const action = pendingEmrAction;
567
+ setPendingEmrAction(null);
568
+ if (action === 'create') {
569
+ onCreatePatient?.();
570
+ } else if (action === 'sync') {
571
+ onSyncPatient?.();
572
+ }
573
+ }}
574
+ >
575
+ <p className={styles.emrConfirmText}>
576
+ {pendingEmrAction === 'create'
577
+ ? `This patient does not yet exist in our records. A new EMR record will be created for CR ${maskCrNumber(
578
+ client.id,
579
+ )} so they can be registered and attended to.`
580
+ : `This patient already exists in our records. Their EMR record for CR ${maskCrNumber(
581
+ client.id,
582
+ )} will be updated with the latest registry details so their information is current before they are attended to.`}
583
+ </p>
584
+ </Modal>
585
+ );
586
+
587
+ // Shows the EMR lookup result for the client and lets the user act on it:
588
+ // create the patient in the EMR (not found) or sync an existing record (found).
589
+ const emrStatusCard = !amrsChecked ? null : amrsPatient ? (
590
+ <div>
591
+ {/* <div className={`${styles.emrStatus} ${styles.emrStatusFound}`}> */}
592
+ {/* <span className={styles.emrStatusIcon}>
593
+ <CheckmarkOutline size={20} />
594
+ </span>
595
+ <div className={styles.emrStatusBody}>
596
+ <span className={styles.emrStatusTitle}>Patient found in the EMR</span>
597
+ <span className={styles.emrStatusText}>
598
+ CR {maskCrNumber(client.id)} already has a record. Review the differences below and update the EMR with the
599
+ details you choose.
600
+ </span>
601
+ {amrsPatient.uuid ? (
602
+ <EmrCompare client={client} patientUuid={amrsPatient.uuid} onUpdated={onSyncPatient} />
603
+ ) : null}
604
+ </div> */}
605
+ </div>
606
+ ) : (
607
+ <div className={`${styles.emrStatus} ${styles.emrStatusMissing}`}>
608
+ <span className={styles.emrStatusIcon}>
609
+ <WarningAltFilled size={20} />
610
+ </span>
611
+ <div className={styles.emrStatusBody}>
612
+ <span className={styles.emrStatusTitle}>Patient not found in the system</span>
613
+ <span className={styles.emrStatusText}>
614
+ No EMR record matches CR {maskCrNumber(client.id)}. Review the details below and create the record to
615
+ continue.
616
+ </span>
617
+ <EmrCreatePreview client={client} onCreate={() => onCreatePatient?.()} />
618
+ </div>
619
+ </div>
620
+ );
621
+
622
+ const launchBiometric = async () => {
623
+ setLaunchingBiometric(true);
624
+ try {
625
+ const url = await getBiometricCaptureUrl(client.id);
626
+ if (url) {
627
+ setBiometricUrl(url);
628
+ } else {
629
+ showSnackbar({ kind: 'error', title: 'Could not start biometric capture', subtitle: 'Please try again.' });
630
+ }
631
+ } finally {
632
+ setLaunchingBiometric(false);
633
+ }
634
+ };
635
+
636
+ const handleBiometricFailed = () => {
637
+ const attempts = failCount + 1;
638
+ setFailCount(attempts);
639
+ setBiometricUrl(null);
640
+ // Messaging is shown in-page (fail count on the scanner, fallback note on the
641
+ // OTP screen) rather than as toasts.
642
+ if (attempts >= BIOMETRIC_MAX_ATTEMPTS) {
643
+ // If OTP is already whitelisted, go straight to sending it (with the
644
+ // override option); otherwise route through the whitelist gate.
645
+ setPhase(isOtpWhitelisted ? 'otp' : 'otp-gate');
646
+ }
647
+ };
648
+
649
+ // `stay` keeps the current screen (both buttons) instead of moving to the
650
+ // pending screen when the status is not yet approved.
651
+ const checkWhitelistStatus = async (stay = false) => {
652
+ setCheckingWhitelist(true);
653
+ try {
654
+ const status = await getOtpWhitelistStatus(client.id);
655
+ if (status === 'approved') {
656
+ setIsOtpWhitelisted(true);
657
+ showSnackbar({ kind: 'success', title: 'Whitelisted', subtitle: 'You can now use OTP verification.' });
658
+ setPhase('otp');
659
+ } else {
660
+ showSnackbar({ kind: 'info', title: 'Awaiting approval', subtitle: 'The SHA team has not approved this yet.' });
661
+ if (!stay) {
662
+ setPhase('whitelist-pending');
663
+ }
664
+ }
665
+ } finally {
666
+ setCheckingWhitelist(false);
667
+ }
668
+ };
669
+
670
+ const submitWhitelistRequest = async () => {
671
+ // Inline validation
672
+ let valid = true;
673
+ if (!reason.trim()) {
674
+ setReasonError('Select a reason for OTP');
675
+ valid = false;
676
+ } else {
677
+ setReasonError('');
678
+ }
679
+ if (!failedImage) {
680
+ setImageError('Attach an image of the failed biometric');
681
+ valid = false;
682
+ } else {
683
+ setImageError('');
684
+ }
685
+ if (!valid) {
686
+ return;
687
+ }
688
+ setSubmittingWhitelist(true);
689
+ try {
690
+ await requestOtpWhitelist({
691
+ crId: client.id,
692
+ reason,
693
+ failureCount: failCount,
694
+ failedBiometricImage: failedImage,
695
+ });
696
+ showSnackbar({ kind: 'success', title: 'Request submitted', subtitle: 'Awaiting approval from the SHA team.' });
697
+ setPhase('whitelist-pending');
698
+ } finally {
699
+ setSubmittingWhitelist(false);
700
+ }
701
+ };
702
+
703
+ const handleStartVisit = () => {
704
+ const usingInsurance = method === 'insurance';
705
+
706
+ // The required fields show their red state on landing (see the derived
707
+ // *InvalidText below) and the button is disabled while any is empty — guard
708
+ // here too as a safety net.
709
+ if (!room || !visitType || (usingInsurance && !insurance)) {
710
+ return;
711
+ }
712
+
713
+ onStartVisit({
714
+ patientCategory,
715
+ room,
716
+ roomUuid: triageQueueByRoom[room] ?? '',
717
+ visitType,
718
+ method,
719
+ insurance: usingInsurance ? insurance : undefined,
720
+ });
721
+ };
722
+
723
+ // Required-field validation. A field flags only once the user has been in it and
724
+ // left it empty, so the step doesn't open pre-painted red; each message then clears
725
+ // reactively the moment its field is filled.
726
+ const roomInvalidText =
727
+ touched.room && !room ? `Select a ${patientCategory === 'Walk-in' ? 'walk-in' : 'triage'} room` : '';
728
+ const visitTypeInvalidText = touched.visitType && !visitType ? 'Select a visit type' : '';
729
+ // The SHA-ineligibility message (set on selecting an ineligible scheme) takes
730
+ // precedence over the "select a scheme" prompt, and is shown regardless of touch
731
+ // state because it's a response to something the user just did.
732
+ const insuranceInvalidText =
733
+ insuranceError ||
734
+ (method === 'insurance' && touched.insurance && !insurance ? 'Select an insurance scheme' : '');
735
+
736
+ // A scheme is active/eligible when its coverage status is '1'.
737
+ const isActiveScheme = (s: Scheme) => s.coverage?.status === '1';
738
+
739
+ // Balance for the benefit line matching the current Visit type, picked from
740
+ // the POMSF balance response fetched above — see pomsf-balance.util.ts for the
741
+ // PMF-07/PMF-12 mapping and the rest of the gating rules.
742
+ const pomsfDisplayBalance = getPomsfDisplayBalance(schemes, visitType, pomsfBalance);
743
+ // The full breakdown (every benefit line, not just the one for the current
744
+ // Visit type) — shown underneath so staff can see all of a patient's POMSF
745
+ // benefits at a glance, not just the auto-picked one.
746
+ const pomsfAllBenefits = pomsfActive ? getAllPomsfBenefitBalances(pomsfBalance) : [];
747
+
748
+ // Every eligible scheme the registry returns for the patient (all active
749
+ // schemes) — shown in full on the consent summary.
750
+ const eligibleSchemes = schemes.filter(isActiveScheme);
751
+
752
+ // SHA eligibility indicator, shown on the consent summary and beside the SHA
753
+ // payment option. Derived from the eligible schemes: eligible when the patient
754
+ // has at least one active scheme.
755
+ const shaActive = eligibleSchemes.length > 0;
756
+
757
+ // Insurance dropdown items. SHA carries its eligibility in the name and is not
758
+ // selectable unless the patient is eligible (has an active eligible scheme).
759
+ const insuranceItems = insuranceSchemes.map((name) => {
760
+ const isSha = /sha|shif/i.test(name);
761
+ if (!isSha) {
762
+ return { id: name, label: name, isSha: false, eligible: true, disabled: false };
763
+ }
764
+ const suffix = loadingEligibility
765
+ ? ' · checking eligibility…'
766
+ : shaActive
767
+ ? ' · eligible'
768
+ : eligibilityChecked
769
+ ? ' · not eligible'
770
+ : ' · eligibility unknown';
771
+ return { id: name, label: `${name}${suffix}`, isSha: true, eligible: shaActive, disabled: !shaActive };
772
+ });
773
+
774
+ const shaEligibilityTag = loadingEligibility ? (
775
+ <InlineLoading className={styles.eligibilityLoading} description="Checking SHA eligibility…" />
776
+ ) : (
777
+ <Tag size="sm" type={shaActive ? 'green' : 'red'}>
778
+ {shaActive ? 'SHA · Eligible' : eligibilityChecked ? 'SHA · Not eligible' : 'SHA · Unknown'}
779
+ </Tag>
780
+ );
781
+
782
+ // The full list of the patient's eligible schemes — shared by the consent
783
+ // summary and the insurance payment section so both show the same detail.
784
+ const eligibleSchemesList =
785
+ eligibleSchemes.length > 0 ? (
786
+ <div className={styles.schemes}>
787
+ <div className={styles.schemesHead}>Eligible scheme{eligibleSchemes.length === 1 ? '' : 's'}</div>
788
+ <ul className={styles.schemeList}>
789
+ {eligibleSchemes.map((s, i) => (
790
+ <li key={`${s.schemeName}-${i}`} className={styles.schemeItem}>
791
+ <div className={styles.schemeTop}>
792
+ <span className={styles.schemeName}>{s.schemeName}</span>
793
+ <Tag size="sm" type="green">
794
+ Active
795
+ </Tag>
796
+ </div>
797
+ <div className={styles.schemeMeta}>
798
+ {s.memberType ? (
799
+ <span>{s.memberType.charAt(0).toUpperCase() + s.memberType.slice(1).toLowerCase()}</span>
800
+ ) : null}
801
+ {s.coverage?.endDate ? <span>Valid to {String(s.coverage.endDate).slice(0, 10)}</span> : null}
802
+ </div>
803
+ </li>
804
+ ))}
805
+ </ul>
806
+ </div>
807
+ ) : null;
808
+
809
+ return (
810
+ <>
811
+ {/* Overlay does NOT close on click — the user must use Close or Cancel */}
812
+ <div className={styles.overlay} />
813
+ <aside className={styles.drawer} role="dialog" aria-label="Registration workflow">
814
+ <header className={styles.header}>
815
+ <h4 className={styles.title}>Patient registration</h4>
816
+ <Button kind="ghost" size="sm" hasIconOnly iconDescription="Close" renderIcon={Close} onClick={onClose} />
817
+ </header>
818
+
819
+ <div className={styles.body}>
820
+ {/* The stepper scrolls with the content */}
821
+ <div className={styles.stepper}>
822
+ <div className={styles.stepperCard}>
823
+ <ProgressIndicator currentIndex={phaseToIndex[phase]} spaceEqually>
824
+ {STEPS.map((label) => (
825
+ <ProgressStep key={label} label={label} />
826
+ ))}
827
+ </ProgressIndicator>
828
+ <p className={styles.stepCaption}>
829
+ Step {phaseToIndex[phase] + 1} of {STEPS.length}: <strong>{STEPS[phaseToIndex[phase]]}</strong>
830
+ </p>
831
+ </div>
832
+ </div>
833
+
834
+ <div className={styles.bodyInner}>
835
+ {/* ---- Step 1: Verify — biometric ---- */}
836
+ {phase === 'biometric' ? (
837
+ <div className={styles.verifyContent}>
838
+ {!biometricUrl && clientStrip}
839
+ {!biometricUrl ? (
840
+ <>
841
+ {/* The scanner card — the primary action */}
842
+ <div className={styles.biometricArea}>
843
+ <button
844
+ type="button"
845
+ className={styles.biometricLaunch}
846
+ onClick={launchBiometric}
847
+ disabled={launchingBiometric}
848
+ >
849
+ <span className={styles.biometricIcon}>
850
+ <FingerprintRecognition size={48} />
851
+ </span>
852
+ <span className={styles.biometricLaunchText}>
853
+ {launchingBiometric ? 'Starting scanner…' : 'Tap to scan fingerprint'}
854
+ </span>
855
+ <span className={styles.biometricLaunchHint}>Confirm the patient&apos;s identity</span>
856
+ </button>
857
+ {failCount > 0 ? (
858
+ <p className={styles.failNote}>
859
+ Attempt {failCount} of {BIOMETRIC_MAX_ATTEMPTS} failed. Please try again.
860
+ </p>
861
+ ) : (
862
+ <></>
863
+ )}
864
+ </div>
865
+ {/* The step-by-step guide, below the scanner */}
866
+ <div className={styles.guidePanel}>
867
+ <div className={styles.guideHead}>
868
+ <Information size={18} className={styles.guideHeadIcon} />
869
+ How verification works
870
+ </div>
871
+ <ol className={styles.guideSteps}>
872
+ <li>Scan the patient&apos;s fingerprint to confirm their identity.</li>
873
+ <li>If the fingerprint fails {BIOMETRIC_MAX_ATTEMPTS} times, switch to an OTP code.</li>
874
+ <li>If OTP isn&apos;t allowed for this patient yet, request OTP whitelisting.</li>
875
+ <li>Once approved (or if already allowed), verify with the OTP sent to their phone.</li>
876
+ </ol>
877
+ </div>
878
+ </>
879
+ ) : (
880
+ <div className={styles.biometricFrameWrap}>
881
+ <iframe title="Fingerprint capture" src={biometricUrl} className={styles.biometricFrame} />
882
+ <div className={styles.capturePrompt}>
883
+ <span className={styles.capturePromptText}>Did the fingerprint match the patient?</span>
884
+ <span className={styles.capturePromptHint}>
885
+ {failCount > 0
886
+ ? `Attempt ${failCount + 1} of ${BIOMETRIC_MAX_ATTEMPTS}. After ${BIOMETRIC_MAX_ATTEMPTS} tries you'll switch to OTP.`
887
+ : `You have ${BIOMETRIC_MAX_ATTEMPTS} tries before switching to OTP.`}
888
+ </span>
889
+ <div className={styles.captureActions}>
890
+ <Button kind="secondary" size="sm" renderIcon={Renew} onClick={handleBiometricFailed}>
891
+ No, try again
892
+ </Button>
893
+ <Button
894
+ kind="primary"
895
+ size="sm"
896
+ renderIcon={CheckmarkOutline}
897
+ onClick={() => {
898
+ setConsent(true);
899
+ setPhase('consent');
900
+ }}
901
+ >
902
+ Yes, identified
903
+ </Button>
904
+ </div>
905
+ </div>
906
+ </div>
907
+ )}
908
+ </div>
909
+ ) : (
910
+ <></>
911
+ )}
912
+
913
+ {/* ---- Step 1: Verify — biometric not configured ---- */}
914
+ {phase === 'biometric-not-setup' ? (
915
+ <div className={styles.verifyContent}>
916
+ {clientStrip}
917
+ <div className={`${styles.statusCard} ${styles.statusCardDanger}`}>
918
+ <span className={`${styles.statusBadge} ${styles.statusBadgeDanger}`}>
919
+ <ScanDisabled size={20} />
920
+ </span>
921
+ <h5 className={styles.statusTitle}>Biometric not detected</h5>
922
+ <p className={styles.statusText}>
923
+ We couldn&apos;t detect a fingerprint scanner on this workstation. You can proceed by verifying the
924
+ patient with a one-time PIN (OTP) sent to their phone.
925
+ </p>
926
+ <Button
927
+ kind="primary"
928
+ size="sm"
929
+ renderIcon={ArrowRight}
930
+ onClick={() => setPhase(isOtpWhitelisted ? 'otp' : 'otp-gate')}
931
+ >
932
+ Use OTP instead
933
+ </Button>
934
+ </div>
935
+ </div>
936
+ ) : (
937
+ <></>
938
+ )}
939
+
940
+ {/* ---- Step 1: Verify — checking whitelist ---- */}
941
+ {phase === 'otp-gate' ? (
942
+ <div className={styles.verifyContent}>
943
+ <div className={styles.loadingCard}>
944
+ <InlineLoading description="Checking OTP whitelist status…" />
945
+ </div>
946
+ </div>
947
+ ) : (
948
+ <></>
949
+ )}
950
+
951
+ {/* ---- Step 1: Verify — whitelist request ---- */}
952
+ {phase === 'whitelist-request' ? (
953
+ <div className={styles.verifyContent}>
954
+ {!showWhitelistForm ? (
955
+ <div className={styles.statusCard}>
956
+ <span className={styles.statusBadge}>
957
+ <WarningAltFilled size={24} />
958
+ </span>
959
+ <h5 className={styles.statusTitle}>Not whitelisted for OTP</h5>
960
+ <p className={styles.statusText}>
961
+ This patient isn&apos;t whitelisted to receive a One-Time Password. Request whitelisting from the
962
+ SHA team to continue verifying by OTP.
963
+ </p>
964
+ <div className={styles.statusActions}>
965
+ <Button
966
+ kind="tertiary"
967
+ size="sm"
968
+ disabled={checkingWhitelist}
969
+ onClick={() => checkWhitelistStatus(true)}
970
+ >
971
+ {checkingWhitelist ? 'Checking…' : 'Check whitelist status'}
972
+ </Button>
973
+ <Button
974
+ kind="primary"
975
+ size="sm"
976
+ renderIcon={ArrowRight}
977
+ onClick={() => setShowWhitelistForm(true)}
978
+ >
979
+ Request whitelisting
980
+ </Button>
981
+ </div>
982
+ </div>
983
+ ) : (
984
+ <div className={styles.panel}>
985
+ <div className={styles.panelHead}>Request OTP whitelisting</div>
986
+ <div className={styles.panelBody}>
987
+ <div className={styles.infoNote}>
988
+ <Information size={20} className={styles.infoNoteIcon} />
989
+ <p className={styles.infoNoteText}>
990
+ OTP is not yet approved for this patient. Submit the details below to request whitelisting
991
+ from the SHA team.
992
+ </p>
993
+ </div>
994
+ <div className={styles.readonlyField}>
995
+ <span className={styles.readonlyLabel}>Biometric attempts failed</span>
996
+ <span className={styles.readonlyValue}>
997
+ {failCount} of {BIOMETRIC_MAX_ATTEMPTS}
998
+ </span>
999
+ </div>
1000
+ <Dropdown
1001
+ id="whitelist-reason"
1002
+ titleText={
1003
+ <span>
1004
+ Reason for OTP <span className={styles.required}>*</span>
1005
+ </span>
1006
+ }
1007
+ label="Select a reason"
1008
+ items={WHITELIST_REASONS}
1009
+ selectedItem={reason || null}
1010
+ invalid={!!reasonError}
1011
+ invalidText={reasonError}
1012
+ onChange={({ selectedItem }) => {
1013
+ setReason((selectedItem as string) ?? '');
1014
+ setReasonError('');
1015
+ }}
1016
+ />
1017
+ <div className={styles.uploadField}>
1018
+ <FormLabel>
1019
+ Image of failed biometric <span className={styles.required}>*</span>
1020
+ </FormLabel>
1021
+ <p className={styles.uploadHint}>
1022
+ Screenshot or photo of the failed attempt · PNG or JPG · one file
1023
+ </p>
1024
+ <div
1025
+ className={`${styles.dropZone} ${dragOver ? styles.dropZoneActive : ''} ${
1026
+ imageError ? styles.dropZoneInvalid : ''
1027
+ }`}
1028
+ role="button"
1029
+ tabIndex={0}
1030
+ onClick={() => fileInputRef.current?.click()}
1031
+ onKeyDown={(e) => {
1032
+ if (e.key === 'Enter' || e.key === ' ') {
1033
+ e.preventDefault();
1034
+ fileInputRef.current?.click();
1035
+ }
1036
+ }}
1037
+ onDragOver={(e) => {
1038
+ e.preventDefault();
1039
+ setDragOver(true);
1040
+ }}
1041
+ onDragLeave={() => setDragOver(false)}
1042
+ onDrop={(e) => {
1043
+ e.preventDefault();
1044
+ setDragOver(false);
1045
+ const file = e.dataTransfer.files?.[0];
1046
+ if (file) {
1047
+ setFailedImage(file);
1048
+ setImageError('');
1049
+ }
1050
+ }}
1051
+ >
1052
+ <span className={styles.dropIcon}>
1053
+ <CloudUpload size={24} />
1054
+ </span>
1055
+ <span className={styles.dropTitle}>Drag and drop an image here</span>
1056
+ <span className={styles.dropSubtitle}>or click to browse</span>
1057
+ <input
1058
+ ref={fileInputRef}
1059
+ type="file"
1060
+ accept=".png,.jpg,.jpeg"
1061
+ className={styles.hiddenInput}
1062
+ onChange={(e) => {
1063
+ const file = e.target.files?.[0] ?? null;
1064
+ setFailedImage(file);
1065
+ if (file) {
1066
+ setImageError('');
1067
+ }
1068
+ }}
1069
+ />
1070
+ </div>
1071
+ {failedImage ? (
1072
+ <FileUploaderItem
1073
+ name={failedImage.name}
1074
+ status="edit"
1075
+ iconDescription="Remove file"
1076
+ onDelete={() => setFailedImage(null)}
1077
+ />
1078
+ ) : null}
1079
+ {imageError ? <p className={styles.fieldError}>{imageError}</p> : null}
1080
+ </div>
1081
+ <Button
1082
+ className={styles.submitBtn}
1083
+ kind="primary"
1084
+ size="sm"
1085
+ disabled={submittingWhitelist || !reason.trim() || !failedImage}
1086
+ onClick={submitWhitelistRequest}
1087
+ >
1088
+ {submittingWhitelist ? 'Submitting…' : 'Submit request'}
1089
+ </Button>
1090
+ </div>
1091
+ </div>
1092
+ )}
1093
+ </div>
1094
+ ) : (
1095
+ <></>
1096
+ )}
1097
+
1098
+ {/* ---- Step 1: Verify — whitelist pending ---- */}
1099
+ {phase === 'whitelist-pending' ? (
1100
+ <div className={styles.verifyContent}>
1101
+ <div className={styles.statusCard}>
1102
+ <span className={styles.statusBadge}>
1103
+ <PendingFilled size={24} />
1104
+ </span>
1105
+ <h5 className={styles.statusTitle}>Awaiting approval</h5>
1106
+ <p className={styles.statusText}>
1107
+ Your OTP whitelisting request is pending approval. Check back to see if it has been approved.
1108
+ </p>
1109
+ <Button kind="primary" size="sm" disabled={checkingWhitelist} onClick={() => checkWhitelistStatus()}>
1110
+ {checkingWhitelist ? 'Checking…' : 'Check whitelist status'}
1111
+ </Button>
1112
+ </div>
1113
+ </div>
1114
+ ) : (
1115
+ <></>
1116
+ )}
1117
+
1118
+ {/* ---- Step 1: Verify — OTP ---- */}
1119
+ {phase === 'otp' && requestCustomOtpDto ? (
1120
+ <div className={styles.verifyContent}>
1121
+ <OtpVerificationStep
1122
+ requestCustomOtpDto={requestCustomOtpDto}
1123
+ phoneNumber={phoneNumber ?? ''}
1124
+ timerSeconds={OTP_EXPIRY_SECONDS}
1125
+ biometricFailedCount={failCount}
1126
+ onVerified={() => {
1127
+ setConsent(true);
1128
+ setPhase('consent');
1129
+ }}
1130
+ />
1131
+ </div>
1132
+ ) : (
1133
+ <></>
1134
+ )}
1135
+
1136
+ {/* ---- Step 2: Consent ---- */}
1137
+ {phase === 'consent' ? (
1138
+ <div className={styles.verifyContent}>
1139
+ <div className={styles.consentConfirmed}>
1140
+ <CheckboxCheckedFilled size={20} className={styles.consentConfirmedIcon} />
1141
+ <span className={styles.consentConfirmedText}>
1142
+ The patient has consented to you accessing their details. You can now proceed.
1143
+ </span>
1144
+ </div>
1145
+
1146
+ {consent ? (
1147
+ <>
1148
+ <div className={styles.panel}>
1149
+ <div className={styles.panelHead}>Patient details</div>
1150
+ <div className={styles.panelBody}>
1151
+ <dl className={styles.detailGrid}>
1152
+ <div className={`${styles.detailRow} ${styles.detailFull}`}>
1153
+ <dt>Full name</dt>
1154
+ <dd>
1155
+ {[client.first_name, client.middle_name, client.last_name].filter(Boolean).join(' ')}
1156
+ </dd>
1157
+ </div>
1158
+ <div className={styles.detailRow}>
1159
+ <dt>CR number</dt>
1160
+ <dd>{client.id}</dd>
1161
+ </div>
1162
+ <div className={styles.detailRow}>
1163
+ <dt>Phone number</dt>
1164
+ <dd>{client.phone || '—'}</dd>
1165
+ </div>
1166
+ <div className={styles.detailRow}>
1167
+ <dt>ID number</dt>
1168
+ <dd>{client.identification_number || '—'}</dd>
1169
+ </div>
1170
+ <div className={styles.detailRow}>
1171
+ <dt>SHA eligibility</dt>
1172
+ <dd>{shaEligibilityTag}</dd>
1173
+ </div>
1174
+ </dl>
1175
+
1176
+ {eligibleSchemesList}
1177
+ </div>
1178
+ </div>
1179
+ {emrStatusCard}
1180
+ {emrConfirmModal}
1181
+ </>
1182
+ ) : (
1183
+ <></>
1184
+ )}
1185
+ </div>
1186
+ ) : (
1187
+ <></>
1188
+ )}
1189
+
1190
+ {/* ---- Step 3: Start visit ---- */}
1191
+ {phase === 'visit' ? (
1192
+ <div className={styles.verifyContent}>
1193
+ <div className={`${styles.panelBody} ${styles.scrollBody}`}>
1194
+ <div {...lockSelection(!!visitType)} onBlurCapture={markTouched('visitType')}>
1195
+ <ComboBox
1196
+ id="visit-type"
1197
+ titleText={
1198
+ <span>
1199
+ Visit type<span className={styles.required}>*</span>
1200
+ </span>
1201
+ }
1202
+ placeholder="Search or select a visit type"
1203
+ items={VISIT_TYPE_OPTIONS}
1204
+ itemToString={(item) => item ?? ''}
1205
+ shouldFilterItem={filterByLabel<string>((item) => item ?? '', visitType)}
1206
+ selectedItem={visitType || null}
1207
+ invalid={!!visitTypeInvalidText}
1208
+ invalidText={visitTypeInvalidText}
1209
+ onChange={({ selectedItem }) => {
1210
+ setVisitType((selectedItem as string) ?? '');
1211
+ }}
1212
+ />
1213
+ </div>
1214
+ <div className={styles.formSection}>
1215
+ <h6 className={styles.sectionLabel}>Patient category</h6>
1216
+ <RadioButtonGroup
1217
+ legendText="Patient destination"
1218
+ name="patient-category-group"
1219
+ orientation="horizontal"
1220
+ valueSelected={patientCategory}
1221
+ onChange={(v) => {
1222
+ setPatientCategory(v as string);
1223
+ setRoom('');
1224
+ }}
1225
+ >
1226
+ {PATIENT_CATEGORIES.map((cat) => (
1227
+ <RadioButton key={cat} id={`cat-${cat.toLowerCase()}`} labelText={cat} value={cat} />
1228
+ ))}
1229
+ </RadioButtonGroup>
1230
+
1231
+ <div {...lockSelection(!!room)} onBlurCapture={markTouched('room')}>
1232
+ <ComboBox
1233
+ id="visit-room"
1234
+ titleText={
1235
+ <span>
1236
+ {patientCategory === 'Walk-in' ? 'Walk-in room' : 'Triage room'}
1237
+ <span className={styles.required}>*</span>
1238
+ </span>
1239
+ }
1240
+ placeholder={
1241
+ patientCategory === 'Walk-in'
1242
+ ? 'Search or select a walk-in room'
1243
+ : loadingRooms
1244
+ ? 'Loading triage rooms…'
1245
+ : triageRooms.length === 0
1246
+ ? 'No triage rooms for this location'
1247
+ : 'Search or select a triage room'
1248
+ }
1249
+ items={patientCategory === 'Walk-in' ? WALK_IN_ROOMS : triageRooms}
1250
+ itemToString={(item) => item ?? ''}
1251
+ shouldFilterItem={filterByLabel<string>((item) => item ?? '', room)}
1252
+ disabled={patientCategory === 'Triage' && (loadingRooms || triageRooms.length === 0)}
1253
+ selectedItem={room || null}
1254
+ invalid={!!roomInvalidText}
1255
+ invalidText={roomInvalidText}
1256
+ onChange={({ selectedItem }) => {
1257
+ setRoom((selectedItem as string) ?? '');
1258
+ }}
1259
+ />
1260
+ </div>
1261
+ </div>
1262
+
1263
+ <div className={styles.formSection}>
1264
+ <h6 className={styles.sectionLabel}>Payment</h6>
1265
+ {hasCashPoint === false ? (
1266
+ <div className={styles.errorNote}>
1267
+ <WarningAltFilled size={20} className={styles.errorNoteIcon} />
1268
+ <p className={styles.errorNoteText}>
1269
+ Payment modes have not been configured. Contact your system administrator.
1270
+ </p>
1271
+ </div>
1272
+ ) : null}
1273
+
1274
+ <RadioButtonGroup
1275
+ legendText="Payment method"
1276
+ name="method-group"
1277
+ orientation="horizontal"
1278
+ valueSelected={method}
1279
+ disabled={hasCashPoint === false}
1280
+ onChange={(v) => {
1281
+ // Switching payment method clears any preselected
1282
+ // insurance so it can't carry into the payer mapping —
1283
+ // insurance→cash and cash→insurance both start fresh.
1284
+ setMethod(v as Method);
1285
+ setInsurance('');
1286
+ setInsuranceError('');
1287
+ }}
1288
+ >
1289
+ <RadioButton id="method-cash" labelText="Cash" value="cash" />
1290
+ <RadioButton id="method-insurance" labelText="Insurance" value="insurance" />
1291
+ </RadioButtonGroup>
1292
+
1293
+ {method === 'cash' && hasCashMode === false ? (
1294
+ <div className={styles.errorNote}>
1295
+ <WarningAltFilled size={20} className={styles.errorNoteIcon} />
1296
+ <p className={styles.errorNoteText}>
1297
+ Cash payment mode is not set. Contact your system administrator.
1298
+ </p>
1299
+ </div>
1300
+ ) : null}
1301
+
1302
+ {method === 'insurance' ? (
1303
+ <div {...lockSelection(!!insurance)} onBlurCapture={markTouched('insurance')}>
1304
+ <ComboBox
1305
+ id="insurance-scheme"
1306
+ titleText={
1307
+ <span>
1308
+ Insurance scheme<span className={styles.required}>*</span>
1309
+ </span>
1310
+ }
1311
+ placeholder={
1312
+ loadingSchemes
1313
+ ? 'Loading insurance schemes…'
1314
+ : insuranceSchemes.length === 0
1315
+ ? 'No insurance schemes available'
1316
+ : 'Search or select insurance scheme'
1317
+ }
1318
+ items={insuranceItems}
1319
+ itemToString={(item) => (item ? item.label : '')}
1320
+ shouldFilterItem={filterByLabel(
1321
+ (item: (typeof insuranceItems)[number]) => item?.label ?? '',
1322
+ insuranceItems.find((i) => i.id === insurance)?.label ?? '',
1323
+ )}
1324
+ itemToElement={(item) =>
1325
+ item ? (
1326
+ item.isSha ? (
1327
+ <span
1328
+ className={`${styles.schemePill} ${
1329
+ item.eligible ? styles.schemePillEligible : styles.schemePillIneligible
1330
+ }`}
1331
+ >
1332
+ {item.label}
1333
+ </span>
1334
+ ) : (
1335
+ <span>{item.label}</span>
1336
+ )
1337
+ ) : null
1338
+ }
1339
+ disabled={loadingSchemes || insuranceSchemes.length === 0}
1340
+ selectedItem={insuranceItems.find((i) => i.id === insurance) ?? null}
1341
+ invalid={!!insuranceInvalidText}
1342
+ invalidText={insuranceInvalidText}
1343
+ onChange={({ selectedItem }) => {
1344
+ if (!selectedItem) {
1345
+ // The combo box's clear button hands back null — drop the selection.
1346
+ setInsurance('');
1347
+ setInsuranceError('');
1348
+ return;
1349
+ }
1350
+ if (selectedItem.disabled) {
1351
+ // Patient isn't SHA-eligible — block the selection.
1352
+ setInsurance('');
1353
+ setInsuranceError('Patient is not eligible for SHA. Choose another scheme.');
1354
+ return;
1355
+ }
1356
+ setInsurance(selectedItem.id);
1357
+ setInsuranceError('');
1358
+ }}
1359
+ />
1360
+ </div>
1361
+ ) : (
1362
+ <></>
1363
+ )}
1364
+
1365
+ {method === 'insurance' && /pomsf/i.test(insurance) && pomsfDisplayBalance !== null ? (
1366
+ <div className={styles.eligibilityRow}>
1367
+ <span className={styles.eligibilityRowLabel}>Eligibility</span>
1368
+ <Tag size="sm" type="green">
1369
+ {`POMSF · Active · ${formatKes(pomsfDisplayBalance)}`}
1370
+ </Tag>
1371
+ </div>
1372
+ ) : null}
1373
+
1374
+ {method === 'insurance' && /sha|shif/i.test(insurance) ? (
1375
+ <div className={styles.eligibilityRow}>
1376
+ <span className={styles.eligibilityRowLabel}>Eligibility</span>
1377
+ {shaEligibilityTag}
1378
+ {eligibleSchemes.map((s, i) => (
1379
+ <Tag key={`${s.schemeName}-${i}`} size="sm" type="green">
1380
+ {/* POMSF's tag additionally carries its balance for the current Visit
1381
+ type (see pomsf-balance.util.ts), once one is picked — this row
1382
+ lists every active scheme regardless of which one is selected above. */}
1383
+ {/pomsf/i.test(s.schemeName) && pomsfDisplayBalance !== null
1384
+ ? `${s.schemeName} · Active · ${formatKes(pomsfDisplayBalance)}`
1385
+ : `${s.schemeName} · Active`}
1386
+ </Tag>
1387
+ ))}
1388
+ </div>
1389
+ ) : null}
1390
+
1391
+ {method === 'insurance' && pomsfAllBenefits.length > 0 ? (
1392
+ <div className={styles.pomsfBenefitsSection}>
1393
+ <span className={styles.eligibilityRowLabel}>POMSF benefits</span>
1394
+ <div className={styles.tableWrapper}>
1395
+ <Table size="sm" aria-label="POMSF benefits">
1396
+ <TableHead>
1397
+ <TableRow>
1398
+ <TableHeader>Benefit</TableHeader>
1399
+ <TableHeader>Balance</TableHeader>
1400
+ </TableRow>
1401
+ </TableHead>
1402
+ <TableBody>
1403
+ {pomsfAllBenefits.map((benefit) => (
1404
+ <TableRow key={benefit.code}>
1405
+ <TableCell>{benefit.name}</TableCell>
1406
+ <TableCell>{benefit.balance !== null ? formatKes(benefit.balance) : '—'}</TableCell>
1407
+ </TableRow>
1408
+ ))}
1409
+ </TableBody>
1410
+ </Table>
1411
+ </div>
1412
+ </div>
1413
+ ) : null}
1414
+ </div>
1415
+ </div>
1416
+ </div>
1417
+ ) : (
1418
+ <></>
1419
+ )}
1420
+ </div>
1421
+ </div>
1422
+
1423
+ <footer className={styles.footer}>
1424
+ {phase === 'consent' && amrsChecked && !amrsPatient ? (
1425
+ <span className={styles.footerHint}>
1426
+ <WarningAltFilled size={16} className={styles.footerHintIcon} />
1427
+ Create the patient in the EMR to continue.
1428
+ </span>
1429
+ ) : (
1430
+ <div />
1431
+ )}
1432
+ <div className={styles.footerRight}>
1433
+ <Button kind="secondary" size="sm" onClick={onClose}>
1434
+ Cancel
1435
+ </Button>
1436
+ {phase === 'consent' ? (
1437
+ <Button
1438
+ kind="primary"
1439
+ size="sm"
1440
+ renderIcon={ArrowRight}
1441
+ // Block continuing until the patient exists in the EMR (found or created).
1442
+ disabled={!consent || !amrsPatient}
1443
+ onClick={() => setPhase('visit')}
1444
+ >
1445
+ Continue
1446
+ </Button>
1447
+ ) : (
1448
+ <></>
1449
+ )}
1450
+ {phase === 'visit' ? (
1451
+ <Button
1452
+ kind="primary"
1453
+ size="sm"
1454
+ renderIcon={ArrowRight}
1455
+ disabled={
1456
+ !room ||
1457
+ !visitType ||
1458
+ hasCashPoint === false ||
1459
+ (method === 'cash' && hasCashMode === false) ||
1460
+ (method === 'insurance' && !insurance)
1461
+ }
1462
+ onClick={handleStartVisit}
1463
+ >
1464
+ Start visit &amp; send to {patientCategory === 'Walk-in' ? 'walk-in' : 'triage'}
1465
+ </Button>
1466
+ ) : (
1467
+ <></>
1468
+ )}
1469
+ </div>
1470
+ </footer>
1471
+ </aside>
1472
+ </>
1473
+ );
1474
+ };
1475
+
1476
+ export default WorkflowDrawer;