diff --git a/src/components/common/Header.tsx b/src/components/common/Header.tsx index 9ce3fd0..6b932b3 100644 --- a/src/components/common/Header.tsx +++ b/src/components/common/Header.tsx @@ -18,8 +18,8 @@ const Header: React.FC = ({ showBack = true, onBackPress, rightAction, - titleColor = colors.primary, - arrowColor = colors.primary + titleColor = '#000', + arrowColor = '#000' }) => { const navigation = useNavigation(); @@ -33,12 +33,12 @@ const Header: React.FC = ({ return ( - {/* {showBack && ( + {showBack && ( - )} */} - {title} + )} + {title} {rightAction} ); @@ -57,6 +57,6 @@ const styles = StyleSheet.create({ headerTitle: { fontSize: 18, fontWeight: "600", - textTransform:'uppercase' + textTransform: "capitalize", }, }); diff --git a/src/screens/GroupScreen.tsx b/src/screens/GroupScreen.tsx index e97539c..32d48de 100644 --- a/src/screens/GroupScreen.tsx +++ b/src/screens/GroupScreen.tsx @@ -190,7 +190,8 @@ export default function GroupScreen() { try { const credentials = await Keychain.getGenericPassword(); if (!credentials) { - Alert.alert("Error", "You are not logged in"); + ToastAndroid.show('You are not logged in', ToastAndroid.SHORT); + return; } const token = credentials.password; @@ -233,7 +234,7 @@ export default function GroupScreen() { const handleViewGroup = (group: Group) => { // navigation.navigate('GroupDetails', { group }); - Alert.alert("View Group", `Viewing details for ${group.groupName}`); + ToastAndroid.show(`Viewing details for ${group.groupName}`, ToastAndroid.SHORT); }; const onRefresh = () => { diff --git a/src/screens/InviteScreen.tsx b/src/screens/InviteScreen.tsx index 5373457..58b9a4d 100644 --- a/src/screens/InviteScreen.tsx +++ b/src/screens/InviteScreen.tsx @@ -8,6 +8,7 @@ import { TouchableOpacity, Alert, ActivityIndicator, + ToastAndroid, } from 'react-native'; import { RootStackParamList } from '../navigation/AppNavigator'; // Adjust path import { apiCall } from '../utils/ApiHelper'; // Adjust path @@ -78,9 +79,10 @@ const InviteScreen: FC = ({ route }) => { // Replace with your actual API call to join the group // For now, it just shows an alert. await apiCall(`http://192.168.1.5:9060/api/fund/groups/join/invite/${code}`, 'POST'); - Alert.alert('Success!', `You have requested to join "${groupDetails.groupName}".`); + ToastAndroid.show(`You have requested to join "${groupDetails.groupName}".`, ToastAndroid.SHORT); + fetchGroupDetails(); // Refresh details after joining } catch (e: any) { - Alert.alert('Join Error', e.message || 'An unexpected error occurred.'); + ToastAndroid.show(e.message || 'An unexpected error occurred.', ToastAndroid.SHORT); } finally { setJoining(false); } diff --git a/src/screens/OrgnizerRagister.tsx b/src/screens/OrgnizerRagister.tsx index ef8fcc5..b20b083 100644 --- a/src/screens/OrgnizerRagister.tsx +++ b/src/screens/OrgnizerRagister.tsx @@ -9,6 +9,7 @@ import { KeyboardAvoidingView, Platform, ScrollView, + ToastAndroid, } from "react-native"; import axios from "axios"; import { ORGRAGISTRATION } from "../utils/ApiUrls"; @@ -30,7 +31,7 @@ export default function OrganizerRegisterScreen() { const [loading, setLoading] = useState(false); const handleSubmit = async () => { if (!bankAccountNumber || !bankName || !branchCode) { - Alert.alert("Error", "All fields are required."); + ToastAndroid.show('All fields are required.', ToastAndroid.SHORT); return; } @@ -42,7 +43,7 @@ const handleSubmit = async () => { const token = creds ? creds.password : null; if (!token) { - Alert.alert("Error", "No token found. Please log in again."); + ToastAndroid.show('No token found. Please log in again.', ToastAndroid.SHORT); setLoading(false); return; } @@ -65,10 +66,13 @@ const handleSubmit = async () => { ); console.log("✅ Organizer Registered:", res.data); - Alert.alert("Success", "Organizer registered successfully!"); + ToastAndroid.show('Organizer registered successfully!', ToastAndroid.SHORT); + // Optionally, reset form fields + setBankAccountNumber(""); + setBankName(""); + setBranchCode(""); } catch (err: any) { console.error("❌ Register Error:", err?.response?.data || err.message); - // Alert.alert("Error", "Failed to register. Please try again."); } finally { setLoading(false); } diff --git a/src/screens/home/GroupList.tsx b/src/screens/home/GroupList.tsx index ece029d..b38c208 100644 --- a/src/screens/home/GroupList.tsx +++ b/src/screens/home/GroupList.tsx @@ -77,7 +77,7 @@ const GroupList = () => { const fetchGroups = async () => { const credentials = await keychain.getGenericPassword(); if (!credentials) { - Alert.alert("Error", "You are not logged in"); + ToastAndroid.show('You are not logged in', ToastAndroid.SHORT); return; } const token = credentials.password; diff --git a/src/screens/home/Home.tsx b/src/screens/home/Home.tsx index 902200a..1b9bdb8 100644 --- a/src/screens/home/Home.tsx +++ b/src/screens/home/Home.tsx @@ -10,6 +10,7 @@ import { Alert, FlatList, ListRenderItem, + ToastAndroid, } from "react-native"; import AppView from "../../components/AppView"; import colors from "../../components/colors"; @@ -188,13 +189,12 @@ const Home: React.FC = () => { {user.firstName || apiUser?.firstName || 'User'} navigation.navigate("Notification" as never)}> - {/* */} {unreadCount > 0 ? unreadCount : ''} - + Quick Actions @@ -240,13 +240,6 @@ const styles = StyleSheet.create({ fontWeight: 'bold', color: colors.textDark, }, - profileImage: { - width: 50, - height: 50, - borderRadius: 25, - borderColor: colors.pastelPink, // Using pastelPink for border - borderWidth: 2, - }, sectionTitle: { fontSize: 20, fontWeight: '600', diff --git a/src/screens/home/RequestList.tsx b/src/screens/home/RequestList.tsx index ca29730..1e4f04b 100644 --- a/src/screens/home/RequestList.tsx +++ b/src/screens/home/RequestList.tsx @@ -8,7 +8,8 @@ import { RefreshControl, Alert, ActivityIndicator, - TextInput + TextInput, + ToastAndroid } from 'react-native'; import { Ionicons } from '@react-native-vector-icons/ionicons'; import colors from '../../components/colors'; @@ -50,7 +51,7 @@ const RequestList: React.FC = () => { const credentials = await keychain.getGenericPassword(); if (!credentials) { - Alert.alert("Error", "You are not logged in"); + ToastAndroid.show('You are not logged in', ToastAndroid.SHORT); return; } const token = credentials.password; @@ -146,14 +147,13 @@ const RequestList: React.FC = () => { // Remove the accepted request from the list const updatedRequests = requests.filter(req => req.requestId !== requestId); setRequests(updatedRequests); - Alert.alert("Success", data.message || "Request accepted successfully"); + ToastAndroid.show(data.message || "Request accepted successfully", ToastAndroid.SHORT); fetchRequests(); } else { throw new Error(data.message || "Failed to accept request"); } } catch (error) { const errorMessage = error instanceof Error ? error.message : "An unknown error occurred"; - // Alert.alert("Error", `Failed to accept request: ${errorMessage}`); console.error("Accept Error:", error); } finally { setProcessingRequest(null); @@ -192,14 +192,15 @@ const RequestList: React.FC = () => { // Remove the declined request from the list const updatedRequests = requests.filter(req => req.requestId !== selectedRequestId); setRequests(updatedRequests); - Alert.alert("Success", data.message || "Request declined successfully"); + ToastAndroid.show(data.message || "Request declined successfully", ToastAndroid.SHORT); + fetchRequests(); } else { throw new Error(data.message || "Failed to decline request"); } } catch (error) { const errorMessage = error instanceof Error ? error.message : "An unknown error occurred"; - // Alert.alert("Error", `Failed to decline request: ${errorMessage}`); + console.error("Decline Error:", error); } finally { setProcessingRequest(null); diff --git a/src/screens/home/UserProfileStatus.tsx b/src/screens/home/UserProfileStatus.tsx index 92d80ce..7592dab 100644 --- a/src/screens/home/UserProfileStatus.tsx +++ b/src/screens/home/UserProfileStatus.tsx @@ -1,249 +1,314 @@ -import React, { use, useCallback, useEffect, useState } from "react"; +import React, { useCallback, useEffect, useState } from "react"; import { - StyleSheet, - Text, - View, - ActivityIndicator, - TouchableOpacity, - Modal, - Alert, + StyleSheet, + Text, + View, + TouchableOpacity, + Modal, + ToastAndroid, + Image, + Animated, } from "react-native"; import * as Keychain from "react-native-keychain"; import { useFocusEffect, useNavigation } from "@react-navigation/native"; import { PUT_USER_STATUS } from "../../utils/ApiUrls"; import colors from "../../components/colors"; import LinearGradient from "react-native-linear-gradient"; -import Ionicons from "@react-native-vector-icons/ionicons"; +import {Ionicons} from "@react-native-vector-icons/ionicons"; export type ApiResponse = { - message: string; - status: string; - statusCode: number; - data: { - role: string; - organizerStatus: string; - profileStatus: boolean; - }; + message: string; + status: string; + statusCode: number; + data: { + role: string; + organizerStatus: string; + profileStatus: boolean; + }; }; +type UserProfileStatusProps = { + profileImage?: { uri: string }; +}; -const UserProfileStatus: React.FC = () => { - const navigation = useNavigation(); - const [loading, setLoading] = useState(true); - const [statusData, setStatusData] = useState(null); - const [error, setError] = useState(null); - const [showModal, setShowModal] = useState(false); - const [intervalId, setIntervalId] = useState(null); +const UserProfileStatus: React.FC = ({ profileImage }) => { + const navigation = useNavigation(); + const [loading, setLoading] = useState(true); + const [statusData, setStatusData] = useState(null); + const [showModal, setShowModal] = useState(false); + const [intervalId, setIntervalId] = useState(null); + const fadeAnim = useState(new Animated.Value(0))[0]; - 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) { + ToastAndroid.show("You are not logged in", ToastAndroid.SHORT); + return; + } + const token = credentials.password; - setLoading(true); - setError(null); - const response = await fetch(PUT_USER_STATUS, { - method: "GET", - headers: { - Accept: "*/*", - Authorization: `Bearer ${token}`, - }, - }); + setLoading(true); + const response = await fetch(PUT_USER_STATUS, { + method: "GET", + headers: { + Accept: "*/*", + Authorization: `Bearer ${token}`, + }, + }); - const json: ApiResponse = await response.json(); - - console.log("Profile Status :", json); - if (json.status === "success") { - setStatusData(json.data); - - if (json.data.profileStatus === false) { - setShowModal(true); - } - } else { - setError(json.message || "Failed to fetch status"); - } - } catch (err) { - setError("Something went wrong. Please try again."); - } finally { - setLoading(false); + const json: ApiResponse = await response.json(); + if (json.status === "success") { + setStatusData(json.data); + if (json.data.profileStatus === false) { + setShowModal(true); } - }; + } else { + ToastAndroid.show("Failed to fetch status", ToastAndroid.SHORT); + } + } catch { + ToastAndroid.show("Something went wrong", ToastAndroid.SHORT); + } finally { + setLoading(false); + } + }; - useFocusEffect( - useCallback(() => { - userStatus(); - }, []) - ); + useFocusEffect( + useCallback(() => { + userStatus(); + }, []) + ); - useEffect(() => { - if (statusData && statusData.profileStatus === false) { - const id = setInterval(() => { - setShowModal(true); - }, 5000); - setIntervalId(id); - return () => clearInterval(id); - } - }, [statusData]); + useEffect(() => { + Animated.timing(fadeAnim, { + toValue: 1, + duration: 600, + useNativeDriver: true, + }).start(); + }, []); - const handleGoToProfile = () => { - // Stop modal repetition - if (intervalId) { - clearInterval(intervalId); - setIntervalId(null); - } + const handleGoToProfile = () => { + if (intervalId) { + clearInterval(intervalId); + setIntervalId(null); + } + setShowModal(false); + navigation.navigate("Profile" as never); + }; - setShowModal(false); + const handlePress = (label: string) => { + ToastAndroid.show(`${label} clicked`, ToastAndroid.SHORT); + }; - // Option 1: Mark profile as completed temporarily (so condition stops) - setStatusData(prev => (prev ? { ...prev, profileStatus: true } : prev)); + return ( + + + {/* LEFT SECTION */} + + Profile Overview - // Navigate to Profile screen - navigation.navigate("Profile" as never); - }; - - return ( - - {/* Welcome Back 👋 */} - - - - Profile Status - Role: {statusData?.role} - Organizer: {statusData?.organizerStatus} - - Profile Completed: {statusData?.profileStatus ? "Yes ✅" : "No ❌"} - - - - - - - {/* Custom Modal */} - {showModal && ( - setShowModal(false)} + + + {[ + "Role", + "Total Active Groups", + "Total Joined Groups", + "Total Created Groups", + "Total Due Payment", + "Total Completed Groups", + ].map((label, i) => ( + handlePress(label)} > - - - Complete Your Profile - - Your profile is incomplete. Please update your details to continue. - + {label} + + ))} + - - Go to Profile - + + {[ + statusData?.role || "-", + "5", + "3", + "2", + "₹1500", + "4", + ].map((value, i) => ( + handlePress(value)} + > + {value} + + ))} + + - { - if (intervalId) { - clearInterval(intervalId); - setIntervalId(null); - } - - setShowModal(false); - }} - > - Close - - - - - )} + + + Organizer: {statusData?.organizerStatus || "-"} + + + Profile Completed:{" "} + {statusData?.profileStatus ? "Yes ✅" : "No ❌"} + + - ); -}; + {/* RIGHT SECTION - IMAGE */} + {/* navigation.navigate("Profile" as never)} + activeOpacity={0.8} + > + {profileImage ? ( + + ) : ( + + )} + */} + + + {/* Modal */} + {showModal && ( + + + + + Complete Your Profile + + Your profile is incomplete. Please update your details to continue. + + + + Go to Profile + + + setShowModal(false)} + > + Later + + + + + )} + + ); +}; export default UserProfileStatus; const styles = StyleSheet.create({ - container: { - // flex: 1, - // padding: 16, - // backgroundColor: "#f5f7fb", - }, - centered: { - flex: 1, - justifyContent: "center", - alignItems: "center", - }, - title: { - fontSize: 22, - fontWeight: "700", - marginBottom: 20, - }, - card: { - backgroundColor: "#fff", - padding: 16, - borderRadius: 12, - elevation: 3, - shadowOpacity: 0.1, - shadowRadius: 6, - marginBottom: 10, - justifyContent:'space-between', - flexDirection:'row' - }, - cardTitle: { - fontSize: 18, - fontWeight: "600", - marginBottom: 10, - color: '#fff' - }, - button: { - backgroundColor: "#007AFF", - paddingVertical: 10, - paddingHorizontal: 20, - borderRadius: 8, - alignItems: "center", - }, - buttonText: { - color: "#fff", - fontWeight: "600", - }, - errorText: { - color: "red", - fontSize: 16, - marginBottom: 12, - }, - modalOverlay: { - flex: 1, - backgroundColor: "rgba(0,0,0,0.4)", - justifyContent: "center", - alignItems: "center", - }, - modalBox: { - width: "85%", - backgroundColor: "#fff", - borderRadius: 16, - padding: 20, - alignItems: "center", - elevation: 5, - }, - modalTitle: { - fontSize: 20, - fontWeight: "700", - marginBottom: 10, - color: colors.primary, - }, - modalText: { - fontSize: 14, - color: "#444", - textAlign: "center", - marginBottom: 20, - }, + container: { + margin: 12, + }, + card: { + flexDirection: "row", + justifyContent: "space-between", + alignItems: "center", + borderRadius: 16, + padding: 18, + elevation: 5, + shadowColor: "#000", + shadowOpacity: 0.2, + shadowRadius: 6, + }, + header: { + fontSize: 20, + fontWeight: "700", + color: "#fff", + marginBottom: 10, + }, + leftSection: { + flex: 1, + }, + infoRow: { + flexDirection: "row", + justifyContent: "space-between", + marginBottom: 10, + }, + infoLabelBox: { + marginBottom: 6, + }, + infoLabel: { + color: "rgba(255,255,255,0.8)", + fontSize: 13, + }, + infoValueBox: { + marginBottom: 6, + alignItems: "flex-end", + }, + infoValue: { + color: "#fff", + fontWeight: "600", + fontSize: 13, + }, + statusBox: { + backgroundColor: "rgba(255,255,255,0.15)", + padding: 10, + borderRadius: 8, + }, + statusText: { + color: "#fff", + fontSize: 13, + }, + avatar: { + width: 80, + height: 80, + borderRadius: 40, + borderWidth: 2, + borderColor: "#fff", + }, + modalOverlay: { + flex: 1, + backgroundColor: "rgba(0,0,0,0.5)", + justifyContent: "center", + alignItems: "center", + }, + modalBox: { + width: "85%", + backgroundColor: "#fff", + borderRadius: 18, + padding: 20, + alignItems: "center", + elevation: 6, + }, + modalTitle: { + fontSize: 20, + fontWeight: "700", + color: colors.primary, + marginVertical: 8, + }, + modalText: { + textAlign: "center", + color: "#444", + fontSize: 14, + marginBottom: 18, + }, + button: { + backgroundColor: colors.primary, + paddingVertical: 10, + paddingHorizontal: 30, + borderRadius: 8, + marginTop: 8, + }, + buttonText: { + color: "#fff", + fontWeight: "600", + }, + secondaryButton: { + backgroundColor: "#eee", + }, + secondaryText: { + color: "#333", + }, }); diff --git a/src/screens/home/user-home/UserHome.tsx b/src/screens/home/user-home/UserHome.tsx index 869de65..beded4a 100644 --- a/src/screens/home/user-home/UserHome.tsx +++ b/src/screens/home/user-home/UserHome.tsx @@ -1,249 +1,267 @@ -import React, { useEffect, useState } from "react"; -import { - StyleSheet, - Text, - View, - FlatList, - TouchableOpacity, - Alert, - RefreshControl, - ScrollView, - Button, -} from "react-native"; -import { useNavigation } from "@react-navigation/native"; -import type { NativeStackNavigationProp } from "@react-navigation/native-stack"; -import type { RootStackParamList } from "../../../navigation/AppNavigator"; -import colors from "../../../components/colors"; -import { Ionicons } from "@react-native-vector-icons/ionicons"; -import { GET_JOINED_GROUP_URL } from "../../../utils/ApiUrls"; -import * as Keychain from "react-native-keychain"; -import AnimatedCard from "../../../components/common/AnimatedCard"; +// import React, { useEffect, useState } from "react"; +// import { +// StyleSheet, +// Text, +// View, +// FlatList, +// TouchableOpacity, +// Alert, +// RefreshControl, +// ScrollView, +// Button, +// ToastAndroid, +// } from "react-native"; +// import { useNavigation } from "@react-navigation/native"; +// import type { NativeStackNavigationProp } from "@react-navigation/native-stack"; +// import type { RootStackParamList } from "../../../navigation/AppNavigator"; +// import colors from "../../../components/colors"; +// import { Ionicons } from "@react-native-vector-icons/ionicons"; +// import { GET_JOINED_GROUP_URL } from "../../../utils/ApiUrls"; +// import * as Keychain from "react-native-keychain"; +// import AnimatedCard from "../../../components/common/AnimatedCard"; -type NavigationProp = NativeStackNavigationProp< - RootStackParamList, - "GroupDetails" ->; +// type NavigationProp = NativeStackNavigationProp< +// RootStackParamList, +// "GroupDetails" +// >; -type Group = { - id: string; - groupName: string; - description: string; - currentParticipants: number; - maxParticipants: number; - contributionAmount: number; - status: string; -}; +// type Group = { +// id: string; +// groupName: string; +// description: string; +// currentParticipants: number; +// maxParticipants: number; +// contributionAmount: number; +// status: string; +// }; + +// const UserHome = () => { +// const navigation = useNavigation(); +// const [groups, setGroups] = useState([]); +// const [loading, setLoading] = useState(false) +// const [refreshing, setRefreshing] = useState(false) + + +// const activeGroups = groups.filter((g) => g.status === "ACTIVE"); + +// const totalGroups = activeGroups.length; + +// const totalContribution = activeGroups.reduce( +// (sum, g) => sum + g.contributionAmount, +// 0 +// ); + +// const onRefresh = async () => { +// setRefreshing(true) +// await handleGroup() +// setRefreshing(false) +// } + +// const handleGroup = async () => { +// try { +// setLoading(true) +// const credentials = await Keychain.getGenericPassword(); +// if (!credentials) { +// ToastAndroid.show('You are not logged in', ToastAndroid.SHORT); +// return; +// } +// const token = credentials.password; + +// const response = await fetch(GET_JOINED_GROUP_URL, { +// method: "GET", +// headers: { +// Accept: "*/*", +// Authorization: `Bearer ${token}`, +// }, +// }); + +// const result = await response.json(); +// if (result.status === "success") { +// console.log("GET_JOINED_GROUP_URL res : ", result); +// setGroups(result.data); // save API data +// setLoading(false) +// } else { +// ToastAndroid.show("Failed to fetch groups", ToastAndroid.SHORT); +// setLoading(false) +// } +// } catch (error) { +// console.error("❌ Error fetching groups:", error); +// } finally { +// setLoading(false) +// } +// }; + +// useEffect(() => { +// handleGroup(); +// }, []); + +// const renderItem = ({ item }: { item: Group }) => { +// return ( +// navigation.navigate("GroupDetails", { item })} +// > +// {item.groupName} +// {item.description} +// +// +// +// {item.currentParticipants}/{item.maxParticipants} members +// +// + +// +// Contribution: ₹{item.contributionAmount} +// +// Status: {item.status} +// +// ); +// }; + +// return ( +// +// {/* Stats */} + +// {/*