diff --git a/src/screens/GroupCreation.tsx b/src/screens/GroupCreation.tsx index 62a08bf..e51bd18 100644 --- a/src/screens/GroupCreation.tsx +++ b/src/screens/GroupCreation.tsx @@ -52,12 +52,12 @@ export default function GroupCreationForm() { const newErrors: any = {}; if (!form.groupName.trim()) newErrors.groupName = "Group name is required."; if (!form.description.trim()) newErrors.description = "Description is required."; - if (!form.minParticipants || Number(form.minParticipants) <= 1) newErrors.minParticipants = "Min participants must be at least 2."; + if (!form.minParticipants || Number(form.minParticipants) <= 0) newErrors.minParticipants = "Min participants must be at least 1."; if (!form.maxParticipants || Number(form.maxParticipants) < Number(form.minParticipants)) newErrors.maxParticipants = "Max must be greater than or equal to min."; if (!form.contributionAmount || Number(form.contributionAmount) <= 0) newErrors.contributionAmount = "Amount must be greater than 0."; - // if (form.cycleType === "CUSTOM" && (!form.customCycleDays || Number(form.customCycleDays) <= 0)) newErrors.customCycleDays = "Custom days must be greater than 0."; - if (form.lateFeeMode && (!form.lateFeeValue || Number(form.lateFeeValue) <= 0)) newErrors.lateFeeValue = "Late fee value is required."; - + if (form.cycleType === "CUSTOM" && (!form.customCycleDays || Number(form.customCycleDays) <= 0)) newErrors.customCycleDays = "Custom days must be greater than 0."; + if (!form.lateFeeMode && (!form.lateFeeValue || Number(form.lateFeeValue) <= 0)) newErrors.lateFeeValue = "Late fee value is required."; + console.log("new errors : ", newErrors) setErrors(newErrors); return Object.keys(newErrors).length === 0; }; @@ -82,7 +82,6 @@ export default function GroupCreationForm() { return ( - { Alert.alert("Success", "Organizer registered successfully!"); } catch (err: any) { console.error("❌ Register Error:", err?.response?.data || err.message); - Alert.alert("Error", "Failed to register. Please try again."); + // Alert.alert("Error", "Failed to register. Please try again."); } finally { setLoading(false); } diff --git a/src/screens/home/RequestList.tsx b/src/screens/home/RequestList.tsx index a99bb99..e19c964 100644 --- a/src/screens/home/RequestList.tsx +++ b/src/screens/home/RequestList.tsx @@ -152,7 +152,7 @@ const RequestList: React.FC = () => { } } catch (error) { const errorMessage = error instanceof Error ? error.message : "An unknown error occurred"; - Alert.alert("Error", `Failed to accept request: ${errorMessage}`); + // Alert.alert("Error", `Failed to accept request: ${errorMessage}`); console.error("Accept Error:", error); } finally { setProcessingRequest(null); @@ -198,7 +198,7 @@ const RequestList: React.FC = () => { } } catch (error) { const errorMessage = error instanceof Error ? error.message : "An unknown error occurred"; - Alert.alert("Error", `Failed to decline request: ${errorMessage}`); + // Alert.alert("Error", `Failed to decline request: ${errorMessage}`); console.error("Decline Error:", error); } finally { setProcessingRequest(null); diff --git a/src/screens/home/user-home/UserHome.tsx b/src/screens/home/user-home/UserHome.tsx index 57da78e..869de65 100644 --- a/src/screens/home/user-home/UserHome.tsx +++ b/src/screens/home/user-home/UserHome.tsx @@ -84,7 +84,7 @@ const UserHome = () => { } } catch (error) { console.error("❌ Error fetching groups:", error); - Alert.alert("Error", "Could not connect to server"); + // Alert.alert("Error", "Could not connect to server"); } finally { setLoading(false) } diff --git a/src/screens/management/EditGroupScreen.tsx b/src/screens/management/EditGroupScreen.tsx index 20f9f04..fc6832a 100644 --- a/src/screens/management/EditGroupScreen.tsx +++ b/src/screens/management/EditGroupScreen.tsx @@ -22,12 +22,14 @@ import Clipboard from '@react-native-clipboard/clipboard'; import { CompositeScreenProps, useNavigation } from '@react-navigation/native'; import { BottomTabScreenProps } from '@react-navigation/bottom-tabs'; // Adjust path -import { UPLOAD_GROUP_IMAGE } from '../../utils/ApiUrls'; +import { BASE_URL, UPLOAD_GROUP_IMAGE } from '../../utils/ApiUrls'; import { launchImageLibrary } from 'react-native-image-picker'; import *as Keychain from 'react-native-keychain' import Ionicons from '@react-native-vector-icons/ionicons'; import { CustomButton } from '../../components/common/Custom'; import { StackNavigationProp } from '@react-navigation/stack'; +import CustomModal from '../../components/common/CustomModal'; +import WinnerUser from './WinnerUser'; // --- Type Definitions --- @@ -91,7 +93,9 @@ type EditingCard = 'groupInfo' | 'financialRules' | 'configuration' | null; type GroupManagementNavProp = StackNavigationProp; // --- Main Screen Component --- const EditGroupScreen: React.FC = ({ route }) => { - const { groupId } = route.params; + const { groupId } = route?.params; + + console.log("edit group screen groupId : ", route?.params) const navigation = useNavigation(); const [editingCard, setEditingCard] = useState(null); @@ -118,7 +122,8 @@ const EditGroupScreen: React.FC = ({ route }) => { const [currentCycle, setCurrentCycle] = useState(null); const [selectedImage, setSelectedImage] = useState() const [imageUpdating, setImageUpdating] = useState(false) - + const [selectedUser, setSelectedUser] = useState() as any + const [selectedUserModal, setSelectedUserModel] = useState(false) const initializeEditableData = (data: GroupDetails) => { setEditableData({ groupName: data.groupName, @@ -139,8 +144,9 @@ const EditGroupScreen: React.FC = ({ route }) => { setLoading(true); setError(null); try { - const response = await apiCall(`http://192.168.1.9:9060/api/fund/group/details?groupId=${groupId}`, 'GET') as { status: string; data?: GroupDetails; message?: string }; + const response = await apiCall(`${BASE_URL}fund/group/details?groupId=${groupId}`, 'GET') as { status: string; data?: GroupDetails; message?: string }; console.log("groupDetails", response) + if (response.status === 'success' && response.data) { setGroupDetails(response.data); initializeEditableData(response.data); @@ -153,19 +159,32 @@ const EditGroupScreen: React.FC = ({ route }) => { setLoading(false); } }, [groupId]); -const getPaymentStatus = async()=>{ - const response = await apiCall(`http://192.168.1.9:9060/api/payments/group/${groupId}/payment/paid`, 'GET') as { status: string; data?: { currentCycle: number ,allPaid: boolean }; message?: string }; - console.log("paymentStatus",response) - if (response.status === 'success') { - setPaymentStatus(response.data?.allPaid || false); - setCurrentCycle(response.data?.currentCycle || null); - } -} + // const getPaymentStatus = async()=>{ + // const response = await apiCall(`${BASE_URL}payments/group/${groupId}/payment/paid`, 'GET') as { status: string; data?: { currentCycle: number ,status: boolean }; message?: string }; + // console.log("paymentStatus",response) + // if (response.status === 'success') { + // setPaymentStatus(response.data?.status || false); + // setCurrentCycle(response.data?.currentCycle || null); + // } + // } + const getPaymentStatus = async () => { + const response = await apiCall(`${BASE_URL}payments/group/${groupId}/payment/paid`, 'GET') as { status: string; data?: { currentCycle: number, allPaid: boolean, selectedUser: any }; message?: string }; + console.log("paymentStatus", response) + if (response.status === 'success') { + setPaymentStatus(response.data?.allPaid || false); + setCurrentCycle(response.data?.currentCycle || null); + setSelectedUser(response.data) + } + } + + console.log("groupid : ", groupId) + useEffect(() => { + getPaymentStatus() + }, []) useEffect(() => { fetchGroupDetails(); - getPaymentStatus(); }, [fetchGroupDetails]); @@ -188,7 +207,7 @@ const getPaymentStatus = async()=>{ setSaving(true); try { - await apiCall(`http://192.168.1.9:9060/api/fund/groups/${groupDetails.id}/edit`, 'PUT', editableData); + await apiCall(`${BASE_URL}fund/groups/${groupDetails.id}/edit`, 'PUT', editableData); Alert.alert('Success', 'Group has been updated.'); setEditingCard(null); await fetchGroupDetails(); @@ -198,10 +217,14 @@ const getPaymentStatus = async()=>{ setSaving(false); } }; + + const handleDistribute = async () => { - navigation.navigate('RandomSelectUserScreen', { groupId: groupDetails?.id || '', cycleNumber: currentCycle || 0 }); + navigation.navigate('RandomSelectUserScreen', { groupId , cycleNumber: currentCycle || 0 }); }; + + const handleStartGroup = async () => { if (!groupDetails) return; @@ -216,9 +239,10 @@ const getPaymentStatus = async()=>{ onPress: async () => { setStarting(true); try { - await apiCall(`http://192.168.1.9:9060/api/fund/group/start?groupId=${groupDetails.id}`, 'GET'); + await apiCall(`${BASE_URL}fund/group/start?groupId=${groupDetails.id}`, 'GET'); Alert.alert('Success', 'Group has been started successfully.'); await fetchGroupDetails(); + navigation.goBack() } catch (e: any) { Alert.alert('Start Error', e.message || 'An unexpected error occurred.'); } finally { @@ -235,7 +259,7 @@ const getPaymentStatus = async()=>{ if (!groupDetails) return; setInviting(true); try { - const response = await apiCall(`http://192.168.1.9:9060/api/invite/generate?groupId=${groupDetails.id}`, 'GET') as { data?: string }; + const response = await apiCall(`${BASE_URL}invite/generate?groupId=${groupDetails.id}`, 'GET') as { data?: string }; const inviteLink = response.data; @@ -354,6 +378,7 @@ const getPaymentStatus = async()=>{ const isInvitable = groupDetails.status === 'APPROVED'; const canStartGroup = groupDetails.status === 'APPROVED' && groupDetails.totalParticipants >= groupDetails.minParticipants; + console.log(" myu status : ", groupDetails.status) // const pickImage = () => { // launchImageLibrary({ mediaType: "photo", quality: 0.5 }, (response) => { // if (response.didCancel) return; @@ -403,7 +428,7 @@ const getPaymentStatus = async()=>{ console.log("✅ Image selected:", { uri: selectedImage.uri, - size: (selectedImage.fileSize / 1024).toFixed(2) + "KB", + size: (selectedImage?.fileSize / 1024).toFixed(2) + "KB", width: selectedImage.width, height: selectedImage.height }); @@ -461,7 +486,7 @@ const getPaymentStatus = async()=>{ } catch (error: any) { console.error("❌ Error updating group image:", error); - Alert.alert("Error", error.message || "Could not update group image"); + // Alert.alert("Error", error.message || "Could not update group image"); } finally { setImageUpdating(false); } @@ -580,7 +605,7 @@ const getPaymentStatus = async()=>{ )} - {paymentStatus && ( + {selectedUser?.cycleStatus !== "PENDING_PAYMENTS" && groupDetails.status === 'ACTIVE' &&( { )} - )} + ) + } + + { + selectedUser?.selectedUser !== null && selectedUser?.cycleStatus === "READY_FOR_WITHDRAWAL" && selectedUser?.canProceedToWithdrawal && + + setSelectedUserModel(true)} + /> + + } + + { + selectedUserModal && setSelectedUserModel(false)} /> + } ); }; diff --git a/src/screens/management/ManagementScreen.tsx b/src/screens/management/ManagementScreen.tsx index 4efbc3f..d394f08 100644 --- a/src/screens/management/ManagementScreen.tsx +++ b/src/screens/management/ManagementScreen.tsx @@ -108,7 +108,7 @@ const ManagementScreen: FC = () => { throw new Error(res?.message || failureMessage); } } catch (err: any) { - Alert.alert("Error", err.message || "An unexpected error occurred."); + // Alert.alert("Error", err.message || "An unexpected error occurred."); } }; diff --git a/src/screens/management/Payments.tsx b/src/screens/management/Payments.tsx index 01946cd..bfe6301 100644 --- a/src/screens/management/Payments.tsx +++ b/src/screens/management/Payments.tsx @@ -5,6 +5,7 @@ import { Ionicons } from "@react-native-vector-icons/ionicons"; import colors from '../../components/colors'; import AppView from '../../components/AppView'; import { apiCall } from '../../utils/ApiHelper'; +import { BASE_URL } from '../../utils/ApiUrls'; // --- CONSTANTS --- const API_BASE_URL = 'http://192.168.1.9:9060/api/payments'; @@ -73,14 +74,17 @@ const Payments: React.FC = () => { const fetchPaymentDetails = useCallback(async () => { if (!refreshing) setLoading(true); try { - const response = await apiCall(`${API_BASE_URL}/current/payment/details/${groupId}`, 'GET') as ApiResponse; + const response = await apiCall(`${BASE_URL}payments/current/payment/details/${groupId}`, 'GET') as ApiResponse; + + console.log("payment response :", response) if (response && response.statusCode === 200) { setPaymentDetails(response.data); } else { Alert.alert("Error", response?.message || "Failed to fetch details."); } } catch (error: any) { - Alert.alert("Error", error.message || "An unexpected error occurred."); + // Alert.alert("Error", error.message || "An unexpected error occurred."); + console.log("payment error : ", error) } finally { setLoading(false); setRefreshing(false); @@ -122,9 +126,9 @@ const Payments: React.FC = () => { try { // Construct the exact URL as provided - const url = `${API_BASE_URL}/groups/${groupId}/cycles/${paymentDetails.currentCycle}/waive/${currentParticipant.userId}?amountToWaive=${amountToWaive}`; + const url = `${BASE_URL}groups/${groupId}/cycles/${paymentDetails.currentCycle}/waive/${currentParticipant.userId}?amountToWaive=${amountToWaive}`; - const response = await apiCall(url, 'PUT', {}); // Body is empty as amount is in URL + const response = await apiCall(url, 'PUT', {}) as any; // Body is empty as amount is in URL if (response && response.statusCode === 200) { Alert.alert("Success", `₹${amountToWaive} has been waived successfully.`); diff --git a/src/screens/management/RandomSelectUserScreen.tsx b/src/screens/management/RandomSelectUserScreen.tsx index 1d05154..1cddebb 100644 --- a/src/screens/management/RandomSelectUserScreen.tsx +++ b/src/screens/management/RandomSelectUserScreen.tsx @@ -4,14 +4,17 @@ import { apiCall } from '../../utils/ApiHelper'; import { Ionicons } from "@react-native-vector-icons/ionicons"; import { useNavigation } from '@react-navigation/native'; import ContributionDetails from '../ContributionScreen'; +import { BASE_URL } from '../../utils/ApiUrls'; const { width } = Dimensions.get('window'); const NUM_COLUMNS = 3; const ITEM_SIZE = width / NUM_COLUMNS - 20; const RandomSelectUserScreen: React.FC<{ route: any }> = ({ route }) => { - const navigation = useNavigation() as never + const navigation = useNavigation() const { groupId, cycleNumber } = route.params; + + const [users, setUsers] = useState<{ id: string; name: string }[]>([]); const [highlightedIndex, setHighlightedIndex] = useState(null); const [winner, setWinner] = useState<{ id: string; name: string } | null>(null); @@ -24,7 +27,7 @@ const RandomSelectUserScreen: React.FC<{ route: any }> = ({ route }) => { useEffect(() => { const fetchParticipants = async () => { try { - const response = await apiCall(`http://192.168.1.9:9060/api/fund/group/all/member?groupId=${groupId}`, "GET") as any; + const response = await apiCall(`${BASE_URL}fund/group/all/member?groupId=${groupId}`, "GET") as any; if (response.status === 'success' && response.data) { const formattedUsers = response.data.map((u: any) => ({ id: u.id, @@ -77,7 +80,7 @@ const RandomSelectUserScreen: React.FC<{ route: any }> = ({ route }) => { const fetchWinner = async () => { const payload = { groupId: groupId }; try { - const response = await apiCall('http://192.168.1.9:9060/api/fund/method/based/userSelect', 'POST', payload) as any; + const response = await apiCall(`${BASE_URL}fund/method/based/userSelect`, 'POST', payload) as any; console.log("random select user response : ", response) if (response.status === 'success' && response.data?.selectedUser?.id) { const winnerData = { id: response?.data?.selectedUser?.id, name: `${response.data.selectedUser.firstName} ${response.data.selectedUser.lastName}` }; @@ -92,6 +95,7 @@ const RandomSelectUserScreen: React.FC<{ route: any }> = ({ route }) => { } else { Alert.alert('Error', 'Failed to determine a winner from the API.'); } + navigation.navigate('EditGroup',{groupId}) } catch (error) { // Alert.alert('Error', 'Could not connect to the server to fetch the winner.'); } finally { @@ -156,7 +160,6 @@ const RandomSelectUserScreen: React.FC<{ route: any }> = ({ route }) => { )} -