import React, { useState, useEffect, useCallback } from "react"; import { StyleSheet, View, Text, ScrollView, Image, TouchableOpacity, Alert, ActivityIndicator, StatusBar, TextInput, KeyboardAvoidingView, Platform, RefreshControl, } from "react-native"; import * as Keychain from "react-native-keychain"; import { Ionicons } from "@react-native-vector-icons/ionicons"; import { launchImageLibrary } from "react-native-image-picker"; import { CustomButton, CustomInput } from "../../components/common/Custom"; import colors from "../../components/colors"; import SwitchNavigator from "./SwitchNavigator"; import { useFocusEffect, useNavigation } from "@react-navigation/native"; import { ApiResponse } from "../home/UserProfileStatus"; import { BASE_URL, PUT_USER_PROFILE, PUT_USER_PROFILE_IMG, PUT_USER_STATUS } from "../../utils/ApiUrls"; import AppView from "../../components/AppView"; import { useDispatch } from "react-redux"; import { clearUser, setUserData } from "../../redux/userSlice"; import { StackNavigationProp } from "@react-navigation/stack"; import { RootStackParamList } from "../../navigation/AppNavigator"; import { firebase } from "@react-native-firebase/messaging"; import FirebaseService from "../../utils/firebase/firebaseServices"; type UserProfile = { id: string; userId: number; firstName: string | null; lastName: string | null; mobile: string | null; gender: string | null; email: string | null; username: string | null; address: string | null; bankName: string | null; branchCode: string | null; filePath: string | null; bankAccountNumber: string | null; imageBlob: string | null; organizerStatus?: string; role?: string; }; const Profile = () => { const navigation = useNavigation>(); const dispatch = useDispatch() const [user, setUser] = useState(null); const [fetching, setFetching] = useState(true); const [editing, setEditing] = useState(false); const [imageUpdating, setImageUpdating] = useState(false); const [loading, setLoading] = useState(false); const [statusData, setStatusData] = useState(null); const [error, setError] = useState(null); const [refreshing, setRefreshing] = useState(false); const fetchUserProfile = async () => { try { const credentials = await Keychain.getGenericPassword(); if (!credentials) { Alert.alert("Error", "You are not logged in"); return; } const token = credentials.password; setFetching(true); const response = await fetch( `${BASE_URL}user/profile/view`, { method: "GET", headers: { Accept: "*/*", Authorization: `Bearer ${token}`, }, } ); const result = await response.json(); console.log("👤 Profile Response:", result); if (result.status === "success") { setUser(result.data); dispatch(setUserData({ id: result?.data.id, userId: result?.data.userId, username: result?.data.username, firstName: result?.data.firstName, lastName: result?.data.lastName, gender: result?.data.gender, mobile: result?.data.mobile, email: result?.data.email, address: result?.data.address, bankAccountNumber: result?.data.bankAccountNumber, bankName: result?.data.bankName, branchCode: result?.data.branchCode, profilePicture: result?.data.filePath, // or keep as `filePath` filePath: result?.data.filePath, imageBlob: result?.data.imageBlob, role: result?.data.role, organizerId: result?.data.organizerId, organizerStatus: result?.data.organizerStatus, profileStatus: true, // set true once profile is fetched })); } else { Alert.alert("Error", "Failed to fetch user profile"); } } catch (error) { console.error("❌ Error fetching profile:", error); // Alert.alert("Error", "Could not connect to server"); } finally { setFetching(false); } }; const updateProfile = async () => { try { const credentials = await Keychain.getGenericPassword(); if (!credentials) { Alert.alert("Error", "You are not logged in"); return; } const token = credentials.password; const response = await fetch( PUT_USER_PROFILE, { method: "PUT", headers: { Accept: "*/*", "Content-Type": "application/json", Authorization: `Bearer ${token}`, }, body: JSON.stringify({ address: user?.address || null, email: user?.email || null, firstName: user?.firstName || null, gender: user?.gender || null, lastName: user?.lastName || null, username: user?.username || null, }), } ); const result = await response.json(); if (result.status === "success") { Alert.alert("Success", "Profile updated successfully"); setEditing(false); fetchUserProfile(); // reload updated data } else { Alert.alert("Error", "Failed to update profile"); } } catch (error) { console.error("❌ Error updating profile:", error); // Alert.alert("Error", "Could not update profile"); } }; const pickImage = () => { launchImageLibrary({ mediaType: "photo", quality: 0.5 }, (response) => { if (response.didCancel) return; if (response.errorCode) { Alert.alert("Error", response.errorMessage || "Something went wrong"); } else if (response.assets && response.assets.length > 0) { const selectedImage = response.assets[0]; setUser((prev: any) => prev ? { ...prev, filePath: selectedImage.uri ?? null } : prev ); } }); }; const handleUpdateImage = async () => { try { const credentials = await Keychain.getGenericPassword(); if (!credentials) { Alert.alert("Error", "You are not logged in"); return; } const token = credentials.password; if (!user?.filePath) { Alert.alert("Error", "Please select an image first"); return; } setImageUpdating(true); const formData = new FormData(); formData.append("file", { uri: user?.filePath, type: "image/jpeg", name: "profile.jpg", } as any); const response = await fetch( PUT_USER_PROFILE_IMG, { method: "PUT", headers: { Accept: "application/json", Authorization: `Bearer ${token}`, }, body: formData, } ); const result = await response.json(); if (result.status === "success") { Alert.alert("Success", "Profile image updated successfully"); // If API returns updated image, set it if (result.data?.imageBlob) { setUser((prev: any) => prev ? { ...prev, imageBlob: result.data.imageBlob, filePath: null } : prev); } else { // Otherwise, keep the local filePath until next fetch setUser((prev: any) => prev ? { ...prev, filePath: user?.filePath } : prev); } // Refresh profile from API as well fetchUserProfile(); } else { Alert.alert("Error", result.message || "Failed to update profile image"); } } catch (error) { console.error("❌ Error updating profile image:", error); // Alert.alert("Error", "Could not update profile image"); } finally { setImageUpdating(false); } }; const userStatus = async () => { try { const credentials = await Keychain.getGenericPassword(); if (!credentials) { Alert.alert("Error", "You are not logged in"); return; } const token = credentials.password; setLoading(true); setError(null); const response = await fetch(PUT_USER_STATUS, { method: "GET", headers: { Accept: "*/*", Authorization: `Bearer ${token}`, }, }); const json: ApiResponse = await response.json(); console.log("👤 Profile Status Response:", json); if (json.status === "success") { setStatusData(json.data); console.log("statusData response :", json); } else { setError(json.message || "Failed to fetch status"); } } catch (err) { setError("Something went wrong. Please try again."); } finally { setLoading(false); } }; const logout = async (navigation: any) => { try { const credentials = await Keychain.getGenericPassword(); if (!credentials) { Alert.alert("Info", "No user is currently logged in"); return; } await FirebaseService.deleteFcmToken(); // Clear stored credentials await Keychain.resetGenericPassword(); dispatch(clearUser()) Alert.alert("Success", "You have been logged out"); navigation.replace("Login"); } catch (error) { console.error("Logout error:", error); // Alert.alert("Error", "Failed to log out. Please try again."); } }; const confirmLogout = (navigation: any) => { Alert.alert( "Logout", "Are you sure you want to log out?", [ { text: "Cancel", style: "cancel" }, { text: "Yes, Logout", style: "destructive", onPress: () => logout(navigation) }, ] ); }; console.log("statusData?.role :", statusData?.role); console.log("statusData?.organizerStatus :", statusData?.organizerStatus); useFocusEffect( useCallback(() => { userStatus(); }, []) ); useEffect(() => { userStatus(); fetchUserProfile(); }, []); const onRefresh = () => { setRefreshing(true); // Simulate a network request or data fetching fetchUserProfile() setTimeout(() => { setRefreshing(false); }, 2000); // 2 seconds delay }; console.log("user image :", user?.filePath); const getProfileImage = () => { if (user?.imageBlob) { return `data:image/jpeg;base64,${user?.imageBlob}`; } if (user?.filePath) { return user?.filePath; } return "https://randomuser?.me/api/portraits/men/1.jpg"; }; return ( {/* Header */} User Profile confirmLogout(navigation)} style={styles.refreshButton}> {/* if (fetching || !user) { return ( */} {fetching || !user && Loading profile... } } > {/* Profile Card */} {/* Profile Image Section */} { statusData?.role === "USER" && statusData?.organizerStatus !== "NOT_APPLIED" ? ( Your Role: {statusData.role} | Organizer Status: {statusData.organizerStatus} ) : ( statusData?.role !== "ORGANIZER" && ( ) ) } console.log("Error loading image")} /> {!editing ? ( <> {/* Profile Details */} Personal Information Become Organizer {/* */} navigation.navigate('Transaction')}> View Transaction setEditing(true)} icon="create" style={styles.editButton} buttonBackground={colors.white} /> Name {user?.firstName} {user?.lastName} Email {user?.email || "Not provided"} Mobile {user?.mobile || "Not provided"} Usernames {user?.username} Address {user?.address || "Not provided"} Gender {user?.gender || "Not specified"} Role {user?.role || "User"} {/* BANK DETAILS SECTION */} Bank Information {/* Navigate to a screen you will create for editing bank details */} { navigation.navigate("EditBankDetails", { currentBankName: user?.bankName, currentAccountNumber: user?.bankAccountNumber, currentBranchCode: user?.branchCode, })}} icon="create-outline" style={styles.editButton} buttonBackground={colors.white} /> Bank Name {user?.bankName || "Not provided"} Branch Code {user?.branchCode || "Not provided"} Account Number {user?.bankAccountNumber || "Not provided"} ) : ( <> {/* Edit Form */} Edit Profile setUser({ ...user, firstName: text })} icon="person" /> setUser({ ...user, lastName: text })} icon="person" /> setUser({ ...user, email: text })} icon="mail" keyboardType="email-address" /> setUser({ ...user, username: text })} icon="at" /> setUser({ ...user, address: text })} icon="location" multiline /> setUser({ ...user, gender: text })} icon="male-female" /> setEditing(false)} icon="close" style={styles.cancelButton} buttonBackground={colors.white} /> )} ); }; const styles = StyleSheet.create({ container: { flex: 1, // backgroundColor: colors.pastelBlue, paddingBottom: '30%', }, loadingContainer: { flex: 1, justifyContent: "center", alignItems: "center", backgroundColor: "#f8fafc" }, loadingText: { marginTop: 10, fontSize: 16, color: "#64748b" }, header: { flexDirection: "row", justifyContent: "space-between", alignItems: "center", padding: 16, borderBottomLeftRadius: 20, borderBottomRightRadius: 20, }, headerTitle: { fontSize: 22, fontWeight: "600", color: colors.primary }, refreshButton: { padding: 4, }, profileCard: { borderRadius: 20, margin: 16, // backgroundColor: "#fff", // padding: 20, // shadowColor: "#000", // shadowOpacity: 0.1, // shadowRadius: 10, // shadowOffset: { width: 0, height: 4 }, // elevation: 5, }, profileImageSection: { alignItems: "center", marginBottom: 24, paddingBottom: 20, borderBottomWidth: 1, borderBottomColor: "#f1f5f9", }, avatarContainer: { position: "relative", marginBottom: 16, }, avatar: { width: 120, height: 120, borderRadius: 60, borderWidth: 4, borderColor: "#e2e8f0", }, cameraIcon: { position: "absolute", right: 0, bottom: 0, backgroundColor: colors.pastelBlue, borderRadius: 20, width: 40, height: 40, justifyContent: "center", alignItems: "center", borderWidth: 3, borderColor: "#fff", elevation: 2, }, updateImageButton: { width: "80%", paddingHorizontal: 10, borderRadius: 25, elevation: 5, }, detailsSection: { marginBottom: "40%", }, sectionTitle: { fontSize: 18, fontWeight: "700", color: "#1e293b", // marginBottom: 16, paddingBottom: 8, borderBottomWidth: 1, borderBottomColor: "#f1f5f9", }, detailRow: { flexDirection: "row", alignItems: "center", marginBottom: 16, paddingHorizontal: 12, }, detailIcon: { marginRight: 20, elevation:5 }, detailLabel: { fontSize: 12, color: "#64748b", marginBottom: 2, }, detailText: { fontSize: 16, color: "#334155", fontWeight: "500", }, editButton: { elevation:5, paddingHorizontal: 10, paddingVertical:4, borderRadius: 15, borderWidth:2, borderColor:colors.pastelBlue }, editSection: { marginBottom: '100%', flex: 1, }, editButtons: { gap: 12, }, saveButton: { marginTop: 8, }, cancelButton: { marginTop: 4, borderWidth: 1, borderColor: "#cbd5e1", }, inputContainer: { marginBottom: 16, }, inputLabel: { fontSize: 14, fontWeight: "600", color: "#374151", marginBottom: 6, }, inputWrapper: { flexDirection: "row", alignItems: "center", position: "relative", }, inputIcon: { position: "absolute", left: 12, zIndex: 1, }, input: { borderWidth: 1, borderColor: "#d1d5db", borderRadius: 12, padding: 12, backgroundColor: "#fff", color: "#1f2937", fontSize: 16, flex: 1, }, inputWithIcon: { paddingLeft: 40, }, buttonSecondary: { backgroundColor: "#f1f5f9", }, buttonDanger: { backgroundColor: "#ef4444", }, buttonOutline: { backgroundColor: "transparent", borderWidth: 1, borderColor: "#6366f1", }, buttonText: { color: "#fff", fontSize: 16, fontWeight: "600", }, buttonTextSecondary: { color: "#334155", }, buttonTextDanger: { color: "#fff", }, buttonTextOutline: { color: "#6366f1", }, buttonIcon: { marginRight: 8, }, }); export default Profile;