diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index 2461564..4ae8bc2 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -19,7 +19,7 @@
android:launchMode="singleTask"
android:windowSoftInputMode="adjustResize"
android:exported="true">
-
+
@@ -27,9 +27,11 @@
-
+
+
+
diff --git a/src/navigation/AppNavigator.tsx b/src/navigation/AppNavigator.tsx
index d7655da..25d7039 100644
--- a/src/navigation/AppNavigator.tsx
+++ b/src/navigation/AppNavigator.tsx
@@ -14,6 +14,7 @@ import YourContacts from "../screens/management/YourContacts";
import Transaction from "../screens/profile/Transaction";
import GroupDetails from "../screens/home/user-home/GroupDetails";
import EditGroupScreen from "../screens/management/EditGroupScreen";
+import EditBankDetails from "../screens/profile/EditBankDetails";
export type RootStackParamList = {
Splash: undefined;
@@ -30,16 +31,20 @@ export type RootStackParamList = {
BecomeOrg: undefined;
YourContacts: undefined;
Transaction: undefined;
+ EditBankDetails: { currentBankName: string | null; currentAccountNumber: string | null; currentBranchCode: string | null };
};
const Stack = createNativeStackNavigator();
export default function AppNavigator() {
const linking = {
- prefixes: ["myapp://", "https://api.godemo.in"],
+ prefixes: [
+ "myapp://", // A custom scheme for internal or test links.
+ "https://192.168.1.19" // Your production domain for verified App Links.
+ ],
config: {
screens: {
- Profile: "EProcurementSB",
+ Profile: "invite",
},
},
};
@@ -60,6 +65,7 @@ export default function AppNavigator() {
+
);
diff --git a/src/screens/SplashScreen.tsx b/src/screens/SplashScreen.tsx
index cde9f53..8d9f920 100644
--- a/src/screens/SplashScreen.tsx
+++ b/src/screens/SplashScreen.tsx
@@ -1,20 +1,21 @@
import React, { useEffect, useRef } from "react";
import { View, Text, StyleSheet, ActivityIndicator, Animated, Alert, ToastAndroid } from "react-native";
import * as Keychain from "react-native-keychain";
-import { StackNavigationProp } from "@react-navigation/stack";
import { useNavigation } from "@react-navigation/native";
import { RootStackParamList } from "../navigation/AppNavigator";
import { PROFILE_URL } from "../utils/ApiUrls";
import { useDispatch } from "react-redux";
import { clearUser, setUserData } from "../redux/userSlice";
import colors from "../components/colors";
+import { StackNavigationProp } from "@react-navigation/stack";
const SplashScreen = () => {
const navigation = useNavigation>();
- const fadeAnim = useRef(new Animated.Value(1)).current;
const dispatch = useDispatch();
+ const fadeAnim = useRef(new Animated.Value(1)).current;
+
const fetchUserProfile = async (dispatch: any, navigation: any) => {
try {
diff --git a/src/screens/home/RequestList.tsx b/src/screens/home/RequestList.tsx
index 4dba2b6..6668595 100644
--- a/src/screens/home/RequestList.tsx
+++ b/src/screens/home/RequestList.tsx
@@ -58,7 +58,7 @@ const RequestList: React.FC = () => {
setError(null);
const response = await fetch(
- "https://api.godemo.in/FundCollect/api/fund/group/pending/request",
+ "https://exotic-humpback-mistakenly.ngrok-free.app/api/fund/group/pending/request",
{
method: "GET",
headers: {
@@ -124,7 +124,7 @@ const RequestList: React.FC = () => {
// Make API call to approve the request
const response = await fetch(
- `https://api.godemo.in/FundCollect/api/fund/requests/${requestId}/approve`,
+ `https://exotic-humpback-mistakenly.ngrok-free.app/api/fund/requests/${requestId}/approve`,
{
method: "PUT",
headers: {
@@ -170,7 +170,7 @@ const RequestList: React.FC = () => {
// Make API call to decline the request
const response = await fetch(
- `https://api.godemo.in/FundCollect/api/fund/requests/${requestedId}/reject?reason=/${reason}`,
+ `https://exotic-humpback-mistakenly.ngrok-free.app/api/fund/requests/${requestedId}/reject?reason=/${reason}`,
{
method: "PUT",
headers: {
diff --git a/src/screens/management/EditGroupScreen.tsx b/src/screens/management/EditGroupScreen.tsx
index 1478ab9..1b7fd02 100644
--- a/src/screens/management/EditGroupScreen.tsx
+++ b/src/screens/management/EditGroupScreen.tsx
@@ -85,7 +85,7 @@ const EditGroupScreen: React.FC = ({ route }) => {
setLoading(true);
setError(null);
try {
- const response = await apiCall(`https://api.godemo.in/FundCollect/api/fund/group/details?groupId=${groupId}`, 'GET') as { status: string; data?: GroupDetails; message?: string };
+ const response = await apiCall(`https://exotic-humpback-mistakenly.ngrok-free.app/api/fund/group/details?groupId=${groupId}`, 'GET') as { status: string; data?: GroupDetails; message?: string };
if (response.status === 'success' && response.data) {
setGroupDetails(response.data);
setEditableData({
@@ -141,7 +141,7 @@ const EditGroupScreen: React.FC = ({ route }) => {
setSaving(true);
try {
- await apiCall(`https://api.godemo.in/FundCollect/api/fund/groups/${groupDetails.id}/edit`, 'PUT', editableData);
+ await apiCall(`https://exotic-humpback-mistakenly.ngrok-free.app/apifund/groups/${groupDetails.id}/edit`, 'PUT', editableData);
Alert.alert('Success', 'Group has been updated.');
setEditingField(null);
await fetchGroupDetails();
@@ -165,7 +165,7 @@ const EditGroupScreen: React.FC = ({ route }) => {
onPress: async () => {
setStarting(true);
try {
- await apiCall(`https://api.godemo.in/FundCollect/api/fund/group/start?groupId=${groupDetails.id}`, 'GET');
+ await apiCall(`https://exotic-humpback-mistakenly.ngrok-free.app/api/fund/group/start?groupId=${groupDetails.id}`, 'GET');
Alert.alert('Success', 'Group has been started successfully.');
await fetchGroupDetails();
} catch (e: any) {
diff --git a/src/screens/management/ManagementScreen.tsx b/src/screens/management/ManagementScreen.tsx
index 9e2f5df..e6e8190 100644
--- a/src/screens/management/ManagementScreen.tsx
+++ b/src/screens/management/ManagementScreen.tsx
@@ -40,16 +40,15 @@ const ManagementScreen: FC = () => {
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
const [userRequest, setUserRequest] = useState([])
-
-
const fetchData = useCallback(async () => {
if (loading) return;
+
setLoading(true);
setError(null);
+
try {
- console.log(" abin user : ", userRole)
if (userRole.role === "ORGANIZER") {
- // Fetch all data concurrently
+ // Fetch all data concurrently for organizers
const [myGroupsRes, joinedGroupsRes, requestsRes] = await Promise.all([
apiCall(MY_GROUPS_URL, "GET") as Promise>,
apiCall(GET_JOINED_GROUP_URL, "GET") as Promise>,
@@ -59,19 +58,22 @@ const ManagementScreen: FC = () => {
console.log("My Groups:", myGroupsRes.data);
console.log("Joined Groups:", joinedGroupsRes.data);
console.log("Requests:", requestsRes.data);
+
setMyGroups(myGroupsRes.data || []);
setJoinedGroups(joinedGroupsRes.data || []);
setRequests(requestsRes.data || []);
} else {
- // Fetch only joined groups for non-organizers
- const [joinedGroupsRes, userRequest] = await Promise.all([
- apiCall(GET_JOINED_GROUP_URL, "GET") as Promise>, // Assuming this is also needed
- apiCall(USER_REQUEST, "GET") as Promise>, // Assuming this is also needed
+ // Fetch only joined groups and user requests for non-organizers
+ const [joinedGroupsRes, userRequestRes] = await Promise.all([
+ apiCall(GET_JOINED_GROUP_URL, "GET") as Promise>,
+ apiCall(USER_REQUEST, "GET") as Promise>,
]);
+
+ console.log("Joined Groups:", joinedGroupsRes.data);
+ console.log("User Requests:", userRequestRes.data);
+
setJoinedGroups(joinedGroupsRes.data || []);
- setUserRequest(userRequest?.data || []);
- console.log("joinedGroupsRes data : ", joinedGroupsRes)
- console.log("user request data : ", userRequest)
+ setUserRequest(userRequestRes.data || []);
}
} catch (e) {
console.error("Fetch Data Error:", e);
diff --git a/src/screens/profile/BecomeOrg.tsx b/src/screens/profile/BecomeOrg.tsx
index bae00a7..0d63471 100644
--- a/src/screens/profile/BecomeOrg.tsx
+++ b/src/screens/profile/BecomeOrg.tsx
@@ -41,7 +41,7 @@ const BecomeOrg = () => {
const token = credentials.password;
const response = await fetch(
- "https://api.godemo.in/FundCollect/api/organizer/registration/apply",
+ "https://exotic-humpback-mistakenly.ngrok-free.app/api/organizer/registration/apply",
{
method: "POST",
headers: {
diff --git a/src/screens/profile/EditBankDetails.tsx b/src/screens/profile/EditBankDetails.tsx
new file mode 100644
index 0000000..6c4a4b1
--- /dev/null
+++ b/src/screens/profile/EditBankDetails.tsx
@@ -0,0 +1,162 @@
+import React, { useState } from "react";
+import {
+ StyleSheet,
+ View,
+ Text,
+ Alert,
+ ActivityIndicator,
+ TouchableOpacity,
+} from "react-native";
+import { useNavigation, useRoute } from "@react-navigation/native";
+import { CustomButton, CustomInput } from "../../components/common/Custom";
+import colors from "../../components/colors";
+import AppView from "../../components/AppView";
+import { Ionicons } from "@react-native-vector-icons/ionicons";
+import { UPDATE_BANK_URL } from "../../utils/ApiUrls";
+import { apiCall } from "../../utils/ApiHelper";
+
+const EditBankDetails = () => {
+ const navigation = useNavigation();
+ const route = useRoute();
+
+ // Get initial data from route parameters passed from the Profile screen
+ const {
+ currentBankName,
+ currentAccountNumber,
+ currentBranchCode
+ } = route.params as {
+ currentBankName?: string;
+ currentAccountNumber?: string;
+ currentBranchCode?: string;
+ };
+
+ // Initialize state with the passed-in details
+ const [bankName, setBankName] = useState(currentBankName || "");
+ const [bankAccountNumber, setBankAccountNumber] = useState(currentAccountNumber || "");
+ const [branchCode, setBranchCode] = useState(currentBranchCode || "");
+ const [loading, setLoading] = useState(false);
+
+ // The update function remains the same, using the local state
+ const handleUpdateBankDetails = async () => {
+ if (!bankName || !bankAccountNumber || !branchCode) {
+ Alert.alert("Validation Error", "Please fill in all bank details.");
+ return;
+ }
+
+ try {
+ setLoading(true);
+ const response = await apiCall(UPDATE_BANK_URL, 'PUT', {
+ bankName,
+ bankAccountNumber,
+ branchCode,
+ }) as { status: string; message?: string };
+ console.log("Update Bank Response:", response);
+ if (response.status === "success") {
+ Alert.alert("Success", response.message || "Bank details updated successfully!");
+ navigation.goBack();
+ } else {
+ Alert.alert("Update Failed", response.message || "Could not update bank details.");
+ }
+ } catch (error: any) {
+ console.error("Error updating bank details:", error);
+ Alert.alert("Error", error.message || "An unexpected error occurred. Please try again.");
+ } finally {
+ setLoading(false);
+ }
+ };
+
+ return (
+
+
+ navigation.goBack()} style={styles.backButton}>
+
+
+ Edit Bank Details
+
+
+
+ Update Your Bank Information
+
+
+
+
+
+
+
+
+
+ navigation.goBack()}
+ style={styles.cancelButton}
+ buttonBackground={colors.pastelBlue}
+ />
+
+
+
+ );
+};
+
+const styles = StyleSheet.create({
+ header: {
+ flexDirection: "row",
+ alignItems: "center",
+ padding: 16,
+ },
+ backButton: {
+ marginRight: 16,
+ },
+ headerTitle: {
+ fontSize: 22,
+ fontWeight: "600",
+ color: colors.Profile,
+ },
+ container: {
+ flex: 1,
+ padding: 16,
+ },
+ sectionTitle: {
+ fontSize: 18,
+ fontWeight: "700",
+ color: "#1e293b",
+ marginBottom: 20,
+ },
+ buttonContainer: {
+ marginTop: 24,
+ },
+ cancelButton: {
+ marginTop: 12,
+ borderWidth: 1,
+ borderColor: "#cbd5e1",
+ },
+});
+
+export default EditBankDetails;
diff --git a/src/screens/profile/Profile.tsx b/src/screens/profile/Profile.tsx
index 7dd5b3b..85f980c 100644
--- a/src/screens/profile/Profile.tsx
+++ b/src/screens/profile/Profile.tsx
@@ -26,6 +26,9 @@ import { BASE_URL, PUT_USER_PROFILE, PUT_USER_PROFILE_IMG, PUT_USER_STATUS } fro
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";
+
type UserProfile = {
id: string;
@@ -46,8 +49,9 @@ type UserProfile = {
role?: string;
};
+
const Profile = () => {
- const navigation = useNavigation();
+ const navigation = useNavigation>();
const dispatch = useDispatch()
const [user, setUser] = useState(null);
const [fetching, setFetching] = useState(true);
@@ -58,6 +62,7 @@ const Profile = () => {
const [error, setError] = useState(null);
const [refreshing, setRefreshing] = useState(false);
+
const fetchUserProfile = async () => {
try {
const credentials = await Keychain.getGenericPassword();
@@ -67,6 +72,7 @@ const Profile = () => {
}
const token = credentials.password;
+
setFetching(true);
const response = await fetch(
`${BASE_URL}user/profile/view`,
@@ -79,6 +85,7 @@ const Profile = () => {
}
);
+
const result = await response.json();
console.log("👤 Profile Response:", result);
if (result.status === "success") {
@@ -115,6 +122,7 @@ const Profile = () => {
}
};
+
const updateProfile = async () => {
try {
const credentials = await Keychain.getGenericPassword();
@@ -124,6 +132,7 @@ const Profile = () => {
}
const token = credentials.password;
+
const response = await fetch(
PUT_USER_PROFILE,
{
@@ -144,6 +153,7 @@ const Profile = () => {
}
);
+
const result = await response.json();
if (result.status === "success") {
Alert.alert("Success", "Profile updated successfully");
@@ -158,6 +168,7 @@ const Profile = () => {
}
};
+
const pickImage = () => {
launchImageLibrary({ mediaType: "photo", quality: 0.5 }, (response) => {
if (response.didCancel) return;
@@ -165,13 +176,14 @@ const Profile = () => {
Alert.alert("Error", response.errorMessage || "Something went wrong");
} else if (response.assets && response.assets.length > 0) {
const selectedImage = response.assets[0];
- setUser((prev:any) =>
+ setUser((prev: any) =>
prev ? { ...prev, filePath: selectedImage.uri ?? null } : prev
);
}
});
};
+
const handleUpdateImage = async () => {
try {
const credentials = await Keychain.getGenericPassword();
@@ -181,13 +193,16 @@ const Profile = () => {
}
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,
@@ -195,6 +210,7 @@ const Profile = () => {
name: "profile.jpg",
} as any);
+
const response = await fetch(
PUT_USER_PROFILE_IMG,
{
@@ -207,18 +223,21 @@ const Profile = () => {
}
);
+
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);
+ 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);
+ setUser((prev: any) => prev ? { ...prev, filePath: user?.filePath } : prev);
}
+
// Refresh profile from API as well
fetchUserProfile();
} else {
@@ -232,6 +251,7 @@ const Profile = () => {
}
};
+
const userStatus = async () => {
try {
const credentials = await Keychain.getGenericPassword();
@@ -241,6 +261,7 @@ const Profile = () => {
}
const token = credentials.password;
+
setLoading(true);
setError(null);
const response = await fetch(PUT_USER_STATUS, {
@@ -251,13 +272,16 @@ const Profile = () => {
},
});
+
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");
}
@@ -268,15 +292,18 @@ const Profile = () => {
}
};
+
const logout = async (navigation: any) => {
try {
const credentials = await Keychain.getGenericPassword();
+
if (!credentials) {
Alert.alert("Info", "No user is currently logged in");
return;
}
+
// Clear stored credentials
await Keychain.resetGenericPassword();
dispatch(clearUser())
@@ -288,6 +315,7 @@ const Profile = () => {
}
};
+
const confirmLogout = (navigation: any) => {
Alert.alert(
"Logout",
@@ -299,17 +327,22 @@ const Profile = () => {
);
};
+ 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
@@ -319,6 +352,7 @@ const Profile = () => {
}, 2000); // 2 seconds delay
};
+
console.log("user image :", user?.filePath);
const getProfileImage = () => {
if (user?.imageBlob) {
@@ -333,6 +367,7 @@ const Profile = () => {
+
return (
{/* Header */}
@@ -350,6 +385,7 @@ const Profile = () => {
Loading profile...
+
}
{
}
>
+
{/* Profile Card */}
{/* Profile Image Section */}
@@ -388,6 +425,7 @@ const Profile = () => {
)
}
+
{
+
{
style={styles.updateImageButton}
buttonBackground={colors.pastelBlue}
+
/>
+
{!editing ? (
<>
{/* Profile Details */}
@@ -420,8 +461,9 @@ const Profile = () => {
Become Organizer
{/*
-
- */}
+
+
+ */}
navigation.navigate('Transaction')}>
@@ -444,6 +486,7 @@ const Profile = () => {
+
@@ -452,6 +495,7 @@ const Profile = () => {
+
@@ -460,6 +504,7 @@ const Profile = () => {
+
@@ -468,6 +513,7 @@ const Profile = () => {
+
@@ -476,6 +522,7 @@ const Profile = () => {
+
@@ -484,6 +531,7 @@ const Profile = () => {
+
@@ -492,7 +540,46 @@ const Profile = () => {
+ {/* 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.pastelBlue}
+ />
+
+
+
+
+ Bank Name
+ {user?.bankName || "Not provided"}
+
+
+
+
+
+ Branch Code
+ {user?.branchCode || "Not provided"}
+
+
+
+
+
+ Account Number
+ {user?.bankAccountNumber || "Not provided"}
+
+
+
@@ -503,8 +590,9 @@ const Profile = () => {
Edit Profile
+
{
icon="person"
/>
+
{
icon="person"
/>
+
{
keyboardType="email-address"
/>
+
{
icon="at"
/>
{
multiline
/>
{
icon="male-female"
/>
+
{
/>
+
>
)}
@@ -584,6 +677,7 @@ const Profile = () => {
);
};
+
const styles = StyleSheet.create({
container: {
flex: 1,
@@ -616,6 +710,7 @@ const styles = StyleSheet.create({
padding: 4,
},
+
profileCard: {
borderRadius: 20,
margin: 16,
@@ -775,4 +870,5 @@ const styles = StyleSheet.create({
},
});
-export default Profile;
\ No newline at end of file
+
+export default Profile;
diff --git a/src/utils/ApiHelper.tsx b/src/utils/ApiHelper.tsx
index 897d140..84552fa 100644
--- a/src/utils/ApiHelper.tsx
+++ b/src/utils/ApiHelper.tsx
@@ -17,7 +17,7 @@ export async function apiCall(
try {
// Get saved credentials from Keychain
const creds = await Keychain.getGenericPassword();
-
+ console.log("hihihi", creds);
const headers = {
"Content-Type": "application/json",
...(creds ? { Authorization: `Bearer ${creds.password}` } : {}),
diff --git a/src/utils/ApiUrls.tsx b/src/utils/ApiUrls.tsx
index 37b43a7..7205ace 100644
--- a/src/utils/ApiUrls.tsx
+++ b/src/utils/ApiUrls.tsx
@@ -17,3 +17,4 @@ export const PUT_USER_PROFILE = `${BASE_URL}user/profile/update`
export const PUT_USER_STATUS = `${BASE_URL}user/profile/status`
export const USER_REQUEST = `${BASE_URL}fund/my-requests`
export const GROUP_ALL_MEMBER = `${BASE_URL}fund/group/all/member`
+export const UPDATE_BANK_URL = `${BASE_URL}user/bank/update`;