added fetch contact from real device icon

This commit is contained in:
Jaanu423
2025-09-19 13:22:30 +05:30
parent 3b1dc58405
commit 660d14260a
4 changed files with 281 additions and 225 deletions
+1 -1
View File
@@ -105,7 +105,7 @@ export default function OtpVerificationScreen() {
{ headers: { "Content-Type": "application/json", Accept: "*/*" } } { headers: { "Content-Type": "application/json", Accept: "*/*" } }
); );
console.log("📩 OTP Resent:", res.data); console.log("📩 OTP Resent:", res);
setCode(Array(CELL_COUNT).fill("")); setCode(Array(CELL_COUNT).fill(""));
inputs.current[0]?.focus(); inputs.current[0]?.focus();
ToastAndroid.show("OTP Sent", ToastAndroid.SHORT); ToastAndroid.show("OTP Sent", ToastAndroid.SHORT);
+250 -205
View File
@@ -1,229 +1,274 @@
import React, { useState, useEffect } from "react"; import React, { useState, useEffect } from "react";
import { import {
StyleSheet, StyleSheet,
Text, Text,
View, View,
FlatList, FlatList,
TouchableOpacity, TouchableOpacity,
Modal, Modal,
PermissionsAndroid, PermissionsAndroid,
Platform, Platform,
NativeModules, NativeModules,
Linking,
Alert,
} from "react-native"; } from "react-native";
import AppView from "../../components/AppView";
const { ContactsModule } = NativeModules; const { ContactsModule } = NativeModules;
const APP_URL = "https://play.google.com/store/apps/details?id=com.yourapp"; // replace with your real app url
const YourContacts = () => { const YourContacts = () => {
const [contacts, setContacts] = useState<any[]>([]); const [contacts, setContacts] = useState<any[]>([]);
const [selectedContact, setSelectedContact] = useState<any>(null); const [selectedContact, setSelectedContact] = useState<any>(null);
const [modalVisible, setModalVisible] = useState(false); const [modalVisible, setModalVisible] = useState(false);
useEffect(() => { useEffect(() => {
handleFetchContacts(); handleFetchContacts();
}, []); }, []);
const handleFetchContacts = async () => { const handleFetchContacts = async () => {
try { try {
if (Platform.OS === "android") { if (Platform.OS === "android") {
const granted = await PermissionsAndroid.request( const granted = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.READ_CONTACTS, PermissionsAndroid.PERMISSIONS.READ_CONTACTS,
{ {
title: "Contacts Permission", title: "Contacts Permission",
message: "This app would like to view your contacts.", message: "This app would like to view your contacts.",
buttonPositive: "OK", buttonPositive: "OK",
} }
); );
if (granted !== PermissionsAndroid.RESULTS.GRANTED) { if (granted !== PermissionsAndroid.RESULTS.GRANTED) {
console.log("Contacts permission denied"); console.log("Contacts permission denied");
return; return;
}
}
const fetchedContacts = await ContactsModule.getContacts();
setContacts(fetchedContacts);
} catch (error) {
console.error("Error fetching contacts:", error);
} }
} };
const fetchedContacts = await ContactsModule.getContacts(); const APP_URL = "https://play.google.com/store/apps/details?id=com.yourapp"; // your app link
setContacts(fetchedContacts); const WHATSAPP_URL = "https://play.google.com/store/apps/details?id=com.whatsapp"; // fallback store link
} catch (error) {
console.error("Error fetching contacts:", error);
}
};
const handleSend = (contact: any) => { const handleSend = async (contact: any) => {
setSelectedContact(contact); if (!contact) return;
setModalVisible(true);
};
const renderContact = ({ item }: { item: any }) => ( const message = `Hey ${contact.name}, check out this awesome app! Download here: ${APP_URL}`;
<View style={styles.contactRow}>
<View style={styles.avatar}>
<Text style={styles.avatarText}>
{item.name ? item.name.charAt(0).toUpperCase() : "?"}
</Text>
</View>
<View style={styles.contactInfo}>
<Text style={styles.contactName}>{item.name}</Text>
<Text style={styles.contactPhone}>{item.phone}</Text>
</View>
<TouchableOpacity
style={styles.inviteButton}
onPress={() => handleSend(item)}
>
<Text style={styles.inviteText}>Invite</Text>
</TouchableOpacity>
</View>
);
return ( // direct send to contact if you want
<View style={styles.container}> const url = `whatsapp://send?phone=${contact.phone}&text=${encodeURIComponent(
<Text style={styles.header}>Select Contact</Text> message
<FlatList )}`;
data={contacts}
keyExtractor={(item, index) => index.toString()}
renderItem={renderContact}
/>
{/* Send Modal */} try {
<Modal const supported = await Linking.canOpenURL("whatsapp://send");
transparent={true} if (supported) {
visible={modalVisible} // WhatsApp installed
animationType="slide" await Linking.openURL(url);
onRequestClose={() => setModalVisible(false)} } else {
> // WhatsApp not installed → send user to Play Store/App Store
<View style={styles.modalOverlay}> if (Platform.OS === "android") {
<View style={styles.modalContent}> await Linking.openURL(WHATSAPP_URL);
<Text style={styles.modalTitle}>Send Invite</Text> } else if (Platform.OS === "ios") {
{selectedContact && ( await Linking.openURL("itms-apps://apps.apple.com/app/whatsapp-messenger/id310633997");
<Text style={styles.modalText}> }
Send invite to {selectedContact.name} ({selectedContact.phone})? }
</Text> } catch (err) {
)} console.error("Error sending to WhatsApp:", err);
<View style={styles.modalActions}> Alert.alert("Error", "Something went wrong while trying to open WhatsApp");
<TouchableOpacity }
style={styles.cancelButton}
onPress={() => setModalVisible(false)} setModalVisible(false);
> };
<Text style={styles.cancelText}>Cancel</Text>
</TouchableOpacity>
<TouchableOpacity const renderContact = ({ item }: { item: any }) => (
style={styles.sendButton} <View style={styles.contactRow}>
onPress={() => setModalVisible(false)} <View style={styles.avatar}>
> <Text style={styles.avatarText}>
<Text style={styles.sendText}>Send</Text> {item.name ? item.name.charAt(0).toUpperCase() : "?"}
</TouchableOpacity> </Text>
</View> </View>
</View> <View style={styles.contactInfo}>
<Text style={styles.contactName}>{item.name}</Text>
<Text style={styles.contactPhone}>{item.phone}</Text>
</View>
<TouchableOpacity
style={styles.inviteButton}
onPress={() => {
setSelectedContact(item);
setModalVisible(true);
}}
>
<Text style={styles.inviteText}>Invite</Text>
</TouchableOpacity>
</View> </View>
</Modal> );
</View>
); return (
<AppView>
<View>
<Text style={styles.header}>Select Contact</Text>
</View>
<FlatList
data={contacts}
keyExtractor={(item, index) => index.toString()}
renderItem={renderContact}
/>
{/* Send Modal */}
<Modal
transparent={true}
visible={modalVisible}
animationType="slide"
onRequestClose={() => setModalVisible(false)}
>
<View style={styles.modalOverlay}>
<View style={styles.modalContent}>
<Text style={styles.modalTitle}>Send Invite</Text>
{selectedContact && (
<Text style={styles.modalText}>
Send invite to {selectedContact.name} ({selectedContact.phone})
</Text>
)}
<View style={styles.modalActions}>
<TouchableOpacity
style={styles.cancelButton}
onPress={() => setModalVisible(false)}
>
<Text style={styles.cancelText}>Cancel</Text>
</TouchableOpacity>
<TouchableOpacity
style={styles.sendButton}
onPress={() => handleSend(selectedContact)}
>
<Text style={styles.sendText}>Send</Text>
</TouchableOpacity>
</View>
</View>
</View>
</Modal>
</AppView>
);
}; };
export default YourContacts; export default YourContacts;
const styles = StyleSheet.create({ const styles = StyleSheet.create({
container: { container: {
flex: 1, flex: 1,
backgroundColor: "#fff", backgroundColor: "#fff",
paddingHorizontal: 10, paddingHorizontal: 10,
paddingTop: 20, paddingTop: 20,
}, },
header: { header: {
fontSize: 20, fontSize: 20,
fontWeight: "bold", fontWeight: "bold",
marginBottom: 15, marginBottom: 15,
}, },
contactRow: { contactRow: {
flexDirection: "row", flexDirection: "row",
alignItems: "center", alignItems: "center",
paddingVertical: 12, paddingVertical: 12,
borderBottomWidth: 0.5, borderBottomWidth: 0.5,
borderBottomColor: "#ddd", borderBottomColor: "#ddd",
}, },
avatar: { avatar: {
width: 45, width: 45,
height: 45, height: 45,
borderRadius: 25, borderRadius: 25,
backgroundColor: "#25D366", backgroundColor: "#25D366",
justifyContent: "center", justifyContent: "center",
alignItems: "center", alignItems: "center",
marginRight: 12, marginRight: 12,
}, },
avatarText: { avatarText: {
color: "#fff", color: "#fff",
fontSize: 18, fontSize: 18,
fontWeight: "bold", fontWeight: "bold",
}, },
contactInfo: { contactInfo: {
flex: 1, flex: 1,
}, },
contactName: { contactName: {
fontSize: 16, fontSize: 16,
fontWeight: "600", fontWeight: "600",
}, },
contactPhone: { contactPhone: {
fontSize: 13, fontSize: 13,
color: "gray", color: "gray",
}, },
inviteButton: { inviteButton: {
paddingHorizontal: 14, paddingHorizontal: 14,
paddingVertical: 6, paddingVertical: 6,
borderRadius: 8, borderRadius: 8,
borderWidth: 1, borderWidth: 1,
borderColor: "#25D366", borderColor: "#25D366",
}, },
inviteText: { inviteText: {
color: "#25D366", color: "#25D366",
fontWeight: "bold", fontWeight: "bold",
}, },
modalOverlay: { modalOverlay: {
flex: 1, flex: 1,
backgroundColor: "rgba(0,0,0,0.5)", backgroundColor: "rgba(0,0,0,0.5)",
justifyContent: "center", justifyContent: "center",
alignItems: "center", alignItems: "center",
}, },
modalContent: { modalContent: {
width: "80%", width: "80%",
backgroundColor: "#fff", backgroundColor: "#fff",
borderRadius: 10, borderRadius: 10,
padding: 20, padding: 20,
alignItems: "center", alignItems: "center",
}, },
modalTitle: { modalTitle: {
fontSize: 18, fontSize: 18,
fontWeight: "bold", fontWeight: "bold",
marginBottom: 10, marginBottom: 10,
}, },
modalText: { modalText: {
fontSize: 15, fontSize: 15,
marginBottom: 20, marginBottom: 20,
textAlign: "center", textAlign: "center",
}, },
modalActions: { modalActions: {
flexDirection: "row", flexDirection: "row",
justifyContent: "space-between", justifyContent: "space-between",
width: "100%", width: "100%",
}, },
cancelButton: { cancelButton: {
flex: 1, flex: 1,
marginRight: 10, marginRight: 10,
paddingVertical: 10, paddingVertical: 10,
borderRadius: 8, borderRadius: 8,
backgroundColor: "#ddd", backgroundColor: "#ddd",
alignItems: "center", alignItems: "center",
}, },
cancelText: { cancelText: {
fontWeight: "bold", fontWeight: "bold",
color: "#333", color: "#333",
}, },
sendButton: { sendButton: {
flex: 1, flex: 1,
marginLeft: 10, marginLeft: 10,
paddingVertical: 10, paddingVertical: 10,
borderRadius: 8, borderRadius: 8,
backgroundColor: "#25D366", backgroundColor: "#25D366",
alignItems: "center", alignItems: "center",
}, },
sendText: { sendText: {
fontWeight: "bold", fontWeight: "bold",
color: "#fff", color: "#fff",
}, },
}); });
+22 -5
View File
@@ -332,11 +332,28 @@ const Profile = () => {
{/* Profile Card */} {/* Profile Card */}
<View style={styles.profileCard}> <View style={styles.profileCard}>
{/* Profile Image Section */} {/* Profile Image Section */}
{ {
statusData?.role && statusData?.organizerStatus ? statusData?.role === "USER" && statusData?.organizerStatus !== "NOT_APPLIED" ? (
<Text style={{ color: "#64748b", marginBottom: 16, textAlign: 'center', fontSize: 18 }}>Your Role: {statusData.role} | Organizer Status: {statusData.organizerStatus}</Text> <Text
: style={{
<SwitchNavigator role={statusData?.role || ''} status={statusData?.organizerStatus || ''} />} color: "#64748b",
marginBottom: 16,
textAlign: "center",
fontSize: 18,
}}
>
Your Role: {statusData.role} | Organizer Status: {statusData.organizerStatus}
</Text>
) : (
statusData?.role !== "ORGANIZER" && (
<SwitchNavigator
role={statusData?.role || ""}
status={statusData?.organizerStatus || ""}
/>
)
)
}
<View style={styles.profileImageSection}> <View style={styles.profileImageSection}>
<View style={styles.avatarContainer}> <View style={styles.avatarContainer}>
<Image <Image
+7 -13
View File
@@ -2,7 +2,6 @@ import React, { useState } from "react";
import { View, Text, StyleSheet, Switch } from "react-native"; import { View, Text, StyleSheet, Switch } from "react-native";
import { useNavigation } from "@react-navigation/native"; import { useNavigation } from "@react-navigation/native";
import type { NativeStackNavigationProp } from "@react-navigation/native-stack"; import type { NativeStackNavigationProp } from "@react-navigation/native-stack";
import colors from "../../components/colors";
type RootStackParamList = { type RootStackParamList = {
BecomeOrg: undefined; BecomeOrg: undefined;
@@ -25,10 +24,6 @@ const SwitchNavigator: React.FC<SwitchNavigatorProps> = ({ role, status }) => {
if (newValue) { if (newValue) {
navigation.navigate("BecomeOrg"); // Navigate when ON navigation.navigate("BecomeOrg"); // Navigate when ON
setTimeout(() => {
setIsEnabled(false);
}, 2000);
// Reset switch to OFF after navigation
} else { } else {
navigation.navigate("Profile"); // Navigate when OFF navigation.navigate("Profile"); // Navigate when OFF
} }
@@ -44,14 +39,13 @@ const SwitchNavigator: React.FC<SwitchNavigatorProps> = ({ role, status }) => {
? "Become an Organizer" ? "Become an Organizer"
: `Request Organizer Role ${status}`} : `Request Organizer Role ${status}`}
</Text> </Text>
{role !== "USER" ? ( <Switch
<Switch trackColor={{ false: "#767577", true: "#81b0ff" }}
trackColor={{ false: "#767577", true: colors.textLight }} thumbColor={isEnabled ? "#007AFF" : "#f4f3f4"}
thumbColor={isEnabled ? colors.pastelBlue : "#f4f3f4"} ios_backgroundColor="#3e3e3e"
ios_backgroundColor="#3e3e3e" onValueChange={toggleSwitch}
onValueChange={toggleSwitch} value={isEnabled}
value={isEnabled} />
/>) : <View> <Text> </Text></View>}
</View> </View>
); );
}; };