diff --git a/src/components/colors.ts b/src/components/colors.ts index a318f82..2fc9052 100644 --- a/src/components/colors.ts +++ b/src/components/colors.ts @@ -22,6 +22,8 @@ const colors = { // Special background colors with transparency alertBackground: "rgba(255, 255, 255, 0.8)", androidBackdrop: "rgba(0, 0, 0, 0.4)", + warning:'#b9b61cff', + danger:'#f04814ff' }; export default colors; diff --git a/src/screens/InviteScreen.tsx b/src/screens/InviteScreen.tsx index d5735cf..5373457 100644 --- a/src/screens/InviteScreen.tsx +++ b/src/screens/InviteScreen.tsx @@ -13,6 +13,7 @@ import { RootStackParamList } from '../navigation/AppNavigator'; // Adjust path import { apiCall } from '../utils/ApiHelper'; // Adjust path import AppView from '../components/AppView'; // Adjust path import colors from '../components/colors'; // Adjust path +import { BASE_URL } from '../utils/ApiUrls'; // --- Type Definitions --- interface Participant { @@ -52,7 +53,7 @@ const InviteScreen: FC = ({ route }) => { setLoading(true); setError(null); try { - const response = await apiCall(`http://192.168.1.5: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 }; if (response.status === 'success' && response.data) { setGroupDetails(response.data); } else { diff --git a/src/screens/home/RequestList.tsx b/src/screens/home/RequestList.tsx index 7c1683b..ca29730 100644 --- a/src/screens/home/RequestList.tsx +++ b/src/screens/home/RequestList.tsx @@ -14,6 +14,7 @@ import { Ionicons } from '@react-native-vector-icons/ionicons'; import colors from '../../components/colors'; import DeclineModal from './DeclineModal'; import * as keychain from 'react-native-keychain' +import { BASE_URL } from '../../utils/ApiUrls'; // Define TypeScript interfaces interface GroupRequest { @@ -58,7 +59,7 @@ const RequestList: React.FC = () => { setError(null); const response = await fetch( - "http://192.168.1.5:9060/api/fund/group/pending/request", + `${BASE_URL}`, { method: "GET", headers: { diff --git a/src/screens/management/EditGroupScreen.tsx b/src/screens/management/EditGroupScreen.tsx index cea8d12..11aa315 100644 --- a/src/screens/management/EditGroupScreen.tsx +++ b/src/screens/management/EditGroupScreen.tsx @@ -71,6 +71,7 @@ export interface EditGroupPayload { groupName: string; description: string; maxParticipants: number; + minParticipants?:number; contributionAmount: number; customCycleDays: number | null; cycleType: 'QUARTERLY' | 'MONTHLY' | 'WEEKLY' | 'CUSTOM'; @@ -288,7 +289,7 @@ const EditGroupScreen: React.FC = ({ route }) => { }; - const renderField = (field: keyof EditGroupPayload, label: string, displayValue: string | number, isEditing: boolean, isEditable: boolean) => { + const renderField = (field: keyof EditGroupPayload, label: string, displayValue: string | number, isEditing: boolean, isEditable?: boolean) => { const commonInputProps = { style: styles.input, placeholderTextColor: "#9CA3AF" }; const getInputForField = () => { @@ -426,12 +427,12 @@ const EditGroupScreen: React.FC = ({ route }) => { return; } - console.log("✅ Image selected:", { - uri: selectedImage.uri, - size: (selectedImage?.fileSize / 1024).toFixed(2) + "KB", - width: selectedImage.width, - height: selectedImage.height - }); + // console.log("✅ Image selected:", { + // uri: selectedImage.uri, + // size: (selectedImage?.fileSize / 1024).toFixed(2) + "KB", + // width: selectedImage.width, + // height: selectedImage.height + // }); setSelectedImage(selectedImage.uri); }); @@ -605,7 +606,7 @@ const EditGroupScreen: React.FC = ({ route }) => { )} - {selectedUser?.cycleStatus !== "PENDING_PAYMENTS" && groupDetails.status === 'ACTIVE' &&( + {selectedUser?.cycleStatus !== "PENDING_PAYMENTS" && groupDetails.status === 'ACTIVE' && selectedUser?.cycleStatus === "PENDING_SELECTION" &&( = ({ route }) => { } { - selectedUser?.selectedUser !== null && selectedUser?.cycleStatus === "READY_FOR_WITHDRAWAL" && selectedUser?.canProceedToWithdrawal && + selectedUser?.selectedUser !== null && selectedUser?.cycleStatus === "READY_FOR_WITHDRAWAL" && ; + +interface Props { + route: MemberScreenRouteProp; +} // --- Main Screen Component --- // This assumes the component receives `groupId` from a navigator (e.g., Tab Navigator) -const MemberScreen = ({ route }) => { +const MemberScreen = ({ route }: Props) => { const { groupId } = route.params; const [members, setMembers] = useState([]); @@ -51,12 +61,12 @@ const MemberScreen = ({ route }) => { setError('Group ID is missing.'); setLoading(false); return; - } + } setLoading(true); try { const response = await apiCall( - `http://192.168.1.5:9060/api/fund/group/all/member?groupId=${groupId}`, + `${BASE_URL}fund/group/all/member?groupId=${groupId}`, 'GET' ); @@ -90,13 +100,13 @@ const MemberScreen = ({ route }) => { {initial} - - {fullName} + + {fullName} {isOrganizer && ( - - Orginzer - - )} + + Orginzer + + )} @{item.username} @@ -126,9 +136,9 @@ const MemberScreen = ({ route }) => { if (members.length === 0) { return ( - - No Members Yet - Invite people to join your group. + + No Members Yet + Invite people to join your group. ) } @@ -145,7 +155,7 @@ const MemberScreen = ({ route }) => { }; return ( - + Group Members {members.length} member(s) diff --git a/src/screens/management/RandomSelectUserScreen.tsx b/src/screens/management/RandomSelectUserScreen.tsx index 1cddebb..9614821 100644 --- a/src/screens/management/RandomSelectUserScreen.tsx +++ b/src/screens/management/RandomSelectUserScreen.tsx @@ -5,17 +5,22 @@ import { Ionicons } from "@react-native-vector-icons/ionicons"; import { useNavigation } from '@react-navigation/native'; import ContributionDetails from '../ContributionScreen'; import { BASE_URL } from '../../utils/ApiUrls'; +import colors from '../../components/colors'; 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() - const { groupId, cycleNumber } = route.params; +interface User { + id: string; + name: string; + selected: boolean; +} - - const [users, setUsers] = useState<{ id: string; name: string }[]>([]); +const RandomSelectUserScreen: React.FC<{ route: any }> = ({ route }) => { + const navigation = useNavigation() + const { groupId, cycleNumber } = route.params; + const [users, setUsers] = useState([]); const [highlightedIndex, setHighlightedIndex] = useState(null); const [winner, setWinner] = useState<{ id: string; name: string } | null>(null); const [isAnimating, setIsAnimating] = useState(false); @@ -28,11 +33,15 @@ const RandomSelectUserScreen: React.FC<{ route: any }> = ({ route }) => { const fetchParticipants = async () => { try { 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, name: `${u.firstName} ${u.lastName}`, + selected: u?.selected })); + console.log("all mem : ", formattedUsers) + setUsers(formattedUsers); } else { Alert.alert('Error', 'Failed to fetch participants.'); @@ -56,18 +65,53 @@ const RandomSelectUserScreen: React.FC<{ route: any }> = ({ route }) => { } }, [highlightedIndex]); + // const handleStartSelection = () => { + // if (users.length === 0 || isAnimating) return; + + // setWinner(null); + // setIsAnimating(true); + + // let highlightCount = 0; + // const maxHighlights = 30 + Math.floor(Math.random() * 10); // Add some randomness + + // const highlightInterval = setInterval(() => { + // const randomIndex = Math.floor(Math.random() * users.length); + // setHighlightedIndex(randomIndex); + // highlightCount++; + + // if (highlightCount >= maxHighlights) { + // clearInterval(highlightInterval); + // fetchWinner(); + // } + // }, 120); + // }; + + + + const handleStartSelection = () => { - if (users.length === 0 || isAnimating) return; + // Exclude already selected users + const availableUsers = users.filter(u => !u.selected); + + if (availableUsers.length === 0 || isAnimating) { + Alert.alert('Info', 'All users are already selected.'); + return; + } setWinner(null); setIsAnimating(true); let highlightCount = 0; - const maxHighlights = 30 + Math.floor(Math.random() * 10); // Add some randomness + const maxHighlights = 30 + Math.floor(Math.random() * 10); const highlightInterval = setInterval(() => { - const randomIndex = Math.floor(Math.random() * users.length); - setHighlightedIndex(randomIndex); + const randomIndex = Math.floor(Math.random() * availableUsers.length); + const selectedUser = availableUsers[randomIndex]; + + // Get original index in `users` for highlighting + const originalIndex = users.findIndex(u => u.id === selectedUser.id); + setHighlightedIndex(originalIndex); + highlightCount++; if (highlightCount >= maxHighlights) { @@ -81,7 +125,7 @@ const RandomSelectUserScreen: React.FC<{ route: any }> = ({ route }) => { const payload = { groupId: groupId }; try { const response = await apiCall(`${BASE_URL}fund/method/based/userSelect`, 'POST', payload) as any; - console.log("random select user response : ", response) + 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}` }; const winnerIndex = users.findIndex(u => u.id === winnerData.id); @@ -95,7 +139,7 @@ const RandomSelectUserScreen: React.FC<{ route: any }> = ({ route }) => { } else { Alert.alert('Error', 'Failed to determine a winner from the API.'); } - navigation.navigate('EditGroup',{groupId}) + navigation.replace('EditGroup', { groupId }) } catch (error) { // Alert.alert('Error', 'Could not connect to the server to fetch the winner.'); } finally { @@ -103,7 +147,7 @@ const RandomSelectUserScreen: React.FC<{ route: any }> = ({ route }) => { } }; - const renderItem = ({ item, index }: { item: { id: string; name: string }, index: number }) => { + const renderItem = ({ item, index }: { item: { id: string; name: string, selected: boolean }, index: number }) => { const isHighlighted = index === highlightedIndex; const isWinner = winner?.id === item.id && !isAnimating; @@ -119,6 +163,7 @@ const RandomSelectUserScreen: React.FC<{ route: any }> = ({ route }) => { isHighlighted && styles.highlightedItem, isWinner && styles.winnerItem, animatedStyle, + { backgroundColor: item?.selected ? colors.pastelGreen : '#fff' } ]} > @@ -223,14 +268,14 @@ const styles = StyleSheet.create({ borderWidth: 1, borderColor: '#e5e7eb', padding: 8, - shadowColor: "#000", - shadowOffset: { - width: 0, - height: 2, - }, - shadowOpacity: 0.1, - shadowRadius: 3.84, - elevation: 5, + // shadowColor: "#000", + // shadowOffset: { + // width: 0, + // height: 2, + // }, + // shadowOpacity: 0.1, + // shadowRadius: 3.84, + // elevation: 5, }, highlightedItem: { borderWidth: 5, diff --git a/src/screens/management/WinnerUser.tsx b/src/screens/management/WinnerUser.tsx index 87eaf18..d69e7d2 100644 --- a/src/screens/management/WinnerUser.tsx +++ b/src/screens/management/WinnerUser.tsx @@ -33,7 +33,7 @@ interface WinnerUserProps { } visible: boolean onClose: () => void - groupId:string + groupId:string | number } const WinnerUser: React.FC = ({ data, visible, onClose, groupId }) => { diff --git a/src/screens/profile/BecomeOrg.tsx b/src/screens/profile/BecomeOrg.tsx index ba9a94b..dad17c9 100644 --- a/src/screens/profile/BecomeOrg.tsx +++ b/src/screens/profile/BecomeOrg.tsx @@ -16,6 +16,7 @@ import colors from "../../components/colors"; import { useNavigation } from "@react-navigation/native"; import AppView from "../../components/AppView"; import { Ionicons } from "@react-native-vector-icons/ionicons"; +import { BASE_URL } from "../../utils/ApiUrls"; const BecomeOrg = () => { const navigation = useNavigation(); @@ -43,7 +44,7 @@ const BecomeOrg = () => { const token = credentials.password; const response = await fetch( - "http://192.168.1.5:9060/api/organizer/registration/apply", + `${BASE_URL}organizer/registration/apply`, { method: "POST", headers: {