added reset-password

This commit is contained in:
Jaanu423
2026-01-19 16:58:53 +05:30
parent b48b569a84
commit 3e9219d9e1
6 changed files with 882 additions and 5 deletions
+2 -1
View File
@@ -21,6 +21,7 @@ const NavigationString = {
LiveTenderDetail:'LiveTenderDetail', LiveTenderDetail:'LiveTenderDetail',
AuctionDetail: 'AuctionDetail', AuctionDetail: 'AuctionDetail',
Profile:'Profile', Profile:'Profile',
ViewTenderDetail:'ViewTenderDetail' ViewTenderDetail:'ViewTenderDetail',
ResetPassword:'ResetPassword'
} }
export default NavigationString export default NavigationString
+1 -1
View File
@@ -46,7 +46,7 @@ export default function MainStack() {
<Stack.Screen name={NavigationString.Registration} component={Screens.Registration} options={option} /> <Stack.Screen name={NavigationString.Registration} component={Screens.Registration} options={option} />
<Stack.Screen name={NavigationString.Partnership} component={Screens.Partnership} options={option} /> <Stack.Screen name={NavigationString.Partnership} component={Screens.Partnership} options={option} />
<Stack.Screen name={NavigationString.LiveTenderDetail} component={Screens.LiveTenderDetail} options={option} /> <Stack.Screen name={NavigationString.LiveTenderDetail} component={Screens.LiveTenderDetail} options={option} />
<Stack.Screen name={NavigationString.ViewTenderDetail} component={Screens.ViewTenderDetail} options={option} /> <Stack.Screen name={NavigationString.ResetPassword} component={Screens.ResetPassword} options={option} />
</Stack.Navigator> </Stack.Navigator>
); );
} }
+252
View File
@@ -0,0 +1,252 @@
import React, { useState } from 'react';
import {
StyleSheet,
Text,
View,
Modal,
TextInput,
TouchableOpacity,
Alert,
KeyboardAvoidingView,
Platform,
TouchableWithoutFeedback,
Keyboard,
ActivityIndicator
} from 'react-native';
import { useNavigation } from '@react-navigation/native';
import colors from '../../Constant/Color';
interface ForgotModalProps {
visible: boolean;
onClose: () => void;
}
export type Navigation = {
navigate(route: string, params?: object): unknown;
};
const ForgotModal: React.FC<ForgotModalProps> = ({
visible,
onClose
}) => {
const navigation = useNavigation() as Navigation;
const [email, setEmail] = useState<string>('');
const [loading, setLoading] = useState<boolean>(false);
const [error, setError] = useState<string>('');
const handleResetPassword = async () => {
// Reset error
setError('');
// Validate email
if (!email) {
setError('Please enter your email address');
return;
}
// Simple email validation
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailRegex.test(email)) {
setError('Please enter a valid email address');
return;
}
setLoading(true);
try {
// Make API call to send OTP for forgot password
const response = await fetch(
`https://procurelinc.in/EProcurementSB/eproc/send-otp-forgot-password?email=${encodeURIComponent(email)}`,
{
method: 'POST',
headers: {
'Accept': '*/*',
'Content-Type': 'application/json',
},
}
);
if (response.ok) {
Alert.alert(
'Success',
'OTP has been sent to your email address. Please check your inbox.',
[
{
text: 'OK',
onPress: () => {
onClose();
navigation.navigate('ResetPassword', { email });
}
}
]
);
setEmail('');
} else {
const errorData = await response.text();
console.error('API Error:', errorData);
setError('Failed to send OTP. Please try again.');
}
} catch (err) {
console.error('Network Error:', err);
setError('Network error. Please check your connection and try again.');
} finally {
setLoading(false);
}
};
const handleClose = () => {
setEmail('');
setError('');
onClose();
};
return (
<Modal
visible={visible}
animationType="slide"
transparent={true}
onRequestClose={handleClose}
>
<TouchableWithoutFeedback onPress={Keyboard.dismiss}>
<View style={styles.centeredView}>
<KeyboardAvoidingView
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
style={styles.keyboardAvoidingView}
>
<View style={styles.modalView}>
<Text style={styles.title}>Reset Password</Text>
<Text style={styles.subtitle}>
Enter your email address and we'll send you an OTP to reset your password.
</Text>
<TextInput
style={styles.input}
placeholder="Email address"
placeholderTextColor="#999"
value={email}
onChangeText={setEmail}
keyboardType="email-address"
autoCapitalize="none"
autoCorrect={false}
editable={!loading}
/>
{error ? <Text style={styles.errorText}>{error}</Text> : null}
<View style={styles.buttonContainer}>
<TouchableOpacity
style={[styles.button, styles.cancelButton]}
onPress={handleClose}
disabled={loading}
>
<Text style={styles.cancelButtonText}>Cancel</Text>
</TouchableOpacity>
<TouchableOpacity
style={[styles.button, styles.resetButton, loading && styles.disabledButton]}
onPress={handleResetPassword}
disabled={loading}
>
{loading ? (
<ActivityIndicator color="#fff" />
) : (
<Text style={styles.resetButtonText}>Send OTP</Text>
)}
</TouchableOpacity>
</View>
</View>
</KeyboardAvoidingView>
</View>
</TouchableWithoutFeedback>
</Modal>
);
};
const styles = StyleSheet.create({
centeredView: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'rgba(0, 0, 0, 0.5)',
},
keyboardAvoidingView: {
width: '100%',
alignItems: 'center',
},
modalView: {
width: '85%',
backgroundColor: 'white',
borderRadius: 12,
padding: 24,
alignItems: 'center',
shadowColor: '#000',
shadowOffset: {
width: 0,
height: 2,
},
shadowOpacity: 0.25,
shadowRadius: 4,
elevation: 5,
},
title: {
fontSize: 22,
fontWeight: 'bold',
marginBottom: 12,
color: '#333',
},
subtitle: {
fontSize: 14,
textAlign: 'center',
marginBottom: 24,
color: '#666',
lineHeight: 20,
},
input: {
width: '100%',
height: 50,
borderWidth: 1,
borderColor: '#ddd',
borderRadius: 8,
paddingHorizontal: 16,
fontSize: 16,
marginBottom: 16,
},
errorText: {
color: '#ff3b30',
fontSize: 14,
marginBottom: 16,
alignSelf: 'flex-start',
},
buttonContainer: {
flexDirection: 'row',
justifyContent: 'space-between',
width: '100%',
},
button: {
borderRadius: 8,
padding: 16,
minWidth: '45%',
alignItems: 'center',
justifyContent: 'center',
},
cancelButton: {
backgroundColor: '#f1f1f1',
},
resetButton: {
backgroundColor: colors.primary,
},
disabledButton: {
opacity: 0.6,
},
cancelButtonText: {
color: '#666',
fontWeight: '600',
},
resetButtonText: {
color: 'white',
fontWeight: '600',
},
});
export default ForgotModal;
+5 -2
View File
@@ -15,6 +15,7 @@ import { useNavigation, CommonActions } from '@react-navigation/native';
import NavigationString from '../../Constant/NavigationString'; import NavigationString from '../../Constant/NavigationString';
import ReactNativeHapticFeedback from 'react-native-haptic-feedback'; import ReactNativeHapticFeedback from 'react-native-haptic-feedback';
import { Loader } from '../../Component/Index'; import { Loader } from '../../Component/Index';
import ForgotModal from './ForgotPassword';
const hapticOptions = { const hapticOptions = {
enableVibrateFallback: true, enableVibrateFallback: true,
@@ -38,6 +39,7 @@ const Login = () => {
const { mutate: auctionMutate } = useAuctionLogin(); const { mutate: auctionMutate } = useAuctionLogin();
const { data } = useGetDesignation(); const { data } = useGetDesignation();
const { mutate: registrationStateMutate } = useRagistrationState(); const { mutate: registrationStateMutate } = useRagistrationState();
const [forgotPassword, setForgotPassword] = useState(false)
const { data: MasterData } = usefetchMasterData() const { data: MasterData } = usefetchMasterData()
@@ -155,7 +157,7 @@ const Login = () => {
); );
} }
} catch (error) { } catch (error) {
setAuctionLoading(false)
} finally { } finally {
setAuctionLoading(false); setAuctionLoading(false);
} }
@@ -249,7 +251,7 @@ const Login = () => {
</View> </View>
{errors.password && touched.password && <Text style={styles.errorText}>{errors.password}</Text>} {errors.password && touched.password && <Text style={styles.errorText}>{errors.password}</Text>}
<TouchableOpacity style={styles.forgotPass}> <TouchableOpacity style={styles.forgotPass} onPress={()=>setForgotPassword(true)} >
<Text style={styles.forgotPassText}>Forgot Password?</Text> <Text style={styles.forgotPassText}>Forgot Password?</Text>
</TouchableOpacity> </TouchableOpacity>
@@ -293,6 +295,7 @@ const Login = () => {
</Animated.View> </Animated.View>
</ScrollView> </ScrollView>
</KeyboardAvoidingView> </KeyboardAvoidingView>
{forgotPassword && <ForgotModal visible={forgotPassword} onClose={()=>setForgotPassword(false)}/>}
</View> </View>
); );
}; };
+619
View File
@@ -0,0 +1,619 @@
import AsyncStorage from '@react-native-async-storage/async-storage';
import axios from 'axios';
import React, { useState, useEffect, useRef } from 'react';
import {
StyleSheet,
Text,
View,
TextInput,
TouchableOpacity,
Alert,
ScrollView,
KeyboardAvoidingView,
Platform,
ActivityIndicator,
NativeSyntheticEvent,
TextInputKeyPressEventData,
ToastAndroid,
} from 'react-native';
import { BASE_URL } from '../../Services/BBPS/ApiUrls';
import colors from '../../Constant/Color';
interface ResetPasswordProps {
route?: any;
navigation?: any;
}
const ResetPassword: React.FC<ResetPasswordProps> = ({ route, navigation }) => {
const [email, setEmail] = useState<string>(route?.params?.email || '');
const [otp, setOtp] = useState<string[]>(['', '', '', '', '', '']);
const [newPassword, setNewPassword] = useState<string>('');
const [confirmPassword, setConfirmPassword] = useState<string>('');
const [loading, setLoading] = useState<boolean>(false);
const [otpLoading, setOtpLoading] = useState<boolean>(false);
const [resendLoading, setResendLoading] = useState<boolean>(false);
const [error, setError] = useState<string>('');
const [otpError, setOtpError] = useState<string>('');
const [passwordError, setPasswordError] = useState<string>('');
const [confirmPasswordError, setConfirmPasswordError] = useState<string>('');
const [isOtpVerified, setIsOtpVerified] = useState<boolean>(false);
const [resendCooldown, setResendCooldown] = useState<number>(0);
const [newPasswordVisible, setNewPasswordVisible] = useState<boolean>(false);
const [confirmPasswordVisible, setConfirmPasswordVisible] = useState<boolean>(false);
const otpInputs = useRef<Array<TextInput | null>>([]);
const newPasswordRef = useRef<TextInput>(null);
const confirmPasswordRef = useRef<TextInput>(null);
const resendTimerRef = useRef<NodeJS.Timeout | null>(null);
// Initialize resend cooldown from storage or set to 0
useEffect(() => {
checkResendCooldown();
}, []);
// Clean up timer on unmount
useEffect(() => {
return () => {
if (resendTimerRef.current) {
clearInterval(resendTimerRef.current);
}
};
}, []);
// Update timer every second
useEffect(() => {
if (resendCooldown > 0) {
resendTimerRef.current = setInterval(() => {
setResendCooldown(prev => {
if (prev <= 1) {
if (resendTimerRef.current) {
clearInterval(resendTimerRef.current);
}
AsyncStorage.removeItem('otpResendTime');
return 0;
}
return prev - 1;
});
}, 1000);
}
return () => {
if (resendTimerRef.current) {
clearInterval(resendTimerRef.current);
}
};
}, [resendCooldown]);
const checkResendCooldown = async () => {
try {
const storedTime = await AsyncStorage.getItem('otpResendTime');
if (storedTime) {
const remainingTime = Math.max(0, Math.floor((300000 - (Date.now() - parseInt(storedTime))) / 1000));
if (remainingTime > 0) {
setResendCooldown(remainingTime);
}
}
} catch (error) {
console.error('Error checking resend cooldown:', error);
}
};
const startResendCooldown = async () => {
const cooldownTime = 300; // 5 minutes in seconds
setResendCooldown(cooldownTime);
await AsyncStorage.setItem('otpResendTime', Date.now().toString());
};
useEffect(() => {
// Auto-submit OTP when all fields are filled
const fullOtp = otp.join('');
if (fullOtp.length === 6 && !isOtpVerified) {
handleSubmitOtp();
}
}, [otp]);
const handleOtpChange = (value: string, index: number) => {
if (!/^\d*$/.test(value)) return; // Only allow numbers
const newOtp = [...otp];
newOtp[index] = value;
setOtp(newOtp);
setOtpError('');
// Auto-focus to next input
if (value && index < 5) {
otpInputs.current[index + 1]?.focus();
}
};
const handleOtpKeyPress = (e: NativeSyntheticEvent<TextInputKeyPressEventData>, index: number) => {
if (e.nativeEvent.key === 'Backspace' && !otp[index] && index > 0) {
// Move focus to previous input on backspace
otpInputs.current[index - 1]?.focus();
}
};
const handleSubmitOtp = async () => {
const fullOtp = otp.join('');
if (fullOtp.length !== 6) {
setOtpError('Please enter a valid 6-digit OTP');
return;
}
if (!email) {
setOtpError('Email is required for OTP verification');
return;
}
setOtpLoading(true);
setOtpError('');
try {
// Make the API request to verify OTP
const res = await axios.post(
`${BASE_URL}eproc/verify-otp?email=${encodeURIComponent(email)}&otp=${fullOtp}`,
null,
{
headers: {
'accept': '*/*',
'Content-Type': 'application/json'
}
}
);
console.log('API Response OTP verification:', res.data);
if (res.data?.statusCode === 200) {
ToastAndroid.show('OTP verified successfully!', ToastAndroid.SHORT);
setIsOtpVerified(true);
// Focus on password field after successful OTP verification
setTimeout(() => {
newPasswordRef.current?.focus();
}, 100);
} else {
throw new Error(res.data?.message || 'OTP verification failed');
}
} catch (error) {
console.error('Verification Error:', error);
const errorMessage = axios.isAxiosError(error)
? error.response?.data?.message || error.message
: error instanceof Error
? error.message
: 'OTP verification failed';
setOtpError(errorMessage);
ToastAndroid.show(errorMessage, ToastAndroid.SHORT);
} finally {
setOtpLoading(false);
}
};
const validateForm = (): boolean => {
let isValid = true;
// Validate OTP
if (!isOtpVerified) {
setOtpError('Please verify OTP first');
isValid = false;
}
// Validate password
if (newPassword.length < 8) {
setPasswordError('Password must be at least 8 characters long');
isValid = false;
}
// Validate confirm password
if (newPassword !== confirmPassword) {
setConfirmPasswordError('Passwords do not match');
isValid = false;
}
return isValid;
};
const handleResetPassword = async () => {
setError('');
setOtpError('');
setPasswordError('');
setConfirmPasswordError('');
if (!validateForm()) return;
setLoading(true);
try {
// Make API call to reset password according to curl
const res = await axios.post(
`${BASE_URL}eproc/reset-password?email=${encodeURIComponent(email)}&otp=${otp.join('')}&newPassword=${encodeURIComponent(newPassword)}&confirmPassword=${encodeURIComponent(confirmPassword)}`,
null,
{
headers: {
'accept': '*/*',
'Content-Type': 'application/json'
}
}
);
console.log('API Response password reset:', res.data);
if (res.data?.statusCode === 200) {
Alert.alert(
'Success',
'Your password has been reset successfully.',
[{
text: 'OK', onPress: () => {
// Navigate to login screen
navigation.navigate('Login');
}
}]
);
} else {
throw new Error(res.data?.message || 'Password reset failed');
}
} catch (err) {
const errorMessage = axios.isAxiosError(err)
? err.response?.data?.message || err.message
: err instanceof Error
? err.message
: 'Failed to reset password. Please try again.';
setError(errorMessage);
ToastAndroid.show(errorMessage, ToastAndroid.SHORT);
} finally {
setLoading(false);
}
};
const handleResendOtp = async () => {
if (resendCooldown > 0) return;
setResendLoading(true);
try {
// Make API call to resend OTP
const res = await axios.post(
`${BASE_URL}eproc/send-otp-forgot-password?email=${encodeURIComponent(email)}`,
null,
{
headers: {
'accept': '*/*',
}
}
);
if (res.data?.statusCode === 200) {
ToastAndroid.show('OTP sent successfully', ToastAndroid.SHORT);
// Clear OTP fields
setOtp(['', '', '', '', '', '']);
setIsOtpVerified(false);
setOtpError('');
// Start the cooldown timer
startResendCooldown();
} else {
throw new Error(res.data?.message || 'Failed to resend OTP');
}
} catch (error) {
const errorMessage = axios.isAxiosError(error)
? error.response?.data?.message || error.message
: error instanceof Error
? error.message
: 'Failed to resend OTP';
ToastAndroid.show(errorMessage, ToastAndroid.SHORT);
} finally {
setResendLoading(false);
}
};
const formatTime = (seconds: number): string => {
const minutes = Math.floor(seconds / 60);
const remainingSeconds = seconds % 60;
return `${minutes}:${remainingSeconds.toString().padStart(2, '0')}`;
};
return (
<KeyboardAvoidingView
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
style={styles.container}
>
<ScrollView contentContainerStyle={styles.scrollContainer}>
<Text style={styles.title}>Reset Password</Text>
<Text style={styles.subtitle}>
Enter the OTP sent to {email} and your new password
</Text>
{/* OTP Input Section */}
<View style={styles.otpSection}>
<Text style={styles.sectionLabel}>OTP Code</Text>
<View style={styles.otpContainer}>
{otp.map((digit, index) => (
<TextInput
key={index}
ref={(ref) => { otpInputs.current[index] = ref; }}
style={[styles.otpInput, otpError ? styles.inputError : null, isOtpVerified && styles.verifiedInput]}
value={digit}
onChangeText={(value) => handleOtpChange(value, index)}
onKeyPress={(e) => handleOtpKeyPress(e, index)}
keyboardType="number-pad"
maxLength={1}
selectTextOnFocus
editable={!isOtpVerified && !otpLoading}
/>
))}
</View>
{otpError ? <Text style={styles.errorText}>{otpError}</Text> : null}
{isOtpVerified ? (
<View style={styles.verifiedContainer}>
<Text style={styles.verifiedText}>✓ OTP Verified</Text>
</View>
) : (
<TouchableOpacity
onPress={handleSubmitOtp}
style={[styles.submitButton, otpLoading && styles.disabledButton]}
disabled={otpLoading}
>
{otpLoading ? (
<ActivityIndicator color="#fff" />
) : (
<Text style={styles.submitButtonText}>Verify OTP</Text>
)}
</TouchableOpacity>
)}
</View>
{/* Password Input Section - Only enabled after OTP verification */}
<View style={styles.passwordSection}>
<Text style={styles.sectionLabel}>New Password</Text>
<View style={styles.passwordInputContainer}>
<TextInput
ref={newPasswordRef}
style={[styles.input, passwordError ? styles.inputError : null, !isOtpVerified && styles.disabledInput]}
placeholder="Enter new password"
placeholderTextColor={!isOtpVerified ? '#4f058bff' : '#000'}
value={newPassword}
onChangeText={(text) => {
setNewPassword(text);
setPasswordError('');
}}
secureTextEntry={!newPasswordVisible}
returnKeyType="next"
onSubmitEditing={() => confirmPasswordRef.current?.focus()}
editable={isOtpVerified}
/>
{isOtpVerified && (
<TouchableOpacity
style={styles.eyeIcon}
onPress={() => setNewPasswordVisible(!newPasswordVisible)}
>
<Text style={styles.eyeIconText}>
{newPasswordVisible ? '🙈' : '👁️'}
</Text>
</TouchableOpacity>
)}
</View>
{passwordError ? <Text style={styles.errorText}>{passwordError}</Text> : null}
<Text style={styles.sectionLabel}>Confirm Password</Text>
<View style={styles.passwordInputContainer}>
<TextInput
ref={confirmPasswordRef}
style={[styles.input, confirmPasswordError ? styles.inputError : null, !isOtpVerified && styles.disabledInput]}
placeholder="Confirm new password"
placeholderTextColor={!isOtpVerified ? '#4f058bff' : '#000'}
value={confirmPassword}
onChangeText={(text) => {
setConfirmPassword(text);
setConfirmPasswordError('');
}}
secureTextEntry={!confirmPasswordVisible}
returnKeyType="done"
onSubmitEditing={handleResetPassword}
editable={isOtpVerified}
/>
{isOtpVerified && (
<TouchableOpacity
style={styles.eyeIcon}
onPress={() => setConfirmPasswordVisible(!confirmPasswordVisible)}
>
<Text style={styles.eyeIconText}>
{confirmPasswordVisible ? '🙈' : '👁️'}
</Text>
</TouchableOpacity>
)}
</View>
{confirmPasswordError ? (
<Text style={styles.errorText}>{confirmPasswordError}</Text>
) : null}
</View>
{error ? <Text style={styles.errorText}>{error}</Text> : null}
<TouchableOpacity
style={[styles.resetButton, (loading || !isOtpVerified) && styles.disabledButton]}
onPress={handleResetPassword}
disabled={loading || !isOtpVerified}
>
{loading ? (
<ActivityIndicator color="#fff" />
) : (
<Text style={styles.resetButtonText}>Reset Password</Text>
)}
</TouchableOpacity>
<TouchableOpacity
style={[styles.resendButton, resendCooldown > 0 && styles.disabledResendButton]}
onPress={handleResendOtp}
disabled={resendLoading || resendCooldown > 0}
>
{resendLoading ? (
<ActivityIndicator color="#007AFF" />
) : resendCooldown > 0 ? (
<Text style={styles.resendButtonText}>
Resend OTP in {formatTime(resendCooldown)}
</Text>
) : (
<Text style={styles.resendButtonText}>Resend OTP</Text>
)}
</TouchableOpacity>
</ScrollView>
</KeyboardAvoidingView>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
justifyContent: 'center',
alignItems: 'center',
},
scrollContainer: {
padding: 20,
paddingTop: 40,
},
title: {
fontSize: 24,
fontWeight: 'bold',
marginBottom: 10,
textAlign: 'center',
color: '#333',
},
subtitle: {
fontSize: 16,
textAlign: 'center',
marginBottom: 30,
color: '#666',
lineHeight: 22,
},
otpSection: {
marginBottom: 25,
alignItems: 'center',
},
passwordSection: {
marginBottom: 20,
},
sectionLabel: {
fontSize: 16,
fontWeight: '600',
marginBottom: 10,
color: '#333',
},
otpContainer: {
flexDirection: 'row',
justifyContent: 'space-between',
marginBottom: 10,
width: '100%',
},
otpInput: {
width: 50,
height: 50,
borderWidth: 1,
borderColor: '#ddd',
borderRadius: 8,
textAlign: 'center',
fontSize: 18,
fontWeight: 'bold',
backgroundColor: '#fff',
},
verifiedInput: {
borderColor: '#34C759',
backgroundColor: '#f0fff4',
},
passwordInputContainer: {
position: 'relative',
marginBottom: 15,
},
input: {
width: '100%',
height: 50,
borderWidth: 1,
borderColor: '#ddd',
borderRadius: 8,
paddingHorizontal: 15,
fontSize: 16,
paddingRight: 50,
backgroundColor: '#fff',
color: '#000',
},
disabledInput: {
backgroundColor: '#f5f5f5',
borderColor: '#eee',
},
inputError: {
borderColor: '#ff3b30',
},
eyeIcon: {
position: 'absolute',
right: 15,
top: 13,
zIndex: 1,
},
eyeIconText: {
fontSize: 20,
},
errorText: {
color: '#ff3b30',
fontSize: 14,
marginBottom: 10,
alignSelf: 'flex-start',
},
submitButton: {
backgroundColor: colors.primary,
padding: 12,
borderRadius: 8,
alignItems: 'center',
marginTop: 10,
minWidth: 120,
},
submitButtonText: {
color: 'white',
fontSize: 16,
fontWeight: '600',
},
verifiedContainer: {
backgroundColor: '#34C759',
padding: 12,
borderRadius: 8,
marginTop: 10,
},
verifiedText: {
color: 'white',
fontSize: 16,
fontWeight: '600',
},
resetButton: {
backgroundColor: colors.primary,
padding: 16,
borderRadius: 8,
alignItems: 'center',
marginBottom: 20,
},
disabledButton: {
opacity: 0.6,
},
resetButtonText: {
color: 'white',
fontSize: 16,
fontWeight: '600',
},
resendButton: {
alignItems: 'center',
padding: 10,
},
disabledResendButton: {
opacity: 0.5,
},
resendButtonText: {
color: colors.primary,
fontSize: 16,
fontWeight: '600',
textDecorationLine: 'underline',
},
});
export default ResetPassword;
+3 -1
View File
@@ -6,6 +6,7 @@ import StartBidding from "./Bidding/StartBidding";
import StartReverseBidding from "./Bidding/StartReverseBidding"; import StartReverseBidding from "./Bidding/StartReverseBidding";
import Home from "./Home/Home"; import Home from "./Home/Home";
import Login from "./Login/Login"; import Login from "./Login/Login";
import ResetPassword from "./Login/ResetPassword";
import Onboarding from "./Onboarding/Onboarding"; import Onboarding from "./Onboarding/Onboarding";
import ProfileTab from "./Profile/ProfileTab"; import ProfileTab from "./Profile/ProfileTab";
import Partnership from "./Ragistration/PartnerShip"; import Partnership from "./Ragistration/PartnerShip";
@@ -42,6 +43,7 @@ const Screens = {
Partnership, Partnership,
LiveTenderDetail, LiveTenderDetail,
ProfileTab, ProfileTab,
ViewTenderDetail ViewTenderDetail,
ResetPassword
} }
export default Screens export default Screens