diff --git a/src/screens/GroupScreen.tsx b/src/screens/GroupScreen.tsx index 70bfb14..83c83d2 100644 --- a/src/screens/GroupScreen.tsx +++ b/src/screens/GroupScreen.tsx @@ -22,7 +22,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, GET_JOINED_GROUP_URL, JOIN_GROUP_URL, PUBLIC_GROUPS_URL, PUT_USER_STATUS } from "../utils/ApiUrls"; +import { BASE_URL, GET_JOINED_GROUP_URL, JOIN_GROUP_URL, PUBLIC_GROUPS_URL, USER_STATUS } from "../utils/ApiUrls"; import colors from "../components/colors"; import { ApiResponse } from "./home/UserProfileStatus"; import * as Keychain from "react-native-keychain"; @@ -214,7 +214,7 @@ export default function GroupScreen() { setLoading(true); setError(null); - const response = await fetch(PUT_USER_STATUS, { + const response = await fetch(USER_STATUS, { method: "GET", headers: { Accept: "*/*", diff --git a/src/screens/home/Home.tsx b/src/screens/home/Home.tsx index 306c1a2..7849ad0 100644 --- a/src/screens/home/Home.tsx +++ b/src/screens/home/Home.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useState } from "react"; +import React, { useEffect, useState, useCallback } from "react"; import { StyleSheet, Text, @@ -9,12 +9,13 @@ import { FlatList, ListRenderItem, Alert, + RefreshControl, } from "react-native"; import AppView from "../../components/AppView"; import colors from "../../components/colors"; import { useDispatch, useSelector } from "react-redux"; import { useNavigation } from "@react-navigation/native"; -import { DASHBOARD_URL, PROFILE_URL } from "../../utils/ApiUrls"; +import { DASHBOARD_URL, PROFILE_URL, USER_STATUS } from "../../utils/ApiUrls"; import { setUserData } from "../../redux/userSlice"; import { TabNavigationProp } from "../../navigation/BottomTabs"; import UserProfileStatus from "./UserProfileStatus"; @@ -35,6 +36,7 @@ type UserProfile = { imageBlob: string | null; role?: string; organizerStatus?: string; + profileStatus?: boolean; }; interface ActionItem { @@ -42,29 +44,29 @@ interface ActionItem { title: string; action: string; tab?: "My Groups" | "Joined Groups" | "Requests" | "Your Requests"; - iconName?: string; + iconName?: any; backOne?: string; backTwo?: string; subtitle?: string; } const organizerActions: ActionItem[] = [ - { id: "1", title: "My Groups", subtitle: "Manage your groups", action: "NAVIGATE_MANAGEMENT", tab: "My Groups", iconName: "people-circle-outline", backOne: "#decbfcff", backTwo: "#B799FF" }, - { id: "2", title: "Joined Groups", subtitle: "View member groups", action: "NAVIGATE_MANAGEMENT", tab: "Joined Groups", iconName: "people-outline", backOne: "#D7E9F7", backTwo: "#82AAE3" }, - { id: "3", title: "Requests", subtitle: "Check new requests", action: "NAVIGATE_MANAGEMENT", tab: "Requests", iconName: "notifications-outline", backOne: "#DFF6DD", backTwo: "#88D18A" }, - { id: "4", title: "Create Group", subtitle: "Create a new group", action: "NAVIGATE_CREATE_GROUP", iconName: "add-circle-outline", backOne: "#FFF4D2", backTwo: "#FFB344" }, - { id: "2", title: "Your Requests", subtitle: "Track your requests", action: "NAVIGATE_MANAGEMENT", tab: "Your Requests", iconName: "mail-open-outline", backOne: "#FFF4D2", backTwo: "#FFB344" }, - { id: "3", title: "Transactions", subtitle: "View your history", action: "TRANSACTION", iconName: "receipt-outline", backOne: "#decbfcff", backTwo: "#B799FF" }, - + { id: "1", title: "My Groups", subtitle: "Manage groups", action: "NAVIGATE_MANAGEMENT", tab: "My Groups", iconName: "people-circle-outline", backOne: "#decbfcff", backTwo: "#B799FF" }, + { id: "2", title: "Joined Groups", subtitle: "View groups", action: "NAVIGATE_MANAGEMENT", tab: "Joined Groups", iconName: "people-outline", backOne: "#D7E9F7", backTwo: "#82AAE3" }, + { id: "3", title: "Requests", subtitle: "Check requests", action: "NAVIGATE_MANAGEMENT", tab: "Requests", iconName: "notifications-outline", backOne: "#DFF6DD", backTwo: "#88D18A" }, + { id: "4", title: "Create Group", subtitle: "Start new group", action: "NAVIGATE_CREATE_GROUP", iconName: "add-circle-outline", backOne: "#FFF4D2", backTwo: "#FFB344" }, + { id: "5", title: "Your Requests", subtitle: "Track requests", action: "NAVIGATE_MANAGEMENT", tab: "Your Requests", iconName: "mail-open-outline", backOne: "#FFF4D2", backTwo: "#FFB344" }, + { id: "6", title: "Transactions", subtitle: "View history", action: "TRANSACTION", iconName: "receipt-outline", backOne: "#decbfcff", backTwo: "#B799FF" }, ]; const userActions: ActionItem[] = [ - { id: "1", title: "Joined Groups", subtitle: "See your groups", action: "NAVIGATE_MANAGEMENT", tab: "Joined Groups", iconName: "person-outline", backOne: "#D7E9F7", backTwo: "#82AAE3" }, - { id: "2", title: "Your Requests", subtitle: "Track your requests", action: "NAVIGATE_MANAGEMENT", tab: "Your Requests", iconName: "mail-open-outline", backOne: "#FFF4D2", backTwo: "#FFB344" }, - { id: "3", title: "Transactions", subtitle: "View your history", action: "TRANSACTION", iconName: "receipt-outline", backOne: "#decbfcff", backTwo: "#B799FF" }, - { id: "4", title: "Create Group", subtitle: "Create a new group", action: "NAVIGATE_CREATE_GROUP", iconName: "add-circle-outline", backOne: "#DFF6DD", backTwo: "#88D18A" }, + { id: "1", title: "Joined Groups", subtitle: "See your groups", action: "NAVIGATE_MANAGEMENT", tab: "Joined Groups", iconName: "people-outline", backOne: "#D7E9F7", backTwo: "#82AAE3" }, + { id: "2", title: "Your Requests", subtitle: "Track requests", action: "NAVIGATE_MANAGEMENT", tab: "Your Requests", iconName: "mail-open-outline", backOne: "#FFF4D2", backTwo: "#FFB344" }, + { id: "3", title: "Transactions", subtitle: "View history", action: "TRANSACTION", iconName: "receipt-outline", backOne: "#decbfcff", backTwo: "#B799FF" }, + { id: "4", title: "Create Group", subtitle: "Start new group", action: "NAVIGATE_CREATE_GROUP", iconName: "add-circle-outline", backOne: "#DFF6DD", backTwo: "#88D18A" }, ]; + const Home: React.FC = () => { const user = useSelector((state: any) => state.user); const notifications = useSelector((state: any) => state.notifications.notifications); @@ -76,11 +78,13 @@ const Home: React.FC = () => { const [alertVisible, setAlertVisible] = useState(false); const [alertAction, setAlertAction] = useState(null); const [userDashboard, setUserDashboard] = useState(null); + const [refreshing, setRefreshing] = useState(false); + const [statusData, setStatusData] = useState(null); const getDashboardData = async () => { try { const result = (await apiCall(DASHBOARD_URL, "GET")) as any; - console.log("DASHBOARD_URL-------", result) if (result.status === "success") { + console.log("dashboard -----",result) setUserDashboard(result.data); } } catch (error) { @@ -88,23 +92,39 @@ const Home: React.FC = () => { } }; - useEffect(() => { - const fetchUserProfile = async () => { - try { - const result = (await apiCall(PROFILE_URL, "GET")) as any; - if (result.status === "success") { - setApiUser(result.data); - dispatch(setUserData({ ...result.data, profileStatus: true })); + const getUserStatus = async () => { + const result = await apiCall(USER_STATUS, "GET") as any; + setStatusData(result.data); } - } catch (error) { - console.error("❌ Error fetching profile:", error); + + const fetchUserProfile = async () => { + try { + const result = (await apiCall(PROFILE_URL, "GET")) as any; + console.log("profile data", result); + if (result.status === "success") { + setApiUser(result.data); + dispatch(setUserData({ ...result.data, profileStatus: true })); } - }; - const unsubscribe = navigation.addListener("focus", fetchUserProfile); - fetchUserProfile(); - getDashboardData(); - return unsubscribe; -}, [navigation, dispatch]); + } catch (error) { + console.error("❌ Error fetching profile:", error); + } + }; + + const fetchData = useCallback(async () => { + await Promise.all([fetchUserProfile(), getDashboardData(), getUserStatus()]); + }, []); + + const onRefresh = useCallback(async () => { + setRefreshing(true); + await fetchData(); + setRefreshing(false); + }, [fetchData]); + + useEffect(() => { + const unsubscribe = navigation.addListener("focus", fetchData); + fetchData(); + return unsubscribe; + }, [navigation, fetchData]); const handleActionPress = (item: ActionItem) => { if (item.action === "NAVIGATE_MANAGEMENT" && item.tab) { @@ -114,11 +134,10 @@ const Home: React.FC = () => { } else if (item.action === "NAVIGATE_CREATE_GROUP") { switch (apiUser?.organizerStatus) { case "NOT_APPLIED": - setAlertVisible(true); setAlertAction({ visible: true, - title: "Become Organizer", - message: "You have to become an organizer to create groups.", + title: "Become an Organizer", + message: "You need to be an organizer to create groups.", buttons: [ { text: "Continue", @@ -127,15 +146,12 @@ const Home: React.FC = () => { navigation.navigate("BecomeOrg" as never); }, }, - { - text: "Close", - onPress: () => setAlertVisible(false), - style: "cancel", - }, + { text: "Close", onPress: () => setAlertVisible(false), style: "cancel" }, ], alertType: "error", onClose: () => setAlertAction(null), }); + setAlertVisible(true); break; case "PENDING": Alert.alert("Pending Approval", "Your organizer request is still pending."); @@ -144,12 +160,12 @@ const Home: React.FC = () => { navigation.navigate("GroupCreation" as never); break; default: - Alert.alert("Unknown action", item.title); + Alert.alert("Unknown Status", "Could not determine your organizer status."); break; } } }; - + const unreadCount = notifications.filter((item: any) => !item.read).length; const renderGridItem: ListRenderItem = ({ item }) => ( @@ -166,7 +182,7 @@ const Home: React.FC = () => { const getProfileImageUri = () => { const blob = user.imageBlob || apiUser?.imageBlob; - return blob ? { uri: `data:image/jpeg;base64,${blob}` } : require("../../assets/images/placeholder.png"); + return blob ? { uri: `data:image/jpeg;base64,${blob}` } : undefined; }; return ( @@ -194,20 +210,27 @@ const Home: React.FC = () => { - + Quick Actions - Alert.alert("Info", "This will allow you to pay all pending contributions.")} - > - Pay All - + } contentContainerStyle={{ paddingBottom: 100 }} + refreshControl={ + + } /> {alertAction && ( @@ -217,6 +240,7 @@ const Home: React.FC = () => { buttons={alertAction.buttons} message={alertAction.message} alertType={"error"} + onClose={() => setAlertVisible(false)} /> )} @@ -239,14 +263,14 @@ const styles = StyleSheet.create({ paddingBottom: 16, }, greeting: { fontSize: 22, color: colors.textDark }, - userName: { fontSize: 28, fontWeight: "bold", color: colors.textDark }, - sectionTitle: { fontSize: 20, fontWeight: "600", color: colors.textDark }, + sectionTitle: { fontSize: 20, fontWeight: "600", color: colors.textDark, flex: 1 }, actionHeader: { flexDirection: "row", justifyContent: "space-between", alignItems: "center", marginHorizontal: 20, marginBottom: 10, + marginTop: 16 }, payAllButton: { paddingHorizontal: 14, diff --git a/src/screens/home/UserProfileStatus.tsx b/src/screens/home/UserProfileStatus.tsx index 2e604f4..50909ec 100644 --- a/src/screens/home/UserProfileStatus.tsx +++ b/src/screens/home/UserProfileStatus.tsx @@ -1,4 +1,4 @@ -import React, { useCallback, useEffect, useMemo, useRef, useState } from "react"; +import React, { useMemo, useState, useEffect } from "react"; import { StyleSheet, Text, @@ -7,343 +7,377 @@ import { Modal, ToastAndroid, Image, - Animated, + ScrollView, + ActivityIndicator, } 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 { useNavigation } from "@react-navigation/native"; import colors from "../../components/colors"; import LinearGradient from "react-native-linear-gradient"; import { Ionicons } from "@react-native-vector-icons/ionicons"; +import { apiCall } from "../../utils/ApiHelper"; +import { PAY_ALL_URL } from "../../utils/ApiUrls"; -export type ApiResponse = { - message: string; - status: string; - statusCode: number; - data: { - role: string; - organizerStatus: string; - profileStatus: boolean; - }; +type StatusData = { + role?: string; + organizerStatus?: string; + profileStatus?: boolean; +}; + +type DashboardData = { + totalPaidAmountMonth?: number; + multiplePayAmount?: number; + completeStatusMyGroupCount?: number; + activeStatusMyGroupCount?: number; + createdGroupActiveCount?: number; + createdGroupCompleteCount?: number; + myCreatedGroups?: any[]; + myJoinedGroups?: Array; + requestList?: any[]; + myRequests?: Array<{ status: string }>; + dueGroupDetails?: Array<{ + groupId: string; + groupName: string; + baseAmount: number; + lateFee: number; + waivedAmount: number; + totalDue: number; + dueDate: string; + isLate: boolean; + currentCycle: number; + lateFeeMode: string; + lateFeeValue: number; + hasPaid: boolean; + }>; }; type UserProfileStatusProps = { profileImage?: { uri: string }; + statusData: StatusData | null; + userDashboard: DashboardData | null; }; -const UserProfileStatus: React.FC = ({ profileImage }) => { +const UserProfileStatus: React.FC = ({ + profileImage, + statusData, + userDashboard, +}) => { const navigation = useNavigation(); - const [loading, setLoading] = useState(true); - const [statusData, setStatusData] = useState(null); const [showModal, setShowModal] = useState(false); - const [moreItem, setMoreItem] = useState(false); - // Animation refs to prevent re-creation on re-render - const fadeAnim = useRef(new Animated.Value(0)).current; - const scaleAnim = useRef(new Animated.Value(0.9)).current; + // Payment UI states + const [showPayDialog, setShowPayDialog] = useState(false); + const [selectedGroupIds, setSelectedGroupIds] = useState([]); + const [submitting, setSubmitting] = useState(false); - // Memoized icons list - const icons = useMemo( - () => ["person", "people", "person-add", "create", "card", "checkmark-done"], - [] - ); - - // Fetch user status - const userStatus = useCallback(async () => { - try { - const credentials = await Keychain.getGenericPassword(); - if (!credentials) { - ToastAndroid.show("You are not logged in", ToastAndroid.SHORT); - return; - } - - setLoading(true); - const token = credentials.password; - - const response = await fetch(PUT_USER_STATUS, { - method: "GET", - headers: { - Accept: "/", - Authorization: `Bearer ${token}`, - }, - }); - - const json: ApiResponse = await response.json(); - - if (json.status === "success") { - setStatusData(json.data); - if (!json.data.profileStatus) 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(); - }, [userStatus]) - ); - - // Animation start + // Preselect all due groups at mount and on change useEffect(() => { - Animated.parallel([ - Animated.timing(fadeAnim, { toValue: 1, duration: 600, useNativeDriver: true }), - Animated.timing(scaleAnim, { toValue: 1, duration: 600, useNativeDriver: true }), - ]).start(); - }, [fadeAnim, scaleAnim]); + if (userDashboard?.dueGroupDetails) { + setSelectedGroupIds(userDashboard.dueGroupDetails.map((g) => g.groupId)); + } + }, [userDashboard?.dueGroupDetails]); - const handleGoToProfile = useCallback(() => { - setShowModal(false); - navigation.navigate("Profile" as never); - }, [navigation]); + // Show profile completion modal only if profile is incomplete + useEffect(() => { + if (statusData && !statusData.profileStatus) setShowModal(true); + }, [statusData]); - const handlePress = useCallback((label: string) => { - ToastAndroid.show(`${label} clicked`, ToastAndroid.SHORT); - }, []); + // Top grid info items + const infoItems = useMemo( + () => [ + { label: "Role", value: statusData?.role || "-" }, + { label: "Active Groups", value: userDashboard?.activeStatusMyGroupCount?.toString() || "0" }, + { label: "Joined Groups", value: userDashboard?.myJoinedGroups?.length?.toString() || "0" }, + { label: "My Groups", value: userDashboard?.myCreatedGroups?.length?.toString() || "0" }, + { label: "Total Due", value: `₹${userDashboard?.multiplePayAmount || 0}` }, + { label: "Completed", value: userDashboard?.completeStatusMyGroupCount?.toString() || "0" }, + ], + [userDashboard, statusData] + ); + // Utility for info color const getValueColor = (value: string) => { if (value.includes("₹") || value === "Active" || value === "Yes ✅") return "#4CAF50"; if (value === "Inactive" || value === "No ❌") return "#FF6B6B"; return "#fff"; }; - const infoItems = useMemo( - () => [ - { label: "Role", value: statusData?.role || "-" }, - { label: "Active", value: "5" }, - { label: "Joined", value: "3" }, - { label: "Created", value: "2" }, - { label: "Due Pay", value: "₹1500" }, - { label: "Completed", value: "4" }, - ], - [statusData] + // Dues and payment logic + const dueGroups = userDashboard?.dueGroupDetails || []; + const totalDue = dueGroups.reduce((sum, item) => sum + (item.totalDue || 0), 0); + const totalDueSelected = useMemo( + () => + dueGroups + .filter((g) => selectedGroupIds.includes(g.groupId)) + .reduce((sum, item) => sum + (item.totalDue || 0), 0), + [dueGroups, selectedGroupIds] + ); + + const handleToggleGroup = (groupId: string) => { + setSelectedGroupIds((prev) => + prev.includes(groupId) + ? prev.filter((id) => id !== groupId) + : [...prev, groupId] + ); + }; + + const handlePayAll = async () => { + if (selectedGroupIds.length === 0) { + ToastAndroid.show("Select at least one group", ToastAndroid.SHORT); + return; + } + setSubmitting(true); + try { + const response = await apiCall(PAY_ALL_URL, 'POST',{ groupIds: selectedGroupIds, payAllDue: true }, undefined, "Payment failed. Try again."); + console.log("-=-=-=-=-=-=-=-=-=-=-=",response) + + // const response = await fetch( + // "https://api.godemo.in/FundCollect/api/payments/payments/bulk", + // { + // method: "POST", + // headers: { "Content-Type": "application/json" }, + // body: JSON.stringify({ groupIds: selectedGroupIds, payAllDue: true }), + // } + // ); + if (response.status) { + ToastAndroid.show("Payment initiated!", ToastAndroid.LONG); + setShowPayDialog(false); + } else { + ToastAndroid.show("Payment failed. Try again.", ToastAndroid.SHORT); + } + } catch { + ToastAndroid.show("Network error. Try again.", ToastAndroid.SHORT); + } + setSubmitting(false); + }; + + // Bottom bar + const renderDueBar = () => ( + + + Total Due: ₹{totalDue} + + setShowPayDialog(true)} + disabled={dueGroups.length === 0} + activeOpacity={0.8} + > + + Pay All + + + ); + + // Payment dialog modal + const renderPayDialog = () => ( + setShowPayDialog(false)}> + + + + + Select Groups to Pay + setShowPayDialog(false)}> + + + + + {dueGroups.map((group) => ( + handleToggleGroup(group.groupId)} + activeOpacity={0.85} + > + + + {group.groupName} + + ₹{group.baseAmount} + {group.lateFee > 0 ? ` (Late: ₹${group.lateFee})` : ""} + + + ₹{group.totalDue} + + ))} + + + + Total: ₹{totalDueSelected} + + + {submitting ? ( + + ) : ( + <> + + Pay Selected + + )} + + + + + ); return ( - - {/* Decorative Background */} - - {["circle1", "circle2", "circle3"].map((c, i) => ( - - ))} - - + - {/* Header */} - - - - Profile Overview - - - - - {statusData?.profileStatus ? "Verified" : "Pending"} - - + + + Profile Overview + + + + + {statusData?.profileStatus ? "Verified" : "Pending"} + - {/* Content Section */} - {/* LEFT SIDE */} - {infoItems.map((item, index) => ( - handlePress(item.label)} - > + {infoItems.map((item, idx) => ( + - + - {item.label} + + {item.label} + - + {item.value} - + ))} - - {/* RIGHT SIDE */} + + - navigation.navigate("Profile" as never)} activeOpacity={0.8}> - + navigation.navigate("Profile" as never)} + activeOpacity={0.8} + > + {profileImage ? ( ) : ( - + )} - + - View Profile - - - - setMoreItem(!moreItem)}> - + - {moreItem && ( - <> - - - - Status Overview - - - - - Organizer: {statusData?.organizerStatus || "-"} - - - Profile: {statusData?.profileStatus ? "Complete ✅" : "Incomplete ❌"} - - - - - - - Profile Completion - - {statusData?.profileStatus ? "100%" : "60%"} - - - - - - - - )} + {renderDueBar()} - {/* Modal */} + {renderPayDialog()} + {showModal && ( - + Complete Your Profile Your profile is incomplete. Update your details to unlock all features. - - + { + setShowModal(false); + navigation.navigate("Profile" as never); + }} + > Complete Profile - - setShowModal(false)} > Remind Later - + )} - + ); }; export default UserProfileStatus; - const styles = StyleSheet.create({ container: { - // margin: 16, - }, - backgroundGraphics: { - position: 'absolute', - width: '100%', - height: '100%', - zIndex: -1, - }, - floatingCircle: { - position: 'absolute', - borderRadius: 50, - backgroundColor: 'rgba(255,255,255,0.1)', - }, - circle1: { - width: 80, - height: 80, - top: -20, - left: -20, - }, - circle2: { - width: 60, - height: 60, - bottom: -10, - right: -10, - }, - circle3: { - width: 40, - height: 40, - top: '40%', - right: '10%', + marginHorizontal: 8, + marginBottom: 16, }, card: { borderRadius: 24, - padding: 20, + overflow: "hidden", elevation: 8, shadowColor: "#000", shadowOpacity: 0.3, shadowRadius: 10, shadowOffset: { width: 0, height: 4 }, - overflow: 'hidden', }, headerSection: { - marginBottom: 16, - }, - headerContent: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', + paddingTop: 16, + paddingHorizontal: 18, + marginBottom: 16, }, - titleWithIcon: { - flexDirection: 'row', - alignItems: 'center', + titleWithIcon: { + flexDirection: 'row', + alignItems: 'center' }, - headerIcon: { - marginRight: 8, + headerIcon: { + marginRight: 8 }, - header: { - fontSize: 22, - fontWeight: "700", - color: "#fff", + header: { + fontSize: 20, + fontWeight: "700", + color: "#fff" }, statusBadge: { flexDirection: 'row', @@ -353,99 +387,70 @@ const styles = StyleSheet.create({ paddingVertical: 6, borderRadius: 20, }, - statusBadgeText: { - color: "#fff", - fontSize: 12, - fontWeight: '600', - marginLeft: 4, + statusBadgeText: { + color: "#fff", + fontSize: 13, + fontWeight: '600', + marginLeft: 4 }, - contentSection: { - flexDirection: 'row', - justifyContent: 'space-between', + contentSection: { + flexDirection: 'row', + alignItems: 'flex-start', + paddingHorizontal: 16, + paddingBottom: 16, }, - leftSection: { - flex: 1, - marginRight: 16, + leftSection: { + flex: 1, + marginRight: 16 }, - infoGrid: { - flexDirection: 'row', - flexWrap: 'wrap', - justifyContent: 'space-between', - // marginBottom: 16, + infoGrid: { + flexDirection: 'row', + flexWrap: 'wrap', + gap: 10 }, infoCard: { - width: '48%', backgroundColor: 'rgba(255,255,255,0.15)', - borderRadius: 12, - padding: 5, - marginBottom: 8, + borderRadius: 14, + padding: 12, borderWidth: 1, borderColor: 'rgba(255,255,255,0.2)', + flex: 1, + minWidth: '45%', + marginBottom: 8, }, - infoCardHeader: { - flexDirection: 'row', - alignItems: 'center', - marginBottom: 6, + infoCardHeader: { + flexDirection: 'row', + alignItems: 'center', + marginBottom: 6 }, iconContainer: { - width: 24, - height: 24, + width: 28, + height: 28, backgroundColor: '#fff', - borderRadius: 6, + borderRadius: 8, justifyContent: 'center', alignItems: 'center', - marginRight: 6, - }, - infoLabel: { - color: "rgba(255,255,255,0.8)", - fontSize: 12, - fontWeight: '500', - }, - infoValue: { - fontWeight: "700", - fontSize: 16, - }, - statusOverview: { - backgroundColor: 'rgba(255,255,255,0.15)', - padding: 16, - borderRadius: 12, - borderWidth: 1, - borderColor: 'rgba(255,255,255,0.2)', - }, - statusHeader: { - flexDirection: 'row', - alignItems: 'center', - marginBottom: 12, - }, - statusOverviewTitle: { - color: "#fff", - fontSize: 16, - fontWeight: '600', - marginLeft: 6, - }, - statusItems: { - gap: 8, - }, - statusItem: { - flexDirection: 'row', - alignItems: 'center', - }, - statusIndicator: { marginRight: 8, }, - statusItemText: { - color: "#fff", - fontSize: 14, + infoLabel: { + color: "rgba(255,255,255,0.9)", + fontSize: 12, + fontWeight: '500', + flexShrink: 1, + }, + infoValue: { + fontWeight: "700", + fontSize: 16, + textAlign: 'left', + color: "#fff" }, profileSection: { + width: 90, alignItems: 'center', + justifyContent: 'center', }, - profileContainer: { - alignItems: 'center', - padding: 16, - borderRadius: 20, - borderWidth: 2, - borderColor: 'rgba(255,255,255,0.3)', + profileContainer: { + alignItems: 'center' }, avatar: { width: 80, @@ -466,52 +471,134 @@ const styles = StyleSheet.create({ }, profileBadge: { position: 'absolute', - top: 12, - right: 12, - width: 24, - height: 24, + bottom: 0, + right: 0, + width: 26, + height: 26, backgroundColor: '#fff', - borderRadius: 12, + borderRadius: 13, justifyContent: 'center', alignItems: 'center', }, - viewProfileText: { - color: "#fff", - fontSize: 12, - fontWeight: '600', - marginTop: 8, - }, - progressSection: { - marginTop: 16, - paddingTop: 16, + dueBar: { + flexDirection: "row", + justifyContent: "space-between", + alignItems: "center", + padding: 16, borderTopWidth: 1, - borderTopColor: 'rgba(255,255,255,0.3)', + borderColor: "rgba(255,255,255,0.15)", + backgroundColor: "rgba(0,0,0,0.15)", }, - progressHeader: { - flexDirection: 'row', - justifyContent: 'space-between', - alignItems: 'center', + dueBarText: { + color: "#fff", + fontSize: 16, + fontWeight: "600" + }, + payAllButton: { + backgroundColor: "#ffffffff", + flexDirection: "row", + alignItems: "center", + paddingHorizontal: 16, + paddingVertical: 10, + borderRadius: 20, + gap: 6, + }, + payAllButtonText: { + color: "#000000ff", + fontWeight: "bold", + fontSize: 16 + }, + payModalOverlay: { + flex: 1, + backgroundColor: "rgba(0,0,0,0.3)", + justifyContent: "center", + alignItems: "center", + }, + payModalBox: { + width: "92%", + borderRadius: 24, + overflow: "hidden", + alignItems: "center", + shadowColor: "#000", + shadowOpacity: 0.15, + shadowRadius: 24, + elevation: 12, + }, + payDialogHeader: { + flexDirection: "row", + alignItems: "center", + width: "100%", + justifyContent: "space-between", + paddingVertical: 14, + paddingHorizontal: 18, + borderBottomWidth: 1, + borderColor: "rgba(255,255,255,0.1)", + }, + payDialogTitle: { + color: "#000000ff", + fontSize: 18, + fontWeight: "700" + }, + payGroupOption: { + flexDirection: "row", + alignItems: "center", + gap: 16, + paddingVertical: 12, + paddingHorizontal: 14, + borderColor: colors.primary, + borderWidth: 1, + borderRadius: 12, marginBottom: 8, }, - progressText: { - color: "#fff", - fontSize: 14, - fontWeight: '600', + payOptionSelected: { + backgroundColor: "rgba(166, 49, 255, 0.2)", + borderColor: colors.primary, + borderWidth: 1, }, - progressPercent: { - color: "#fff", - fontSize: 14, - fontWeight: '700', + payGroupName: { + color: "#000000ff", + fontWeight: "700", + fontSize: 16 }, - progressBar: { - height: 6, - backgroundColor: 'rgba(255,255,255,0.3)', - borderRadius: 3, - overflow: 'hidden', + payDueText: { + color: "rgba(0, 0, 0, 0.8)", + fontSize: 13, + marginTop: 2 }, - progressFill: { - height: '100%', - borderRadius: 3, + payAmount: { + fontWeight: "bold", + fontSize: 16, + color: "#4CAF50" + }, + payDialogFooter: { + flexDirection: "row", + alignItems: "center", + width: "100%", + justifyContent: "space-between", + paddingVertical: 16, + paddingHorizontal: 18, + }, + payDialogTotal: { + color: "#000000ff", + fontWeight: "600", + fontSize: 17 + }, + payConfirmButton: { + flexDirection: "row", + alignItems: "center", + backgroundColor: colors.primary, + paddingVertical: 12, + paddingHorizontal: 24, + borderRadius: 20, + elevation: 4, + borderColor:colors.primary, + borderWidth:1, + gap: 8, + }, + payButtonText: { + color: "#ffffffff", + fontWeight: "bold", + fontSize: 16 }, modalOverlay: { flex: 1, @@ -526,23 +613,6 @@ const styles = StyleSheet.create({ padding: 24, alignItems: "center", elevation: 12, - shadowColor: "#000", - shadowOpacity: 0.3, - shadowRadius: 15, - shadowOffset: { width: 0, height: 6 }, - }, - modalGraphic: { - position: 'relative', - marginBottom: 16, - }, - modalPulse: { - position: 'absolute', - top: -10, - left: -10, - right: -10, - bottom: -10, - borderRadius: 40, - backgroundColor: 'rgba(76, 175, 80, 0.2)', }, modalTitle: { fontSize: 22, @@ -558,38 +628,15 @@ const styles = StyleSheet.create({ lineHeight: 20, marginBottom: 20, }, - modalProgress: { - width: '100%', - marginBottom: 20, - }, - modalProgressText: { - textAlign: 'center', - color: "#333", - fontSize: 12, - fontWeight: '600', - marginBottom: 6, - }, - modalProgressBar: { - height: 4, - backgroundColor: '#f0f0f0', - borderRadius: 2, - overflow: 'hidden', - }, - modalProgressFill: { - height: '100%', - backgroundColor: colors.primary, - borderRadius: 2, - }, modalButtons: { width: '100%', - gap: 8, + gap: 10, }, button: { flexDirection: 'row', alignItems: 'center', justifyContent: 'center', - paddingVertical: 12, - paddingHorizontal: 24, + paddingVertical: 14, borderRadius: 12, gap: 8, }, @@ -604,9 +651,9 @@ const styles = StyleSheet.create({ buttonText: { color: "#fff", fontWeight: "600", - fontSize: 14, + fontSize: 16, }, secondaryText: { color: "#666", }, -}); \ No newline at end of file +}); diff --git a/src/screens/management/EditGroupScreen.tsx b/src/screens/management/EditGroupScreen.tsx index d0d1861..a925e5d 100644 --- a/src/screens/management/EditGroupScreen.tsx +++ b/src/screens/management/EditGroupScreen.tsx @@ -863,7 +863,7 @@ const styles = StyleSheet.create({ infoValue: { fontSize: 16, fontWeight: "600", color: "#111827", textTransform: "capitalize" }, input: { backgroundColor: "#F9FAFB", borderWidth: 1, borderColor: "#D1D5DB", borderRadius: 10, padding: 14, fontSize: 16, color: "#111827" }, textArea: { height: 100, textAlignVertical: "top" }, - picker: { backgroundColor: "#F9FAFB", borderWidth: 1, borderColor: "#D1D5DB", borderRadius: 10 }, + picker: { backgroundColor: "#F9FAFB", borderWidth: 1, borderColor: "#D1D5DB", borderRadius: 10 ,color:colors.black}, participantRow: { flexDirection: "row", justifyContent: "space-between", alignItems: "center", paddingVertical: 12, borderBottomWidth: 1, borderBottomColor: "#F3F4F6" }, participantName: { fontSize: 16, fontWeight: "600", color: "#111827" }, participantMobile: { fontSize: 14, color: "#6B7280", marginTop: 4 }, diff --git a/src/screens/management/Payments.tsx b/src/screens/management/Payments.tsx index 74d43aa..eef0178 100644 --- a/src/screens/management/Payments.tsx +++ b/src/screens/management/Payments.tsx @@ -131,7 +131,7 @@ const Payments: React.FC = () => { } try { - const url = `http://192.168.1.18:9060/api/payments/groups/${groupId}/cycles/${paymentDetails.currentCycle}/waive/${currentParticipant.userId}?amountToWaive=${amountToWaive}`; + const url = `https://api.godemo.in/FundCollect/api/payments/groups/${groupId}/cycles/${paymentDetails.currentCycle}/waive/${currentParticipant.userId}?amountToWaive=${amountToWaive}`; const response = await apiCall(url, 'PUT', {}) as any; if (response && response.statusCode === 200) { diff --git a/src/screens/profile/Profile.tsx b/src/screens/profile/Profile.tsx index 42e08f9..fc7a82a 100644 --- a/src/screens/profile/Profile.tsx +++ b/src/screens/profile/Profile.tsx @@ -23,7 +23,7 @@ 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 { BASE_URL, PUT_USER_PROFILE, PUT_USER_PROFILE_IMG, USER_STATUS } from "../../utils/ApiUrls"; import AppView from "../../components/AppView"; import { useDispatch } from "react-redux"; import { clearUser, setUserData } from "../../redux/userSlice"; @@ -265,7 +265,7 @@ const Profile = () => { setLoading(true); setError(null); - const response = await fetch(PUT_USER_STATUS, { + const response = await fetch(USER_STATUS, { method: "GET", headers: { Accept: "*/*", diff --git a/src/utils/ApiUrls.tsx b/src/utils/ApiUrls.tsx index 3026c5a..9570ecb 100644 --- a/src/utils/ApiUrls.tsx +++ b/src/utils/ApiUrls.tsx @@ -1,5 +1,5 @@ -export const BASE_URL = "http://192.168.1.18:9060/api/" +export const BASE_URL = "https://api.godemo.in/FundCollect/api/" // export const BASE_URL = "http://192.168.1.5:9060/api/" export const LOGIN_URL = `${BASE_URL}user/generate/otp?mobiles=` export const VARIFY_OTP_URL = `${BASE_URL}user/otp/verify` @@ -15,7 +15,7 @@ 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 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`; @@ -24,4 +24,5 @@ export const TRANSACTION = `${BASE_URL}payments/my-transactions`; export const UPLOAD_GROUP_IMAGE = `${BASE_URL}fund/groups/`; export const STORE_FCM_TOKEN = `${BASE_URL}token/store?fcmToken=` export const REMOVE_FCM_TOKEN = `${BASE_URL}token/remove?fcmToken=` -export const DASHBOARD_URL = `${BASE_URL}fund/dashboard` \ No newline at end of file +export const DASHBOARD_URL = `${BASE_URL}fund/dashboard` +export const PAY_ALL_URL = `${BASE_URL}payments/payments/bulk` \ No newline at end of file