@eka-care/abha-stg 0.1.34 → 0.1.35

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 (116) hide show
  1. package/README.md +369 -101
  2. package/{dist/index.html → index.html} +1 -2
  3. package/package/styles/pds2/border.ts +69 -0
  4. package/package/styles/pds2/colors.ts +70 -0
  5. package/package/styles/pds2/spacing.ts +1007 -0
  6. package/package/tailwind/tailwind.config.ts +124 -0
  7. package/package.json +9 -8
  8. package/postcss.config.js +6 -0
  9. package/scripts/build-purged-css.cjs +70 -0
  10. package/src/App.css +0 -0
  11. package/src/App.tsx +43 -0
  12. package/src/api-queries/aorta-go/v3/get-profile-patient.ts +32 -0
  13. package/src/api-queries/aorta-go/v3/get-profiles-phr-user.ts +26 -0
  14. package/src/api-queries/aorta-go/v3/post-auth-init-v2.ts +34 -0
  15. package/src/api-queries/aorta-go/v3/post-auth-logout-v2.ts +32 -0
  16. package/src/api-queries/aorta-go/v3/post-auth-verify-v2.ts +38 -0
  17. package/src/api-queries/aorta-go/v3/post-profile-switch.ts +39 -0
  18. package/src/api-queries/ndhm/get-abdm-register-suggest.ts +37 -0
  19. package/src/api-queries/ndhm/get-pincode-details.ts +28 -0
  20. package/src/api-queries/ndhm/post-abdm-login-init.ts +37 -0
  21. package/src/api-queries/ndhm/post-abdm-login-phr.ts +37 -0
  22. package/src/api-queries/ndhm/post-abdm-login-verify.ts +37 -0
  23. package/src/api-queries/ndhm/post-abdm-profile-eka-link-phr.ts +40 -0
  24. package/src/api-queries/ndhm/post-abdm-profile-eka.ts +66 -0
  25. package/src/api-queries/ndhm/post-abdm-register-abha-number-create-phr.ts +37 -0
  26. package/src/api-queries/ndhm/post-abdm-register-mobile-create-phr.ts +66 -0
  27. package/src/api-queries/ndhm/post-abdm-register-mobile-resend-otp.ts +32 -0
  28. package/src/api-queries/ndhm/post-abdm-register-mobile-verify.ts +38 -0
  29. package/src/api-queries/ndhm/post-abdm-register-phr-check.ts +34 -0
  30. package/src/api-queries/ndhm/post-register-aadhaar-create-phr.ts +37 -0
  31. package/src/api-queries/ndhm/post-register-aadhaar-init.ts +34 -0
  32. package/src/api-queries/ndhm/post-register-aadhaar-mobile-resend-otp.ts +34 -0
  33. package/src/api-queries/ndhm/post-register-aadhaar-mobile-verify.ts +37 -0
  34. package/src/api-queries/ndhm/post-register-aadhaar-resend-otp.ts +34 -0
  35. package/src/api-queries/ndhm/post-register-aadhaar-verify.ts +40 -0
  36. package/src/api-queries/ndhm/post-register-mobile-init.ts +34 -0
  37. package/src/api-queries/use-get-profiles-patient.ts +12 -0
  38. package/src/api-queries/use-get-profiles-phr-user.ts +28 -0
  39. package/src/api-queries/use-post-abdm-login-verify-v1.ts +26 -0
  40. package/src/api-queries/use-post-auth-verify-v2.ts +50 -0
  41. package/src/api-queries/use-post-profile-switch.ts +58 -0
  42. package/src/api-queries/use-post-register-mobile-create-phr.ts +39 -0
  43. package/src/api-queries/user-post-abdm-profile-login-phr.ts +26 -0
  44. package/src/assets/Success.json +1 -0
  45. package/src/assets/react.svg +1 -0
  46. package/src/atoms/button/custom-button.tsx +32 -0
  47. package/src/atoms/button/index.tsx +40 -0
  48. package/src/atoms/button/types.d.ts +31 -0
  49. package/src/atoms/header.tsx +25 -0
  50. package/src/atoms/input-field/index.tsx +63 -0
  51. package/src/atoms/input-field/patient-input-field.tsx +16 -0
  52. package/src/atoms/input-field/types.ts +24 -0
  53. package/src/atoms/pds2-otp-input/index.tsx +35 -0
  54. package/src/atoms/pds2-otp-input/types.d.ts +3 -0
  55. package/src/atoms/single-input-chip/index.tsx +32 -0
  56. package/src/atoms/single-input-chip/types.ts +6 -0
  57. package/src/atoms/spinner.tsx +33 -0
  58. package/src/atoms/text-separator.tsx +11 -0
  59. package/src/atoms/ui/spinner.tsx +75 -0
  60. package/src/constants/constants.ts +376 -0
  61. package/src/fetch-client/index.ts +164 -0
  62. package/src/index.css +152 -0
  63. package/src/main.tsx +374 -0
  64. package/src/molecules/abha/bottom-sheet/bottom-sheet-wrapper.tsx +40 -0
  65. package/src/molecules/abha/bottom-sheet/index.tsx +66 -0
  66. package/src/molecules/abha/spaced-input-component.tsx +168 -0
  67. package/src/molecules/copyright-year.tsx +16 -0
  68. package/src/molecules/exit-popup/index.tsx +101 -0
  69. package/src/molecules/pds2-otp-component/index.tsx +147 -0
  70. package/src/organisms/abha/abha-header.tsx +25 -0
  71. package/src/organisms/abha/abha-stepper.tsx +83 -0
  72. package/src/organisms/abha/error-bottom-sheet.tsx +27 -0
  73. package/src/organisms/abha/otp-card.tsx +99 -0
  74. package/src/organisms/abha/verification-status.tsx +30 -0
  75. package/src/organisms/choose-language/choose-language.tsx +53 -0
  76. package/src/organisms/choose-language/types.ts +10 -0
  77. package/src/organisms/screen-switcher/screen-switcher.tsx +80 -0
  78. package/src/routes/abha-aadhaar-verification-status-screen.tsx +246 -0
  79. package/src/routes/abha-created-screen.tsx +45 -0
  80. package/src/routes/abha-login-otp-verify-screen.tsx +519 -0
  81. package/src/routes/abha-mobile-linking-status-screen.tsx +267 -0
  82. package/src/routes/abha-otp-and-mobile-screen.tsx +435 -0
  83. package/src/routes/abha-phone-number-verification-screen.tsx +388 -0
  84. package/src/routes/create-abha-address-screen.tsx +928 -0
  85. package/src/routes/create-abha-with-aadhaar-screen.tsx +986 -0
  86. package/src/routes/create-eka-profile-screen.tsx +831 -0
  87. package/src/routes/get-all-profiles-screen.tsx +161 -0
  88. package/src/routes/login-or-create-abha-address-screen.tsx +1056 -0
  89. package/src/routes/login-with-abha-screen.tsx +454 -0
  90. package/src/routes/select-abha-from-list-screen.tsx +792 -0
  91. package/src/routes/select-eka-profile-screen.tsx +446 -0
  92. package/src/routes/utils/trackAbhaEvent.ts +41 -0
  93. package/src/stores/auth-abha-store/index.ts +152 -0
  94. package/src/stores/auth-abha-store/types.ts +217 -0
  95. package/src/utils/mock-auth-response.ts +29 -0
  96. package/src/utils/send-event-utils.ts +76 -0
  97. package/src/utils/validations.ts +89 -0
  98. package/src/vite-env.d.ts +1 -0
  99. package/tailwind.config.ts +9 -0
  100. package/tsconfig.json +25 -0
  101. package/tsconfig.node.json +10 -0
  102. package/tsconfig.node.tsbuildinfo +1 -0
  103. package/tsconfig.tsbuildinfo +1 -0
  104. package/vite.config.d.ts +2 -0
  105. package/vite.config.js +30 -0
  106. package/vite.config.ts +35 -0
  107. package/dist/sdk/abha/css/abha.css +0 -1
  108. package/dist/sdk/abha/js/abha.js +0 -146
  109. /package/{dist → public}/images/adhaar.webp +0 -0
  110. /package/{dist → public}/images/at-the-rate.webp +0 -0
  111. /package/{dist → public}/images/avatar.webp +0 -0
  112. /package/{dist → public}/images/ayushman-bharat.webp +0 -0
  113. /package/{dist → public}/images/circle-checkmark.webp +0 -0
  114. /package/{dist → public}/images/link-abha.webp +0 -0
  115. /package/{dist → public}/images/national-authority.webp +0 -0
  116. /package/{dist → public}/images/three-dots.webp +0 -0
