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/components/JoinedGroupCard.tsx b/src/components/JoinedGroupCard.tsx
index 08383b0..e2f9a52 100644
--- a/src/components/JoinedGroupCard.tsx
+++ b/src/components/JoinedGroupCard.tsx
@@ -22,7 +22,7 @@ interface JoinedGroup {
}
interface JoinedGroupCardProps {
- item: JoinedGroup;
+ item: JoinedGroup | any;
}
// Helper function to format dates
diff --git a/src/components/common/Custom.tsx b/src/components/common/Custom.tsx
index fcd837e..5855ceb 100644
--- a/src/components/common/Custom.tsx
+++ b/src/components/common/Custom.tsx
@@ -14,7 +14,7 @@ import colors from "../colors";
type CustomInputProps = TextInputProps & {
label?: string;
icon?: IoniconsIconName;
- error:string
+ error?:string
};
const CustomInput: React.FC = ({
diff --git a/src/components/common/Header.tsx b/src/components/common/Header.tsx
new file mode 100644
index 0000000..b2c63a8
--- /dev/null
+++ b/src/components/common/Header.tsx
@@ -0,0 +1,62 @@
+import React from "react";
+import { View, Text, TouchableOpacity, StyleSheet } from "react-native";
+import { useNavigation } from "@react-navigation/native";
+import { Ionicons } from "@react-native-vector-icons/ionicons"
+
+type HeaderProps = {
+ title: string;
+ showBack?: boolean; // optional, default true
+ onBackPress?: () => void; // optional custom back action
+};
+
+const Header: React.FC = ({
+ title,
+ showBack = true,
+ onBackPress,
+}) => {
+ const navigation = useNavigation();
+
+ const handleBack = () => {
+ if (onBackPress) {
+ onBackPress();
+ } else {
+ navigation.goBack();
+ }
+ };
+
+ return (
+
+ {showBack && (
+
+
+
+ )}
+ {title}
+
+ );
+};
+
+export default Header;
+
+const styles = StyleSheet.create({
+ header: {
+ flexDirection: "row",
+ alignItems: "center",
+ paddingHorizontal: 16,
+ paddingVertical: 12,
+ backgroundColor: "#fff",
+ shadowColor: "#000",
+ shadowOpacity: 0.05,
+ shadowOffset: { width: 0, height: 2 },
+ shadowRadius: 6,
+ elevation: 3,
+ },
+ backButton: {
+ marginRight: 12,
+ },
+ headerTitle: {
+ fontSize: 18,
+ fontWeight: "600",
+ color: "#000",
+ },
+});
diff --git a/src/navigation/AppNavigator.tsx b/src/navigation/AppNavigator.tsx
index 7d05f0e..25d7039 100644
--- a/src/navigation/AppNavigator.tsx
+++ b/src/navigation/AppNavigator.tsx
@@ -1,7 +1,6 @@
import * as React from "react";
import { NavigationContainer } from "@react-navigation/native";
import { createNativeStackNavigator } from "@react-navigation/native-stack";
-import { View, Text, Button } from "react-native";
import LoginScreen from "../screens/LoginScreen";
import OtpVerificationScreen from "../screens/OtpVarificationScreen";
import SplashScreen from "../screens/SplashScreen";
@@ -11,48 +10,47 @@ import GroupCreation from "../screens/GroupCreation";
import GroupReview from "../screens/GroupReview";
import BottomTabs from "./BottomTabs";
import BecomeOrg from "../screens/profile/BecomeOrg";
-import EditGroupScreen from "../screens/management/EditGroupScreen";
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";
-const Stack = createNativeStackNavigator();
export type RootStackParamList = {
+ Splash: undefined;
Login: undefined;
OtpVarify: { mobile: string };
- Home: undefined
- HomeTabs: undefined
- splash: undefined
- OrganizerRegister: undefined
+ Home: undefined;
+ HomeTabs: undefined;
+ OrganizerRegister: undefined;
Profile: undefined;
GroupCreation: undefined;
GroupReview: undefined;
- EditGroup: { groupId: string}
-
+ EditGroup: { groupId: string | number };
+ GroupDetails: { groupId: string | number };
+ BecomeOrg: undefined;
+ YourContacts: undefined;
+ Transaction: undefined;
+ EditBankDetails: { currentBankName: string | null; currentAccountNumber: string | null; currentBranchCode: string | null };
};
-function HomeScreen() {
- return (
-
- Home Screen
-
-
- );
-}
-
-
+const Stack = createNativeStackNavigator();
export default function AppNavigator() {
const linking = {
- prefixes: ["myapp://", "https://api.godemo.in"], // supports both
+ 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", // dynamic route
+ Profile: "invite",
},
},
};
+
return (
-
+
@@ -64,7 +62,10 @@ export default function AppNavigator() {
+
+
+
);
diff --git a/src/screens/GroupScreen.tsx b/src/screens/GroupScreen.tsx
index ae662c8..f3a8b07 100644
--- a/src/screens/GroupScreen.tsx
+++ b/src/screens/GroupScreen.tsx
@@ -11,6 +11,7 @@ import {
Image,
ScrollView,
Alert,
+ RefreshControl,
} from "react-native";
import { FAB } from "react-native-paper";
import { Ionicons } from "@react-native-vector-icons/ionicons";
@@ -20,7 +21,7 @@ import { StackNavigationProp } from "@react-navigation/stack";
import { RootStackParamList } from "../navigation/AppNavigator";
import AppView from "../components/AppView";
import { apiCall } from "../utils/ApiHelper";
-import { BASE_URL, JOIN_GROUP_URL, PUBLIC_GROUPS_URL } from "../utils/ApiUrls";
+import { BASE_URL, JOIN_GROUP_URL, PUBLIC_GROUPS_URL, PUT_USER_STATUS } from "../utils/ApiUrls";
import colors from "../components/colors";
import { ApiResponse } from "./home/UserProfileStatus";
import * as Keychain from "react-native-keychain";
@@ -92,6 +93,7 @@ export default function GroupScreen() {
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
const [role, setRole] = useState(null);
+ const [refreshing, setRefreshing] = useState(false)
const fetchGroups = async () => {
if (loading) return;
@@ -140,56 +142,64 @@ export default function GroupScreen() {
Alert.alert("Error", "An unexpected error occurred.");
}
};
- const userStatus = async () => {
- try {
- const credentials = await Keychain.getGenericPassword();
- if (!credentials) {
- Alert.alert("Error", "You are not logged in");
- return;
- }
- const token = credentials.password;
+ 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(`${BASE_URL}user/profile/status`, {
- method: "GET",
- headers: {
- Accept: "*/*",
- Authorization: `Bearer ${token}`,
- },
- });
+ setLoading(true);
+ setError(null);
+ const response = await fetch(PUT_USER_STATUS, {
+ method: "GET",
+ headers: {
+ Accept: "*/*",
+ Authorization: `Bearer ${token}`,
+ },
+ });
- const json: ApiResponse = await response.json();
+ const json: ApiResponse = await response.json();
- console.log("👤 Profile Status Response:", json);
- if (json.status === "success") {
- setRole(json.data.role);
+ console.log("👤 Profile Status Response:", json);
+ if (json.status === "success") {
+ setRole(json.data.role);
+
+ if (json.data.profileStatus === false) {
- if (json.data.profileStatus === false) {
-
- }
- } else {
- setError(json.message || "Failed to fetch status");
- }
- } catch (err) {
- setError("Something went wrong. Please try again.");
- } finally {
- setLoading(false);
}
- };
+ } else {
+ setError(json.message || "Failed to fetch status");
+ }
+ } catch (err) {
+ setError("Something went wrong. Please try again.");
+ } finally {
+ setLoading(false);
+ }
+ };
+
+ useFocusEffect(
+ useCallback(() => {
+ userStatus();
+ }, [])
+ );
- useFocusEffect(
- useCallback(() => {
- userStatus();
- }, [])
- );
-
const handleViewGroup = (group: Group) => {
// navigation.navigate('GroupDetails', { group });
Alert.alert("View Group", `Viewing details for ${group.groupName}`);
};
+ const onRefresh = () => {
+ setRefreshing(true)
+ fetchGroups()
+ setTimeout(() => {
+ setRefreshing(false)
+ }, 20000);
+ }
+
const renderContent = () => {
let data: Group[];
switch (activeTab) {
@@ -226,6 +236,10 @@ export default function GroupScreen() {
)}
columnWrapperStyle={isGridView ? { justifyContent: 'space-between' } : null}
contentContainerStyle={{ paddingBottom: 150 }}
+ refreshControl={
+
+ }
+ ListFooterComponent={}
/>
);
};
@@ -265,7 +279,7 @@ export default function GroupScreen() {
setActiveTab(tab)}>
{tab}
- ))) }
+ )))}
setIsGridView(!isGridView)} style={styles.layoutToggleButton}>
@@ -289,7 +303,7 @@ const styles = StyleSheet.create({
searchContainer: { flexDirection: 'row', alignItems: 'center', backgroundColor: '#fff', borderRadius: 12, paddingHorizontal: 10, elevation: 2, marginVertical: 20 },
searchIcon: { marginRight: 8 },
searchInput: { flex: 1, height: 45, fontSize: 16, color: '#333' },
- sectionTitle: { fontSize: 20, fontWeight: 'bold', color: '#333', marginBottom: 12, paddingHorizontal: 16 },
+ sectionTitle: { fontSize: 20, fontWeight: 'bold', color: colors.Group, marginBottom: 12, paddingHorizontal: 16 },
featuredList: { paddingLeft: 16, marginBottom: 20 },
featuredCard: { width: width * 0.45, marginRight: 15, backgroundColor: '#fff', borderRadius: 12, elevation: 3, overflow: 'hidden' },
featuredImage: { width: '100%', height: 100 },
diff --git a/src/screens/LoginScreen.tsx b/src/screens/LoginScreen.tsx
index 8fce795..e37fdeb 100644
--- a/src/screens/LoginScreen.tsx
+++ b/src/screens/LoginScreen.tsx
@@ -42,8 +42,8 @@ export default function LoginScreen() {
const fade = useRef(new Animated.Value(0)).current;
const slide = useRef(new Animated.Value(24)).current;
const ctaScale = useRef(new Animated.Value(1)).current;
- const user = useSelector((state:any) => state.user)
- console.log("current user ----",user)
+ const user = useSelector((state: any) => state.user)
+ console.log("current user ----", user)
useEffect(() => {
Animated.parallel([
Animated.timing(fade, { toValue: 1, duration: 600, useNativeDriver: true }),
@@ -51,91 +51,109 @@ export default function LoginScreen() {
]).start();
}, []);
- const handleContinue = async () => {
- if (mobile.length === 10) {
- setLoading(true);
- try {
- const res = await axios.get(LOGIN_URL + mobile);
- console.log("OTP sent response:", res)
-
- if (res.data.statusCode === 200) {
- navigation.navigate("OtpVarify", { mobile });
- }
- } catch (error) {
- console.error("Login error:", error);
- Alert.alert("Error", "Failed to send OTP. Please try again.");
- } finally {
- setLoading(false);
+ const handleContinue = async () => {
+ if (mobile.length === 10) {
+ setLoading(true);
+ try {
+ console.log("LOGIN_URL console:", LOGIN_URL, "mobile:", mobile);
+
+ const res = await axios.get(LOGIN_URL, {
+ params: { mobile },
+ });
+
+ console.log("OTP sent response:", res.data);
+
+ if (res.data.statusCode === 200) {
+ navigation.navigate("OtpVarify", { mobile });
+ } else {
+ Alert.alert("Error", res.data.message || "Failed to send OTP");
}
- } else {
- Alert.alert("Please enter a valid 10-digit mobile number");
+ } catch (error: any) {
+ console.error("Login error:", error);
+
+ if (axios.isAxiosError(error)) {
+ console.log("Error message:", error.message);
+ console.log("Error response:", error.response?.data);
+ console.log("Error status:", error.response?.status);
+ console.log("Error headers:", error.response?.headers);
+ } else {
+ console.log("Unexpected error:", error);
+ }
+
+ Alert.alert("Error", "Failed to send OTP. Please try again.");
+ } finally {
+ setLoading(false);
}
- };
+ } else {
+ Alert.alert("Please enter a valid 10-digit mobile number");
+ }
+};
- const onPressIn = () =>
- Animated.spring(ctaScale, {
- toValue: 0.97,
- useNativeDriver: true,
- speed: 20,
- bounciness: 0,
- }).start();
- const onPressOut = () =>
- Animated.spring(ctaScale, {
- toValue: 1,
- useNativeDriver: true,
- speed: 20,
- bounciness: 6,
- }).start();
+const onPressIn = () =>
+ Animated.spring(ctaScale, {
+ toValue: 0.97,
+ useNativeDriver: true,
+ speed: 20,
+ bounciness: 0,
+ }).start();
- return (
-
-
+const onPressOut = () =>
+ Animated.spring(ctaScale, {
+ toValue: 1,
+ useNativeDriver: true,
+ speed: 20,
+ bounciness: 6,
+ }).start();
- {/* Top content */}
-
- CircleCollect
- Welcome Back 👋
-
- Enter your mobile number to sign in and continue.
-
+return (
+
+
-
-
-
-
+ {/* Top content */}
+
+ CircleCollect
+ Welcome Back 👋
+
+ Enter your mobile number to sign in and continue.
+
- {/* Bottom Button */}
-
-
-
- By continuing, you agree to our{" "}
-
- Terms & Privacy
-
-
+
-
- );
+
+
+ {/* Bottom Button */}
+
+
+
+
+ By continuing, you agree to our{" "}
+
+ Terms & Privacy
+
+
+
+
+);
}
const styles = StyleSheet.create({
diff --git a/src/screens/SplashScreen.tsx b/src/screens/SplashScreen.tsx
index 96d0bd9..ded22d9 100644
--- a/src/screens/SplashScreen.tsx
+++ b/src/screens/SplashScreen.tsx
@@ -1,101 +1,107 @@
-import React, { useEffect, useRef, useState } from "react";
-import { View, StyleSheet, ActivityIndicator, Animated, Alert } from "react-native";
+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 { useNavigation } from "@react-navigation/native";
-import { StackNavigationProp } from "@react-navigation/stack";
+import { RootStackParamList } from "../navigation/AppNavigator";
+import { PROFILE_URL } from "../utils/ApiUrls";
import { useDispatch } from "react-redux";
-
-// --- Import your project files ---
-import { RootStackParamList } from "../navigation/AppNavigator"; // Adjust path
-import { BASE_URL } from "../utils/ApiUrls";
-import { fetchUserProfile } from "../utils/HelperFunction";
-import { setUserData } from "../redux/userSlice";
+import { clearUser, setUserData } from "../redux/userSlice";
import colors from "../components/colors";
-import { ApiResponse } from "./home/UserProfileStatus";
+import { StackNavigationProp } from "@react-navigation/stack";
const SplashScreen = () => {
const navigation = useNavigation>();
const dispatch = useDispatch();
const fadeAnim = useRef(new Animated.Value(1)).current;
- // State to track the outcome of initialization
- const [isReady, setIsReady] = useState(false);
- const [isLoggedIn, setIsLoggedIn] = useState(false);
+
+ const fetchUserProfile = async (dispatch: any, navigation: any) => {
+ try {
+ const credentials = await Keychain.getGenericPassword();
+ if (!credentials) {
+ return null;
+ }
+
+ const token = credentials.password;
+ const response = await fetch(PROFILE_URL, {
+ method: "GET",
+ headers: {
+ Accept: "*/*",
+ Authorization: `Bearer ${token}`,
+ },
+ });
+
+ const result = await response.json();
+
+ if (response.status === 200 && result.status === "success") {
+ // Save user data in Redux
+ 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,
+ filePath: result.data.filePath,
+ imageBlob: result.data.imageBlob,
+ role: result.data.role,
+ organizerId: result.data.organizerId,
+ organizerStatus: result.data.organizerStatus,
+ profileStatus: true,
+ })
+ );
+ return result.data.role;
+ } else if (response.status === 401 || result.status === 401) {
+ // Unauthorized: reset credentials and navigate to login
+ await Keychain.resetGenericPassword();
+ dispatch(clearUser());
+ ToastAndroid.show(result.message || "Session expired. Please login again.", ToastAndroid.SHORT);
+ navigation.replace("Login");
+ return null;
+ } else {
+ console.warn("Unexpected response:", result);
+ return null;
+ }
+ } catch (error) {
+ console.error("❌ Error fetching profile:", error);
+ ToastAndroid.show("Failed to fetch profile. Please try again.", ToastAndroid.SHORT);
+ return null;
+ }
+ };
useEffect(() => {
- // A single function to handle all startup tasks
- const initializeApp = async () => {
- try {
- // 1. Check for stored credentials
- const credentials = await Keychain.getGenericPassword();
- if (!credentials) {
- console.log("No credentials found. User needs to log in.");
- setIsLoggedIn(false);
- return; // Stop here if not logged in
- }
+ const startSplash = async () => {
+ const role = await fetchUserProfile(dispatch, navigation);
- console.log("🔑 Credentials found. Proceeding with user data fetches.");
- const { password: token } = credentials;
-
- // 2. Fetch all necessary data in parallel for efficiency
- const [statusResponse, userProfile] = await Promise.all([
- fetch(`${BASE_URL}user/profile/status`, {
- method: "GET",
- headers: {
- Accept: "*/*",
- Authorization: `Bearer ${token}`,
- },
- }),
- fetchUserProfile(dispatch), // Assuming fetchUserProfile handles its own errors and dispatches to Redux
- ]);
-
- // 3. Process the profile status response
- if (!statusResponse.ok) {
- throw new Error(`Server responded with status: ${statusResponse.status}`);
- }
-
- const statusJson: ApiResponse = await statusResponse.json();
- console.log("👤 Profile Status Response:", statusJson);
-
- if (statusJson.status === "success") {
- // You could dispatch more data here if needed
- // dispatch(setUserData(statusJson.data));
- setIsLoggedIn(true);
+ Animated.timing(fadeAnim, {
+ toValue: 0,
+ duration: 1500,
+ useNativeDriver: true,
+ delay: 1500,
+ }).start(() => {
+ // Navigate based on role
+ if (!role) {
+ navigation.replace("Login");
+ } else if (role === "USER") {
+ navigation.replace("Home");
+ } else if (role === "ORGANIZER") {
+ navigation.replace("Home"); // Replace with Organizer screen if you have one
} else {
- throw new Error(statusJson.message || "Failed to verify user status.");
+ navigation.replace("Login");
}
-
- } catch (error) {
- console.error("Initialization failed:", error);
- Alert.alert("Error", "Your session may have expired. Please log in again.");
- setIsLoggedIn(false); // Ensure login status is false on any error
- } finally {
- // 4. Signal that all tasks are done, whether they succeeded or failed
- setIsReady(true);
- }
+ });
};
- // Trigger the animation, and run initialization logic after it completes
- Animated.timing(fadeAnim, {
- toValue: 0,
- duration: 1500,
- useNativeDriver: true,
- delay: 1500,
- }).start(() => {
- initializeApp();
- });
- }, [fadeAnim, dispatch]);
-
- // This effect handles the final navigation step once everything is ready
- useEffect(() => {
- if (isReady) {
- if (isLoggedIn) {
- navigation.replace("Home");
- } else {
- navigation.replace("Login");
- }
- }
- }, [isReady, isLoggedIn, navigation]);
+ startSplash();
+ }, [navigation, fadeAnim, dispatch]);
return (
diff --git a/src/screens/home/GroupList.tsx b/src/screens/home/GroupList.tsx
index 56ca9f7..9bd3476 100644
--- a/src/screens/home/GroupList.tsx
+++ b/src/screens/home/GroupList.tsx
@@ -85,7 +85,7 @@ const GroupList = () => {
const res = await fetch(`${BASE_URL}fund/getAll/my/groups`, {
headers: { Accept: "*/*", Authorization: `Bearer ${token}` },
});
- console.log("my groups response", res);
+ console.log("my groups response : ", res);
const data = await res.json();
setGroups(data.data || []);
setFilteredGroups(data.data || []);
diff --git a/src/screens/home/Home.tsx b/src/screens/home/Home.tsx
index 136eb9a..9abb27d 100644
--- a/src/screens/home/Home.tsx
+++ b/src/screens/home/Home.tsx
@@ -11,10 +11,10 @@ import {
import AppView from "../../components/AppView";
import UserProfileStatus from "./UserProfileStatus";
import colors from "../../components/colors";
-import { Ionicons } from "@react-native-vector-icons/ionicons";
import GroupsTabs from "./GroupsTabs";
import { useSelector } from "react-redux";
import { useNavigation } from "@react-navigation/native";
+import UserHome from "./user-home/UserHome";
// Enable animation for Android
if (Platform.OS === "android" && UIManager.setLayoutAnimationEnabledExperimental) {
UIManager.setLayoutAnimationEnabledExperimental(true);
@@ -29,11 +29,7 @@ const Home = () => {
Hello, {user.firstName} {user.lastName}👋
navigation.navigate("Profile" as never)}>
- {/* */}
+
{
{/* Status */}
-
+ {user?.role === "USER" ? :
+ }
);
};
diff --git a/src/screens/home/UserProfileStatus.tsx b/src/screens/home/UserProfileStatus.tsx
index f031f9b..3da10fd 100644
--- a/src/screens/home/UserProfileStatus.tsx
+++ b/src/screens/home/UserProfileStatus.tsx
@@ -10,7 +10,7 @@ import {
} from "react-native";
import * as Keychain from "react-native-keychain";
import { useFocusEffect, useNavigation } from "@react-navigation/native";
-import { BASE_URL } from "../../utils/ApiUrls";
+import { BASE_URL, PUT_USER_STATUS } from "../../utils/ApiUrls";
import colors from "../../components/colors";
export type ApiResponse = {
@@ -44,7 +44,7 @@ const UserProfileStatus: React.FC = () => {
setLoading(true);
setError(null);
- const response = await fetch(`${BASE_URL}user/profile/status`, {
+ const response = await fetch(PUT_USER_STATUS, {
method: "GET",
headers: {
Accept: "*/*",
diff --git a/src/screens/home/user-home/GroupDetails.tsx b/src/screens/home/user-home/GroupDetails.tsx
new file mode 100644
index 0000000..c25acf3
--- /dev/null
+++ b/src/screens/home/user-home/GroupDetails.tsx
@@ -0,0 +1,248 @@
+import React, { useRef, useEffect } from "react";
+import {
+ StyleSheet,
+ Text,
+ View,
+ TouchableOpacity,
+ FlatList,
+ Animated,
+} from "react-native";
+import { useRoute } from "@react-navigation/native";
+import AppView from "../../../components/AppView";
+import colors from "../../../components/colors";
+import Ionicons from "@react-native-vector-icons/ionicons";
+
+const GroupDetails = () => {
+ const route = useRoute();
+ const { groupId } = route.params as { groupId: string };
+
+ const group = {
+ id: groupId,
+ name: "Wedding Fund",
+ collected: 12000,
+ goal: 20000,
+ description:
+ "This group is created to collect contributions for the wedding celebration. Everyone can contribute as per their convenience.",
+ members: [
+ { id: "1", name: "Alice", contribution: 3000, role: "Organizer" },
+ { id: "2", name: "Bob", contribution: 2500, role: "Member" },
+ { id: "3", name: "Charlie", contribution: 4000, role: "Member" },
+ { id: "4", name: "David", contribution: 2500, role: "Member" },
+ ],
+ };
+
+ const progress = Math.min(group.collected / group.goal, 1);
+
+ // Animation refs
+ const animatedValues = useRef(group.members.map(() => new Animated.Value(0))).current;
+
+ useEffect(() => {
+ const animations = group.members.map((_, i) =>
+ Animated.timing(animatedValues[i], {
+ toValue: 1,
+ duration: 400,
+ delay: i * 100,
+ useNativeDriver: true,
+ })
+ );
+ Animated.stagger(100, animations).start();
+ }, []);
+
+ const renderMember = ({ item, index }: { item: typeof group.members[0]; index: number }) => {
+ return (
+
+
+
+
+
+ {item.name} {item.role === "Organizer" ? "(Organizer)" : "(Member)"}
+
+ Contribution: ₹{item.contribution}
+
+
+
+
+
+ );
+ };
+
+ return (
+
+ {/* Group Title */}
+ {group.name}
+ {group.description}
+
+ {/* Progress Bar */}
+
+
+
+
+
+
+ ₹{group.collected} / ₹{group.goal}
+
+
+
+ {/* Stats */}
+
+
+ {group.members.length}
+ Members
+
+
+ ₹{group.collected}
+ Collected
+
+
+ ₹{group.goal}
+ Goal
+
+
+
+ {/* Members List */}
+ Members
+ item.id}
+ renderItem={({ item, index }) => renderMember({ item, index })}
+ contentContainerStyle={styles.membersListContainer}
+ />
+
+ {/* Actions */}
+
+
+ Contribute
+
+
+
+ );
+};
+
+export default GroupDetails;
+
+const styles = StyleSheet.create({
+ groupName: {
+ fontSize: 22,
+ fontWeight: "700",
+ color: "#0f172a",
+ marginBottom: 6,
+ },
+ description: {
+ fontSize: 14,
+ color: "#475569",
+ marginBottom: 20,
+ lineHeight: 20,
+ },
+ progressContainer: {
+ marginBottom: 24,
+ },
+ progressBar: {
+ flexDirection: "row",
+ height: 8,
+ borderRadius: 4,
+ backgroundColor: "#e2e8f0",
+ overflow: "hidden",
+ marginBottom: 6,
+ },
+ progressFill: {
+ backgroundColor: colors.Home,
+ },
+ amount: {
+ fontSize: 13,
+ color: "#64748b",
+ },
+ statsRow: {
+ flexDirection: "row",
+ justifyContent: "space-between",
+ marginBottom: 20,
+ },
+ statBox: {
+ flex: 1,
+ backgroundColor: "#fff",
+ marginHorizontal: 4,
+ padding: 16,
+ borderRadius: 12,
+ alignItems: "center",
+ shadowColor: "#000",
+ shadowOpacity: 0.05,
+ shadowOffset: { width: 0, height: 2 },
+ shadowRadius: 6,
+ elevation: 2,
+ },
+ statValue: {
+ fontSize: 18,
+ fontWeight: "700",
+ color: "#1e293b",
+ },
+ statLabel: {
+ fontSize: 12,
+ color: "#64748b",
+ marginTop: 4,
+ },
+ sectionTitle: {
+ fontSize: 16,
+ fontWeight: "600",
+ color: "#0f172a",
+ marginBottom: 12,
+ },
+ membersListContainer: {
+ paddingBottom: 20,
+ },
+ memberCard: {
+ backgroundColor: "#fff",
+ padding: 16,
+ borderRadius: 12,
+ marginBottom: 10,
+ // shadowColor: "#000",
+ // shadowOpacity: 0.05,
+ // shadowOffset: { width: 0, height: 2 },
+ // shadowRadius: 4,
+ // elevation: 2,
+ borderLeftWidth:5,
+ borderColor:colors.primary
+ },
+ memberName: {
+ fontSize: 15,
+ fontWeight: "600",
+ color: "#1e293b",
+ marginBottom: 4,
+ },
+ memberDetail: {
+ fontSize: 13,
+ color: "#475569",
+ },
+ actions: {
+ marginTop: 16,
+ },
+ button: {
+ backgroundColor: colors.Home,
+ paddingVertical: 14,
+ borderRadius: 10,
+ alignItems: "center",
+ marginBottom: 12,
+ },
+ buttonText: {
+ fontSize: 15,
+ fontWeight: "600",
+ color: "#fff",
+ },
+});
diff --git a/src/screens/home/user-home/UserHome.tsx b/src/screens/home/user-home/UserHome.tsx
new file mode 100644
index 0000000..c0acf8a
--- /dev/null
+++ b/src/screens/home/user-home/UserHome.tsx
@@ -0,0 +1,168 @@
+import React from "react";
+import {
+ StyleSheet,
+ Text,
+ View,
+ FlatList,
+ TouchableOpacity,
+} from "react-native";
+import { useNavigation } from "@react-navigation/native";
+import type { NativeStackNavigationProp } from "@react-navigation/native-stack";
+import type { RootStackParamList } from "../../../navigation/AppNavigator"; // adjust path
+import colors from "../../../components/colors";
+import Ionicons from "@react-native-vector-icons/ionicons";
+
+type NavigationProp = NativeStackNavigationProp;
+
+type Group = {
+ id: string;
+ name: string;
+ members: number;
+ collected: number;
+ goal: number;
+};
+
+const groups: Group[] = [
+ { id: "1", name: "Wedding Fund", members: 25, collected: 12000, goal: 20000 },
+ { id: "2", name: "Birthday Gift", members: 10, collected: 4500, goal: 6000 },
+ { id: "3", name: "Community Event", members: 50, collected: 22000, goal: 30000 },
+];
+
+const UserHome = () => {
+ const navigation = useNavigation();
+
+ const totalGroups = groups.length;
+ const totalCollected = groups.reduce((sum, g) => sum + g.collected, 0);
+
+ const renderItem = ({ item }: { item: Group }) => {
+ const progress = Math.min(item.collected / item.goal, 1) * 100;
+
+ return (
+ navigation.navigate("GroupDetails", { groupId: item.id })}
+ >
+ {item.name}
+
+
+ {item.members} members
+
+
+ {/* Progress Bar */}
+
+
+
+
+
+ ₹{item.collected} / ₹{item.goal}
+
+
+ );
+ };
+
+ return (
+
+ {/* Stats */}
+
+
+ {totalGroups}
+ Groups Joined
+
+
+ ₹{totalCollected}
+ Total Contributed
+
+
+
+ {/* Groups List */}
+ Your Groups
+ item.id}
+ renderItem={renderItem}
+ contentContainerStyle={{ paddingBottom: 20 }}
+ />
+
+ );
+};
+
+export default UserHome;
+
+const styles = StyleSheet.create({
+
+
+ statsRow: {
+ flexDirection: "row",
+ gap: 10
+ },
+ statBox: {
+ flex: 1,
+ backgroundColor: "#fff",
+ // marginHorizontal: 6,
+ padding: 16,
+ borderRadius: 12,
+ alignItems: "center",
+ shadowColor: "#000",
+ shadowOpacity: 0.05,
+ shadowOffset: { width: 0, height: 2 },
+ shadowRadius: 6,
+ elevation: 2,
+ },
+ statValue: {
+ fontSize: 18,
+ fontWeight: "700",
+ color: colors.Home,
+ },
+ statLabel: {
+ fontSize: 12,
+ color: "#64748b",
+ marginTop: 4,
+ },
+ sectionTitle: {
+ fontSize: 18,
+ fontWeight: "600",
+ color: colors.Home,
+ marginBottom: 12,
+ },
+ card: {
+ backgroundColor: "#ffffff",
+ padding: 16,
+ marginBottom: 12,
+ borderRadius: 12,
+ shadowColor: "#000",
+ shadowOpacity: 0.05,
+ shadowOffset: { width: 0, height: 2 },
+ shadowRadius: 6,
+ elevation: 2,
+ },
+ groupName: {
+ fontSize: 16,
+ fontWeight: "600",
+ color: colors.Home,
+ marginBottom: 6,
+ },
+ detail: {
+ fontSize: 13,
+ color: "#475569",
+ marginBottom: 8,
+ },
+ progressBar: {
+ height: 6,
+ borderRadius: 3,
+ backgroundColor: "#e2e8f0",
+ marginBottom: 6,
+ overflow: "hidden",
+ },
+ progressFill: {
+ backgroundColor: colors.primary,
+ height: "100%",
+ },
+ amount: {
+ fontSize: 13,
+ color: "#64748b",
+ },
+});
diff --git a/src/screens/management/YourContacts.tsx b/src/screens/management/YourContacts.tsx
index d256c99..ed53a37 100644
--- a/src/screens/management/YourContacts.tsx
+++ b/src/screens/management/YourContacts.tsx
@@ -15,6 +15,7 @@ import {
Alert,
} from "react-native";
import AppView from "../../components/AppView";
+import colors from "../../components/colors";
const { ContactsModule } = NativeModules;
@@ -187,7 +188,7 @@ const styles = StyleSheet.create({
width: 45,
height: 45,
borderRadius: 25,
- backgroundColor: "#25D366",
+ backgroundColor: colors.pastelOrange,
justifyContent: "center",
alignItems: "center",
marginRight: 12,
@@ -213,10 +214,10 @@ const styles = StyleSheet.create({
paddingVertical: 6,
borderRadius: 8,
borderWidth: 1,
- borderColor: "#25D366",
+ borderColor: colors.Settings,
},
inviteText: {
- color: "#25D366",
+ color: colors.Settings,
fontWeight: "bold",
},
modalOverlay: {
@@ -264,7 +265,7 @@ const styles = StyleSheet.create({
marginLeft: 10,
paddingVertical: 10,
borderRadius: 8,
- backgroundColor: "#25D366",
+ backgroundColor: colors.pastelOrange,
alignItems: "center",
},
sendText: {
diff --git a/src/screens/profile/BecomeOrg.tsx b/src/screens/profile/BecomeOrg.tsx
index 1ac795c..bae00a7 100644
--- a/src/screens/profile/BecomeOrg.tsx
+++ b/src/screens/profile/BecomeOrg.tsx
@@ -81,7 +81,7 @@ const BecomeOrg = () => {
navigation.replace("Home" as never)} >
- User Profile
+ Become Organizer
{
keyboardType="numeric"
value={bankAccountNumber}
onChangeText={setBankAccountNumber}
- icon="card-outline"
- />
+ icon="card-outline" error={""} />
{
value={branchCode}
onChangeText={setBranchCode}
icon="key-outline"
+ error=""
/>
{
+ 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 f9f9d07..47bb309 100644
--- a/src/screens/profile/Profile.tsx
+++ b/src/screens/profile/Profile.tsx
@@ -22,11 +22,12 @@ import colors from "../../components/colors";
import SwitchNavigator from "./SwitchNavigator";
import { useFocusEffect, useNavigation } from "@react-navigation/native";
import { ApiResponse } from "../home/UserProfileStatus";
-import { BASE_URL } from "../../utils/ApiUrls";
+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 { setUserData } from "../../redux/userSlice";
-
+import { clearUser, setUserData } from "../../redux/userSlice";
+import { StackNavigationProp } from "@react-navigation/stack";
+import { RootStackParamList } from "../../navigation/AppNavigator";
type UserProfile = {
@@ -48,10 +49,11 @@ type UserProfile = {
role?: string;
};
+
const Profile = () => {
- const navigation = useNavigation();
+ const navigation = useNavigation>();
const dispatch = useDispatch()
- const [user, setUser] = useState(null);
+ const [user, setUser] = useState(null);
const [fetching, setFetching] = useState(true);
const [editing, setEditing] = useState(false);
const [imageUpdating, setImageUpdating] = useState(false);
@@ -60,6 +62,7 @@ const Profile = () => {
const [error, setError] = useState(null);
const [refreshing, setRefreshing] = useState(false);
+
const fetchUserProfile = async () => {
try {
const credentials = await Keychain.getGenericPassword();
@@ -69,6 +72,7 @@ const Profile = () => {
}
const token = credentials.password;
+
setFetching(true);
const response = await fetch(
`${BASE_URL}user/profile/view`,
@@ -81,31 +85,32 @@ const Profile = () => {
}
);
+
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
- }));
+ 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");
}
@@ -117,6 +122,7 @@ const Profile = () => {
}
};
+
const updateProfile = async () => {
try {
const credentials = await Keychain.getGenericPassword();
@@ -126,8 +132,9 @@ const Profile = () => {
}
const token = credentials.password;
+
const response = await fetch(
- `${BASE_URL}user/profile/update`,
+ PUT_USER_PROFILE,
{
method: "PUT",
headers: {
@@ -146,6 +153,7 @@ const Profile = () => {
}
);
+
const result = await response.json();
if (result.status === "success") {
Alert.alert("Success", "Profile updated successfully");
@@ -160,6 +168,7 @@ const Profile = () => {
}
};
+
const pickImage = () => {
launchImageLibrary({ mediaType: "photo", quality: 0.5 }, (response) => {
if (response.didCancel) return;
@@ -167,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) =>
+ setUser((prev: any) =>
prev ? { ...prev, filePath: selectedImage.uri ?? null } : prev
);
}
});
};
+
const handleUpdateImage = async () => {
try {
const credentials = await Keychain.getGenericPassword();
@@ -183,22 +193,26 @@ 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,
+ uri: user?.filePath,
type: "image/jpeg",
name: "profile.jpg",
} as any);
+
const response = await fetch(
- `${BASE_URL}user/update/userImg`,
+ PUT_USER_PROFILE_IMG,
{
method: "PUT",
headers: {
@@ -209,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) => 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) => prev ? { ...prev, filePath: user.filePath } : prev);
+ setUser((prev: any) => prev ? { ...prev, filePath: user?.filePath } : prev);
}
+
// Refresh profile from API as well
fetchUserProfile();
} else {
@@ -234,6 +251,7 @@ const Profile = () => {
}
};
+
const userStatus = async () => {
try {
const credentials = await Keychain.getGenericPassword();
@@ -243,9 +261,10 @@ const Profile = () => {
}
const token = credentials.password;
+
setLoading(true);
setError(null);
- const response = await fetch(`${BASE_URL}user/profile/status`, {
+ const response = await fetch(PUT_USER_STATUS, {
method: "GET",
headers: {
Accept: "*/*",
@@ -253,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");
}
@@ -270,17 +292,21 @@ 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())
Alert.alert("Success", "You have been logged out");
navigation.replace("Login");
} catch (error) {
@@ -289,6 +315,7 @@ const Profile = () => {
}
};
+
const confirmLogout = (navigation: any) => {
Alert.alert(
"Logout",
@@ -300,20 +327,24 @@ 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
@@ -323,26 +354,21 @@ const Profile = () => {
}, 2000); // 2 seconds delay
};
+
console.log("user image :", user?.filePath);
const getProfileImage = () => {
if (user?.imageBlob) {
- return `data:image/jpeg;base64,${user.imageBlob}`;
+ return `data:image/jpeg;base64,${user?.imageBlob}`;
}
if (user?.filePath) {
- return user.filePath;
+ return user?.filePath;
}
- return "https://randomuser.me/api/portraits/men/1.jpg";
+ return "https://randomuser?.me/api/portraits/men/1.jpg";
};
- if (fetching || !user) {
- return (
-
-
- Loading profile...
-
- );
- }
+
+
return (
@@ -350,9 +376,19 @@ const Profile = () => {
User Profile
confirmLogout(navigation)} style={styles.refreshButton}>
-
+
+ {/* if (fetching || !user) {
+ return ( */}
+ {fetching || !user &&
+
+
+ Loading profile...
+
+
+
+ }
{
}
>
+
{/* Profile Card */}
{/* Profile Image Section */}
@@ -390,6 +427,7 @@ const Profile = () => {
)
}
+
{
+
{
style={styles.updateImageButton}
buttonBackground={colors.pastelBlue}
+
/>
+
{!editing ? (
<>
{/* Profile Details */}
@@ -422,10 +463,14 @@ const Profile = () => {
Become Organizer
{/*
-
- */}
+
+
+ */}
+ navigation.navigate('Transaction')}>
+ View Transaction
+
setEditing(true)}
@@ -439,59 +484,104 @@ const Profile = () => {
Name
- {user.firstName} {user.lastName}
+ {user?.firstName} {user?.lastName}
+
Email
- {user.email || "Not provided"}
+ {user?.email || "Not provided"}
+
Mobile
- {user.mobile || "Not provided"}
+ {user?.mobile || "Not provided"}
+
Username
- {user.username}
+ {user?.username}
+
Address
- {user.address || "Not provided"}
+ {user?.address || "Not provided"}
+
Gender
- {user.gender || "Not specified"}
+ {user?.gender || "Not specified"}
+
Role
- {user.role || "User"}
+ {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.pastelBlue}
+ />
+
+
+
+
+ Bank Name
+ {user?.bankName || "Not provided"}
+
+
+
+
+
+ Branch Code
+ {user?.branchCode || "Not provided"}
+
+
+
+
+
+ Account Number
+ {user?.bankAccountNumber || "Not provided"}
+
+
+
@@ -502,54 +592,65 @@ const Profile = () => {
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"
/>
+
{
/>
+
>
)}
@@ -577,6 +679,7 @@ const Profile = () => {
);
};
+
const styles = StyleSheet.create({
container: {
flex: 1,
@@ -609,6 +712,7 @@ const styles = StyleSheet.create({
padding: 4,
},
+
profileCard: {
borderRadius: 20,
margin: 16,
@@ -692,7 +796,7 @@ const styles = StyleSheet.create({
paddingHorizontal: 8,
},
editSection: {
- marginBottom: '40%',
+ marginBottom: '100%',
flex: 1,
},
editButtons: {
@@ -768,4 +872,5 @@ const styles = StyleSheet.create({
},
});
-export default Profile;
\ No newline at end of file
+
+export default Profile;
diff --git a/src/screens/profile/Transaction.tsx b/src/screens/profile/Transaction.tsx
new file mode 100644
index 0000000..a4ee84f
--- /dev/null
+++ b/src/screens/profile/Transaction.tsx
@@ -0,0 +1,17 @@
+import { StyleSheet, Text, View } from 'react-native'
+import React from 'react'
+import AppView from '../../components/AppView'
+
+const Transaction = () => {
+ return (
+
+ Transaction
+
+ )
+}
+
+export default Transaction
+
+const styles = StyleSheet.create({
+
+})
\ No newline at end of file
diff --git a/src/utils/ApiUrls.tsx b/src/utils/ApiUrls.tsx
index 1862450..42e0c4b 100644
--- a/src/utils/ApiUrls.tsx
+++ b/src/utils/ApiUrls.tsx
@@ -1,17 +1,18 @@
-// export const BASE_URL = "https://api.godemo.in/FundCollect/api/"
export const BASE_URL = "https://exotic-humpback-mistakenly.ngrok-free.app/api/"
-export const LOGIN_URL = `${BASE_URL}user/generate/otp?mobile=`
-export const VARIFY_OTP_URL = `${BASE_URL}user/otp/verify`
-export const ORGRAGISTRATION = `${BASE_URL}organizer/registration/apply`
-export const GROUP_CREATION_URL = `${BASE_URL}fund/groups/{organizerId}`
-export const PROFILE_URL =`${BASE_URL}user/profile/view`
-export const PUBLIC_GROUPS_URL =`${BASE_URL}fund/user/public`
+// export const BASE_URL = "https://api.godemo.in/FundCollect/api/"
+export const LOGIN_URL = `${BASE_URL}user/generate/otp?mobiles=`
+export const VARIFY_OTP_URL = `${BASE_URL}user/otp/verify`
+export const ORGRAGISTRATION = `${BASE_URL}organizer/registration/apply`
+export const GROUP_CREATION_URL = `${BASE_URL}fund/groups/{organizerId}`
+export const PROFILE_URL = `${BASE_URL}user/profile/view`
+export const PUBLIC_GROUPS_URL = `${BASE_URL}fund/user/public`
export const JOIN_GROUP_URL = `${BASE_URL}fund/`;
-export const MY_GROUPS_URL =`${BASE_URL}fund/getAll/my/groups`
-
-export const REQUESTS_URL =`${BASE_URL}fund/group/pending/request`
-//https://api.godemo.in/FundCollect/api/fund/groups/2a80cdaa-8532-4b8a-87f0-9c1023d18a7f/join/64
-export const APPROVE_REQUEST_URL =`${BASE_URL}fund/requests/`
-export const DECLINE_REQUEST_URL =`${BASE_URL}fund/user/my/groups`
-// https://api.godemo.in/FundCollect/api/fund/groups/b89f56a1-952d-41b3-ab8d-3c28c91697f5/join/100005
-export const GET_JOINED_GROUP_URL = `${BASE_URL}fund/my/join/groups`
\ No newline at end of file
+export const MY_GROUPS_URL = `${BASE_URL}fund/getAll/my/groups`
+export const REQUESTS_URL = `${BASE_URL}fund/group/pending/request`
+export const APPROVE_REQUEST_URL = `${BASE_URL}fund/requests/`
+export const DECLINE_REQUEST_URL = `${BASE_URL}fund/user/my/groups`
+export const GET_JOINED_GROUP_URL = `${BASE_URL}fund/my/join/groups`
+export const PUT_USER_PROFILE_IMG = `${BASE_URL}user/update/userImg`
+export const PUT_USER_PROFILE = `${BASE_URL}user/profile/update`
+export const PUT_USER_STATUS = `${BASE_URL}user/profile/status`
+export const UPDATE_BANK_URL = `${BASE_URL}user/bank/update`;
diff --git a/src/utils/HelperFunction.tsx b/src/utils/HelperFunction.tsx
index 2279126..1588b17 100644
--- a/src/utils/HelperFunction.tsx
+++ b/src/utils/HelperFunction.tsx
@@ -4,60 +4,58 @@ import * as Keychain from "react-native-keychain";
import { setUserData } from "../redux/userSlice";
import { Alert } from "react-native";
-
-
export const fetchUserProfile = async () => {
- const dispatch = useDispatch();
- 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(
- `${BASE_URL}user/profile/view`,
- {
- method: "GET",
- headers: {
- Accept: "*/*",
- Authorization: `Bearer ${token}`,
- },
- }
- );
-
- const result = await response.json();
- console.log("user api data",result)
- if (result.status === "success") {
- 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
- }));
-
- console.log("splash user data:", result.data);
- } 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");
+ const dispatch = useDispatch();
+ 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(
+ `${BASE_URL}user/profile/view`,
+ {
+ method: "GET",
+ headers: {
+ Accept: "*/*",
+ Authorization: `Bearer ${token}`,
+ },
}
- };
\ No newline at end of file
+ );
+
+ const result = await response.json();
+ console.log("user api data", result)
+ if (result.status === "success") {
+ 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
+ }));
+
+ console.log("splash user data:", result.data);
+ } 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");
+ }
+};
\ No newline at end of file