@truworth/twc-auth 1.2.6 → 1.2.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/src/components/VerifyMobileOTP/index.native.js +6 -1
- package/build/src/contexts/AuthContext.js +0 -1
- package/build/src/helpers/network.js +1 -1
- package/build/src/screens/EnterPassword/hooks/internal/useEnterPassword.js +24 -5
- package/build/src/screens/EnterPassword/index.js +27 -8
- package/build/src/screens/EnterPassword/index.native.js +15 -4
- package/build/src/screens/LoginWithEmailOTP/hooks/internal/useLoginWithEmailOTP.js +22 -10
- package/build/src/screens/LoginWithEmailOTP/index.js +2 -2
- package/build/src/screens/LoginWithEmailOTP/index.native.js +2 -2
- package/build/src/screens/SSOLogin/SSOCallback/components/SSOCallbackComponent/index.js +1 -1
- package/build/src/screens/VerifyEmail/hooks/internal/useVerifyEmail.js +2 -2
- package/build/src/screens/VerifyResetPasswordOTP/hooks/internal/useVerifyResetPasswordOTP.js +1 -1
- package/build/src/screens/Welcome/SocialAuth/hooks/useSocialAuth.native.js +10 -11
- package/build/src/screens/Welcome/SocialAuth/hooks/web/useFacebookAuth.web.js +1 -1
- package/build/src/screens/Welcome/components/SocialLoginModal/index.native.js +2 -2
- package/build/types/navigator/index.native.d.ts +3 -0
- package/build/types/screens/EnterPassword/hooks/internal/useEnterPassword.d.ts +6 -1
- package/build/types/screens/EnterPassword/types.d.ts +3 -0
- package/build/types/screens/LoginWithEmailOTP/hooks/internal/useLoginWithEmailOTP.d.ts +4 -1
- package/build/types/screens/LoginWithEmailOTP/index.d.ts +4 -1
- package/package.json +17 -17
|
@@ -10,6 +10,11 @@ const { gray } = Colors;
|
|
|
10
10
|
const VerifyMobileOTP = ({ validateOTP, timer, status, resendOTP, phone }) => {
|
|
11
11
|
const [otp, setOtp] = useState('');
|
|
12
12
|
const { otpValue } = useAuthPackageContext();
|
|
13
|
+
useEffect(() => {
|
|
14
|
+
if (otp && otp.length == 6) {
|
|
15
|
+
return validateOTP(otp);
|
|
16
|
+
}
|
|
17
|
+
}, [otp]);
|
|
13
18
|
useEffect(() => {
|
|
14
19
|
if (otpValue && otpValue.length == 6) {
|
|
15
20
|
setOtp(otpValue);
|
|
@@ -24,7 +29,7 @@ const VerifyMobileOTP = ({ validateOTP, timer, status, resendOTP, phone }) => {
|
|
|
24
29
|
}, codeInputHighlightStyle: { borderColor: '#03DAC6' }, style: {
|
|
25
30
|
height: 50,
|
|
26
31
|
width: Dimensions.get('window').width - 100,
|
|
27
|
-
}, code: otp ?? '', onCodeFilled: code =>
|
|
32
|
+
}, code: otp ?? '', onCodeFilled: code => setOtp(code) }) }), timer <= 0 &&
|
|
28
33
|
_jsxs(View, { style: { flexDirection: 'row', alignItems: 'center' }, children: [_jsx(Text, { style: { fontSize: 12, color: '#000', fontWeight: '400', opacity: 0.5 }, children: "Did not receive OTP?" }), _jsx(TouchableOpacity, { disabled: timer > 0, onPress: () => {
|
|
29
34
|
setOtp('');
|
|
30
35
|
resendOTP();
|
|
@@ -80,7 +80,7 @@ export const createHttpClient = ({ token, onRefreshSession, onLogout }) => {
|
|
|
80
80
|
showMessage({ message: 'Your session has expired. Please login again.' });
|
|
81
81
|
}
|
|
82
82
|
catch (err) {
|
|
83
|
-
console.
|
|
83
|
+
console.log('Error logging out:', err);
|
|
84
84
|
}
|
|
85
85
|
};
|
|
86
86
|
return { request };
|
|
@@ -9,28 +9,46 @@ import { showMessage } from "../../../../helpers/show-message";
|
|
|
9
9
|
const useEnterPassword = () => {
|
|
10
10
|
const [password, setPassword] = useState("");
|
|
11
11
|
const [isPasswordVisible, setIsPasswordVisible] = useState(false);
|
|
12
|
+
const [invalidPassword, setInvalidPassword] = useState(false);
|
|
12
13
|
const [loading, setLoading] = useState(false);
|
|
13
14
|
const { onTokenChange, onLogin, appConfig } = useAuthPackageContext();
|
|
14
15
|
const togglePasswordVisibility = useCallback(() => {
|
|
15
16
|
setIsPasswordVisible((prev) => !prev);
|
|
16
17
|
}, []);
|
|
17
18
|
const handlePasswordChange = useCallback((value) => {
|
|
19
|
+
setInvalidPassword(false);
|
|
18
20
|
setPassword(value);
|
|
19
21
|
}, []);
|
|
20
|
-
const handleSubmit = useCallback(async ({ email, source }) => {
|
|
22
|
+
const handleSubmit = useCallback(async ({ email, source, verifyEmailOTP }) => {
|
|
21
23
|
setLoading(true);
|
|
22
24
|
try {
|
|
23
|
-
const response = await axiosClient.post("/auth/login", {
|
|
25
|
+
const response = await axiosClient.post("/auth/login/v2", {
|
|
24
26
|
email,
|
|
25
27
|
password,
|
|
26
28
|
source,
|
|
27
29
|
});
|
|
28
|
-
|
|
29
|
-
|
|
30
|
+
// Check if MFA is enabled
|
|
31
|
+
if (response.data.mfaEnabled && response.data.sessionToken) {
|
|
32
|
+
// Navigate to LoginWithEmailOTP screen with sessionToken
|
|
33
|
+
if (verifyEmailOTP) {
|
|
34
|
+
verifyEmailOTP({
|
|
35
|
+
mfaEnabled: response.data.mfaEnabled,
|
|
36
|
+
sessionToken: response.data.sessionToken
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
setLoading(false);
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
// Normal login flow (no MFA)
|
|
43
|
+
if (response.data.token) {
|
|
44
|
+
onTokenChange(response.data.token);
|
|
45
|
+
onLogin(response.data);
|
|
46
|
+
}
|
|
30
47
|
}
|
|
31
48
|
catch (error) {
|
|
32
49
|
const errorMessage = error?.response?.data?.errors?.[0]?.message;
|
|
33
50
|
if (error?.response?.status === 400) {
|
|
51
|
+
setInvalidPassword(true);
|
|
34
52
|
showMessage({ message: errorMessage ?? 'Email and password do not match!' });
|
|
35
53
|
return;
|
|
36
54
|
}
|
|
@@ -52,7 +70,8 @@ const useEnterPassword = () => {
|
|
|
52
70
|
handleSubmit,
|
|
53
71
|
isDisabled,
|
|
54
72
|
handlePasswordChange,
|
|
55
|
-
appName: appConfig.appName
|
|
73
|
+
appName: appConfig.appName,
|
|
74
|
+
invalidPassword
|
|
56
75
|
};
|
|
57
76
|
};
|
|
58
77
|
export { useEnterPassword };
|
|
@@ -9,28 +9,47 @@ import VerifyResetPasswordOTP from '../VerifyResetPasswordOTP';
|
|
|
9
9
|
const EnterPassword = ({ email, onPressBack, onVerifiedResetPasswordOTP }) => {
|
|
10
10
|
const [showResetPasswordOTPModal, setShowResetPasswordOTPModal] = useState(false);
|
|
11
11
|
const [showLoginWithEmailOTPModal, setShowLoginWithEmailOTPModal] = useState(false);
|
|
12
|
+
const [mfaSessionToken, setMfaSessionToken] = useState(undefined);
|
|
13
|
+
const [mfaEnabled, setMfaEnabled] = useState(false);
|
|
12
14
|
const { loading, password, handlePasswordChange, handleSubmit, appName } = useEnterPassword();
|
|
13
15
|
const form = useForm({ defaultValues: { password } });
|
|
14
16
|
return (_jsxs(_Fragment, { children: [_jsxs(ScreenLayout, { title: `Hi, Welcome To ${appName}!`, subTitle: email, buttonProps: {
|
|
15
17
|
loading,
|
|
16
18
|
label: 'Continue',
|
|
17
|
-
onClick: () => {
|
|
18
|
-
|
|
19
|
+
onClick: () => {
|
|
20
|
+
if (email)
|
|
21
|
+
handleSubmit({
|
|
22
|
+
email,
|
|
23
|
+
source: 'web',
|
|
24
|
+
verifyEmailOTP: ({ mfaEnabled, sessionToken }) => {
|
|
25
|
+
setMfaSessionToken(sessionToken);
|
|
26
|
+
setMfaEnabled(mfaEnabled);
|
|
27
|
+
setShowLoginWithEmailOTPModal(true);
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
},
|
|
19
31
|
disabled: !password || !email || loading,
|
|
20
|
-
}, onPressBack: onPressBack, children: [_jsx(Form, { className: "w-full", form: form,
|
|
21
|
-
handleSubmit({ email, source: 'web' }); }, children: _jsx(Form.Item, { name: "password", label: "Password", children: _jsx(PasswordInput, { placeholder: "Enter your password", value: password, showStrengthIndicator: false, className: `border rounded-md px-3 py-2 border-gray-300`, ...form.register('password', {
|
|
32
|
+
}, onPressBack: onPressBack, children: [_jsx(Form, { className: "w-full", form: form, children: _jsx(Form.Item, { name: "password", label: "Password", children: _jsx(PasswordInput, { placeholder: "Enter your password", value: password, showStrengthIndicator: false, className: `border rounded-md px-3 py-2 border-gray-300`, ...form.register('password', {
|
|
22
33
|
onChange: (e) => {
|
|
23
34
|
handlePasswordChange(e.target.value);
|
|
24
35
|
}
|
|
25
|
-
}) }) }) }), _jsx(Button, { type: "button", size: 'small', variant: 'link', label: "Forgot Password?", className: "px-0 h-auto ml-auto block mt-4", onClick: () => setShowResetPasswordOTPModal(true) })] }), _jsxs(Flex, { align: "center", className: "mt-6 mb-6", children: [_jsx(Flex, { className: "flex-1 border-t border-gray-300" }), _jsx(Typography, { type: 'body', size: 'small', className: "text-gray-500 px-4", children: "OR" }), _jsx(Flex, { className: "flex-1 border-t border-gray-300" })] }), _jsx(Button, { label: 'Sign In with Email OTP', variant: 'secondary', className: 'flex-none', isFullWidth: true, type: "button", onClick: () =>
|
|
36
|
+
}) }) }) }), _jsx(Button, { type: "button", size: 'small', variant: 'link', label: "Forgot Password?", className: "px-0 h-auto ml-auto block mt-4", onClick: () => setShowResetPasswordOTPModal(true) })] }), _jsxs(Flex, { align: "center", className: "mt-6 mb-6", children: [_jsx(Flex, { className: "flex-1 border-t border-gray-300" }), _jsx(Typography, { type: 'body', size: 'small', className: "text-gray-500 px-4", children: "OR" }), _jsx(Flex, { className: "flex-1 border-t border-gray-300" })] }), _jsx(Button, { label: 'Sign In with Email OTP', variant: 'secondary', className: 'flex-none', isFullWidth: true, type: "button", onClick: () => {
|
|
37
|
+
setMfaSessionToken(undefined);
|
|
38
|
+
setMfaEnabled(false);
|
|
39
|
+
setShowLoginWithEmailOTPModal(true);
|
|
40
|
+
} }), _jsx(SupportDetails, {}), showResetPasswordOTPModal &&
|
|
26
41
|
_jsx(VerifyResetPasswordOTPModal, { email: email, show: showResetPasswordOTPModal, hide: () => setShowResetPasswordOTPModal(false), onVerifiedOTP: (sessionToken) => {
|
|
27
42
|
setShowResetPasswordOTPModal(false);
|
|
28
43
|
onVerifiedResetPasswordOTP(sessionToken);
|
|
29
44
|
} }), showLoginWithEmailOTPModal &&
|
|
30
|
-
_jsx(LoginWithEmailOTPModal, { email: email, show: showLoginWithEmailOTPModal, hide: () =>
|
|
45
|
+
_jsx(LoginWithEmailOTPModal, { email: email, password: password, sessionToken: mfaSessionToken, mfaEnabled: mfaEnabled, show: showLoginWithEmailOTPModal, hide: () => {
|
|
46
|
+
setShowLoginWithEmailOTPModal(false);
|
|
47
|
+
setMfaSessionToken(undefined);
|
|
48
|
+
setMfaEnabled(false);
|
|
49
|
+
} })] }));
|
|
31
50
|
};
|
|
32
|
-
const LoginWithEmailOTPModal = ({ show, hide, email }) => {
|
|
33
|
-
return (_jsx(ResponsiveModal, { open: show, onClose: hide, title: _jsx(Typography, { type: "heading", size: "h6", className: "text-center mb-0", children: "Verify Your Email" }), showCloseButton: false, maskClosable: false, size: 'sm', children: _jsx(LoginWithEmailOTP, { email: email }) }));
|
|
51
|
+
const LoginWithEmailOTPModal = ({ show, hide, email, password, sessionToken, mfaEnabled }) => {
|
|
52
|
+
return (_jsx(ResponsiveModal, { open: show, onClose: hide, title: _jsx(Typography, { type: "heading", size: "h6", className: "text-center mb-0", children: "Verify Your Email" }), showCloseButton: false, maskClosable: false, size: 'sm', children: _jsx(LoginWithEmailOTP, { email: email, password: password, sessionToken: sessionToken, mfaEnabled: mfaEnabled }) }));
|
|
34
53
|
};
|
|
35
54
|
const VerifyResetPasswordOTPModal = ({ show, hide, email, onVerifiedOTP }) => {
|
|
36
55
|
return (_jsx(ResponsiveModal, { title: "Reset Your Password", open: show, onClose: hide, maskClosable: false, showCloseButton: false, size: 'sm', children: _jsx(VerifyResetPasswordOTP, { email: email, onVerifiedOTP: onVerifiedOTP }) }));
|
|
@@ -7,14 +7,25 @@ import { useEnterPassword } from './hooks/internal/useEnterPassword';
|
|
|
7
7
|
const { primary } = Colors;
|
|
8
8
|
const EnterPassword = ({ navigation, route }) => {
|
|
9
9
|
const { email } = route.params;
|
|
10
|
-
const { loading, password, isPasswordVisible, togglePasswordVisibility, handlePasswordChange, isDisabled, handleSubmit } = useEnterPassword();
|
|
10
|
+
const { loading, password, isPasswordVisible, togglePasswordVisibility, handlePasswordChange, isDisabled, handleSubmit, invalidPassword } = useEnterPassword();
|
|
11
11
|
return (_jsxs(Layout, { style: { flex: 1, backgroundColor: primary.white }, children: [_jsxs(ScreenLayout, { title: "Enter Your Password", buttonProps: {
|
|
12
12
|
loading,
|
|
13
13
|
label: 'Continue',
|
|
14
|
-
onPress: () => {
|
|
15
|
-
|
|
14
|
+
onPress: () => {
|
|
15
|
+
if (email)
|
|
16
|
+
handleSubmit({
|
|
17
|
+
email,
|
|
18
|
+
source: Platform.OS,
|
|
19
|
+
verifyEmailOTP: ({ mfaEnabled, sessionToken }) => {
|
|
20
|
+
navigation.navigate('LoginWithEmailOTP', { email, password, mfaEnabled, sessionToken });
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
},
|
|
16
24
|
disabled: isDisabled,
|
|
17
|
-
}, children: [_jsx(View, { style: { position: 'relative' }, children: _jsx(TextInputField, { placeholder: 'Enter password...', onChangeValue: handlePasswordChange, secureTextEntry: !isPasswordVisible, value: password, rightIcon2: isPasswordVisible ? 'eye-outline' : 'eye-off-outline', onPressRightIcon2: () => togglePasswordVisibility(),
|
|
25
|
+
}, children: [_jsx(View, { style: { position: 'relative' }, children: _jsx(TextInputField, { placeholder: 'Enter password...', onChangeValue: handlePasswordChange, secureTextEntry: !isPasswordVisible, value: password, rightIcon2: isPasswordVisible ? 'eye-outline' : 'eye-off-outline', onPressRightIcon2: () => togglePasswordVisibility(), error: {
|
|
26
|
+
show: invalidPassword,
|
|
27
|
+
message: 'Email and password do not match!'
|
|
28
|
+
}, autoFocus: true }) }), _jsx(TouchableOpacity, { activeOpacity: 0.8, style: { marginTop: 10, alignSelf: 'flex-end' }, onPress: () => navigation.navigate('VerifyResetPasswordOTP', { email }), children: _jsx(Text, { style: {
|
|
18
29
|
fontSize: 12, fontWeight: '600',
|
|
19
30
|
color: primary.primary_main, lineHeight: 20,
|
|
20
31
|
}, children: "Forgot Password?" }) })] }), _jsxs(View, { style: { paddingHorizontal: 16 }, children: [_jsxs(View, { style: {
|
|
@@ -6,29 +6,33 @@ import { axiosClient } from "../../../../api/axiosClient";
|
|
|
6
6
|
* @internal
|
|
7
7
|
* Hook for handling Email OTP Login flow.
|
|
8
8
|
*/
|
|
9
|
-
const useLoginWithEmailOTP = ({ email, source }) => {
|
|
9
|
+
const useLoginWithEmailOTP = ({ email, password, source, sessionToken, mfaEnabled }) => {
|
|
10
10
|
const [resendOTPCounter, setResendOTPCounter] = useState(0);
|
|
11
11
|
const [status, setStatus] = useState("idle");
|
|
12
|
-
const sessionTokenRef = useRef("");
|
|
13
|
-
const { onLogin } = useAuthPackageContext();
|
|
12
|
+
const sessionTokenRef = useRef(sessionToken || "");
|
|
13
|
+
const { onLogin, onTokenChange } = useAuthPackageContext();
|
|
14
14
|
/**
|
|
15
15
|
* Sends an OTP to the provided email.
|
|
16
16
|
*/
|
|
17
17
|
const sendOtp = useCallback(() => {
|
|
18
18
|
setStatus("loading");
|
|
19
|
+
const payload = { email, source };
|
|
20
|
+
if (password && mfaEnabled) {
|
|
21
|
+
payload.password = password;
|
|
22
|
+
}
|
|
19
23
|
axiosClient({
|
|
20
|
-
url: '/auth/login/email',
|
|
24
|
+
url: mfaEnabled ? '/auth/login/v2' : '/auth/login/email',
|
|
21
25
|
method: 'POST',
|
|
22
|
-
data:
|
|
26
|
+
data: payload
|
|
23
27
|
}).then((res) => {
|
|
24
28
|
setResendOTPCounter(prevCounter => prevCounter + 1);
|
|
25
29
|
sessionTokenRef.current = res.data.sessionToken;
|
|
26
30
|
}).catch((error) => {
|
|
27
|
-
console.
|
|
31
|
+
console.log('Failed to send OTP:', error);
|
|
28
32
|
const message = error?.response?.data?.errors?.[0]?.message || "Failed to send OTP. Please try again.";
|
|
29
33
|
showMessage({ message });
|
|
30
34
|
}).finally(() => setStatus("idle"));
|
|
31
|
-
}, [email, source]);
|
|
35
|
+
}, [email, source, password, mfaEnabled]);
|
|
32
36
|
/**
|
|
33
37
|
* Verifies the entered OTP and logs the user in.
|
|
34
38
|
*/
|
|
@@ -41,6 +45,9 @@ const useLoginWithEmailOTP = ({ email, source }) => {
|
|
|
41
45
|
}).then((res) => {
|
|
42
46
|
setStatus('valid');
|
|
43
47
|
const { token, member } = res.data;
|
|
48
|
+
if (token) {
|
|
49
|
+
onTokenChange(token);
|
|
50
|
+
}
|
|
44
51
|
onLogin({ token, member });
|
|
45
52
|
}).catch((error) => {
|
|
46
53
|
const errorCode = error?.response?.status;
|
|
@@ -56,15 +63,20 @@ const useLoginWithEmailOTP = ({ email, source }) => {
|
|
|
56
63
|
return () => clearTimeout(timeoutId);
|
|
57
64
|
}
|
|
58
65
|
});
|
|
59
|
-
}, [
|
|
66
|
+
}, [onLogin, onTokenChange]);
|
|
60
67
|
/**
|
|
61
68
|
* Automatically sends OTP when email and source are provided.
|
|
69
|
+
* Skip if mfaEnabled & sessionToken is already provided (from MFA flow).
|
|
62
70
|
*/
|
|
63
71
|
useEffect(() => {
|
|
64
|
-
if (email && source) {
|
|
72
|
+
if (email && source && !mfaEnabled) {
|
|
65
73
|
sendOtp();
|
|
66
74
|
}
|
|
67
|
-
|
|
75
|
+
else if (mfaEnabled && sessionToken) {
|
|
76
|
+
// If sessionToken is provided, we already have a session, just initialize
|
|
77
|
+
sessionTokenRef.current = sessionToken;
|
|
78
|
+
}
|
|
79
|
+
}, [email, source, sessionToken, sendOtp]);
|
|
68
80
|
return {
|
|
69
81
|
sendOtp,
|
|
70
82
|
verifyOtp,
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { useLoginWithEmailOTP } from "./hooks/internal/useLoginWithEmailOTP";
|
|
3
3
|
import { VerifyEmailOTP } from "../../components/VerifyEmailOTP";
|
|
4
|
-
const LoginWithEmailOTP = ({ email }) => {
|
|
5
|
-
const { resendOTPCounter, status, verifyOtp, sendOtp, } = useLoginWithEmailOTP({ email, source: 'web' });
|
|
4
|
+
const LoginWithEmailOTP = ({ email, password, sessionToken, mfaEnabled }) => {
|
|
5
|
+
const { resendOTPCounter, status, verifyOtp, sendOtp, } = useLoginWithEmailOTP({ email, password, source: 'web', sessionToken, mfaEnabled });
|
|
6
6
|
return (_jsx(VerifyEmailOTP, { email: email, validateOTP: verifyOtp, resendOTP: sendOtp, status: status, resendOTPCounter: resendOTPCounter }));
|
|
7
7
|
};
|
|
8
8
|
export default LoginWithEmailOTP;
|
|
@@ -3,8 +3,8 @@ import { Platform } from 'react-native';
|
|
|
3
3
|
import { VerifyEmailOTP } from '../../components/VerifyEmailOTP';
|
|
4
4
|
import { useLoginWithEmailOTP } from './hooks/internal/useLoginWithEmailOTP';
|
|
5
5
|
const LoginWithEmailOTP = ({ route }) => {
|
|
6
|
-
const { email } = route.params;
|
|
7
|
-
const { resendOTPCounter, status, verifyOtp, sendOtp, } = useLoginWithEmailOTP({ email, source: Platform.OS });
|
|
6
|
+
const { email, sessionToken, mfaEnabled, password } = route.params;
|
|
7
|
+
const { resendOTPCounter, status, verifyOtp, sendOtp, } = useLoginWithEmailOTP({ email, password, source: Platform.OS, sessionToken, mfaEnabled });
|
|
8
8
|
return (_jsx(VerifyEmailOTP, { email: email, status: status, validateOTP: verifyOtp, resendOTP: sendOtp, resendOTPCounter: resendOTPCounter }));
|
|
9
9
|
};
|
|
10
10
|
export default LoginWithEmailOTP;
|
|
@@ -21,7 +21,7 @@ const SSOCallbackComponents = () => {
|
|
|
21
21
|
setCode(typeof code === 'string' ? code : '');
|
|
22
22
|
}
|
|
23
23
|
catch (error) {
|
|
24
|
-
console.
|
|
24
|
+
console.log('Failed to read from localStorage:', error);
|
|
25
25
|
setCode(typeof code === 'string' ? code : '');
|
|
26
26
|
// Fallback: proceed without stored values
|
|
27
27
|
}
|
|
@@ -15,7 +15,7 @@ const useVerifyEmail = ({ sessionToken }) => {
|
|
|
15
15
|
}, []);
|
|
16
16
|
const resendOTP = useCallback(() => {
|
|
17
17
|
if (!sessionTokenState) {
|
|
18
|
-
console.
|
|
18
|
+
console.log('useVerifyEmail: sessionToken is required to resend OTP');
|
|
19
19
|
return;
|
|
20
20
|
}
|
|
21
21
|
setResendOTPCounter(prevCounter => prevCounter + 1);
|
|
@@ -33,7 +33,7 @@ const useVerifyEmail = ({ sessionToken }) => {
|
|
|
33
33
|
}, [sessionTokenState]);
|
|
34
34
|
const validateOTP = useCallback(({ otp, onVerifiedOTP }) => {
|
|
35
35
|
if (!sessionTokenState) {
|
|
36
|
-
console.
|
|
36
|
+
console.log('useVerifyEmail: sessionToken is required to resend OTP');
|
|
37
37
|
return;
|
|
38
38
|
}
|
|
39
39
|
setStatus('loading');
|
package/build/src/screens/VerifyResetPasswordOTP/hooks/internal/useVerifyResetPasswordOTP.js
CHANGED
|
@@ -27,7 +27,7 @@ const useVerifyResetPasswordOTP = ({ email }) => {
|
|
|
27
27
|
setResendOTPCounter(prevCounter => prevCounter + 1);
|
|
28
28
|
sessionTokenRef.current = res.data.sessionToken;
|
|
29
29
|
}).catch((error) => {
|
|
30
|
-
console.
|
|
30
|
+
console.log('Failed to send OTP:', error);
|
|
31
31
|
const message = error?.response?.data?.errors?.[0]?.message || "Failed to send OTP. Please try again.";
|
|
32
32
|
showMessage({ message });
|
|
33
33
|
}).finally(() => setStatus("idle"));
|
|
@@ -7,7 +7,7 @@ import { handleAppleAuth, handleFacebookAuth, handleGoogleAuth, SocialAuthStatus
|
|
|
7
7
|
import { RegistrationMethod, SocialLoginsEnum } from "../../../../enums";
|
|
8
8
|
import { showMessage } from "../../../../helpers/show-message";
|
|
9
9
|
import { AccessToken, GraphRequest, GraphRequestManager, LoginManager } from "react-native-fbsdk-next";
|
|
10
|
-
import
|
|
10
|
+
import appleAuth from '@invertase/react-native-apple-authentication';
|
|
11
11
|
import { axiosClient } from "../../../../api/axiosClient";
|
|
12
12
|
const useSocialAuth = () => {
|
|
13
13
|
const [loading, setLoading] = useState(false);
|
|
@@ -20,7 +20,7 @@ const useSocialAuth = () => {
|
|
|
20
20
|
GoogleSignin.configure({ webClientId: googleAppId });
|
|
21
21
|
await GoogleSignin.hasPlayServices();
|
|
22
22
|
const googleResponse = await GoogleSignin.signIn();
|
|
23
|
-
const { user, idToken } = googleResponse
|
|
23
|
+
const { user, idToken } = googleResponse || {};
|
|
24
24
|
if (!user || !idToken) {
|
|
25
25
|
return showMessage({
|
|
26
26
|
message: "Google login failed",
|
|
@@ -40,7 +40,7 @@ const useSocialAuth = () => {
|
|
|
40
40
|
}, SocialLoginsEnum.Google);
|
|
41
41
|
}
|
|
42
42
|
catch (err) {
|
|
43
|
-
console.
|
|
43
|
+
console.log("Google login failed:", err);
|
|
44
44
|
return { error: err };
|
|
45
45
|
}
|
|
46
46
|
finally {
|
|
@@ -83,7 +83,7 @@ const useSocialAuth = () => {
|
|
|
83
83
|
}, SocialLoginsEnum.Facebook);
|
|
84
84
|
}
|
|
85
85
|
catch (err) {
|
|
86
|
-
console.
|
|
86
|
+
console.log("Facebook login failed:", err);
|
|
87
87
|
return { error: err };
|
|
88
88
|
}
|
|
89
89
|
finally {
|
|
@@ -92,13 +92,12 @@ const useSocialAuth = () => {
|
|
|
92
92
|
}, []);
|
|
93
93
|
const loginWithApple = useCallback(async () => {
|
|
94
94
|
try {
|
|
95
|
-
const appleAuthResponse = await
|
|
96
|
-
requestedOperation:
|
|
97
|
-
requestedScopes: [
|
|
98
|
-
AppleAuthRequestScope.FULL_NAME],
|
|
95
|
+
const appleAuthResponse = await appleAuth.performRequest({
|
|
96
|
+
requestedOperation: appleAuth.Operation.LOGIN,
|
|
97
|
+
requestedScopes: [appleAuth.Scope.FULL_NAME, appleAuth.Scope.EMAIL],
|
|
99
98
|
});
|
|
100
|
-
const credentialState = await
|
|
101
|
-
if (credentialState !==
|
|
99
|
+
const credentialState = await appleAuth.getCredentialStateForUser(appleAuthResponse.user);
|
|
100
|
+
if (credentialState !== appleAuth.State.AUTHORIZED) {
|
|
102
101
|
return;
|
|
103
102
|
}
|
|
104
103
|
setLoading(true);
|
|
@@ -150,7 +149,7 @@ const useSocialAuth = () => {
|
|
|
150
149
|
}, SocialLoginsEnum.Apple);
|
|
151
150
|
}
|
|
152
151
|
catch (error) {
|
|
153
|
-
console.
|
|
152
|
+
console.log("Apple login failed:", error);
|
|
154
153
|
return { error: error };
|
|
155
154
|
}
|
|
156
155
|
finally {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useEffect } from 'react';
|
|
3
3
|
import { Text } from 'react-native';
|
|
4
|
-
import { BottomSheet, RoundedButton } from '@truworth/twc-rn-common';
|
|
4
|
+
import { BottomSheet, isIphoneX, RoundedButton } from '@truworth/twc-rn-common';
|
|
5
5
|
import { useModalize } from 'react-native-modalize';
|
|
6
6
|
const SocialLoginModal = ({ visible, hide, socialLoginType, onClick }) => {
|
|
7
7
|
const { ref: socialSheetRef, open: openSheet, close: closeSheet } = useModalize();
|
|
@@ -13,7 +13,7 @@ const SocialLoginModal = ({ visible, hide, socialLoginType, onClick }) => {
|
|
|
13
13
|
closeSheet();
|
|
14
14
|
}
|
|
15
15
|
}, [visible]);
|
|
16
|
-
return (_jsxs(BottomSheet, { title: 'Corporate Users', sheetRef: socialSheetRef, childrenStyle: { padding: 16 }, onClose: hide, children: [_jsxs(Text, { style: {
|
|
16
|
+
return (_jsxs(BottomSheet, { title: 'Corporate Users', sheetRef: socialSheetRef, childrenStyle: { padding: 16, marginBottom: isIphoneX() ? 18 : 0 }, onClose: hide, children: [_jsxs(Text, { style: {
|
|
17
17
|
fontSize: 12, fontWeight: '600', color: '#000',
|
|
18
18
|
lineHeight: 16, marginBottom: 30,
|
|
19
19
|
}, children: ["If you are a corporate user, you will", ' ', _jsx(Text, { style: { textDecorationLine: 'underline' }, children: "NOT" }), ' ', "be able to avail all the health benefits offered on The Wellness Corner by your employer if you login through ", socialLoginType, ".", '\n', '\n', "In that case you will have to go back ", '&', " register using your official Email Address."] }), _jsx(RoundedButton, { label: "I understand, I'm NOT a corporate user", onPress: onClick })] }));
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
type SubmitProps = {
|
|
2
2
|
email: string;
|
|
3
3
|
source: string;
|
|
4
|
+
verifyEmailOTP?: (params: {
|
|
5
|
+
mfaEnabled: boolean;
|
|
6
|
+
sessionToken: string;
|
|
7
|
+
}) => void;
|
|
4
8
|
};
|
|
5
9
|
/**
|
|
6
10
|
* @internal
|
|
@@ -12,9 +16,10 @@ declare const useEnterPassword: () => {
|
|
|
12
16
|
setPassword: import("react").Dispatch<import("react").SetStateAction<string>>;
|
|
13
17
|
isPasswordVisible: boolean;
|
|
14
18
|
togglePasswordVisibility: () => void;
|
|
15
|
-
handleSubmit: ({ email, source }: SubmitProps) => Promise<void>;
|
|
19
|
+
handleSubmit: ({ email, source, verifyEmailOTP }: SubmitProps) => Promise<void>;
|
|
16
20
|
isDisabled: boolean;
|
|
17
21
|
handlePasswordChange: (value: string) => void;
|
|
18
22
|
appName: string | undefined;
|
|
23
|
+
invalidPassword: boolean;
|
|
19
24
|
};
|
|
20
25
|
export { useEnterPassword };
|
|
@@ -17,5 +17,8 @@ interface LoginWithEmailOTPModalProps {
|
|
|
17
17
|
show: boolean;
|
|
18
18
|
hide: () => void;
|
|
19
19
|
email: string;
|
|
20
|
+
password?: string;
|
|
21
|
+
sessionToken?: string;
|
|
22
|
+
mfaEnabled?: boolean;
|
|
20
23
|
}
|
|
21
24
|
export type { EnterPasswordProps, VerifyResetPasswordOTPModalProps, LoginWithEmailOTPModalProps };
|
|
@@ -2,9 +2,12 @@
|
|
|
2
2
|
* @internal
|
|
3
3
|
* Hook for handling Email OTP Login flow.
|
|
4
4
|
*/
|
|
5
|
-
declare const useLoginWithEmailOTP: ({ email, source }: {
|
|
5
|
+
declare const useLoginWithEmailOTP: ({ email, password, source, sessionToken, mfaEnabled }: {
|
|
6
6
|
email: string;
|
|
7
|
+
password?: string;
|
|
7
8
|
source: string;
|
|
9
|
+
sessionToken?: string;
|
|
10
|
+
mfaEnabled?: boolean;
|
|
8
11
|
}) => {
|
|
9
12
|
sendOtp: () => void;
|
|
10
13
|
verifyOtp: (otp: string) => void;
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
declare const LoginWithEmailOTP: ({ email }: {
|
|
1
|
+
declare const LoginWithEmailOTP: ({ email, password, sessionToken, mfaEnabled }: {
|
|
2
2
|
email: string;
|
|
3
|
+
password?: string;
|
|
4
|
+
sessionToken?: string;
|
|
5
|
+
mfaEnabled?: boolean;
|
|
3
6
|
}) => import("react/jsx-runtime").JSX.Element;
|
|
4
7
|
export default LoginWithEmailOTP;
|
package/package.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"access": "public"
|
|
5
5
|
},
|
|
6
6
|
"description": "Truworth Auth Package for React Native and Web",
|
|
7
|
-
"version": "1.2.
|
|
7
|
+
"version": "1.2.8",
|
|
8
8
|
"main": "build/src/index.js",
|
|
9
9
|
"types": "build/types/index.d.ts",
|
|
10
10
|
"files": [
|
|
@@ -20,14 +20,14 @@
|
|
|
20
20
|
"pub": "git add . && git commit -m \"Updates\" && git push && npm run build && npm version patch && npm publish"
|
|
21
21
|
},
|
|
22
22
|
"devDependencies": {
|
|
23
|
-
"@invertase/react-native-apple-authentication": "
|
|
24
|
-
"@react-native-clipboard/clipboard": "1.
|
|
23
|
+
"@invertase/react-native-apple-authentication": "2.5.0",
|
|
24
|
+
"@react-native-clipboard/clipboard": "1.16.3",
|
|
25
25
|
"@react-native-community/datetimepicker": "8.1.1",
|
|
26
|
-
"@react-native-google-signin/google-signin": "
|
|
27
|
-
"@react-navigation/native": "
|
|
28
|
-
"@react-navigation/native-stack": "
|
|
29
|
-
"@truworth/twc-rn-common": "
|
|
30
|
-
"@truworth/twc-web-design": "
|
|
26
|
+
"@react-native-google-signin/google-signin": "12.2.1",
|
|
27
|
+
"@react-navigation/native": "6.1.17",
|
|
28
|
+
"@react-navigation/native-stack": "6.10.0",
|
|
29
|
+
"@truworth/twc-rn-common": "1.0.15",
|
|
30
|
+
"@truworth/twc-web-design": "1.11.0",
|
|
31
31
|
"@twotalltotems/react-native-otp-input": "1.3.11",
|
|
32
32
|
"@types/crypto-js": "^4.2.2",
|
|
33
33
|
"@types/fbemitter": "^2.0.35",
|
|
@@ -47,24 +47,24 @@
|
|
|
47
47
|
"lottie-react-native": "6.7.2",
|
|
48
48
|
"moment": "^2.30.1",
|
|
49
49
|
"next": "^15.0.4",
|
|
50
|
-
"react": "
|
|
50
|
+
"react": "18.3.1",
|
|
51
51
|
"react-dom": "^18.2.0",
|
|
52
52
|
"react-google-login": "^5.2.2",
|
|
53
53
|
"react-google-recaptcha": "^3.1.0",
|
|
54
54
|
"react-infinite-scroll-component": "^6.1.0",
|
|
55
55
|
"react-lottie": "^1.2.3",
|
|
56
|
-
"react-native": "
|
|
57
|
-
"react-native-fast-image": "
|
|
58
|
-
"react-native-fbsdk-next": "
|
|
59
|
-
"react-native-linear-gradient": "
|
|
56
|
+
"react-native": "0.76.1",
|
|
57
|
+
"react-native-fast-image": "8.6.3",
|
|
58
|
+
"react-native-fbsdk-next": "13.4.1",
|
|
59
|
+
"react-native-linear-gradient": "2.8.3",
|
|
60
60
|
"react-native-modalize": "2.1.1",
|
|
61
61
|
"react-native-parsed-text": "^0.0.22",
|
|
62
|
-
"react-native-reanimated": "
|
|
63
|
-
"react-native-rsa-native": "
|
|
64
|
-
"react-native-safe-area-context": "
|
|
62
|
+
"react-native-reanimated": "3.16.1",
|
|
63
|
+
"react-native-rsa-native": "2.0.5",
|
|
64
|
+
"react-native-safe-area-context": "4.14.0",
|
|
65
65
|
"react-native-svg": "15.8.0",
|
|
66
66
|
"react-native-svg-uri": "^1.2.3",
|
|
67
|
-
"react-native-vector-icons": "
|
|
67
|
+
"react-native-vector-icons": "9.2.0",
|
|
68
68
|
"react-redux": "^9.2.0",
|
|
69
69
|
"sweetalert2": "^11.23.0",
|
|
70
70
|
"typescript": "^5.0.0",
|