@@ -0,0 +1,1056 @@
1
+ import React, { useEffect, useState, useRef } from 'react';
2
+ import { unMount } from '../main';
3
+ import useAuthAbhaStore from '../stores/auth-abha-store';
4
+ import Pds2Header from '../atoms/header';
5
+ import { ChevronDownRegularIcon, PhoneSolidIcon, ArrowLeftRegularIcon } from '@eka-care/icons';
6
+ import {
7
+ ABHA_AUTH_FLOW_METHOD,
8
+ LOADING_STATE,
9
+ AUTH_METHOD,
10
+ REGISTRATION_TYPE,
11
+ GET_EXTRA_HEADERS,
12
+ } from '../constants/constants';
13
+ import Pds2InputField from '../atoms/input-field';
14
+ import SpacedInputComponent from '../molecules/abha/spaced-input-component';
15
+ import Pds2Button from '../atoms/button';
16
+ import { SCREEN_NAMES } from '../stores/auth-abha-store/types';
17
+ import AbhaStepper from '../organisms/abha/abha-stepper';
18
+ import handleSendEvent from '../utils/send-event-utils';
19
+ import postAbdmLoginInit from '../api-queries/ndhm/post-abdm-login-init';
20
+ import postAuthLogoutV2 from '../api-queries/aorta-go/v3/post-auth-logout-v2';
21
+ import postAuthInitV2 from '../api-queries/aorta-go/v3/post-auth-init-v2';
22
+ import postRegisterMobileInit from '../api-queries/ndhm/post-register-mobile-init';
23
+ import postRegisterAadhaarInit from '../api-queries/ndhm/post-register-aadhaar-init';
24
+
25
+ const isProd = import.meta.env.VITE_APP_ENV === 'PROD';
26
+ type InitMethod = 'aadhaar' | 'mobile';
27
+
28
+ const LoginorCreateAbhaScreen = () => {
29
+ const clientId = useAuthAbhaStore((state) => state.clientId);
30
+
31
+ useEffect(() => {
32
+ if (window.EkaAbha?.changeStatusBarColor) {
33
+ window.EkaAbha.changeStatusBarColor('#F2F4F7');
34
+ return () => {
35
+ if (window.EkaAbha?.changeStatusBarColor) window?.EkaAbha?.changeStatusBarColor('#FFFFFF');
36
+ };
37
+ }
38
+ }, []);
39
+
40
+ const handleBackButtonClick = () => {
41
+ window.EkaAbha?.onAbhaClose();
42
+ unMount();
43
+ };
44
+
45
+ const hideBackButtonFor = ['eka-web', 'phr'];
46
+
47
+ return (
48
+ <div className="pds2-h-full pds2-overflow-y-auto">
49
+ {/* * if clientId is eka-web or phr, do not show back button */}
50
+ {!hideBackButtonFor.includes(clientId) && (
51
+ <Pds2Header
52
+ prefixIcon={
53
+ <button onClick={handleBackButtonClick}>
54
+ <ArrowLeftRegularIcon />
55
+ </button>
56
+ }
57
+ title=""
58
+ className="pds2-bg-bg-01"
59
+ />
60
+ )}
61
+ <LoginOrCreateWithDifferentMethods />
62
+ </div>
63
+ );
64
+ };
65
+
66
+ const LoginOrCreateWithDifferentMethods = () => {
67
+ // State management from custom store
68
+ const selectedMethod = useAuthAbhaStore(
69
+ (state) => state.abhaAuthFlowMethod || ABHA_AUTH_FLOW_METHOD.MOBILE
70
+ );
71
+ const setAbhaAuthFlowMethod = useAuthAbhaStore((state) => state.setAbhaAuthFlowMethod);
72
+ const [identifierValue, setIdentifierValue] = useState<string>('');
73
+ const [abdmLoginInitApiStatus, setAbdmLoginInitApiStatus] = useState<LOADING_STATE>(
74
+ LOADING_STATE.IDLE
75
+ );
76
+ const isEkaAppLogin = useAuthAbhaStore((state) => state.isEkaAppLogin);
77
+ const [error, setError] = useState<string | null>('');
78
+ const setSelectedAbhaAddress = useAuthAbhaStore((state) => state.setSelectedAbhaAddress);
79
+ const setLoginIdentifierValue = useAuthAbhaStore((state) => state.setLoginIdentifierValue);
80
+ const setScreen = useAuthAbhaStore((state) => state.setScreen);
81
+ const [initApiStatus, setInitApiStatus] = useState<Record<InitMethod, LOADING_STATE>>({
82
+ aadhaar: LOADING_STATE.IDLE,
83
+ mobile: LOADING_STATE.IDLE,
84
+ });
85
+ const setRegistrationType = useAuthAbhaStore((state) => state.setRegistrationType);
86
+ const setAadhaarInitResponse = useAuthAbhaStore((state) => state.setAadhaarInitResponse);
87
+ const setMobileInitResponse = useAuthAbhaStore((state) => state.setMobileInitResponse);
88
+ const initAbhaAppMobileNumber = useAuthAbhaStore((state) => state.initAbhaAppMobileNumber);
89
+ const initAbhaAppIdentifierType = useAuthAbhaStore((state) => state.initAbhaAppIdentifierType);
90
+ const initAbhaAppIdentifier = useAuthAbhaStore((state) => state.initAbhaAppIdentifier);
91
+
92
+ const [mobileNumber, setMobileNumber] = useState('');
93
+ const [isValidMobileNumber, setIsValidMobileNumber] = useState(false);
94
+
95
+ const [isValidAadhaar, setIsValidAadhaar] = useState<boolean>(false);
96
+ const [aadhaarNumber, setAadhaarNumber] = useState('');
97
+
98
+ const [abhaNumber, setAbhaNumber] = useState('');
99
+ const [phrAddressFromDocApp, setPhrAddressFromDocApp] = useState('');
100
+ const [abhaAddress, setAbhaAddress] = useState('');
101
+
102
+ const isNewLoginOrCreateFlow = useAuthAbhaStore((state) => state.isNewLoginOrCreateFlow);
103
+ const setIsNewLoginOrCreateFlow = useAuthAbhaStore((state) => state.setIsNewLoginOrCreateFlow);
104
+ const clientId = useAuthAbhaStore((state) => state.clientId);
105
+ const hasInitApiTriggered = useRef(false);
106
+ const isInitApiTriggered = useAuthAbhaStore((state) => state.isInitApiTriggered);
107
+ const setIsInitApiTriggered = useAuthAbhaStore((state) => state.setIsInitApiTriggered);
108
+ const setIdentityValue = useAuthAbhaStore((state) => state.setIdentityValue);
109
+ const identityValue = useAuthAbhaStore((state) => state.identityValue);
110
+ const extra_headers = GET_EXTRA_HEADERS();
111
+ const setSelectedAbhaFlow = useAuthAbhaStore((state) => state.setSelectedAbhaFlow);
112
+ const isDocAppRequest = useAuthAbhaStore((state) => state.isDocAppRequest);
113
+ const txnId = useAuthAbhaStore((state) => state.txnId);
114
+
115
+ // Analytics: Track screen view
116
+ useEffect(() => {
117
+ trackAbhaEvent({
118
+ name: 'abha_login_or_create_screen',
119
+ data: {
120
+ flow: selectedMethod.toString()
121
+ },
122
+ });
123
+ });
124
+
125
+ // Prefill mobile number if present (from Eka app) and set validity
126
+ useEffect(() => {
127
+ if (!!initAbhaAppIdentifier && initAbhaAppIdentifierType === ABHA_AUTH_FLOW_METHOD.PHR_ADDRESS) {
128
+ setPhrAddressFromDocApp(initAbhaAppIdentifier);
129
+ setIdentifierValue(initAbhaAppIdentifier.split("@")[0]);
130
+ setIsDropdownOpen(true);
131
+ setIsPhrAddressSheetOpen(true);
132
+ setAbhaAuthFlowMethod(ABHA_AUTH_FLOW_METHOD.PHR_ADDRESS);
133
+ } else if (!!initAbhaAppIdentifier && initAbhaAppIdentifierType === ABHA_AUTH_FLOW_METHOD.ABHA_NUMBER) {
134
+ setIdentifierValue(initAbhaAppIdentifier);
135
+ setAbhaNumber(initAbhaAppIdentifier);
136
+ setIsDropdownOpen(true);
137
+ setIsAbhaNumberSheetOpen(true);
138
+ setAbhaAuthFlowMethod(ABHA_AUTH_FLOW_METHOD.ABHA_NUMBER);
139
+ } else if (!!initAbhaAppIdentifier && initAbhaAppIdentifierType === ABHA_AUTH_FLOW_METHOD.AADHAR_NUMBER) {
140
+ setAadhaarNumber(initAbhaAppIdentifier);
141
+ setIsValidAadhaar(true);
142
+ setIdentifierValue(initAbhaAppIdentifier);
143
+ setAbhaAuthFlowMethod(ABHA_AUTH_FLOW_METHOD.AADHAR_NUMBER);
144
+ } else if (!!initAbhaAppIdentifier && initAbhaAppIdentifierType === ABHA_AUTH_FLOW_METHOD.MOBILE) {
145
+ setMobileNumber(initAbhaAppIdentifier);
146
+ setIdentifierValue(initAbhaAppIdentifier);
147
+ setIsValidMobileNumber(initAbhaAppIdentifier.length === 10);
148
+ setError(null);
149
+ setAbhaAuthFlowMethod(ABHA_AUTH_FLOW_METHOD.MOBILE);
150
+ } else {
151
+ setIdentifierValue('');
152
+ setError(null);
153
+ setIsValidMobileNumber(false);
154
+ setIsDropdownOpen(false);
155
+ setIsPhrAddressSheetOpen(false);
156
+ setIsAbhaNumberSheetOpen(false);
157
+ setAbhaAuthFlowMethod(ABHA_AUTH_FLOW_METHOD.MOBILE);
158
+ }
159
+ }, [initAbhaAppIdentifierType]);
160
+
161
+ // Auto-submit for mobile method when 10 digits are entered
162
+ useEffect(() => {
163
+ if (isInitApiTriggered || hasInitApiTriggered.current) {
164
+ return;
165
+ }
166
+ if (mobileNumber && mobileNumber.length === 10) {
167
+ setIsInitApiTriggered(true);
168
+ hasInitApiTriggered.current = true;
169
+ handleNextClick("auto_submit_mobile");
170
+ }
171
+ }, [mobileNumber]);
172
+
173
+ // Auto-submit for Aadhaar method when 12 digits are entered
174
+ useEffect(() => {
175
+ if (isInitApiTriggered || hasInitApiTriggered.current) {
176
+ return;
177
+ }
178
+ if (aadhaarNumber && aadhaarNumber.length === 12) {
179
+ setIsInitApiTriggered(true);
180
+ hasInitApiTriggered.current = true;
181
+ handleNextClick("auto_submit_aadhaar");
182
+ }
183
+ }, [aadhaarNumber]);
184
+
185
+ // Auto-submit for abha number method when 14 digits + 3 hyphens are entered
186
+ useEffect(() => {
187
+ if (isInitApiTriggered || hasInitApiTriggered.current) {
188
+ return;
189
+ }
190
+ if (abhaNumber && abhaNumber.length === 17) {
191
+ setIsInitApiTriggered(true);
192
+ hasInitApiTriggered.current = true;
193
+ handleNextClick("auto_submit_abha");
194
+ }
195
+ }, [abhaNumber]);
196
+
197
+ // Auto-submit for phr address method when phrAddress contains @
198
+ useEffect(() => {
199
+ if (isInitApiTriggered || hasInitApiTriggered.current) {
200
+ return;
201
+ }
202
+ if (phrAddressFromDocApp && phrAddressFromDocApp.includes(isProd ? "@abdm" : "@sbx")) {
203
+ setIsInitApiTriggered(true);
204
+ hasInitApiTriggered.current = true;
205
+ handleNextClick("auto_submit_phr");
206
+ }
207
+ }, [phrAddressFromDocApp]);
208
+
209
+ // Analytics event tracker
210
+ const trackAbhaEvent = ({ name, data = {} }: { name: string; data?: Record<string, any> }) => {
211
+ const baseProps = {
212
+ login_platform: clientId,
213
+ is_eka_app_login: isEkaAppLogin ? 'true' : 'false',
214
+ is_new_login_or_create_flow: isNewLoginOrCreateFlow ? 'true' : 'false',
215
+ oid: extra_headers?.['X-User-ID'] ? 'true' : 'false',
216
+ access_token: extra_headers?.['auth'] ? 'true' : 'false',
217
+ txn_id: txnId || 'missing txnId',
218
+ flow: selectedMethod ?? ""
219
+ };
220
+
221
+ const eventData = {
222
+ ...baseProps,
223
+ ...data,
224
+ };
225
+
226
+ handleSendEvent({
227
+ eventName: name,
228
+ eventData,
229
+ });
230
+
231
+ window.curio?.pushToMixpanel?.(name, eventData);
232
+ };
233
+
234
+ // Dynamic heading based on selected method
235
+ const methodText = React.useMemo(() => {
236
+ switch (selectedMethod) {
237
+ case ABHA_AUTH_FLOW_METHOD.MOBILE:
238
+ return 'Enter your Mobile Number';
239
+ case ABHA_AUTH_FLOW_METHOD.AADHAR_NUMBER:
240
+ return 'Enter your Aadhaar Number';
241
+ default:
242
+ return '';
243
+ }
244
+ }, [selectedMethod]);
245
+
246
+ // Handle user input and apply formatting + validation
247
+ const handleIdentifierValueChange: React.ChangeEventHandler<HTMLInputElement> = (e) => {
248
+ const val = e.target.value;
249
+ switch (selectedMethod) {
250
+ case ABHA_AUTH_FLOW_METHOD.PHR_ADDRESS:
251
+ if (val.length > 20) return;
252
+ setAbhaAddress(val);
253
+ setIdentifierValue(val);
254
+ break;
255
+
256
+ case ABHA_AUTH_FLOW_METHOD.MOBILE:
257
+ if ((val && !/^[0-9]+$/.test(val)) || val.length > 10) return;
258
+ setMobileNumber(val);
259
+ setIsValidMobileNumber(true);
260
+ setIdentifierValue(val);
261
+ break;
262
+
263
+ case ABHA_AUTH_FLOW_METHOD.ABHA_NUMBER:
264
+ if (!/^[\d-]*$/.test(val) || val.length > 17) return;
265
+ const value = e.target.value.replace(/-/g, '');
266
+ let abhaNumber = '';
267
+ if (value.length > 0) abhaNumber += value.slice(0, 2);
268
+ if (value.length > 2) abhaNumber += `-${value.slice(2, 6)}`;
269
+ if (value.length > 6) abhaNumber += `-${value.slice(6, 10)}`;
270
+ if (value.length > 10) abhaNumber += `-${value.slice(10, 14)}`;
271
+ setAbhaNumber(abhaNumber);
272
+ return setIdentifierValue(abhaNumber.trim());
273
+
274
+ case ABHA_AUTH_FLOW_METHOD.AADHAR_NUMBER:
275
+ if (val && !/^[0-9]+$/.test(val)) return;
276
+ if (val.length > 12) return;
277
+
278
+ setAadhaarNumber(val);
279
+ setIsValidAadhaar(true);
280
+ setIdentifierValue(val);
281
+ break;
282
+ }
283
+ setIdentifierValue(val.trim());
284
+ };
285
+
286
+ // Disable editing if mobile is prefilled from Eka app
287
+ const isMobileNonEditable =
288
+ selectedMethod === ABHA_AUTH_FLOW_METHOD.MOBILE && !!initAbhaAppMobileNumber;
289
+
290
+ // Check if current identifier is valid based on method
291
+ const isValidIdentifier = React.useMemo(() => {
292
+ switch (selectedMethod) {
293
+ case ABHA_AUTH_FLOW_METHOD.PHR_ADDRESS:
294
+ return identifierValue.length >= 4 && identifierValue.length <= 20; // changing the lower limit to 4, since the address can be as short as 4 characters
295
+ case ABHA_AUTH_FLOW_METHOD.MOBILE:
296
+ return identifierValue.length === 10;
297
+ case ABHA_AUTH_FLOW_METHOD.ABHA_NUMBER:
298
+ return identifierValue.length === 17;
299
+ case ABHA_AUTH_FLOW_METHOD.AADHAR_NUMBER:
300
+ return identifierValue.length === 12;
301
+ }
302
+ }, [selectedMethod, identifierValue]);
303
+
304
+ // Utility to update API init status
305
+ const updateInitStatus = (method: InitMethod, status: LOADING_STATE) => {
306
+ setInitApiStatus((prev) => ({
307
+ ...prev,
308
+ [method]: status,
309
+ }));
310
+ };
311
+
312
+ // When Aadhaar OTP input is completed
313
+ const handleOnAadhaarInputComplete = ({ inputVal: newAadhaarNo }: { inputVal: string }) => {
314
+ if (newAadhaarNo.length === 12) {
315
+ setIdentifierValue(newAadhaarNo);
316
+ setAadhaarNumber(newAadhaarNo);
317
+ setIsValidAadhaar(true);
318
+ }
319
+ };
320
+
321
+ // Debug log for method change
322
+ useEffect(() => {
323
+ console.log('selectedMethod changed:==================>', selectedMethod);
324
+ }, [selectedMethod]);
325
+
326
+ const handleNextClick = async (flowStepType: string) => {
327
+ // Set the flag to indicate this is a new login/create ABHA flow
328
+ setIsNewLoginOrCreateFlow(true);
329
+ // Track event for clicking 'Next' on ABHA login
330
+ trackAbhaEvent({
331
+ name: 'abha_login_next_click',
332
+ data: {
333
+ flow_step_type: flowStepType,
334
+ },
335
+ });
336
+
337
+ // Begin login/auth process
338
+ setAbdmLoginInitApiStatus(LOADING_STATE.LOADING);
339
+
340
+ // Assume flow is login until proven otherwise (error in init)
341
+ setRegistrationType(REGISTRATION_TYPE.LOGIN);
342
+
343
+ let authTxnId = '';
344
+
345
+ // If login is not coming from Eka app, start ABDM auth init
346
+ if (!isEkaAppLogin) {
347
+ // Clear any previous auth sessions, logout is specifcally for outside the app flows
348
+ // clientIds are www-eka, android -> outside the app flow.
349
+ // Clear any previous auth sessions, logout is specifically for outside the app flows
350
+ const logoutSuccess = await postAuthLogoutV2();
351
+ trackAbhaEvent({
352
+ name: logoutSuccess ? 'abha_logout_success' : 'abha_logout_failure',
353
+ data: {
354
+ platform: clientId,
355
+ },
356
+ });
357
+
358
+ const { txn_id: txnId, error } = await postAuthInitV2({
359
+ method: AUTH_METHOD.ABHA,
360
+ });
361
+
362
+ if (!txnId || error) {
363
+ trackAbhaEvent({
364
+ name: 'abha_auth_init_failure',
365
+ data: {
366
+ flow_step_type: 'init',
367
+ authTxnId: authTxnId,
368
+ error_message: error || 'missing_txnId_or_unknown_error',
369
+ error_message_exists: !!error,
370
+ txn_id_exists: !!txnId,
371
+ },
372
+ });
373
+ setError(error?.message || 'Something went wrong. Please try again.');
374
+ setAbdmLoginInitApiStatus(LOADING_STATE.REJECTED);
375
+ return;
376
+ }
377
+ authTxnId = txnId;
378
+
379
+ // Track successful auth API call
380
+ trackAbhaEvent({
381
+ name: 'abha_auth_init_success.',
382
+ data: {
383
+ flow_step_type: 'init',
384
+ auth_txnId: authTxnId,
385
+ },
386
+ });
387
+ }
388
+
389
+ // Construct identifier (append domain if using ABHA address)
390
+ const loginIdentifier =
391
+ selectedMethod === ABHA_AUTH_FLOW_METHOD.PHR_ADDRESS
392
+ ? `${identifierValue}${isProd ? '@abdm' : '@sbx'}`
393
+ : identifierValue;
394
+
395
+ // ----- MOBILE LOGIN FLOW -----
396
+ if (
397
+ selectedMethod === ABHA_AUTH_FLOW_METHOD.MOBILE ||
398
+ selectedMethod === ABHA_AUTH_FLOW_METHOD.ABHA_NUMBER ||
399
+ selectedMethod === ABHA_AUTH_FLOW_METHOD.PHR_ADDRESS
400
+ ) {
401
+ const {
402
+ txn_id: abdmTxnId,
403
+ error: abdmLoginError,
404
+ action: abdmLoginErrorAction,
405
+ hint,
406
+ } = await postAbdmLoginInit({
407
+ method: selectedMethod,
408
+ identifier: loginIdentifier,
409
+ });
410
+
411
+ setIdentityValue(loginIdentifier); // Store identity used
412
+
413
+ // Track login init call
414
+ trackAbhaEvent({
415
+ name: 'abha_login_init_triggered',
416
+ data: {
417
+ flow_step_type: 'init',
418
+ authTxnId: authTxnId,
419
+ ndhmTxnId: abdmTxnId,
420
+ method: selectedMethod,
421
+ },
422
+ });
423
+
424
+ // ----- ABHA ADDRESS FLOW -----
425
+ if (selectedMethod === ABHA_AUTH_FLOW_METHOD.PHR_ADDRESS) {
426
+ setSelectedAbhaAddress(loginIdentifier);
427
+ }
428
+
429
+ if (abdmLoginError || !abdmTxnId) {
430
+ if (abdmLoginErrorAction?.cta?.pid === 'abha_mobile_enroll' && selectedMethod === ABHA_AUTH_FLOW_METHOD.MOBILE) {
431
+ // Attempt fallback to registration flow
432
+ updateInitStatus('mobile', LOADING_STATE.LOADING);
433
+ setRegistrationType(REGISTRATION_TYPE.CREATE);
434
+ const {
435
+ txn_id,
436
+ hint,
437
+ error: abdmRegMobileError,
438
+ action: abdmRegErrorAction,
439
+ } = await postRegisterMobileInit({
440
+ mobile_number: identifierValue,
441
+ });
442
+ setIdentityValue(identifierValue);
443
+ setSelectedAbhaFlow('mobile');
444
+
445
+ if (txn_id && hint) {
446
+ // Successful fallback to registration
447
+ setMobileInitResponse({
448
+ authTxnId,
449
+ txnId: txn_id,
450
+ mobileOtpSentToHint: hint,
451
+ });
452
+
453
+ trackAbhaEvent({
454
+ name: 'abha_mobile_registration_init_success',
455
+ data: {
456
+ flow_step_type: 'init',
457
+ authTxnId: authTxnId,
458
+ ndhmTxnId: abdmTxnId,
459
+ error_message: abdmRegMobileError,
460
+ error_action: abdmLoginErrorAction,
461
+ },
462
+ });
463
+
464
+ updateInitStatus('mobile', LOADING_STATE.RESOLVED);
465
+ setAbdmLoginInitApiStatus(LOADING_STATE.RESOLVED);
466
+ setRegistrationType(REGISTRATION_TYPE.CREATE);
467
+ setScreen(SCREEN_NAMES.ABHA_PHONE_NUMBER_VERIFICATION);
468
+ return;
469
+ }
470
+
471
+ updateInitStatus('mobile', LOADING_STATE.REJECTED);
472
+ trackAbhaEvent({
473
+ name: 'abha_mobile_registration_init_failure',
474
+ data: {
475
+ flow_step_type: 'init',
476
+ authTxnId: authTxnId,
477
+ error_message: abdmRegMobileError || 'unknown_error',
478
+ error_message_exists: !!abdmRegMobileError,
479
+ error_action_exists: !!abdmRegErrorAction,
480
+ },
481
+ });
482
+ if (abdmRegErrorAction) {
483
+ if (abdmRegErrorAction?.cta?.pid) {
484
+ return setScreen(SCREEN_NAMES.LOGIN_OR_CREATE_ABHA);
485
+ }
486
+ } else {
487
+ setError(abdmRegMobileError || 'Something went wrong');
488
+ }
489
+ setError(abdmRegMobileError || 'Something went wrong. Please try again.');
490
+ setAbdmLoginInitApiStatus(LOADING_STATE.REJECTED);
491
+ return;
492
+ }
493
+ trackAbhaEvent({
494
+ name: 'abha_login_init_failure',
495
+ data: {
496
+ flow_step_type: 'init',
497
+ authTxnId: authTxnId,
498
+ error_message: abdmLoginError || 'unknown_error',
499
+ error_message_exists: !!abdmLoginError,
500
+ error_action_exists: !!abdmLoginErrorAction,
501
+ },
502
+ });
503
+ setError(abdmLoginError || 'Something went wrong. Please try again.');
504
+ setAbdmLoginInitApiStatus(LOADING_STATE.REJECTED);
505
+ return;
506
+ }
507
+ // Login init success
508
+ trackAbhaEvent({
509
+ name: 'abha_login_init_success',
510
+ data: {
511
+ flow_step_type: 'init',
512
+ authTxnId: authTxnId,
513
+ ndhmTxnId: abdmTxnId,
514
+ hint: hint,
515
+ },
516
+ });
517
+
518
+ setAadhaarInitResponse({
519
+ authTxnId,
520
+ txnId: abdmTxnId,
521
+ aadhaarOtpSentToHint: hint || null,
522
+ });
523
+
524
+ setLoginIdentifierValue(loginIdentifier);
525
+ setAbdmLoginInitApiStatus(LOADING_STATE.RESOLVED);
526
+ setScreen(SCREEN_NAMES.VERIFY_OTP_LOGIN_WITH_ABHA);
527
+ return;
528
+ }
529
+
530
+ // ----- AADHAAR REGISTRATION FLOW -----
531
+ if (selectedMethod === ABHA_AUTH_FLOW_METHOD.AADHAR_NUMBER) {
532
+ updateInitStatus('aadhaar', LOADING_STATE.LOADING);
533
+ trackAbhaEvent({
534
+ name: 'aadhaar_registration_init_start',
535
+ data: {
536
+ flow_step_type: 'init',
537
+ authTxnId: authTxnId,
538
+ aadhaarNumber: identifierValue,
539
+ },
540
+ });
541
+ const {
542
+ txn_id,
543
+ hint,
544
+ error: aadhaarError,
545
+ action: errorAction,
546
+ } = await postRegisterAadhaarInit({
547
+ aadhaar_number: identifierValue,
548
+ });
549
+
550
+ setIdentityValue(identifierValue);
551
+ setSelectedAbhaFlow('aadhaar');
552
+
553
+ if (txn_id && hint) {
554
+ setAadhaarInitResponse({
555
+ authTxnId,
556
+ txnId: txn_id,
557
+ aadhaarOtpSentToHint: hint,
558
+ });
559
+
560
+ trackAbhaEvent({
561
+ name: 'aadhaar_registration_init_success',
562
+ data: {
563
+ flow_step_type: 'verify',
564
+ ndhmTxnId: txn_id,
565
+ authTxnId: authTxnId,
566
+ },
567
+ });
568
+ updateInitStatus('aadhaar', LOADING_STATE.RESOLVED);
569
+ setRegistrationType(REGISTRATION_TYPE.CREATE);
570
+ setAbdmLoginInitApiStatus(LOADING_STATE.RESOLVED);
571
+ setScreen(SCREEN_NAMES.ABHA_OTP_AND_MOBILE);
572
+ return;
573
+ }
574
+
575
+ trackAbhaEvent({
576
+ name: 'abha_registration_init_failure',
577
+ data: {
578
+ error_message: aadhaarError || 'unknown_error',
579
+ error_message_exists: !!aadhaarError,
580
+ auth_txn_id: authTxnId,
581
+ error_action: errorAction,
582
+ error_action_exists: !!errorAction,
583
+ },
584
+ });
585
+
586
+ updateInitStatus('aadhaar', LOADING_STATE.REJECTED);
587
+ setAbdmLoginInitApiStatus(LOADING_STATE.REJECTED);
588
+ // Error handler for Aadhaar registration failure
589
+ if (errorAction || aadhaarError) {
590
+ if (errorAction?.cta?.pid) {
591
+ setScreen(SCREEN_NAMES.LOGIN_OR_CREATE_ABHA);
592
+ } else {
593
+ setError(aadhaarError || 'Something went wrong');
594
+ }
595
+ return;
596
+ }
597
+ }
598
+ };
599
+
600
+ const [isDropdownOpen, setIsDropdownOpen] = useState(false);
601
+ const [isAbhaNumberSheetOpen, setIsAbhaNumberSheetOpen] = useState(false);
602
+ const [isPhrAddressSheetOpen, setIsPhrAddressSheetOpen] = useState(false);
603
+
604
+ return (
605
+ <>
606
+ <div className="pds2-pt-22 pds2-p-16 pds2-bg-bg-01 pds2-space-y-16 pds2-text-center pds2-rounded-b-24">
607
+ <AbhaStepper/>
608
+ <div className="pds2-flex pds2-justify-center pds2-items-center pds2-gap-16">
609
+ <div className="pds2-bg-bg-white pds2-rounded-16">
610
+ <img
611
+ src="https://cdn.eka.care/vagus/cm4ml1lwu00000tfs1okl7hs9.webp"
612
+ alt="abha"
613
+ className="pds2-w-64 pds2-h-64"
614
+ />
615
+ </div>
616
+ </div>
617
+
618
+ <div className="Heading3Semibold pds2-text-text-black">
619
+ {clientId === 'phr'
620
+ ? 'Login or Create your ABHA'
621
+ : isDocAppRequest
622
+ ? 'Add Patient via ABHA'
623
+ : 'Create your ABHA'}
624
+ </div>
625
+ <div className="pds2-text-text-03" style={{ marginTop: '4px' }}>
626
+ {selectedMethod === ABHA_AUTH_FLOW_METHOD.MOBILE
627
+ ? 'Enter your Mobile Number'
628
+ : selectedMethod === ABHA_AUTH_FLOW_METHOD.AADHAR_NUMBER
629
+ ? 'Enter your Aadhaar Number'
630
+ : selectedMethod === ABHA_AUTH_FLOW_METHOD.ABHA_NUMBER
631
+ ? 'Enter your ABHA Number'
632
+ : selectedMethod === ABHA_AUTH_FLOW_METHOD.PHR_ADDRESS
633
+ ? 'Enter your ABHA Address'
634
+ : methodText}
635
+ </div>
636
+
637
+ {/* Tabs for Mobile and Aadhaar - Only show for Mobile/Aadhaar methods */}
638
+ {(selectedMethod === ABHA_AUTH_FLOW_METHOD.MOBILE ||
639
+ selectedMethod === ABHA_AUTH_FLOW_METHOD.AADHAR_NUMBER) && (
640
+ <div className="pds2-relative pds2-flex pds2-bg-bg-seperator-dark pds2-rounded-12 pds2-mt-4">
641
+ {/* Sliding Background */}
642
+ <div
643
+ className="pds2-absolute pds2-top-0 pds2-bottom-0 pds2-bg-bg-white pds2-rounded-12 pds2-transition-all pds2-duration-300"
644
+ style={{
645
+ left: selectedMethod === ABHA_AUTH_FLOW_METHOD.MOBILE ? 0 : '50%',
646
+ width: '50%',
647
+ boxShadow: '0px 10px 4px -6px #18274B17',
648
+ }}
649
+ />
650
+ {/* Mobile Tab */}
651
+ <button
652
+ onClick={() => {
653
+ setAbhaAuthFlowMethod(ABHA_AUTH_FLOW_METHOD.MOBILE);
654
+ setError('');
655
+ }}
656
+ className='pds2-flex-1 pds2-py-6 pds2-flex pds2-items-center pds2-justify-center pds2-gap-8 pds2-relative pds2-z-10'
657
+ >
658
+ <PhoneSolidIcon className="pds2-w-14 pds2-h-14 pds2-text-icon-success-02" />
659
+ <span
660
+ className={`pds2-text-base ${
661
+ selectedMethod === ABHA_AUTH_FLOW_METHOD.MOBILE
662
+ ? 'pds2-font-bold pds2-text-fg-default'
663
+ : 'pds2-font-normal pds2-text-fg-subtle'
664
+ }`}
665
+ style={
666
+ selectedMethod === ABHA_AUTH_FLOW_METHOD.MOBILE
667
+ ? { fontWeight: 700 }
668
+ : { fontWeight: 400 }
669
+ }
670
+ >
671
+ Mobile
672
+ </span>
673
+ </button>
674
+ {/* Aadhaar Tab */}
675
+ <button
676
+ onClick={() => {
677
+ setAbhaAuthFlowMethod(ABHA_AUTH_FLOW_METHOD.AADHAR_NUMBER);
678
+ setError('');
679
+ }}
680
+ className='pds2-flex-1 pds2-py-6 pds2-flex pds2-items-center pds2-justify-center pds2-gap-8 pds2-relative pds2-z-10'
681
+ >
682
+ <img
683
+ src="https://cdn.eka.care/vagus/cm5mcdm3h00070tfs9fjkepff.webp"
684
+ alt="Aadhaar"
685
+ className="pds2-w-24 pds2-h-24"
686
+ />
687
+ <span
688
+ className={`pds2-text-base ${
689
+ selectedMethod === ABHA_AUTH_FLOW_METHOD.AADHAR_NUMBER
690
+ ? 'pds2-font-bold pds2-text-fg-default'
691
+ : 'pds2-font-normal pds2-text-fg-subtle'
692
+ }`}
693
+ style={
694
+ selectedMethod === ABHA_AUTH_FLOW_METHOD.AADHAR_NUMBER
695
+ ? { fontWeight: 700 }
696
+ : { fontWeight: 400 }
697
+ }
698
+ >
699
+ Aadhaar
700
+ </span>
701
+ </button>
702
+ </div>
703
+ )}
704
+
705
+ {/* Input Field Section - Only show for Mobile/Aadhaar methods */}
706
+ {(selectedMethod === ABHA_AUTH_FLOW_METHOD.MOBILE ||
707
+ selectedMethod === ABHA_AUTH_FLOW_METHOD.AADHAR_NUMBER) && (
708
+ <div className="pds2-mt-16 pds2-w-full pds2-max-w-md pds2-mx-auto pds2-px-4 pds2-relative">
709
+ {selectedMethod === ABHA_AUTH_FLOW_METHOD.AADHAR_NUMBER ? (
710
+ <SpacedInputComponent
711
+ initialValues={
712
+ initAbhaAppIdentifierType === ABHA_AUTH_FLOW_METHOD.AADHAR_NUMBER
713
+ ? (initAbhaAppIdentifier?.match(/.{1,4}/g) ?? undefined)
714
+ : undefined
715
+ }
716
+ disabled={initAbhaAppIdentifierType === ABHA_AUTH_FLOW_METHOD.AADHAR_NUMBER && !!initAbhaAppIdentifier}
717
+ numberOfInputs={3}
718
+ length={4}
719
+ placeholder="XXXX"
720
+ onSubmit={handleOnAadhaarInputComplete}
721
+ setIsValid={setIsValidAadhaar}
722
+ />
723
+ ) : (
724
+ <Pds2InputField
725
+ value={
726
+ initAbhaAppIdentifierType === ABHA_AUTH_FLOW_METHOD.MOBILE
727
+ ? initAbhaAppIdentifier || ''
728
+ : mobileNumber
729
+ }
730
+ disabled={initAbhaAppIdentifierType === ABHA_AUTH_FLOW_METHOD.MOBILE && !!initAbhaAppIdentifier}
731
+ onChange={handleIdentifierValueChange}
732
+ type="tel"
733
+ placeholder="Mobile Number"
734
+ inputMode="numeric"
735
+ autoFocus={true}
736
+ maxLength={10}
737
+ PrefixComponent={
738
+ <div className="pds2-flex pds2-items-center pds2-gap-x-8 pds2-border-r pds2-border-border-brand-02 pds2-pr-24">
739
+ <img
740
+ src="https://cdn.eka.care/vagus/cm4mlct2900000tg98p8u967s.webp"
741
+ alt="India Flag"
742
+ className="pds2-w-24 pds2-h-24"
743
+ />
744
+ <span className="pds2-text-text-black pds2-text-sm">+91</span>
745
+ </div>
746
+ }
747
+ />
748
+ )}
749
+ </div>
750
+ )}
751
+
752
+ {error && (selectedMethod === ABHA_AUTH_FLOW_METHOD.MOBILE ||
753
+ selectedMethod === ABHA_AUTH_FLOW_METHOD.AADHAR_NUMBER) && <div className="pds2-text-text-error Body3Regular">{error}</div>}
754
+
755
+ {/* Next Button - Only show for Mobile/Aadhaar methods */}
756
+ {(selectedMethod === ABHA_AUTH_FLOW_METHOD.MOBILE ||
757
+ selectedMethod === ABHA_AUTH_FLOW_METHOD.AADHAR_NUMBER) && (
758
+ <Pds2Button
759
+ title="Next"
760
+ IconComponent={() => (
761
+ <ChevronDownRegularIcon className="pds2-w-16 pds2-h-16 -pds2-rotate-90 pds2-ml-8" />
762
+ )}
763
+ state={!isValidIdentifier || abdmLoginInitApiStatus === LOADING_STATE.LOADING ? 'disabled' : 'enabled'}
764
+ isLoading={abdmLoginInitApiStatus === LOADING_STATE.LOADING}
765
+ onClick={() => handleNextClick("aadhaar_or_mobile_on_click")}
766
+ className="pds2-w-full"
767
+ />
768
+ )}
769
+ </div>
770
+
771
+ {/* Other Login Options Dropdown */}
772
+ <div className="pds2-m-16 pds2-bg-bg-white pds2-rounded-16 pds2-border pds2-border-border-03 pds2-overflow-hidden">
773
+ {/* Dropdown Header */}
774
+ <button
775
+ onClick={() => setIsDropdownOpen(!isDropdownOpen)}
776
+ className="pds2-w-full pds2-flex pds2-items-center pds2-justify-between pds2-p-16 pds2-bg-bg-white hover:pds2-bg-bg-02 pds2-transition-colors"
777
+ >
778
+ <span className="pds2-text-text-03">Other login options for ABHA</span>
779
+ <ChevronDownRegularIcon
780
+ className={`pds2-w-16 pds2-h-16 pds2-text-text-03 pds2-transition-transform ${
781
+ isDropdownOpen ? 'pds2-rotate-180' : ''
782
+ }`}
783
+ />
784
+ </button>
785
+
786
+ {/* Dropdown Content */}
787
+ <div
788
+ className={`pds2-overflow-hidden pds2-transition-all pds2-duration-300 ${
789
+ isDropdownOpen ? 'pds2-max-h-126 pds2-opacity-100' : 'pds2-max-h-0 pds2-opacity-0'
790
+ }`}
791
+ >
792
+ {/* Login -> ABHA Number */}
793
+ <button
794
+ onClick={() => {
795
+ setIsDropdownOpen(false);
796
+ setAbhaAuthFlowMethod(ABHA_AUTH_FLOW_METHOD.ABHA_NUMBER);
797
+ setIsAbhaNumberSheetOpen(true);
798
+ setError('');
799
+ }}
800
+ className="pds2-w-full pds2-flex pds2-items-center pds2-justify-between pds2-p-12 hover:pds2-bg-bg-02 pds2-transition-colors"
801
+ >
802
+ <div className="pds2-flex pds2-items-center pds2-gap-12">
803
+ <div className="pds2-w-40 pds2-h-40 pds2-rounded-full pds2-bg-bg-02 pds2-flex pds2-items-center pds2-justify-center">
804
+ <img
805
+ src="https://cdn.eka.care/vagus/cm4ml1lwu00000tfs1okl7hs9.webp"
806
+ alt="ABHA"
807
+ className="pds2-w-24 pds2-h-24"
808
+ />
809
+ </div>
810
+ <span className="Body1Regular pds2-text-text-black">Login with ABHA Number</span>
811
+ </div>
812
+ <ChevronDownRegularIcon className="pds2-w-16 pds2-h-16 -pds2-rotate-90 pds2-text-text-03" />
813
+ </button>
814
+
815
+ {/* Login with ABHA Address */}
816
+ <button
817
+ onClick={() => {
818
+ setIsDropdownOpen(false);
819
+ setAbhaAuthFlowMethod(ABHA_AUTH_FLOW_METHOD.PHR_ADDRESS);
820
+ setIsPhrAddressSheetOpen(true);
821
+ setError('');
822
+ }}
823
+ className="pds2-w-full pds2-flex pds2-items-center pds2-justify-between pds2-p-12 hover:pds2-bg-bg-02 pds2-transition-colors"
824
+ >
825
+ <div className="pds2-flex pds2-items-center pds2-gap-12">
826
+ <div className="pds2-w-40 pds2-h-40 pds2-rounded-full pds2-bg-bg-02 pds2-flex pds2-items-center pds2-justify-center">
827
+ <img
828
+ src="https://cdn.eka.care/vagus/cm4ml1lwu00000tfs1okl7hs9.webp"
829
+ alt="ABHA"
830
+ className="pds2-w-24 pds2-h-24"
831
+ />
832
+ </div>
833
+ <span className="Body1Regular pds2-text-text-black">Login with ABHA Address</span>
834
+ </div>
835
+ <ChevronDownRegularIcon className="pds2-w-16 pds2-h-16 -pds2-rotate-90 pds2-text-text-03" />
836
+ </button>
837
+ </div>
838
+ </div>
839
+
840
+ {/* Bottom Sheet for ABHA Number */}
841
+ <AbhaBottomSheet isOpen={isAbhaNumberSheetOpen} setIsOpen={setIsAbhaNumberSheetOpen} setFlowMethod={setAbhaAuthFlowMethod}>
842
+ <div className="pds2-p-24 pds2-text-center pds2-h-full pds2-flex pds2-flex-col">
843
+ {/* Close button */}
844
+ <div className="pds2-flex pds2-justify-end pds2-mb-16">
845
+ <button
846
+ onClick={() => {
847
+ setError(null);
848
+ setIsAbhaNumberSheetOpen(false);
849
+ setAbhaAuthFlowMethod(ABHA_AUTH_FLOW_METHOD.MOBILE);
850
+ }}
851
+ className="pds2-w-24 pds2-h-24 pds2-flex pds2-items-center pds2-justify-center pds2-text-text-03 hover:pds2-text-text-black"
852
+ >
853
+
854
+ </button>
855
+ </div>
856
+
857
+ {/* Content - flex grow to fill available space */}
858
+ <div className="pds2-flex-1 pds2-flex pds2-flex-col pds2-justify-start">
859
+ {/* ABHA Logo */}
860
+ <div className="pds2-flex pds2-justify-center pds2-mb-16">
861
+ <div className="pds2-w-64 pds2-h-64 pds2-rounded-full pds2-bg-bg-01 pds2-flex pds2-items-center pds2-justify-center">
862
+ <img
863
+ src="https://cdn.eka.care/vagus/cm4ml1lwu00000tfs1okl7hs9.webp"
864
+ alt="ABHA Logo"
865
+ className="pds2-w-48 pds2-h-48"
866
+ />
867
+ </div>
868
+ </div>
869
+
870
+ {/* Title and Description */}
871
+ <h2 className="Heading3Semibold pds2-text-text-black">Login with ABHA Number</h2>
872
+ <p className="Body2Regular pds2-text-text-03 pds2-mb-24">
873
+ Enter your 14 digit ABHA Number
874
+ </p>
875
+
876
+ {/* Input Field */}
877
+
878
+ <Pds2InputField
879
+ value={
880
+ initAbhaAppIdentifierType === ABHA_AUTH_FLOW_METHOD.ABHA_NUMBER
881
+ ? initAbhaAppIdentifier || ''
882
+ : abhaNumber
883
+ }
884
+ disabled={initAbhaAppIdentifierType === ABHA_AUTH_FLOW_METHOD.ABHA_NUMBER && !!initAbhaAppIdentifier}
885
+ onChange={handleIdentifierValueChange}
886
+ placeholder="00-0000-0000-0000"
887
+ padding="pds2-p-18"
888
+ textStyle="Body2Regular pds2-text-center pds2-text-lg"
889
+ borderStyle="focus-within:pds2-border-border-brand-01"
890
+ type="tel"
891
+ inputMode="numeric"
892
+ autoFocus={true}
893
+ onKeyDown={(e) => {
894
+ e.key === 'Enter' && handleNextClick('after_enter_abha_number_on_click_by_user');
895
+ }}
896
+ // className="pds2-w-full"
897
+ />
898
+
899
+ {error && <div className="pds2-text-text-error Body3Regular pds2-mt-12">{error}</div>}
900
+ {/* Next Button */}
901
+ <Pds2Button
902
+ title="Next"
903
+ IconComponent={() => (
904
+ <ChevronDownRegularIcon className="pds2-w-16 pds2-h-16 -pds2-rotate-90 pds2-ml-8" />
905
+ )}
906
+ state={!identifierValue || abdmLoginInitApiStatus === LOADING_STATE.LOADING ? 'disabled' : 'enabled'}
907
+ onClick={() => handleNextClick("after_enter_abha_number_on_click_by_user")}
908
+ className={`pds2-w-full ${error ? 'pds2-mt-12' : 'pds2-mt-24'}`}
909
+ isLoading={abdmLoginInitApiStatus === LOADING_STATE.LOADING}
910
+ />
911
+ </div>
912
+ </div>
913
+ </AbhaBottomSheet>
914
+
915
+ {/* Bottom Sheet for ABHA Address */}
916
+ <AbhaBottomSheet isOpen={isPhrAddressSheetOpen} setIsOpen={setIsPhrAddressSheetOpen} setFlowMethod={setAbhaAuthFlowMethod}>
917
+ <div className="pds2-p-24 pds2-text-center pds2-h-full pds2-flex pds2-flex-col">
918
+ {/* Close button */}
919
+ <div className="pds2-flex pds2-justify-end pds2-mb-16">
920
+ <button
921
+ onClick={() => {
922
+ setError(null);
923
+ setIsPhrAddressSheetOpen(false);
924
+ setAbhaAuthFlowMethod(ABHA_AUTH_FLOW_METHOD.MOBILE);
925
+ }}
926
+ className="pds2-w-24 pds2-h-24 pds2-flex pds2-items-center pds2-justify-center pds2-text-text-03 hover:pds2-text-text-black"
927
+ >
928
+
929
+ </button>
930
+ </div>
931
+
932
+ {/* Content - flex grow to fill available space */}
933
+ <div className="pds2-flex-1 pds2-flex pds2-flex-col pds2-justify-start">
934
+ {/* ABHA Logo */}
935
+ <div className="pds2-flex pds2-justify-center pds2-mb-16">
936
+ <div className="pds2-w-64 pds2-h-64 pds2-rounded-full pds2-bg-bg-01 pds2-flex pds2-items-center pds2-justify-center">
937
+ <img
938
+ src="https://cdn.eka.care/vagus/cm4ml1lwu00000tfs1okl7hs9.webp"
939
+ alt="ABHA Logo"
940
+ className="pds2-w-48 pds2-h-48"
941
+ />
942
+ </div>
943
+ </div>
944
+
945
+ {/* Title and Description */}
946
+ <h2 className="Heading3Semibold pds2-text-text-black">Login with ABHA Address</h2>
947
+ <p className="Body2Regular pds2-text-text-03 pds2-mb-24">
948
+ Enter your ABHA Address below
949
+ </p>
950
+
951
+ {/* Input Field with suffix */}
952
+ <div className="pds2-relative">
953
+ <Pds2InputField
954
+ value={
955
+ initAbhaAppIdentifierType === ABHA_AUTH_FLOW_METHOD.PHR_ADDRESS
956
+ ? initAbhaAppIdentifier?.split("@")[0] || ''
957
+ : abhaAddress
958
+ }
959
+ disabled={initAbhaAppIdentifierType === ABHA_AUTH_FLOW_METHOD.PHR_ADDRESS && !!initAbhaAppIdentifier}
960
+ onChange={handleIdentifierValueChange}
961
+ placeholder="Enter ABHA Address"
962
+ inputMode="text"
963
+ autoFocus={true}
964
+ onKeyDown={(e) => {
965
+ e.key === 'Enter' && handleNextClick('after_enter_abha_address_on_click_by_user');
966
+ }}
967
+ // className="pds2-w-full pds2-pr-64"
968
+ />
969
+ <div className="pds2-absolute pds2-right-16 pds2-top-16 Body1Regular pds2-text-text-03">
970
+ {isProd ? '@abdm' : '@sbx'}
971
+ </div>
972
+ </div>
973
+
974
+ {error && <div className="pds2-text-text-error Body3Regular pds2-mt-12">{error}</div>}
975
+
976
+ {/* Next Button */}
977
+ <Pds2Button
978
+ title="Next"
979
+ IconComponent={() => (
980
+ <ChevronDownRegularIcon className="pds2-w-16 pds2-h-16 -pds2-rotate-90 pds2-ml-8" />
981
+ )}
982
+ state={!identifierValue || abdmLoginInitApiStatus === LOADING_STATE.LOADING ? 'disabled' : 'enabled'}
983
+ onClick={() => handleNextClick("after_enter_abha_address_on_click_by_user")}
984
+ className={`pds2-w-full ${error ? 'pds2-mt-12' : 'pds2-mt-24'}`}
985
+ isLoading={abdmLoginInitApiStatus === LOADING_STATE.LOADING}
986
+ />
987
+ </div>
988
+ </div>
989
+ </AbhaBottomSheet>
990
+ </>
991
+ );
992
+ };
993
+
994
+ export default LoginorCreateAbhaScreen;
995
+
996
+ interface AbhaBottomSheetProps {
997
+ isOpen: boolean;
998
+ setFlowMethod: (val: ABHA_AUTH_FLOW_METHOD) => void;
999
+ setIsOpen: (isOpen: boolean) => void;
1000
+ children: React.ReactNode;
1001
+ overlayClassName?: string;
1002
+ }
1003
+
1004
+ const AbhaBottomSheet: React.FC<AbhaBottomSheetProps> = ({
1005
+ isOpen,
1006
+ setIsOpen,
1007
+ children,
1008
+ setFlowMethod,
1009
+ overlayClassName = 'pds2-bg-text-black pds2-bg-opacity-50',
1010
+ }) => {
1011
+ const [show, setShow] = useState(isOpen);
1012
+
1013
+ // Sync state with animation
1014
+ useEffect(() => {
1015
+ if (isOpen) setShow(true);
1016
+ else {
1017
+ // Wait for animation to finish before hiding
1018
+ const timeout = setTimeout(() => setShow(false), 300); // match duration
1019
+ return () => clearTimeout(timeout);
1020
+ }
1021
+ }, [isOpen]);
1022
+
1023
+ if (!show) return null; // unmount after closing animation
1024
+
1025
+ return (
1026
+ <div
1027
+ className={`pds2-absolute pds2-inset-0 pds2-z-50 pds2-flex pds2-items-end pds2-transition-all pds2-duration-300 ${
1028
+ isOpen ? 'pds2-opacity-100' : 'pds2-opacity-0 pointer-events-none'
1029
+ }`}
1030
+ >
1031
+ {/* Overlay */}
1032
+ <div
1033
+ className={`pds2-absolute pds2-inset-0 ${overlayClassName} pds2-transition-opacity pds2-duration-300`}
1034
+ style={{ backgroundColor: 'rgba(0, 0, 0, 0.5)' }}
1035
+ onClick={() => {
1036
+ setIsOpen(false);
1037
+ setFlowMethod(ABHA_AUTH_FLOW_METHOD.MOBILE);
1038
+ }}
1039
+ />
1040
+
1041
+ {/* Bottom Sheet */}
1042
+ <div
1043
+ className={`pds2-relative pds2-bg-bg-white pds2-rounded-t-24 pds2-w-full pds2-transition-transform pds2-duration-300 ${
1044
+ isOpen ? 'pds2-translate-y-0' : 'pds2-translate-y-full'
1045
+ }`}
1046
+ style={{
1047
+ height: '75%',
1048
+ maxHeight: '600px',
1049
+ overflowY: 'auto',
1050
+ }}
1051
+ >
1052
+ {children}
1053
+ </div>
1054
+ </div>
1055
+ );
1056
+ };