@eka-care/abha 0.0.6 → 0.0.7

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 (85) hide show
  1. package/{index.html → dist/index.html} +2 -1
  2. package/dist/sdk/abha/css/abha.css +1 -0
  3. package/dist/sdk/abha/js/abha.js +136 -0
  4. package/package.json +1 -1
  5. package/.eslintignore +0 -3
  6. package/.eslintrc +0 -29
  7. package/.prettierrc +0 -7
  8. package/dev-abha-ios-android.zip +0 -0
  9. package/postcss.config.js +0 -6
  10. package/prod-abha-mixpanel.zip +0 -0
  11. package/scripts/build-purged-css.cjs +0 -70
  12. package/src/App.css +0 -0
  13. package/src/App.tsx +0 -32
  14. package/src/api-queries/use-get-profiles-patient.ts +0 -12
  15. package/src/api-queries/use-get-profiles-phr-user.ts +0 -27
  16. package/src/api-queries/use-post-abdm-login-verify-v1.ts +0 -25
  17. package/src/api-queries/use-post-auth-verify-v2.ts +0 -74
  18. package/src/api-queries/use-post-profile-switch.ts +0 -57
  19. package/src/api-queries/use-post-register-mobile-create-phr.ts +0 -39
  20. package/src/api-queries/user-post-abdm-profile-login-phr.ts +0 -25
  21. package/src/assets/react.svg +0 -1
  22. package/src/atoms/button/custom-button.tsx +0 -32
  23. package/src/atoms/button/index.tsx +0 -40
  24. package/src/atoms/button/types.d.ts +0 -31
  25. package/src/atoms/header.tsx +0 -25
  26. package/src/atoms/input-field/index.tsx +0 -62
  27. package/src/atoms/input-field/patient-input-field.tsx +0 -16
  28. package/src/atoms/input-field/types.ts +0 -24
  29. package/src/atoms/pds2-otp-input/index.tsx +0 -35
  30. package/src/atoms/pds2-otp-input/types.d.ts +0 -3
  31. package/src/atoms/single-input-chip/index.tsx +0 -32
  32. package/src/atoms/single-input-chip/types.ts +0 -6
  33. package/src/atoms/spinner.tsx +0 -33
  34. package/src/atoms/text-separator.tsx +0 -11
  35. package/src/index.css +0 -118
  36. package/src/main.tsx +0 -313
  37. package/src/molecules/abha/bottom-sheet/bottom-sheet-wrapper.tsx +0 -40
  38. package/src/molecules/abha/bottom-sheet/index.tsx +0 -66
  39. package/src/molecules/abha/spaced-input-component.tsx +0 -150
  40. package/src/molecules/copyright-year.tsx +0 -16
  41. package/src/molecules/exit-popup/index.tsx +0 -99
  42. package/src/molecules/pds2-otp-component/index.tsx +0 -148
  43. package/src/organisms/abha/abha-header.tsx +0 -25
  44. package/src/organisms/abha/error-bottom-sheet.tsx +0 -27
  45. package/src/organisms/abha/otp-card.tsx +0 -99
  46. package/src/organisms/abha/verification-status.tsx +0 -40
  47. package/src/organisms/choose-language/choose-language.tsx +0 -53
  48. package/src/organisms/choose-language/types.ts +0 -10
  49. package/src/organisms/screen-switcher/screen-switcher.tsx +0 -80
  50. package/src/routes/abha-aadhaar-verification-status-screen.tsx +0 -209
  51. package/src/routes/abha-created-screen.tsx +0 -45
  52. package/src/routes/abha-login-otp-verify-screen.tsx +0 -523
  53. package/src/routes/abha-mobile-linking-status-screen.tsx +0 -267
  54. package/src/routes/abha-otp-and-mobile-screen.tsx +0 -429
  55. package/src/routes/abha-phone-number-verification-screen.tsx +0 -373
  56. package/src/routes/create-abha-address-screen.tsx +0 -928
  57. package/src/routes/create-abha-with-aadhaar-screen.tsx +0 -984
  58. package/src/routes/create-eka-profile-screen.tsx +0 -777
  59. package/src/routes/get-all-profiles-screen.tsx +0 -161
  60. package/src/routes/login-or-create-abha-address-screen.tsx +0 -953
  61. package/src/routes/login-with-abha-screen.tsx +0 -448
  62. package/src/routes/select-abha-from-list-screen.tsx +0 -718
  63. package/src/routes/select-eka-profile-screen.tsx +0 -444
  64. package/src/routes/utils/trackAbhaEvent.ts +0 -41
  65. package/src/stores/auth-abha-store/index.ts +0 -138
  66. package/src/stores/auth-abha-store/types.ts +0 -204
  67. package/src/utils/mock-auth-response.ts +0 -31
  68. package/src/vite-env.d.ts +0 -1
  69. package/tailwind.config.ts +0 -9
  70. package/tsconfig.app.json +0 -26
  71. package/tsconfig.json +0 -25
  72. package/tsconfig.node.json +0 -10
  73. package/tsconfig.node.tsbuildinfo +0 -1
  74. package/tsconfig.tsbuildinfo +0 -1
  75. package/vite.config.d.ts +0 -2
  76. package/vite.config.js +0 -30
  77. package/vite.config.ts +0 -35
  78. /package/{public → dist}/images/adhaar.webp +0 -0
  79. /package/{public → dist}/images/at-the-rate.webp +0 -0
  80. /package/{public → dist}/images/avatar.webp +0 -0
  81. /package/{public → dist}/images/ayushman-bharat.webp +0 -0
  82. /package/{public → dist}/images/circle-checkmark.webp +0 -0
  83. /package/{public → dist}/images/link-abha.webp +0 -0
  84. /package/{public → dist}/images/national-authority.webp +0 -0
  85. /package/{public → dist}/images/three-dots.webp +0 -0
