import React, { useState, useRef, useEffect } from 'react'; import { View, Text, TextInput, StyleSheet, TouchableOpacity, KeyboardAvoidingView, Platform, Animated, StatusBar, ActivityIndicator, Dimensions, } from 'react-native'; import { LOGIN_URL } from '../utils/ApiUrls'; import axios from 'axios'; import { useNavigation } from '@react-navigation/native'; import type { StackNavigationProp } from '@react-navigation/stack'; import { RootStackParamList } from '../navigation/AppNavigator'; import LinearGradient from 'react-native-linear-gradient'; import Ionicons from '@react-native-vector-icons/ionicons'; import MaterialRipple from 'react-native-material-ripple'; // For the button ripple effect import CustomAlert from '../components/CostomAlart'; import colors from '../components/colors'; const { width } = Dimensions.get('window'); const BLOCK_SIZE = width / 3; // Note: You will need to install react-native-material-ripple // npm install react-native-material-ripple export default function LoginScreen() { const navigation = useNavigation>(); const [mobile, setMobile] = useState(''); const [loading, setLoading] = useState(false); const [alertInfo, setAlertInfo] = useState({ visible: false, title: '', message: '', buttons: [] as { text: string; onPress: () => void; style?: 'cancel' | 'destructive' | 'default' }[], alertType: 'info' as 'info' | 'success' | 'error', }); const fade = useRef(new Animated.Value(0)).current; const slide = useRef(new Animated.Value(30)).current; const ctaScale = useRef(new Animated.Value(1)).current; useEffect(() => { Animated.parallel([ Animated.timing(fade, { toValue: 1, duration: 800, useNativeDriver: true }), Animated.spring(slide, { toValue: 0, friction: 5, tension: 40, useNativeDriver: true }), ]).start(); }, []); const showAlert = ( title: string, message: string, buttons: { text: string; onPress: () => void; style?: 'cancel' | 'destructive' | 'default' }[], alertType: 'info' | 'success' | 'error' = 'info', ) => { setAlertInfo({ visible: true, title, message, buttons, alertType }); }; const hideAlert = () => { setAlertInfo({ ...alertInfo, visible: false }); }; const handleContinue = async () => { if (mobile.length === 10) { setLoading(true); try { const res = await axios.get(LOGIN_URL, { params: { mobile } }); if (res.data.statusCode === 200) { navigation.navigate('OtpVarify', { mobile }); } else { showAlert('Login Failed', res.data.message || 'Could not send OTP.', [{ text: 'Try Again', onPress: hideAlert }], 'error'); } } catch (error: any) { showAlert('An Error Occurred', 'Failed to send OTP. Please check your connection and try again.', [{ text: 'OK', onPress: hideAlert }], 'error'); } finally { setLoading(false); } } else { showAlert('Invalid Number', 'Please enter a valid 10-digit mobile number.', [{ text: 'Got it', onPress: hideAlert }], 'info'); } }; const colorsBlocks = [ colors.pastelPink, colors.pastelBlue, colors.pastelGreen, colors.pastelOrange, colors.pastelBlue, colors.pastelPink, colors.pastelGreen, colors.pastelOrange, colors.pastelPink, ]; return ( {/* Funky grid blocks background (Unchanged) */} {colorsBlocks.map((bgColor, index) => ( ))} CircleCollect Welcome Back! Let's get you signed in to your community. {loading ? ( ) : ( Continue )} Your privacy is our priority. Your information is always secure. ); } const styles = StyleSheet.create({ container: { flex: 1, }, gridContainer: { ...StyleSheet.absoluteFillObject, flexDirection: 'row', flexWrap: 'wrap', }, gridBlock: { width: BLOCK_SIZE, height: BLOCK_SIZE, margin: 2, borderRadius: 16, }, elevatedBlock: { shadowColor: '#000', shadowOffset: { width: 0, height: 5 }, shadowOpacity: 0.15, shadowRadius: 10, elevation: 7, }, keyboardAvoidingContainer: { flex: 1, }, contentContainer: { flex: 1, justifyContent: 'space-between', padding: 24, }, topSection: { flex: 0.8, justifyContent: 'center', alignItems: 'center', }, brand: { fontSize: 28, fontWeight: '700', color: colors.primary, textAlign: 'center', letterSpacing: 2, marginBottom: 16, textShadowColor: 'rgba(0, 0, 0, 0.1)', textShadowOffset: { width: 1, height: 1 }, textShadowRadius: 2, }, title: { fontSize: 40, fontWeight: 'bold', color: colors.textDark, textAlign: 'center', marginBottom: 14, }, subtitle: { fontSize: 16, color: colors.textDark, textAlign: 'center', lineHeight: 26, maxWidth: 320, }, inputWrapper: { flexDirection: 'row', alignItems: 'center', backgroundColor: 'rgba(255, 255, 255, 0.85)', borderRadius: 36, borderWidth: 2, borderColor: colors.pastelPink, paddingHorizontal: 20, shadowColor: colors.primary, shadowOffset: { width: 0, height: 6 }, shadowOpacity: 0.2, shadowRadius: 14, elevation: 8, }, inputIcon: { marginRight: 16, }, input: { flex: 1, fontSize: 18, fontWeight: '600', color: colors.textLight, height: 58, }, bottomSection: { alignItems: 'center', paddingBottom: Platform.OS === 'ios' ? 20 : 10, }, button: { width: '100%', borderRadius: 30, shadowColor: colors.primary, shadowOffset: { width: 0, height: 10 }, shadowOpacity: 0.4, shadowRadius: 20, elevation: 14, marginTop: 20, }, buttonGradient: { borderRadius: 30, paddingVertical: 18, flexDirection: 'row', justifyContent: 'center', alignItems: 'center', }, buttonContent: { flexDirection: 'row', alignItems: 'center', }, buttonText: { color: colors.white, fontWeight: '800', fontSize: 18, }, footerText: { fontSize: 14, color: 'rgba(0,0,0,0.5)', marginTop: 28, textAlign: 'center', maxWidth: 300, }, });