@kenyaemr/esm-shr-app 5.4.4-pre.43 → 5.4.4-pre.430

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 (428) hide show
  1. package/.turbo/turbo-build.log +5 -5
  2. package/dist/1072.js +1 -1
  3. package/dist/1072.js.map +1 -1
  4. package/dist/1278.js +1 -0
  5. package/dist/1278.js.map +1 -0
  6. package/dist/15.js +1 -0
  7. package/dist/15.js.map +1 -0
  8. package/dist/1620.js +1 -0
  9. package/dist/1620.js.map +1 -0
  10. package/dist/1789.js +1 -0
  11. package/dist/1789.js.map +1 -0
  12. package/dist/1823.js +1 -0
  13. package/dist/1823.js.map +1 -0
  14. package/dist/1831.js +1 -0
  15. package/dist/1831.js.map +1 -0
  16. package/dist/1844.js +1 -0
  17. package/dist/1844.js.map +1 -0
  18. package/dist/1854.js +1 -0
  19. package/dist/1854.js.map +1 -0
  20. package/dist/1919.js +1 -0
  21. package/dist/1919.js.map +1 -0
  22. package/dist/1946.js +1 -0
  23. package/dist/1946.js.map +1 -0
  24. package/dist/2007.js +1 -1
  25. package/dist/2007.js.map +1 -1
  26. package/dist/2127.js +1 -0
  27. package/dist/2127.js.map +1 -0
  28. package/dist/2146.js +1 -0
  29. package/dist/2146.js.map +1 -0
  30. package/dist/2202.js +1 -0
  31. package/dist/2202.js.map +1 -0
  32. package/dist/2394.js +1 -0
  33. package/dist/2394.js.map +1 -0
  34. package/dist/2468.js +1 -0
  35. package/dist/2468.js.map +1 -0
  36. package/dist/2498.js +1 -0
  37. package/dist/2498.js.map +1 -0
  38. package/dist/2534.js +1 -1
  39. package/dist/2534.js.map +1 -1
  40. package/dist/2556.js +1 -0
  41. package/dist/2556.js.map +1 -0
  42. package/dist/26.js +1 -0
  43. package/dist/26.js.map +1 -0
  44. package/dist/{2561.js → 2648.js} +1 -1
  45. package/dist/2648.js.map +1 -0
  46. package/dist/2709.js +1 -0
  47. package/dist/2709.js.map +1 -0
  48. package/dist/2744.js +1 -0
  49. package/dist/2744.js.map +1 -0
  50. package/dist/2823.js +1 -0
  51. package/dist/2823.js.map +1 -0
  52. package/dist/2840.js +1 -0
  53. package/dist/2840.js.map +1 -0
  54. package/dist/2842.js +1 -0
  55. package/dist/2842.js.map +1 -0
  56. package/dist/2916.js +1 -0
  57. package/dist/2916.js.map +1 -0
  58. package/dist/2924.js +1 -0
  59. package/dist/2924.js.map +1 -0
  60. package/dist/3137.js +1 -0
  61. package/dist/3137.js.map +1 -0
  62. package/dist/3219.js +1 -0
  63. package/dist/3219.js.map +1 -0
  64. package/dist/3285.js +1 -0
  65. package/dist/3285.js.map +1 -0
  66. package/dist/3302.js +1 -0
  67. package/dist/3302.js.map +1 -0
  68. package/dist/3335.js +1 -0
  69. package/dist/3335.js.map +1 -0
  70. package/dist/3378.js +1 -0
  71. package/dist/3378.js.map +1 -0
  72. package/dist/3504.js +1 -0
  73. package/dist/3504.js.map +1 -0
  74. package/dist/356.js +1 -0
  75. package/dist/356.js.map +1 -0
  76. package/dist/3569.js +1 -0
  77. package/dist/3569.js.map +1 -0
  78. package/dist/3580.js +1 -0
  79. package/dist/3580.js.map +1 -0
  80. package/dist/3690.js +1 -0
  81. package/dist/3690.js.map +1 -0
  82. package/dist/3723.js +1 -0
  83. package/dist/3723.js.map +1 -0
  84. package/dist/3745.js +1 -0
  85. package/dist/3745.js.map +1 -0
  86. package/dist/3796.js +1 -0
  87. package/dist/3796.js.map +1 -0
  88. package/dist/3813.js +1 -0
  89. package/dist/3813.js.map +1 -0
  90. package/dist/3847.js +1 -0
  91. package/dist/3847.js.map +1 -0
  92. package/dist/393.js +6 -0
  93. package/dist/393.js.map +1 -0
  94. package/dist/3953.js +1 -0
  95. package/dist/3953.js.map +1 -0
  96. package/dist/4178.js +1 -1
  97. package/dist/4178.js.map +1 -1
  98. package/dist/4212.js +1 -0
  99. package/dist/4212.js.map +1 -0
  100. package/dist/4308.js +1 -1
  101. package/dist/4308.js.map +1 -1
  102. package/dist/4487.js +11 -0
  103. package/dist/4487.js.map +1 -0
  104. package/dist/4588.js +1 -0
  105. package/dist/4588.js.map +1 -0
  106. package/dist/4637.js +1 -1
  107. package/dist/4637.js.map +1 -1
  108. package/dist/466.js +1 -1
  109. package/dist/466.js.map +1 -1
  110. package/dist/4711.js +1 -0
  111. package/dist/4711.js.map +1 -0
  112. package/dist/4759.js +1 -0
  113. package/dist/4759.js.map +1 -0
  114. package/dist/4817.js +1 -0
  115. package/dist/4817.js.map +1 -0
  116. package/dist/4818.js +1 -0
  117. package/dist/4818.js.map +1 -0
  118. package/dist/500.js +1 -0
  119. package/dist/500.js.map +1 -0
  120. package/dist/5086.js +1 -1
  121. package/dist/5086.js.map +1 -1
  122. package/dist/5117.js +1 -0
  123. package/dist/5117.js.map +1 -0
  124. package/dist/5256.js +1 -0
  125. package/dist/5256.js.map +1 -0
  126. package/dist/5262.js +1 -0
  127. package/dist/5262.js.map +1 -0
  128. package/dist/5362.js +1 -0
  129. package/dist/5362.js.map +1 -0
  130. package/dist/5366.js +1 -0
  131. package/dist/5366.js.map +1 -0
  132. package/dist/5567.js +1 -0
  133. package/dist/5567.js.map +1 -0
  134. package/dist/5598.js +1 -0
  135. package/dist/5598.js.map +1 -0
  136. package/dist/5676.js +1 -1
  137. package/dist/5676.js.map +1 -1
  138. package/dist/5731.js +5 -0
  139. package/dist/5731.js.map +1 -0
  140. package/dist/5821.js +1 -0
  141. package/dist/5821.js.map +1 -0
  142. package/dist/5825.js +1 -0
  143. package/dist/5825.js.map +1 -0
  144. package/dist/5932.js +1 -0
  145. package/dist/5932.js.map +1 -0
  146. package/dist/5941.js +1 -0
  147. package/dist/5941.js.map +1 -0
  148. package/dist/6104.js +1 -1
  149. package/dist/6104.js.map +1 -1
  150. package/dist/6273.js +1 -0
  151. package/dist/6273.js.map +1 -0
  152. package/dist/6337.js +1 -0
  153. package/dist/6337.js.map +1 -0
  154. package/dist/6357.js +1 -0
  155. package/dist/6357.js.map +1 -0
  156. package/dist/6427.js +1 -1
  157. package/dist/6427.js.map +1 -1
  158. package/dist/6478.js +7 -0
  159. package/dist/6478.js.map +1 -0
  160. package/dist/6479.js +1 -1
  161. package/dist/6479.js.map +1 -1
  162. package/dist/6508.js +1 -0
  163. package/dist/6508.js.map +1 -0
  164. package/dist/6567.js +1 -0
  165. package/dist/6567.js.map +1 -0
  166. package/dist/6570.js +1 -0
  167. package/dist/6570.js.map +1 -0
  168. package/dist/6634.js +1 -0
  169. package/dist/6634.js.map +1 -0
  170. package/dist/6688.js +1 -0
  171. package/dist/6688.js.map +1 -0
  172. package/dist/6698.js +1 -0
  173. package/dist/6698.js.map +1 -0
  174. package/dist/682.js +1 -1
  175. package/dist/682.js.map +1 -1
  176. package/dist/689.js +1 -1
  177. package/dist/689.js.map +1 -1
  178. package/dist/7085.js +1 -0
  179. package/dist/7085.js.map +1 -0
  180. package/dist/740.js +1 -0
  181. package/dist/740.js.map +1 -0
  182. package/dist/7478.js +1 -1
  183. package/dist/7478.js.map +1 -1
  184. package/dist/7539.js +1 -0
  185. package/dist/7539.js.map +1 -0
  186. package/dist/7686.js +1 -0
  187. package/dist/7686.js.map +1 -0
  188. package/dist/7782.js +1 -0
  189. package/dist/7782.js.map +1 -0
  190. package/dist/7808.js +1 -0
  191. package/dist/7808.js.map +1 -0
  192. package/dist/781.js +1 -1
  193. package/dist/781.js.map +1 -1
  194. package/dist/8183.js +1 -0
  195. package/dist/8183.js.map +1 -0
  196. package/dist/8196.js +1 -1
  197. package/dist/8196.js.map +1 -1
  198. package/dist/820.js +1 -0
  199. package/dist/820.js.map +1 -0
  200. package/dist/8240.js +1 -1
  201. package/dist/8240.js.map +1 -1
  202. package/dist/8455.js +1 -0
  203. package/dist/8455.js.map +1 -0
  204. package/dist/8472.js +1 -0
  205. package/dist/8472.js.map +1 -0
  206. package/dist/8521.js +1 -0
  207. package/dist/8521.js.map +1 -0
  208. package/dist/8602.js +1 -0
  209. package/dist/8602.js.map +1 -0
  210. package/dist/8607.js +1 -0
  211. package/dist/8607.js.map +1 -0
  212. package/dist/8743.js +1 -0
  213. package/dist/8743.js.map +1 -0
  214. package/dist/8762.js +1 -0
  215. package/dist/8762.js.map +1 -0
  216. package/dist/8812.js +1 -0
  217. package/dist/8812.js.map +1 -0
  218. package/dist/8985.js +1 -0
  219. package/dist/8985.js.map +1 -0
  220. package/dist/9.js +1 -0
  221. package/dist/9.js.map +1 -0
  222. package/dist/901.js +1 -0
  223. package/dist/901.js.map +1 -0
  224. package/dist/9011.js +1 -1
  225. package/dist/9011.js.map +1 -1
  226. package/dist/9087.js +1 -0
  227. package/dist/9087.js.map +1 -0
  228. package/dist/9148.js +1 -0
  229. package/dist/9148.js.map +1 -0
  230. package/dist/9168.js +1 -0
  231. package/dist/9168.js.map +1 -0
  232. package/dist/935.js +1 -0
  233. package/dist/935.js.map +1 -0
  234. package/dist/9425.js +1 -1
  235. package/dist/9520.js +1 -1
  236. package/dist/9520.js.map +1 -1
  237. package/dist/9547.js +1 -0
  238. package/dist/9547.js.map +1 -0
  239. package/dist/9549.js +1 -0
  240. package/dist/9549.js.map +1 -0
  241. package/dist/9612.js +1 -0
  242. package/dist/9612.js.map +1 -0
  243. package/dist/9621.js +1 -0
  244. package/dist/9621.js.map +1 -0
  245. package/dist/9774.js +1 -0
  246. package/dist/9774.js.map +1 -0
  247. package/dist/9800.js +1 -0
  248. package/dist/9800.js.map +1 -0
  249. package/dist/9806.js +1 -0
  250. package/dist/9806.js.map +1 -0
  251. package/dist/9885.js +1 -0
  252. package/dist/9885.js.map +1 -0
  253. package/dist/992.js +1 -0
  254. package/dist/992.js.map +1 -0
  255. package/dist/kenyaemr-esm-shr-app.js +6 -5
  256. package/dist/kenyaemr-esm-shr-app.js.buildmanifest.json +1495 -598
  257. package/dist/kenyaemr-esm-shr-app.js.map +1 -1
  258. package/dist/main.js +6 -5
  259. package/dist/main.js.map +1 -1
  260. package/dist/routes.json +1 -1
  261. package/package.json +2 -2
  262. package/src/config-schema.ts +6 -6
  263. package/src/hooks/usePatient.ts +23 -9
  264. package/src/hooks/useSHRSummary.ts +1 -3
  265. package/src/index.ts +1 -4
  266. package/src/referrals/dependents/dependents.component.tsx +8 -1
  267. package/src/referrals/referral-reasons/referral-reasons.component.tsx +2 -2
  268. package/src/referrals/referral-tabs/referrals-tabs.component.tsx +9 -2
  269. package/src/referrals/referrals-actions.component.tsx +66 -7
  270. package/src/referrals/referrals.component.tsx +2 -2
  271. package/src/routes.json +92 -78
  272. package/src/shr-summary/shr-summary.component.tsx +12 -35
  273. package/src/shr-summary/shr-summary.resource.ts +74 -74
  274. package/src/shr-summary/tables/shr-summary-table.component.tsx +53 -23
  275. package/src/utils/function.tsx +9 -4
  276. package/src/workspace/referral-workspace.resource.ts +1 -2
  277. package/src/workspace/referral.workspace.scss +4 -2
  278. package/src/workspace/referrals.workspace.component.tsx +190 -183
  279. package/translations/am.json +4 -2
  280. package/translations/en.json +4 -2
  281. package/translations/fr.json +4 -2
  282. package/translations/sw.json +4 -2
  283. package/tsconfig.json +1 -1
  284. package/dist/1172.js +0 -1
  285. package/dist/1172.js.map +0 -1
  286. package/dist/132.js +0 -1
  287. package/dist/132.js.map +0 -1
  288. package/dist/1525.js +0 -1
  289. package/dist/1525.js.map +0 -1
  290. package/dist/1729.js +0 -17
  291. package/dist/1729.js.map +0 -1
  292. package/dist/1761.js +0 -1
  293. package/dist/1761.js.map +0 -1
  294. package/dist/1809.js +0 -7
  295. package/dist/1809.js.map +0 -1
  296. package/dist/1866.js +0 -1
  297. package/dist/1866.js.map +0 -1
  298. package/dist/1962.js +0 -1
  299. package/dist/1962.js.map +0 -1
  300. package/dist/2045.js +0 -1
  301. package/dist/2045.js.map +0 -1
  302. package/dist/2163.js +0 -1
  303. package/dist/2163.js.map +0 -1
  304. package/dist/2267.js +0 -1
  305. package/dist/2267.js.map +0 -1
  306. package/dist/235.js +0 -1
  307. package/dist/235.js.map +0 -1
  308. package/dist/2561.js.map +0 -1
  309. package/dist/2564.js +0 -1
  310. package/dist/2564.js.map +0 -1
  311. package/dist/2810.js +0 -2
  312. package/dist/2810.js.map +0 -1
  313. package/dist/2867.js +0 -1
  314. package/dist/2867.js.map +0 -1
  315. package/dist/3040.js +0 -1
  316. package/dist/3228.js +0 -1
  317. package/dist/3228.js.map +0 -1
  318. package/dist/329.js +0 -1
  319. package/dist/329.js.map +0 -1
  320. package/dist/3491.js +0 -1
  321. package/dist/3491.js.map +0 -1
  322. package/dist/3509.js +0 -1
  323. package/dist/3509.js.map +0 -1
  324. package/dist/3576.js +0 -1
  325. package/dist/3576.js.map +0 -1
  326. package/dist/4146.js +0 -1
  327. package/dist/4146.js.map +0 -1
  328. package/dist/4224.js +0 -1
  329. package/dist/4224.js.map +0 -1
  330. package/dist/4402.js +0 -1
  331. package/dist/4402.js.map +0 -1
  332. package/dist/4724.js +0 -1
  333. package/dist/4724.js.map +0 -1
  334. package/dist/4972.js +0 -1
  335. package/dist/4972.js.map +0 -1
  336. package/dist/509.js +0 -1
  337. package/dist/509.js.map +0 -1
  338. package/dist/5096.js +0 -1
  339. package/dist/5096.js.map +0 -1
  340. package/dist/5119.js +0 -1
  341. package/dist/5119.js.map +0 -1
  342. package/dist/5159.js +0 -13
  343. package/dist/5159.js.map +0 -1
  344. package/dist/5361.js +0 -1
  345. package/dist/5361.js.map +0 -1
  346. package/dist/5576.js +0 -1
  347. package/dist/5576.js.map +0 -1
  348. package/dist/5600.js +0 -1
  349. package/dist/5600.js.map +0 -1
  350. package/dist/5604.js +0 -1
  351. package/dist/5604.js.map +0 -1
  352. package/dist/5633.js +0 -1
  353. package/dist/5633.js.map +0 -1
  354. package/dist/5809.js +0 -1
  355. package/dist/5809.js.map +0 -1
  356. package/dist/5882.js +0 -1
  357. package/dist/5939.js +0 -5
  358. package/dist/5939.js.map +0 -1
  359. package/dist/6004.js +0 -1
  360. package/dist/6004.js.map +0 -1
  361. package/dist/6121.js +0 -3
  362. package/dist/6121.js.map +0 -1
  363. package/dist/6129.js +0 -1
  364. package/dist/6129.js.map +0 -1
  365. package/dist/6137.js +0 -1
  366. package/dist/6137.js.map +0 -1
  367. package/dist/6232.js +0 -1
  368. package/dist/6232.js.map +0 -1
  369. package/dist/6356.js +0 -1
  370. package/dist/6356.js.map +0 -1
  371. package/dist/6548.js +0 -1
  372. package/dist/6548.js.map +0 -1
  373. package/dist/6571.js +0 -1
  374. package/dist/6571.js.map +0 -1
  375. package/dist/6589.js +0 -1
  376. package/dist/6589.js.map +0 -1
  377. package/dist/6626.js +0 -1
  378. package/dist/6626.js.map +0 -1
  379. package/dist/6643.js +0 -1
  380. package/dist/6643.js.map +0 -1
  381. package/dist/6721.js +0 -1
  382. package/dist/6721.js.map +0 -1
  383. package/dist/6868.js +0 -1
  384. package/dist/6868.js.map +0 -1
  385. package/dist/7127.js +0 -1
  386. package/dist/7177.js +0 -1
  387. package/dist/7177.js.map +0 -1
  388. package/dist/7402.js +0 -1
  389. package/dist/7402.js.map +0 -1
  390. package/dist/7419.js +0 -1
  391. package/dist/7419.js.map +0 -1
  392. package/dist/7544.js +0 -1
  393. package/dist/7544.js.map +0 -1
  394. package/dist/7560.js +0 -1
  395. package/dist/7560.js.map +0 -1
  396. package/dist/8179.js +0 -6
  397. package/dist/8179.js.map +0 -1
  398. package/dist/8189.js +0 -1
  399. package/dist/8189.js.map +0 -1
  400. package/dist/8249.js +0 -1
  401. package/dist/8249.js.map +0 -1
  402. package/dist/8502.js +0 -1
  403. package/dist/8502.js.map +0 -1
  404. package/dist/8512.js +0 -1
  405. package/dist/8512.js.map +0 -1
  406. package/dist/8522.js +0 -1
  407. package/dist/8522.js.map +0 -1
  408. package/dist/8633.js +0 -1
  409. package/dist/8633.js.map +0 -1
  410. package/dist/8775.js +0 -11
  411. package/dist/8775.js.map +0 -1
  412. package/dist/8776.js +0 -1
  413. package/dist/8776.js.map +0 -1
  414. package/dist/8869.js +0 -1
  415. package/dist/8869.js.map +0 -1
  416. package/dist/887.js +0 -1
  417. package/dist/887.js.map +0 -1
  418. package/dist/8927.js +0 -1
  419. package/dist/8927.js.map +0 -1
  420. package/dist/916.js +0 -1
  421. package/dist/9355.js +0 -1
  422. package/dist/9355.js.map +0 -1
  423. package/dist/9675.js +0 -1
  424. package/dist/9675.js.map +0 -1
  425. package/dist/9931.js +0 -1
  426. package/dist/9931.js.map +0 -1
  427. package/jest.config.js +0 -3
  428. package/src/shr-summary/shr-authorization-form.workspace.tsx +0 -149