@@ -1,150 +0,0 @@
1
- import { useRef, useState } from 'react';
2
-
3
- type SpacedInputComponentProps = {
4
- numberOfInputs: number;
5
- length?: number;
6
- placeholder?: string;
7
- setIsValid?: (val: boolean) => void;
8
- onSubmit: ({ inputVal }: { inputVal: string }) => void;
9
- error?: string | null;
10
- containerClassName?: string;
11
- setError?: (val: string | null) => void;
12
- };
13
-
14
- const SpacedInputComponent = ({
15
- numberOfInputs,
16
- length = 1,
17
- placeholder = '',
18
- setIsValid,
19
- onSubmit,
20
- error,
21
- containerClassName,
22
- setError,
23
- }: SpacedInputComponentProps) => {
24
- const inputRefs = useRef<HTMLInputElement[]>([]);
25
- const [inputValues, setInputValues] = useState<string[]>(Array(numberOfInputs).fill(''));
26
-
27
- const handleOnChange = (e: React.ChangeEvent<HTMLInputElement>, index: number) => {
28
- if (setError) setError(null);
29
- const value = e.target.value;
30
-
31
- const isValueNan = isNaN(Number(value));
32
- if (isValueNan) return;
33
-
34
- // To autoread OTP from keyboard clipboard
35
- if (value.trim().length === numberOfInputs * length) {
36
- handleClipboardOtp({
37
- otpValue: value,
38
- index: 0,
39
- });
40
- return;
41
- }
42
- const currentValues = [...inputValues];
43
- currentValues[index] = value;
44
- const totalLength = currentValues.join('').length;
45
- if (totalLength > numberOfInputs * length) return;
46
-
47
- // Update current input value
48
- setInputValues(currentValues);
49
-
50
- if (totalLength === numberOfInputs * length) {
51
- setIsValid?.(true);
52
- onSubmit({ inputVal: currentValues.join('') });
53
- } else {
54
- setIsValid?.(false);
55
- }
56
-
57
- // Move to next input if current is full
58
- if (value.length === length && index < numberOfInputs - 1) {
59
- inputRefs.current[index + 1]?.focus();
60
- }
61
- };
62
-
63
- const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>, index: number) => {
64
- if (e.key === 'Backspace' && !inputValues[index] && index > 0) {
65
- inputRefs.current[index - 1]?.focus();
66
- setInputValues((prev) => {
67
- const newValues = [...prev];
68
- newValues[index - 1] = '';
69
- return newValues;
70
- });
71
- }
72
- };
73
-
74
- const handlePaste = (e: React.ClipboardEvent<HTMLInputElement>, index: number) => {
75
- e.preventDefault();
76
- const pastedData = e.clipboardData.getData('text').replace(/\D/g, ''); // Only keep digits
77
-
78
- if (!pastedData) return;
79
-
80
- const maxLength = numberOfInputs * length;
81
- const validPastedData = pastedData.slice(0, maxLength);
82
- handleClipboardOtp({
83
- otpValue: validPastedData,
84
- index,
85
- });
86
- };
87
-
88
- const handleClipboardOtp = ({ otpValue, index }: { otpValue: string; index: number }) => {
89
- const chunks = otpValue.match(new RegExp(`.{1,${length}}`, 'g')) || [];
90
-
91
- const newValues = [...inputValues];
92
-
93
- chunks.forEach((chunk, i) => {
94
- if (index + i < numberOfInputs) {
95
- newValues[index + i] = chunk;
96
- }
97
- });
98
-
99
- setInputValues(newValues);
100
-
101
- // Focus the next empty input or the last input
102
- const nextEmptyIndex = newValues.findIndex((val, i) => i >= index && !val);
103
- if (nextEmptyIndex !== -1) {
104
- inputRefs.current[nextEmptyIndex]?.focus();
105
- } else {
106
- inputRefs.current[numberOfInputs - 1]?.focus();
107
- }
108
-
109
- // Hit endpoint if all inputs are filled
110
- if (newValues.join('').length === numberOfInputs * length) {
111
- setIsValid?.(true);
112
- onSubmit({ inputVal: newValues.join('') });
113
- } else {
114
- setIsValid?.(false);
115
- }
116
- };
117
-
118
- return (
119
- <div
120
- className={`pds2-flex pds2-justify-center pds2-items-center pds2-space-x-8 ${containerClassName}`}
121
- >
122
- {Array.from({ length: numberOfInputs }).map((_, index) => (
123
- <label
124
- key={index}
125
- className={`focus-within:pds2-border-border-brand-01 pds2-border ${error ? 'pds2-border-border-error' : 'pds2-border-border-03'} pds2-rounded-12 pds2-bg-bg-white`}
126
- >
127
- <input
128
- autoFocus={index === 0 ? true : false}
129
- placeholder={placeholder}
130
- value={inputValues[index]}
131
- key={index}
132
- type="text"
133
- inputMode="numeric"
134
- pattern="[0-9]*"
135
- // maxLength={length}
136
- onPaste={(e) => handlePaste(e, index)}
137
- ref={(el) => {
138
- if (el) inputRefs.current[index] = el;
139
- }}
140
- onChange={(e) => handleOnChange(e, index)}
141
- onKeyDown={(e) => handleKeyDown(e, index)}
142
- className={`pds2-w-full pds2-text-center pds2-px-16 pds2-h-48 pds2-rounded-12 pds2-outline-none pds2-bg-transparent`}
143
- />
144
- </label>
145
- ))}
146
- </div>
147
- );
148
- };
149
-
150
- export default SpacedInputComponent;
@@ -1,16 +0,0 @@
1
- import { useEffect, useState } from 'react';
2
-
3
- const CopyrightYearComponent = () => {
4
- const [year, setYear] = useState<number>(new Date().getFullYear());
5
-
6
- useEffect(() => {
7
- setYear(new Date().getFullYear());
8
- }, []);
9
- return (
10
- <div className="pds2-absolute pds2-bottom-5 BodyRegular pds2-text-darwin-neutral-600">
11
- {`Copyright © ${year} eka.care`}
12
- </div>
13
- );
14
- };
15
-
16
- export default CopyrightYearComponent;
@@ -1,99 +0,0 @@
1
- import Pds2CustomButton from '../../atoms/button/custom-button';
2
- import useAuthAbhaStore from '../../stores/auth-abha-store';
3
- import { handleSendEvent } from '@elixir/utils';
4
- import { ABHA_AUTH_FLOW_METHOD } from '@elixir/types';
5
-
6
- const ExitPopup = ({ open, setOpen }: { open: boolean; setOpen: (val: boolean) => void }) => {
7
- // State selectors from ABHA auth store
8
- const goBackLoginScreen = useAuthAbhaStore((state) => state.goBackLoginScreen);
9
- const clientId = useAuthAbhaStore((state) => state.clientId);
10
- const isEkaAppLogin = useAuthAbhaStore((state) => state.isEkaAppLogin);
11
- const isNewLoginOrCreateFlow = useAuthAbhaStore((state) => state.isNewLoginOrCreateFlow);
12
- const setAbhaAuthFlowMethod = useAuthAbhaStore((state) => state.setAbhaAuthFlowMethod);
13
- const txnId = useAuthAbhaStore((state) => state.txnId);
14
-
15
- /**
16
- * Event tracker for ABHA-related events.
17
- * Sends data to internal logger and Mixpanel with base context.
18
- */
19
- const trackAbhaEvent = ({ name, data = {} }: { name: string; data?: Record<string, any> }) => {
20
- const baseProps = {
21
- login_platform: clientId,
22
- is_eka_app_login: isEkaAppLogin ? 'true' : 'false',
23
- is_new_login_or_create_flow: isNewLoginOrCreateFlow ? 'true' : 'false',
24
- txn_id : txnId || 'missing txnId',
25
- };
26
-
27
- const eventData = {
28
- ...baseProps,
29
- ...data,
30
- };
31
-
32
- // Mixpanel tracking
33
- handleSendEvent({
34
- eventName: name,
35
- eventData,
36
- });
37
-
38
- window.curio?.pushToMixpanel?.(name, eventData);
39
- };
40
-
41
- /**
42
- * Handles the user's confirmation to exit the ABHA flow.
43
- * Resets flow to mobile method and navigates back to login.
44
- */
45
- const handleExitConfirmed = () => {
46
- trackAbhaEvent({
47
- name: 'abha_exit_popup_confirmed',
48
- data: {
49
- action: 'go_back_to_login_screen',
50
- },
51
- });
52
-
53
- // Reset flow method to mobile as default
54
- setAbhaAuthFlowMethod(ABHA_AUTH_FLOW_METHOD.MOBILE);
55
- // Navigate back to login screen
56
- goBackLoginScreen();
57
- };
58
-
59
- return (
60
- <>
61
- {open ? (
62
- <div className="pds2-z-[60]">
63
- <div
64
- className="pds2-flex pds2-items-center pds2-justify-center pds2-fixed pds2-top-0 pds2-inset-0 pds2-bg-text-black pds2-bg-opacity-60 pds2-transition-opacity pds2-duration-300"
65
- onClick={() => setOpen(false)}
66
- />
67
- <div className="pds2-fixed pds2-top-1/2 pds2-transform pds2--translate-y-1/2 pds2-px-24">
68
- <div className="pds2-flex pds2-flex-col pds2-space-y-16 pds2-bg-bg-white pds2-rounded-16 pds2-w-full pds2-p-24">
69
- <h2 className="pds2-text-text-black pds2-font-500 pds2-text-18">
70
- Are you sure you want to exit?
71
- </h2>
72
- <p className="pds2-text-text-03 pds2-text-14 pds2-font-400">
73
- Confirm if you'd like to exit. Any unsaved changes may be lost.
74
- </p>
75
- <div className="pds2-flex pds2-justify-end pds2-gap-x-8">
76
- <Pds2CustomButton
77
- title="Not yet"
78
- padding="pds2-px-12 pds2-py-8"
79
- className="pds2-text-text-error pds2-font-600 pds2-text-16 pds2-border-none"
80
- width="pds2-w-fit"
81
- onClick={() => setOpen(false)}
82
- />
83
- <Pds2CustomButton
84
- title="Yes, I'm done"
85
- padding="pds2-px-12 pds2-py-8"
86
- className="pds2-text-text-brand pds2-font-600 pds2-text-16 pds2-border-none"
87
- width="pds2-w-fit"
88
- onClick={handleExitConfirmed}
89
- />
90
- </div>
91
- </div>
92
- </div>
93
- </div>
94
- ) : null}
95
- </>
96
- );
97
- };
98
-
99
- export default ExitPopup;
@@ -1,148 +0,0 @@
1
- import { CircleExclamationRegularIcon } from '@elixir/icons';
2
- import React, { useState } from 'react';
3
- import ReactOTPInput, { AllowedInputTypes } from 'react-otp-input';
4
- import { LinkButton, SecondaryButton } from 'ui';
5
- import Pds2OtpInput from '../../atoms/pds2-otp-input';
6
-
7
- const OtpErrorComponent = ({ errorMessage }: { errorMessage: string }) => {
8
- return (
9
- <div className="pds2-flex pds2-space-x-4 pds2-items-center pds2-text-text-error">
10
- <div className="pds2-p-8">
11
- <CircleExclamationRegularIcon className="pds2-w-12 pds2-h-12" />
12
- </div>
13
- <div className="Body2Regular">{errorMessage}</div>
14
- </div>
15
- );
16
- };
17
-
18
- const ResendCodeComponent = ({ handleResendCode }: { handleResendCode: () => void }) => {
19
- return (
20
- <div className="pds2-flex pds2-justify-center pds2-py-16 pds2-text-text-doc">
21
- <div onClick={handleResendCode} role="button">
22
- Resend code
23
- </div>
24
- </div>
25
- );
26
- };
27
-
28
- const ResendTimerComponent = ({ secondsRemaining }: { secondsRemaining: string }) => {
29
- return (
30
- <div className="BodyRegular pds2-text-text-03 pds2-text-center pds2-py-16">{`Resend in 00:${secondsRemaining}`}</div>
31
- );
32
- };
33
-
34
- type TOtpComponentProps = {
35
- /**
36
- * Number of fields in the OTP input
37
- */
38
- numberOfFields: number;
39
- inputType?: AllowedInputTypes;
40
- /**
41
- * Error message to be displayed
42
- */
43
- errorMessage?: string | null;
44
- /**
45
- * Function to set error message
46
- */
47
- setErrorMessage: (message: string) => void;
48
- /**
49
- * Function to handle OTP submission
50
- */
51
- onSubmit: ({ otp }: { otp: string }) => void;
52
- /**
53
- * Function to handle resend code
54
- */
55
- onResendCode: () => void;
56
- /**
57
- * Function to reset identifier entered by the user
58
- */
59
- onResetIdentifier: () => void;
60
- /**
61
- * Function to set the enable/disable state of button
62
- */
63
- setIsValid?: (val: boolean) => void;
64
- };
65
-
66
- const Pds2OtpComponent = ({
67
- numberOfFields,
68
- inputType = 'tel',
69
- errorMessage,
70
- setErrorMessage,
71
- onSubmit,
72
- onResendCode,
73
- onResetIdentifier,
74
- setIsValid,
75
- }: TOtpComponentProps) => {
76
- const [otp, setOtp] = useState('');
77
- const [timerSeconds, setTimerSeconds] = useState<number>(30);
78
- const resendTimerIntervalId = React.useRef<NodeJS.Timeout>();
79
- const [activeInput, setActiveInput] = useState<number>(-1);
80
-
81
- const handleOtpChange = (newOtp: string) => {
82
- setOtp(newOtp);
83
- setErrorMessage('');
84
-
85
- if (newOtp.length === numberOfFields) {
86
- setIsValid?.(true);
87
- onSubmit({ otp: newOtp });
88
- // setTimerSeconds(30);
89
- } else {
90
- setIsValid?.(false);
91
- }
92
- };
93
-
94
- React.useEffect(() => {
95
- resendTimerIntervalId.current = setInterval(() => {
96
- setTimerSeconds((timer) => timer - 1);
97
- }, 1000);
98
-
99
- return () => {
100
- clearInterval(resendTimerIntervalId.current);
101
- };
102
- }, []);
103
-
104
- React.useEffect(() => {
105
- if (timerSeconds < 1) {
106
- clearInterval(resendTimerIntervalId.current);
107
- setTimerSeconds(-1);
108
- }
109
- }, [timerSeconds]);
110
-
111
- const handleResendCodeClick = () => {
112
- setOtp('');
113
- setTimerSeconds(30);
114
- resendTimerIntervalId.current = setInterval(() => {
115
- setTimerSeconds((timer) => timer - 1);
116
- }, 1000);
117
- onResendCode();
118
- };
119
-
120
- return (
121
- <div className="pds2-space-y-8">
122
- <ReactOTPInput
123
- inputStyle="pds2-rounded-8 pds2-border-1 pds2-p-10 pds2-border-border-03 BodyRegular pds2-w-36 pds2-bg-bg-white pds2-text-text-04 placeholder:pds2-text-text-03 pds2-outline-none pds2-text-center"
124
- inputType={inputType}
125
- value={otp}
126
- onChange={handleOtpChange}
127
- numInputs={numberOfFields}
128
- renderInput={(props) => Pds2OtpInput({ ...props, isError: errorMessage ? true : false })}
129
- skipDefaultStyles={true}
130
- renderSeparator={() => <div className="pds2-p-4" />}
131
- shouldAutoFocus={true}
132
- />
133
- {errorMessage || timerSeconds === -1 ? (
134
- <div className="pds2-flex pds2-flex-col pds2-items-center pds2-space-x-8">
135
- {errorMessage ? <OtpErrorComponent errorMessage={errorMessage} /> : null}
136
- {timerSeconds === -1 ? (
137
- <ResendCodeComponent handleResendCode={handleResendCodeClick} />
138
- ) : null}
139
- </div>
140
- ) : null}
141
- {timerSeconds > -1 ? (
142
- <ResendTimerComponent secondsRemaining={timerSeconds.toString().padStart(2, '0')} />
143
- ) : null}
144
- </div>
145
- );
146
- };
147
-
148
- export default Pds2OtpComponent;
@@ -1,25 +0,0 @@
1
- const AbhaHeader = ({
2
- prefixIcon = <div className="pds2-w-24 pds2-h-24" />,
3
- title,
4
- suffixIcon = <div className="pds2-w-24 pds2-h-24" />,
5
- className = '',
6
- }: {
7
- prefixIcon?: React.ReactNode;
8
- title: string;
9
- suffixIcon?: React.ReactNode;
10
- className?: string;
11
- }) => {
12
- return (
13
- <div
14
- className={`pds2-flex pds2-items-center pds2-justify-between pds2-w-full pds2-p-16 pds2-sticky pds2-top-0 pds2-z-50 pds2-bg-bg-white ${className}`}
15
- >
16
- {prefixIcon}
17
- <div className="pds2-flex-1 Heading4Semibold pds2-text-center pds2-text-text-black">
18
- {title}
19
- </div>
20
- {suffixIcon}
21
- </div>
22
- );
23
- };
24
-
25
- export default AbhaHeader;
@@ -1,27 +0,0 @@
1
- import AbhaBottomSheet from '../../molecules/abha/bottom-sheet';
2
- import useAuthAbhaStore from '../../stores/auth-abha-store';
3
- type TAbhaErrorBottomSheetProps = {
4
- onSubmitClick: () => void;
5
- };
6
- const AbhaErrorBottomSheet = ({ onSubmitClick }: TAbhaErrorBottomSheetProps) => {
7
- const bottomsheetErrorInfo = useAuthAbhaStore((state) => state.bottomsheetErrorInfo);
8
- const setBottomsheetErrorInfo = useAuthAbhaStore((state) => state.setBottomsheetErrorInfo);
9
- const handleCloseBottomsheet = () => {
10
- setBottomsheetErrorInfo(null);
11
- };
12
-
13
- return (
14
- <AbhaBottomSheet
15
- description={bottomsheetErrorInfo?.title || 'Something went wrong'}
16
- subText={bottomsheetErrorInfo?.description || 'Something went wrong'}
17
- submitText={bottomsheetErrorInfo?.cta.title || 'Retry'}
18
- onSubmitClick={onSubmitClick}
19
- iconUrl={bottomsheetErrorInfo?.img}
20
- isBottomSheetOpen={bottomsheetErrorInfo ? true : false}
21
- onBottomSheetClose={handleCloseBottomsheet}
22
- shouldCloseOnClickOutside={false}
23
- />
24
- );
25
- };
26
-
27
- export default AbhaErrorBottomSheet;
@@ -1,99 +0,0 @@
1
- import { useEffect, useState } from 'react';
2
- import SpacedInputComponent from '../../molecules/abha/spaced-input-component';
3
-
4
- function formatTime(timeLeft: number): React.ReactNode {
5
- const minutes = Math.floor(timeLeft / 60);
6
- const seconds = timeLeft % 60;
7
- return `${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
8
- }
9
-
10
- type TResendTimerProps = {
11
- time: number;
12
- onResendOtpClick: () => void;
13
- error?: string | null;
14
- };
15
-
16
- const ResendTimer = ({ time, onResendOtpClick, error }: TResendTimerProps) => {
17
- const [timeLeft, setTimeLeft] = useState(time);
18
-
19
- useEffect(() => {
20
- const interval = setInterval(() => {
21
- setTimeLeft(timeLeft - 1);
22
- }, 1000);
23
- return () => clearInterval(interval);
24
- }, [timeLeft]);
25
-
26
- if (timeLeft > 0) {
27
- return (
28
- <div className="pds2-flex pds2-justify-between pds2-items-center pds2-w-full">
29
- <div className="pds2-text-text-04">
30
- <span className="Body3CapsSemibold">Resend OTP in</span>{' '}
31
- <span className="Body3CapsSemibold">{formatTime(timeLeft)}</span>
32
- </div>
33
- {/* {error && <div className="Body3Semibold pds2-text-text-error">Invalid OTP</div>} */}
34
- </div>
35
- );
36
- }
37
-
38
- return (
39
- <div className="pds2-flex pds2-justify-between pds2-items-center pds2-w-full">
40
- <button
41
- className="Body3CapsSemibold pds2-text-text-brand cursor-pointer"
42
- onClick={() => {
43
- setTimeLeft(time);
44
- onResendOtpClick();
45
- }}
46
- >
47
- Resend OTP
48
- </button>
49
- {/* {error && <div className="Body3Semibold pds2-text-text-error">Invalid OTP</div>} */}
50
- </div>
51
- );
52
- };
53
-
54
- type TAbhaOtpCardProps = {
55
- otpSentToText: string;
56
- onOtpCompletion: ({ otp }: { otp: string }) => void;
57
- onResendOtpClick: () => void;
58
- setIsValid: (isValid: boolean) => void;
59
- error?: string | null;
60
- prefixIcon?: React.ReactNode;
61
- };
62
-
63
- const AbhaOtpCard = ({
64
- otpSentToText,
65
- onOtpCompletion,
66
- onResendOtpClick,
67
- setIsValid,
68
- error,
69
- prefixIcon = (
70
- <img
71
- src="https://cdn.eka.care/vagus/cm5mcdm3h00070tfs9fjkepff.webp"
72
- alt="adhaar"
73
- className="pds2-w-48"
74
- />
75
- ),
76
- }: TAbhaOtpCardProps) => {
77
- return (
78
- <div className="pds2-flex pds2-flex-col pds2-w-full pds2-p-16 pds2-rounded-16 pds2-bg-bg-01 pds2-space-y-8">
79
- <div className="pds2-flex pds2-items-center pds2-space-x-16">
80
- <div className="Body1Regular pds2-text-text-01 pds2-flex-1">
81
- {otpSentToText}
82
- <sup className="pds2-text-text-error Body3Semibold"> *</sup>
83
- </div>
84
- {prefixIcon}
85
- </div>
86
- <SpacedInputComponent
87
- numberOfInputs={6}
88
- length={1}
89
- onSubmit={({ inputVal }) => onOtpCompletion({ otp: inputVal })}
90
- setIsValid={setIsValid}
91
- error={error}
92
- />
93
- <ResendTimer time={60} onResendOtpClick={onResendOtpClick} error={error} />
94
- {error && <div className="Body3Semibold pds2-text-text-error">{error}</div>}
95
- </div>
96
- );
97
- };
98
-
99
- export default AbhaOtpCard;
@@ -1,40 +0,0 @@
1
- type TAbhaVerificationStatus = {
2
- loading: boolean;
3
- loadingText: string;
4
- successText: string;
5
- };
6
-
7
- const AbhaVerificationStatus = ({
8
- loading = false,
9
- loadingText,
10
- successText,
11
- }: TAbhaVerificationStatus) => {
12
- return (
13
- <div
14
- className="pds2-px-16 pds2-w-full pds2-min-h-screen pds2-flex pds2-flex-col pds2-items-center pds2-justify-center pds2-text-center"
15
- style={{ backgroundColor: '#F2F2F2' }}
16
- >
17
- {loading ? (
18
- <>
19
- <img
20
- src="https://cdn.eka.care/vagus/cm5m96sno000d0tg92v2g42tx.webp"
21
- alt="loading"
22
- className="pds2-w-60"
23
- />
24
- <div className="pds2-text-text-01 Heading4Semibold pds2-mt-48">{loadingText}</div>
25
- </>
26
- ) : (
27
- <>
28
- <img
29
- src="https://cdn.eka.care/vagus/cm5m97vt600060tfs273o59zn.webp"
30
- alt="success"
31
- className="pds2-w-142"
32
- />
33
- <div className="pds2-text-text-01 Heading4Semibold pds2-mt-23">{successText}</div>
34
- </>
35
- )}
36
- </div>
37
- );
38
- };
39
-
40
- export default AbhaVerificationStatus;
@@ -1,53 +0,0 @@
1
- import { CircleCheckSolidIcon } from '@elixir/icons';
2
- import { Language, LanguageKey } from './types';
3
-
4
- const ChooseLanguage = ({
5
- selectedLanguage,
6
- languages,
7
- onChangeLanguage,
8
- }: {
9
- selectedLanguage: LanguageKey;
10
- languages: Language[];
11
- onChangeLanguage: (language: LanguageKey) => void;
12
- }) => {
13
- return (
14
- <div className="pds2-flex pds2-px-16 pds2-py-8 pds2-items-center pds2-justify-between">
15
- <div className="Body3Regular pds2-text-text-04">Choose language:</div>
16
- <div className="pds2-flex pds2-flex-row pds2-gap-8">
17
- {languages.map((language) => {
18
- const isSelected = language.key === selectedLanguage;
19
- return (
20
- <label
21
- key={language.key}
22
- className={`pds2-flex pds2-items-center pds2-cursor-pointer pds2-py-8 pds2-px-12 pds2-border pds2-rounded-8
23
- ${
24
- isSelected
25
- ? 'pds2-border-border-brand-01 pds2-gap-6 pds2-text-text-brand Body3Semibold'
26
- : 'pds2-border-border-03 pds2-text-text-secondary Body3Regular'
27
- }
28
- focus-within:pds2-ring-2 focus-within:pds2-ring-border-brand-01 focus-within:pds2-ring-offset-2
29
- active:pds2-bg-bg-brand-02 hover:pds2-bg-bg-hover-01
30
- pds2-transition-colors pds2-duration-200
31
- `}
32
- >
33
- <input
34
- type="radio"
35
- name="language"
36
- value={language.key}
37
- checked={isSelected}
38
- onChange={() => onChangeLanguage(language.key)}
39
- className="focus:pds2-outline-none pds2-appearance-none"
40
- />
41
- {isSelected && (
42
- <CircleCheckSolidIcon className="pds2-w-12 pds2-h-12 pds2-text-icon-success-02" />
43
- )}
44
- <span>{language.title}</span>
45
- </label>
46
- );
47
- })}
48
- </div>
49
- </div>
50
- );
51
- };
52
-
53
- export default ChooseLanguage;
@@ -1,10 +0,0 @@
1
- export enum LanguageKey {
2
- ENGLISH = 'en',
3
- HINDI = 'hi',
4
- TAMIL = 'ta',
5
- }
6
-
7
- export type Language = {
8
- title: string;
9
- key: LanguageKey;
10
- };