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