import React, { useEffect, useState } from "react";
import { View, Text, FlatList, TouchableOpacity, StyleSheet, SafeAreaView, TextInput, PermissionsAndroid, Platform, Alert, NativeModules } from "react-native";
import Icon from "react-native-vector-icons/FontAwesome";
import Contacts from 'react-native-contacts';
import MainLayout from "../components/MainLayout";
const ContactsScreen: React.FC = () => {
const [deviceContacts, setDeviceContacts] = useState<any[]>([]);
const [searchText, setSearchText] = useState<string>("");
const requestContactsPermission = async () => {
if (Platform.OS === 'android') {
const granted = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.READ_CONTACTS,
{
title: 'Contacts Permission',
message: 'This app needs access to your contacts to display them.',
buttonPositive: 'OK',
buttonNegative: 'Cancel',
}
);
if (granted === PermissionsAndroid.RESULTS.GRANTED) {
return true;
} else if (granted === PermissionsAndroid.RESULTS.NEVER_ASK_AGAIN) {
Alert.alert(
'Permission Required',
'Please enable contacts permission from settings to view contacts.',
[{ text: 'OK' }]
);
}
return false;
}
return true;
};
const fetchContacts = async () => {
const hasPermission = await requestContactsPermission();
if (!hasPermission) {
console.warn('Permission denied');
return;
}
try {
const permissionStatus = await Contacts.checkPermission();
console.log('Contacts Permission Status:', permissionStatus);
if (permissionStatus === 'authorized') {
const contacts = await Contacts.getAll();
console.log('Fetched Contacts:', contacts);
const formattedContacts = contacts.map((contact) => ({
id: contact.recordID,
name: contact.displayName || contact.phoneNumbers[0]?.number || 'Unknown',
phone: contact.phoneNumbers[0]?.number || 'N/A',
}));
const sortedContacts = formattedContacts.sort((a, b) => {
const isANumber = !isNaN(Number(a.name.replace(/\s/g, '')));
const isBNumber = !isNaN(Number(b.name.replace(/\s/g, '')));
if (isANumber === isBNumber) {
return a.name.localeCompare(b.name);
}
return isANumber ? 1 : -1; // Push numbers to the bottom
});
setDeviceContacts(sortedContacts);
} else {
Alert.alert('Permission Denied', 'Contacts permission is not authorized.');
}
} catch (error) {
console.error('Failed to fetch contacts:', error);
Alert.alert('Error', 'Failed to fetch contacts');
}
};
const filteredContacts = deviceContacts.filter(
(contact) =>
contact.name.toLowerCase().includes(searchText.toLowerCase()) ||
contact.phone.toLowerCase().includes(searchText.toLowerCase())
);
useEffect(() => {
fetchContacts();
}, []);
const renderContact = ({ item }: { item: typeof deviceContacts[0] }) => (
<View style={styles.card}>
<View style={styles.contactContainer}>
<Icon name="user-circle" size={40} color="#00B4D8" style={styles.icon} />
<View style={styles.textContainer}>
<Text style={styles.name}>{item.name}</Text>
<Text style={styles.phone}>{item.phone}</Text>
</View>
<Icon name="ellipsis-v" size={20} color="#999" style={styles.optionsIcon} />
</View>
</View>
);
return (
<MainLayout>
<SafeAreaView style={styles.safeArea}>
<View style={styles.container}>
<View style={styles.tabsContainer}>
<TouchableOpacity style={[styles.tab, styles.activeTab]}>
<Text style={[styles.tabText, styles.activeTabText]}>All Contacts</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.tab}>
<Text style={styles.tabText}>Office</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.tab}>
<Text style={styles.tabText}>Family</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.newGroupButton}>
<Text style={styles.newGroupText}>+ New Group</Text>
</TouchableOpacity>
</View>
<View style={styles.searchBarContainer}>
<Icon name="search" size={20} color="#999" style={styles.searchIcon} />
<TextInput
placeholder="Search by name or number"
style={styles.searchBar}
value={searchText}
onChangeText={setSearchText}
/>
</View>
<FlatList
data={filteredContacts}
renderItem={renderContact}
keyExtractor={(item) => item.id}
contentContainerStyle={styles.list}
/>
<TouchableOpacity style={styles.addButton}>
<Text style={styles.addButtonText}>Add New Contact</Text>
</TouchableOpacity>
</View>
</SafeAreaView>
</MainLayout>
);
};
// YOUR EXISTING STYLES (UNCHANGED)
const styles = StyleSheet.create({
safeArea: {
flex: 1,
width: '100%',
backgroundColor: "#F0F4F8",
},
container: {
width: '100%',
flex: 1,
backgroundColor: "#F0F4F8",
},
title: {
fontSize: 28,
fontWeight: "bold",
color: "#333",
marginVertical: 20,
},
tabsContainer: {
flexDirection: "row",
marginBottom: 20,
alignItems: "center",
},
tab: {
marginRight: 15,
paddingVertical: 5,
},
activeTab: {
borderBottomWidth: 2,
borderBottomColor: "#1e90ff",
},
tabText: {
fontSize: 16,
color: "#666",
},
activeTabText: {
color: "#1e90ff",
fontWeight: "600",
},
newGroupButton: {
backgroundColor: "#1e90ff",
paddingVertical: 5,
paddingHorizontal: 10,
borderRadius: 12,
},
newGroupText: {
color: "#fff",
fontSize: 14,
fontWeight: "600",
},
searchBarContainer: {
flexDirection: "row",
alignItems: "center",
backgroundColor: "#fff",
borderRadius: 12,
paddingHorizontal: 10,
marginBottom: 20,
shadowColor: "pink",
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.1,
shadowRadius: 4,
elevation: 2,
},
searchIcon: {
marginRight: 10,
},
searchBar: {
flex: 1,
height: 40,
fontSize: 16,
color: "#333",
},
list: {
paddingBottom: 16,
},
card: {
width: '100%',
backgroundColor: "#FFFFFF",
padding: 20,
borderRadius: 16,
marginBottom: 16,
shadowColor: "pink",
shadowOffset: { width: 0, height: 5 },
shadowOpacity: 0.1,
shadowRadius: 6,
elevation: 5,
justifyContent: "center",
},
contactContainer: {
flexDirection: "row",
alignItems: "center",
},
icon: {
marginRight: 15,
},
textContainer: {
flex: 1,
},
name: {
fontSize: 18,
fontWeight: "600",
color: "#E76F51",
},
phone: {
fontSize: 16,
color: "#555",
marginTop: 4,
},
optionsIcon: {
marginLeft: 10,
},
addButton: {
backgroundColor: "#1e90ff",
paddingVertical: 12,
borderRadius: 12,
alignItems: "center",
},
addButtonText: {
color: "#fff",
fontSize: 16,
fontWeight: "600",
},
});
export default ContactsScreen;