148 lines
4.3 KiB
TypeScript
148 lines
4.3 KiB
TypeScript
/*
|
|
* File: LoginScreen.tsx
|
|
* Description: Login screen with a loading indicator on the submit button.
|
|
* Design & Developed by Tech4Biz Solutions
|
|
* Copyright (c) Spurrin Innovations. All rights reserved.
|
|
*/
|
|
|
|
import React, { useState } from 'react';
|
|
import {
|
|
View,
|
|
Text,
|
|
StyleSheet,
|
|
TouchableWithoutFeedback,
|
|
Keyboard,
|
|
TouchableOpacity,
|
|
TextInput, // Using default TextInput for container styling
|
|
} from 'react-native';
|
|
import { Button } from '../../../../shared/src/components/Button';
|
|
import { Colors, Spacing, Typography } from '../../../../shared/src/theme';
|
|
import { useAppDispatch } from '../../../redux/hooks';
|
|
import { login } from '../redux/authActions';
|
|
import { showError } from '../../../../shared/src/utils/helpers/Toast';
|
|
import { validateEmail } from '../../../../shared/src/utils/validation/validators';
|
|
import Icon from 'react-native-vector-icons/Feather';
|
|
|
|
const LoginScreen: React.FC = () => {
|
|
const [email, setEmail] = useState('');
|
|
const [password, setPassword] = useState('');
|
|
const [isPasswordVisible, setPasswordVisible] = useState(false);
|
|
const [loading, setLoading] = useState(false); // Add loading state
|
|
const dispatch = useAppDispatch();
|
|
|
|
const handleLogin = () => {
|
|
if (!email.trim() || !password.trim()) {
|
|
showError('Validation Error', 'Email and password are required.');
|
|
return;
|
|
}
|
|
if (!validateEmail(email)) {
|
|
showError('Validation Error', 'Please enter a valid email address.');
|
|
return;
|
|
}
|
|
|
|
setLoading(true); // Start loading
|
|
dispatch(login({ email, password }));
|
|
|
|
// Simulate a network request for 4 seconds
|
|
setTimeout(() => {
|
|
setLoading(false); // Stop loading after 4 seconds
|
|
}, 4000);
|
|
};
|
|
|
|
return (
|
|
<TouchableWithoutFeedback onPress={Keyboard.dismiss}>
|
|
<View style={styles.container}>
|
|
<Text style={styles.title}>Radiologist Portal</Text>
|
|
|
|
{/* Email Input */}
|
|
<View style={styles.inputContainer}>
|
|
<Icon name="mail" size={20} color={Colors.textSecondary} style={styles.inputIcon} />
|
|
<TextInput
|
|
placeholder="Email"
|
|
value={email}
|
|
onChangeText={setEmail}
|
|
style={styles.inputField}
|
|
autoCapitalize="none"
|
|
keyboardType="email-address"
|
|
placeholderTextColor={Colors.textMuted}
|
|
/>
|
|
</View>
|
|
|
|
{/* Password Input */}
|
|
<View style={styles.inputContainer}>
|
|
<Icon name="lock" size={20} color={Colors.textSecondary} style={styles.inputIcon} />
|
|
<TextInput
|
|
placeholder="Password"
|
|
value={password}
|
|
onChangeText={setPassword}
|
|
style={styles.inputField}
|
|
secureTextEntry={!isPasswordVisible}
|
|
placeholderTextColor={Colors.textMuted}
|
|
/>
|
|
<TouchableOpacity
|
|
onPress={() => setPasswordVisible(!isPasswordVisible)}
|
|
style={styles.eyeIcon}>
|
|
<Icon name={isPasswordVisible ? 'eye-off' : 'eye'} size={22} color={Colors.textSecondary} />
|
|
</TouchableOpacity>
|
|
</View>
|
|
|
|
<Button
|
|
title="Login"
|
|
onPress={handleLogin}
|
|
style={styles.button}
|
|
loading={loading} // Pass loading state to button
|
|
/>
|
|
</View>
|
|
</TouchableWithoutFeedback>
|
|
);
|
|
};
|
|
|
|
const styles = StyleSheet.create({
|
|
container: {
|
|
flex: 1,
|
|
backgroundColor: Colors.background,
|
|
justifyContent: 'center',
|
|
padding: Spacing.lg,
|
|
},
|
|
title: {
|
|
fontFamily: Typography.fontFamily.bold,
|
|
fontSize: Typography.fontSize.title,
|
|
color: Colors.primary,
|
|
marginBottom: Spacing.xl,
|
|
textAlign: 'center',
|
|
},
|
|
inputContainer: {
|
|
flexDirection: 'row',
|
|
alignItems: 'center',
|
|
backgroundColor: Colors.backgroundAlt,
|
|
borderWidth: 1,
|
|
borderColor: Colors.border,
|
|
borderRadius: 8,
|
|
marginBottom: Spacing.md,
|
|
paddingHorizontal: Spacing.md,
|
|
paddingVertical:2
|
|
},
|
|
inputIcon: {
|
|
marginRight: Spacing.sm,
|
|
},
|
|
inputField: {
|
|
flex: 1,
|
|
paddingVertical: Spacing.md,
|
|
fontSize: Typography.fontSize.md,
|
|
color: Colors.textPrimary,
|
|
},
|
|
eyeIcon: {
|
|
paddingLeft: Spacing.sm,
|
|
},
|
|
button: {
|
|
marginTop: Spacing.md,
|
|
},
|
|
});
|
|
|
|
export default LoginScreen;
|
|
|
|
/*
|
|
* End of File: LoginScreen.tsx
|
|
* Design & Developed by Tech4Biz Solutions
|
|
* Copyright (c) Spurrin Innovations. All rights reserved.
|
|
*/
|