@@ -1,91 +1,91 @@
1
1
  import { openmrsFetch, restBaseUrl } from '@openmrs/esm-framework';
2
- import dayjs from 'dayjs';
3
- import { z } from 'zod';
4
- import { PHONE_NUMBER_REGEX } from '../constants';
5
2
 
6
- export const authorizationSchema = z
7
- .object({
8
- otp: z.string().min(1, 'Required'),
9
- receiver: z.string().regex(PHONE_NUMBER_REGEX).optional(),
10
- authMethod: z.string(),
11
- })
12
- .refine(
13
- (data) => {
14
- if (data.authMethod === 'otp') {
15
- return data.receiver;
16
- }
17
- return true;
18
- },
3
+ interface SmsResponseData {
4
+ status: string;
5
+ message: string;
6
+ id: string;
7
+ }
8
+ interface TokenResponse {
9
+ token: string;
10
+ issued: number; // Unix timestamp in milliseconds
11
+ expires: number; // Unix timestamp in milliseconds
12
+ status: string; // e.g., "success"
13
+ expires_in: number; // Expiration duration in milliseconds (e.g., 1440000 ms = 24 minutes)
14
+ }
15
+
16
+ interface VerifyResponseData {
17
+ response: string;
18
+ }
19
+
20
+ export const sendSHAOtp = async (phoneNumber: string, nationalId: string): Promise<SmsResponseData> => {
21
+ const messageTemplate = 'Message template';
22
+ const response = await openmrsFetch(
23
+ `${restBaseUrl}/kenyaemr/send-kenyaemr-sms?phone=${phoneNumber}&nationalId=${nationalId}&message=${messageTemplate}`,
19
24
  {
20
- message: 'Required',
21
- path: ['receiver'],
25
+ method: 'POST',
26
+ headers: { 'Content-Type': 'application/json' },
22
27
  },
23
28
  );
24
29
 
25
- export function generateOTP(length = 5) {
26
- let otpNumbers = '0123456789';
27
- let OTP = '';
28
- const len = otpNumbers.length;
29
- for (let i = 0; i < length; i++) {
30
- OTP += otpNumbers[Math.floor(Math.random() * len)];
31
- }
32
- return OTP;
33
- }
30
+ const rawResponseText = response.data;
34
31
 
35
- export function persistOTP(otp: string, patientUuid: string) {
36
- sessionStorage.setItem(
37
- patientUuid,
38
- JSON.stringify({
39
- otp,
40
- timestamp: new Date().toISOString(),
41
- }),
42
- );
43
- }
32
+ if (!rawResponseText) {
33
+ throw new Error('SMS Gateway returned an empty response.');
34
+ }
44
35
 
45
- export async function sendOtp({ otp, receiver }: z.infer<typeof authorizationSchema>, patientName: string) {
46
- const payload = parseMessage(
47
- { otp, patient_name: patientName, expiry_time: 5 },
48
- 'Dear {{patient_name}}, your OTP for accessing your Shared Health Records (SHR) is {{otp}}. Please enter this code to proceed. The code is valid for {{expiry_time}} minutes.',
49
- );
36
+ // Use the extraction logic
37
+ const extractedData = extractSmsData(rawResponseText);
50
38
 
51
- const url = `${restBaseUrl}/kenyaemr/send-kenyaemr-sms?message=${payload}&phone=${receiver}`;
39
+ // Throw an error if parsing failed or the payload was missing
40
+ if (!extractedData) {
41
+ throw new Error(`Failed to parse SMS gateway response. Raw response: ${rawResponseText}`);
42
+ }
52
43
 
53
- const res = await openmrsFetch(url, {
54
- method: 'POST',
55
- redirect: 'follow',
56
- });
57
- if (res.ok) {
58
- return await res.json();
44
+ // Explicitly check for successful status from the gateway payload
45
+ if (extractedData.status !== 'success') {
46
+ throw new Error(`SMS delivery failed with status: ${extractedData.status}. Message: ${extractedData.message}`);
59
47
  }
60
- throw new Error('Error sending otp');
61
- }
62
48
 
63
- function parseMessage(object, template) {
64
- const placeholderRegex = /{{(.*?)}}/g;
49
+ // Return the strongly-typed data to the caller
50
+ return extractedData;
51
+ };
65
52
 
66
- const parsedMessage = template.replace(placeholderRegex, (match, fieldName) => {
67
- if (object.hasOwnProperty(fieldName)) {
68
- return object[fieldName];
69
- } else {
70
- return match;
53
+ /**
54
+ * Extracts and parses the JSON payload from a mixed-text SMS API response.
55
+ * @param responseString The raw string response from the provider
56
+ * @returns SmsResponseData object or null if parsing fails
57
+ */
58
+ export function extractSmsData(responseString: string): SmsResponseData | null {
59
+ try {
60
+ // Regex to capture everything between the first '{' and the last '}'
61
+ const jsonMatch = responseString.match(/\{.*\}/);
62
+
63
+ if (!jsonMatch) {
64
+ console.error('No JSON payload found in the response string.');
65
+ return null;
71
66
  }
72
- });
73
67
 
74
- return parsedMessage;
75
- }
76
- export function verifyOtp(otp: string, patientUuid: string) {
77
- const data = sessionStorage.getItem(patientUuid);
78
- if (!data) {
79
- throw new Error('Invalid OTP');
68
+ // Parse the extracted JSON string
69
+ const parsedData: SmsResponseData = JSON.parse(jsonMatch[0]);
70
+ return parsedData;
71
+ } catch (error) {
72
+ console.error('Failed to parse SMS response data:', error);
73
+ return null;
80
74
  }
81
- const { otp: storedOtp, timestamp } = JSON.parse(data);
82
- const isExpired = dayjs(timestamp).add(5, 'minutes').isBefore(dayjs());
83
- if (storedOtp !== otp) {
84
- throw new Error('Invalid OTP');
85
- }
86
- if (isExpired) {
87
- throw new Error('OTP Expired');
88
- }
89
- sessionStorage.removeItem(patientUuid);
90
- return 'Verification success';
91
75
  }
76
+
77
+ export const verifyOtp = async (otp: string, uuid: string) => {
78
+ const url = `${restBaseUrl}/kenyaemr/validate-otp`;
79
+ const res = await openmrsFetch<VerifyResponseData>(url, {
80
+ method: 'POST',
81
+ headers: { 'Content-Type': 'application/json' },
82
+ body: { id: uuid, otp },
83
+ });
84
+ const data = res?.data?.response;
85
+ try {
86
+ const _data = JSON.parse(data) as TokenResponse;
87
+ return { status: 'success', data: _data };
88
+ } catch (error) {
89
+ return { status: 'error', error: data };
90
+ }
91
+ };
@@ -1,29 +1,25 @@
1
1
  import { Button, DataTableSkeleton, Layer, Tile } from '@carbon/react';
2
2
  import { ArrowRight } from '@carbon/react/icons';
3
- import { launchWorkspace, useLayoutType } from '@openmrs/esm-framework';
4
- import {
5
- CardHeader,
6
- EmptyDataIllustration,
7
- ErrorState,
8
- getPatientUuidFromStore,
9
- } from '@openmrs/esm-patient-common-lib';
10
- import React, { useState } from 'react';
3
+ import { showModal, showSnackbar } from '@openmrs/esm-framework';
4
+ import { CardHeader, EmptyDataIllustration, ErrorState } from '@openmrs/esm-patient-common-lib';
5
+ import React, { useRef, useState } from 'react';
11
6
  import { useTranslation } from 'react-i18next';
12
7
  import usePatient from '../../hooks/usePatient';
13
8
  import SharedHealthRecordsSummary from '../../shrpatient-summary/shrpatient-summary.component';
9
+ import { sendSHAOtp, verifyOtp } from '../shr-summary.resource';
14
10
  import styles from './shr-tables.scss';
15
11
 
16
- interface PatientSHRSummaryTableProps {}
12
+ interface PatientSHRSummaryTableProps {
13
+ patientUuid: string;
14
+ patient: fhir.Patient;
15
+ }
17
16
 
18
- const PatientSHRSummaryTable: React.FC<PatientSHRSummaryTableProps> = () => {
17
+ const PatientSHRSummaryTable: React.FC<PatientSHRSummaryTableProps> = ({ patient, patientUuid }) => {
19
18
  const { t } = useTranslation();
20
- const [pageSize, setPageSize] = useState(10);
21
- const layout = useLayoutType();
22
- const headerTitle = t('shrRecords', 'SHR Records');
23
-
24
- const patientUuid = getPatientUuidFromStore();
25
- const [accessGranted, setAccessGranted] = useState(false);
26
- const { error, isLoading, patientPhoneNumber, patientName } = usePatient(patientUuid);
19
+ const idRef = useRef<string>();
20
+ const [accessGranted, setAccessGranted] = useState(true);
21
+ const [isAuthorizing, setIsAuthorizing] = useState(false);
22
+ const { error, isLoading, patientPhoneNumber, patientName, nationalId } = usePatient(patientUuid);
27
23
 
28
24
  if (isLoading) {
29
25
  return <DataTableSkeleton />;
@@ -33,14 +29,48 @@ const PatientSHRSummaryTable: React.FC<PatientSHRSummaryTableProps> = () => {
33
29
  }
34
30
 
35
31
  const handleInitiateAuthorization = () => {
36
- launchWorkspace('shr-authorization-form', {
37
- workspaceTitle: 'SHR Pull Authorization Form',
38
- patientUuid,
39
- onVerified: () => {
32
+ const dispose = showModal('otp-verification-modal', {
33
+ onClose: () => {
34
+ if (!accessGranted) {
35
+ setIsAuthorizing(false);
36
+ }
37
+ dispose();
38
+ },
39
+ phoneNumber: patientPhoneNumber || '',
40
+ otpLength: 5,
41
+ expiryMinutes: 5,
42
+ centerBoxes: true,
43
+ onRequestOtp: async (_phone: string) => {
44
+ const { status, id } = await sendSHAOtp(_phone, nationalId as string);
45
+ idRef.current = id;
46
+ if (status !== 'success') {
47
+ throw new Error(t('otpFailed', 'Failed to send OTP'));
48
+ }
49
+ },
50
+
51
+ onVerify: async (enteredOtp: string) => {
52
+ const { status, data, error } = await verifyOtp(enteredOtp, idRef.current as string);
53
+ if (status !== 'success') {
54
+ throw new Error(t('authorizeFailed', 'Authorization failed'));
55
+ }
56
+ },
57
+
58
+ onVerificationSuccess: () => {
59
+ dispose();
60
+ setIsAuthorizing(false);
40
61
  setAccessGranted(true);
62
+ showSnackbar({
63
+ title: t('success', 'Success'),
64
+ subtitle: t('otpVerificationSuccessMessage', 'OTP Vefification succesfull'),
65
+ kind: 'success',
66
+ });
67
+ },
68
+
69
+ onCleanup: () => {
70
+ if (!accessGranted) {
71
+ setIsAuthorizing(false);
72
+ }
41
73
  },
42
- patientPhoneNumber,
43
- patientName,
44
74
  });
45
75
  };
46
76
 
@@ -139,11 +139,10 @@ export const getPatientAddress = (patient: Patient) => {
139
139
 
140
140
  export const getPatientIdentifiers = (patient: Patient) => {
141
141
  const identifiers = [];
142
-
143
- if (patient?.identifiers?.length) {
142
+ if (patient?.identifiers?.length && patient.identifiers.length > 0) {
144
143
  patient.identifiers.forEach((id) => {
145
- if (id.identifier && id.identifierType?.name) {
146
- const idTypeName = id.identifierType.name.toUpperCase();
144
+ if (id.identifier && id.identifierType?.display) {
145
+ const idTypeName = id.identifierType.display.toUpperCase();
147
146
 
148
147
  if (
149
148
  idTypeName.includes('CCC') ||
@@ -168,6 +167,12 @@ export const getPatientIdentifiers = (patient: Patient) => {
168
167
  IDENTIFIER_TYPE: 'FACILITY_ID',
169
168
  ASSIGNING_AUTHORITY: 'FACILITY',
170
169
  });
170
+ } else if (idTypeName.includes('CR')) {
171
+ identifiers.push({
172
+ ID: id.identifier,
173
+ IDENTIFIER_TYPE: 'CR_NUMBER',
174
+ ASSIGNING_AUTHORITY: 'SHA',
175
+ });
171
176
  }
172
177
  }
173
178
  });
@@ -20,10 +20,9 @@ export const useFacilities = (searchTerm: string) => {
20
20
  };
21
21
 
22
22
  export const useSendReferralToArtDirectory = () => {
23
- const { artDirectoryUrl } = useConfig<ReferralConfigObject>();
24
-
25
23
  const sendReferral = async (apiPayload: ReferralPayload): Promise<ReferralResponse> => {
26
24
  try {
25
+ const artDirectoryUrl = `${restBaseUrl}/kenyaemril/outboundReferral`;
27
26
  const response = await openmrsFetch(artDirectoryUrl, {
28
27
  method: 'POST',
29
28
  headers: {
@@ -23,14 +23,16 @@
23
23
  display: flex;
24
24
  flex-direction: column;
25
25
  height: 100%;
26
- padding-bottom: 20px;
27
26
  }
28
27
 
29
28
  .buttonSet {
30
29
  margin-top: auto;
31
30
  display: flex;
32
31
  justify-content: flex-end;
33
- margin-right: layout.$spacing-04;
32
+
33
+ & > button {
34
+ min-width: 50%;
35
+ }
34
36
  }
35
37
 
36
38
  .grid {