diff --git a/src/components/JoinedGroupCard.tsx b/src/components/JoinedGroupCard.tsx index a9f7fc6..16046c3 100644 --- a/src/components/JoinedGroupCard.tsx +++ b/src/components/JoinedGroupCard.tsx @@ -29,12 +29,15 @@ interface JoinedGroupCardProps { hasPaid?: boolean; // whether user has already paid } -const formatDate = (dateArray: [number, number, number] | null): string => { - if (!dateArray) return 'N/A'; - const date = new Date(dateArray[0], dateArray[1] - 1, dateArray[2]); - return date.toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' }); +const formatDate = (dateStr: string | null): string => { + if (!dateStr) return 'N/A'; + + const [year, month, day] = dateStr.split('-'); + return `${day}-${month}-${year}`; }; + + const getStatusStyle = (status: JoinedGroup['status']) => { switch (status) { case 'ACTIVE': @@ -67,6 +70,9 @@ export const JoinedGroupCard: FC = ({ item, onViewPress, h const [loading, setLoading] = React.useState(false); const [payable, setPayable] = React.useState(); + + + const onPayPress = async () => { // Navigate to payment screen or handle payment logic // navigation.navigate('PaymentScreen', { groupId: item.id, amount: item.contributionAmount }); @@ -126,18 +132,29 @@ export const JoinedGroupCard: FC = ({ item, onViewPress, h {/* Footer with Dates & Buttons */} - {formatDate(item.startDate)} - {formatDate(item.endDate)} + {formatDate(item.startDate)} to {formatDate(item.endDate)} {/* Add Pay / Paid button here */} - {hasPaid ? ( + {/* {hasPaid ? ( Paid ) : ( + - {loading ? 'Loading...' : 'Pay'} + {loading ? 'Loading...' : ' Pay'} - )} + )} */} + { + hasPaid && + Paid + + } + { + item.status !== 'COMPLETED' && + {loading ? 'Loading...' : ' Pay'} + + } ); diff --git a/src/components/common/Header.tsx b/src/components/common/Header.tsx index 6b932b3..9e25417 100644 --- a/src/components/common/Header.tsx +++ b/src/components/common/Header.tsx @@ -37,7 +37,7 @@ const Header: React.FC = ({ - )} + )} {title} {rightAction} @@ -49,14 +49,15 @@ export default Header; const styles = StyleSheet.create({ header: { flexDirection: "row", - alignItems: "center", - justifyContent: "space-between", + // alignItems: "center", + // justifyContent: "space-between", paddingVertical: 12, paddingHorizontal:12 }, headerTitle: { - fontSize: 18, + fontSize: 22, fontWeight: "600", - textTransform: "capitalize", + // textTransform: "capitalize", }, + }); diff --git a/src/screens/home/UserProfileStatus.tsx b/src/screens/home/UserProfileStatus.tsx index 3efacc5..3dc82f3 100644 --- a/src/screens/home/UserProfileStatus.tsx +++ b/src/screens/home/UserProfileStatus.tsx @@ -69,6 +69,7 @@ const UserProfileStatus: React.FC = ({ const [selectedGroupIds, setSelectedGroupIds] = useState([]); const [submitting, setSubmitting] = useState(false); + // console.log("user me : ", userDashboard) // Preselect all due groups at mount and on change useEffect(() => { if (userDashboard?.dueGroupDetails) { @@ -77,22 +78,25 @@ const UserProfileStatus: React.FC = ({ }, [userDashboard?.dueGroupDetails]); // Show profile completion modal only if profile is incomplete + + console.log("userDashboard : ", userDashboard) useEffect(() => { if (statusData && !statusData.profileStatus) setShowModal(true); }, [statusData]); // 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] - ); + () => [ + { icon: , label: "Role", value: statusData?.role || "-" }, + { icon: , label: "Active Groups", value: userDashboard?.activeStatusMyGroupCount?.toString() || "0" }, + { icon: , label: "Joined Groups", value: userDashboard?.myJoinedGroups?.length?.toString() || "0" }, + { icon: , label: "My Groups", value: userDashboard?.myCreatedGroups?.length?.toString() || "0" }, + { icon: , label: "Total Due", value: `₹${userDashboard?.multiplePayAmount || 0}` }, + { icon: , label: "Completed", value: userDashboard?.completeStatusMyGroupCount?.toString() || "0" }, + ], + [userDashboard, statusData] +); + // Utility for info color const getValueColor = (value: string) => { @@ -127,18 +131,9 @@ const UserProfileStatus: React.FC = ({ } setSubmitting(true); try { - const response = await apiCall(PAY_ALL_URL, 'POST',{ groupIds: selectedGroupIds }, undefined, "Payment failed. Try again.") as any; - - 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 }), - // } - // ); + const response = await apiCall(PAY_ALL_URL, 'POST', { groupIds: selectedGroupIds }, undefined, "Payment failed. Try again.") as any; + + console.log("-=-=-=-=-=-=-=-=-=-=-=", response) if (response.status) { ToastAndroid.show("Payment initiated!", ToastAndroid.LONG); setShowPayDialog(false); @@ -186,7 +181,7 @@ const UserProfileStatus: React.FC = ({ - @@ -261,7 +256,6 @@ const UserProfileStatus: React.FC = ({ - @@ -269,7 +263,7 @@ const UserProfileStatus: React.FC = ({ - + {item.icon} {item.label} @@ -289,17 +283,19 @@ const UserProfileStatus: React.FC = ({ activeOpacity={0.8} > - {profileImage ? ( + {profileImage !== undefined ? ( ) : ( )} - - - + + Total Paid Amount {userDashboard?.totalPaidAmountMonth} + {/* Total Paid Amount {userDashboard?.totalPaidAmountMonth} */} + + @@ -318,8 +314,8 @@ const UserProfileStatus: React.FC = ({ Your profile is incomplete. Update your details to unlock all features. - { setShowModal(false); navigation.navigate("Profile" as never); @@ -328,8 +324,8 @@ const UserProfileStatus: React.FC = ({ Complete Profile - setShowModal(false)} > @@ -368,17 +364,17 @@ const styles = StyleSheet.create({ paddingHorizontal: 18, marginBottom: 16, }, - titleWithIcon: { - flexDirection: 'row', - alignItems: 'center' + titleWithIcon: { + flexDirection: 'row', + alignItems: 'center' }, - headerIcon: { - marginRight: 8 + headerIcon: { + marginRight: 8 }, - header: { - fontSize: 20, - fontWeight: "700", - color: "#fff" + header: { + fontSize: 20, + fontWeight: "700", + color: "#fff" }, statusBadge: { flexDirection: 'row', @@ -388,26 +384,26 @@ const styles = StyleSheet.create({ paddingVertical: 6, borderRadius: 20, }, - statusBadgeText: { - color: "#fff", - fontSize: 13, - fontWeight: '600', - marginLeft: 4 + statusBadgeText: { + color: "#fff", + fontSize: 13, + fontWeight: '600', + marginLeft: 4 }, - contentSection: { - flexDirection: 'row', - alignItems: 'flex-start', + 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', - gap: 10 + infoGrid: { + flexDirection: 'row', + flexWrap: 'wrap', + gap: 10 }, infoCard: { backgroundColor: 'rgba(255,255,255,0.15)', @@ -419,10 +415,20 @@ const styles = StyleSheet.create({ minWidth: '45%', marginBottom: 8, }, - infoCardHeader: { - flexDirection: 'row', - alignItems: 'center', - marginBottom: 6 + infoCardOne: { + backgroundColor: 'rgba(255,255,255,0.15)', + borderRadius: 14, + padding: 12, + borderWidth: 1, + borderColor: 'rgba(255,255,255,0.2)', + // flex: 1, + minWidth: '45%', + marginTop: 21, + }, + infoCardHeader: { + flexDirection: 'row', + alignItems: 'center', + marginBottom: 6 }, iconContainer: { width: 28, @@ -439,9 +445,9 @@ const styles = StyleSheet.create({ fontWeight: '500', flexShrink: 1, }, - infoValue: { - fontWeight: "700", - fontSize: 16, + infoValue: { + fontWeight: "700", + fontSize: 16, textAlign: 'left', color: "#fff" }, @@ -450,8 +456,8 @@ const styles = StyleSheet.create({ alignItems: 'center', justifyContent: 'center', }, - profileContainer: { - alignItems: 'center' + profileContainer: { + alignItems: 'center' }, avatar: { width: 80, @@ -490,10 +496,10 @@ const styles = StyleSheet.create({ borderColor: "rgba(255,255,255,0.15)", backgroundColor: "rgba(0,0,0,0.15)", }, - dueBarText: { - color: "#fff", - fontSize: 16, - fontWeight: "600" + dueBarText: { + color: "#fff", + fontSize: 16, + fontWeight: "600" }, payAllButton: { backgroundColor: "#ffffffff", @@ -504,10 +510,10 @@ const styles = StyleSheet.create({ borderRadius: 20, gap: 6, }, - payAllButtonText: { - color: "#000000ff", - fontWeight: "bold", - fontSize: 16 + payAllButtonText: { + color: "#000000ff", + fontWeight: "bold", + fontSize: 16 }, payModalOverlay: { flex: 1, @@ -535,10 +541,10 @@ const styles = StyleSheet.create({ borderBottomWidth: 1, borderColor: "rgba(255,255,255,0.1)", }, - payDialogTitle: { - color: "#000000ff", - fontSize: 18, - fontWeight: "700" + payDialogTitle: { + color: "#000000ff", + fontSize: 18, + fontWeight: "700" }, payGroupOption: { flexDirection: "row", @@ -546,7 +552,7 @@ const styles = StyleSheet.create({ gap: 16, paddingVertical: 12, paddingHorizontal: 14, - borderColor: colors.primary, + borderColor: colors.primary, borderWidth: 1, borderRadius: 12, marginBottom: 8, @@ -556,20 +562,20 @@ const styles = StyleSheet.create({ borderColor: colors.primary, borderWidth: 1, }, - payGroupName: { - color: "#000000ff", - fontWeight: "700", - fontSize: 16 + payGroupName: { + color: "#000000ff", + fontWeight: "700", + fontSize: 16 }, - payDueText: { - color: "rgba(0, 0, 0, 0.8)", - fontSize: 13, - marginTop: 2 + payDueText: { + color: "rgba(0, 0, 0, 0.8)", + fontSize: 13, + marginTop: 2 }, - payAmount: { - fontWeight: "bold", - fontSize: 16, - color: "#4CAF50" + payAmount: { + fontWeight: "bold", + fontSize: 16, + color: "#4CAF50" }, payDialogFooter: { flexDirection: "row", @@ -579,10 +585,10 @@ const styles = StyleSheet.create({ paddingVertical: 16, paddingHorizontal: 18, }, - payDialogTotal: { - color: "#000000ff", - fontWeight: "600", - fontSize: 17 + payDialogTotal: { + color: "#000000ff", + fontWeight: "600", + fontSize: 17 }, payConfirmButton: { flexDirection: "row", @@ -592,14 +598,14 @@ const styles = StyleSheet.create({ paddingHorizontal: 24, borderRadius: 20, elevation: 4, - borderColor:colors.primary, - borderWidth:1, + borderColor: colors.primary, + borderWidth: 1, gap: 8, }, - payButtonText: { - color: "#ffffffff", - fontWeight: "bold", - fontSize: 16 + payButtonText: { + color: "#ffffffff", + fontWeight: "bold", + fontSize: 16 }, modalOverlay: { flex: 1, diff --git a/src/screens/home/user-home/CycleDashboard.tsx b/src/screens/home/user-home/CycleDashboard.tsx index 4d0259e..1884efe 100644 --- a/src/screens/home/user-home/CycleDashboard.tsx +++ b/src/screens/home/user-home/CycleDashboard.tsx @@ -9,7 +9,7 @@ import { UIManager, Platform, } from 'react-native'; -import { Ionicons } from "@react-native-vector-icons/ionicons";import colors from "../../../components/colors"; // Assuming a colors file +import { Ionicons } from "@react-native-vector-icons/ionicons"; import colors from "../../../components/colors"; // Assuming a colors file // Enable LayoutAnimation for Android if (Platform.OS === 'android' && UIManager.setLayoutAnimationEnabledExperimental) { @@ -68,14 +68,11 @@ interface CycleDashboardData { // --- Helper Functions --- -const formatDate = (dateArray: [number, number, number]): string => { - if (!dateArray || dateArray.length < 3) return 'N/A'; - const [year, month, day] = dateArray; - return new Date(year, month - 1, day).toLocaleDateString('en-US', { - month: 'short', - day: 'numeric', - year: 'numeric', - }); +const formatDate = (dateStr: string | null): string => { + if (!dateStr) return 'N/A'; + + const [year, month, day] = dateStr.split('-'); + return `${day}-${month}-${year}`; }; const formatCurrency = (amount: number): string => { @@ -106,7 +103,7 @@ const CycleItem = ({ item, isExpanded, onToggle }: { item: Cycle, isExpanded: bo {/* Withdrawal Info */} {item.withdrawal && ( - + Withdrawal @@ -116,18 +113,19 @@ const CycleItem = ({ item, isExpanded, onToggle }: { item: Cycle, isExpanded: bo {formatDate(item.withdrawal.paidDate)} - + )} {/* Contributions List */} Contributions ({item.paidParticipants}/{item.totalParticipants}) {item.contributions.map(contribution => ( - + - {contribution.userName} + {contribution.userName} {formatDate(contribution.paidDate)} + {contribution.status} {formatCurrency(contribution.totalAmount)} @@ -150,6 +148,7 @@ const CycleDashboard = ({ data }: { data: CycleDashboardData }) => { setExpandedCycle(expandedCycle === cycleNumber ? null : cycleNumber); }; + console.log("expanded cycle : ", data) const renderHeader = () => ( {data.groupName} @@ -297,6 +296,9 @@ const styles = StyleSheet.create({ flexDirection: 'row', alignItems: 'center', paddingVertical: 10, + paddingHorizontal: 8, + borderRadius: 6, + marginBottom: 10, borderBottomWidth: 1, borderBottomColor: '#f1f5f9', }, diff --git a/src/screens/home/user-home/GroupDetails.tsx b/src/screens/home/user-home/GroupDetails.tsx index e74d4bf..c5913ac 100644 --- a/src/screens/home/user-home/GroupDetails.tsx +++ b/src/screens/home/user-home/GroupDetails.tsx @@ -77,7 +77,7 @@ const GroupDetails = () => { const [openModal, setOpenModal] = useState(false); const [payable, setPayable] = useState(); const [refreshing, setRefreshing] = useState(false); - const [cycleDashboardData, setCycleDashboardData] = useState(); + const [cycleDashboardData, setCycleDashboardData] = useState([]); const [selectedCycleNumber, setSelectedCycleNumber] = useState(null); const [cycleItems, setCycleItems] = useState([]); const [selectedUser, setSelectedUser] = useState() as string | any; @@ -109,8 +109,8 @@ const GroupDetails = () => { try { const response = await apiCall(`${BASE_URL}payments/groups/${group.id || route?.params?.groupId}/cycle-dashboard`, "GET") as any; const responseData = response.data; - setCycleDashboardData(responseData); - console.log("cycledata", responseData) + setCycleDashboardData(responseData || []); + console.log("cycle data", responseData) if (responseData?.cycles) { const items = responseData.cycles.map((cycle: any) => ({ label: `Cycle ${cycle.cycleNumber}`, @@ -191,7 +191,8 @@ const GroupDetails = () => { }; - const selectedCycleData = cycleDashboardData?.cycles.find((c: any) => c.cycleNumber === selectedCycleNumber); + const selectedCycleData = cycleDashboardData?.cycles?.find((c: any) => c.cycleNumber === selectedCycleNumber); + // const selectedCycleData = cycleDashboardData?.cycles.find((c: any) => c.cycleNumber === selectedCycleNumber); return ( @@ -263,14 +264,12 @@ const GroupDetails = () => { ))} - {cycleDashboardData?.status === 'ACTIVE' || cycleDashboardData?.status === 'DELAY' && !payable?.hasPaid && ( + {(cycleDashboardData?.status === 'ACTIVE' || cycleDashboardData?.status === 'DELAY') && !payable?.hasPaid && ( setOpenModal(true)} style={styles.button}> Contribute )} - - {openModal && ( { Participants - {paymentDetails.participants.map(renderParticipant)} + { paymentDetails?.cycleCompleted && + Next Cycle from : {paymentDetails?.nextCycleStart} + }{paymentDetails.participants.map(renderParticipant)} )} diff --git a/src/screens/management/WinnerUser.tsx b/src/screens/management/WinnerUser.tsx index 3601d2b..6284f36 100644 --- a/src/screens/management/WinnerUser.tsx +++ b/src/screens/management/WinnerUser.tsx @@ -34,7 +34,7 @@ interface WinnerUserProps { } visible: boolean onClose: () => void - groupId:string | number + groupId: string | number } const WinnerUser: React.FC = ({ data, visible, onClose, groupId }) => { @@ -95,7 +95,7 @@ const WinnerUser: React.FC = ({ data, visible, onClose, groupId const onConfirm = async () => { try { - const res = await apiCall(`${BASE_URL}payments/withdraw/${groupId}/${data?.selectedUser?.id}`, 'PUT') + const res = await apiCall(`${BASE_URL}payments/withdraw`, 'PUT', { groupId, userId: data?.selectedUser?.id, cycleNumber: currentCycle }) as any console.log("res winner user : ", res) ToastAndroid.show('Withdrawal successful', ToastAndroid.SHORT) onClose() @@ -119,7 +119,7 @@ const WinnerUser: React.FC = ({ data, visible, onClose, groupId {/* Header */} - Cycle {currentCycle} Winner + Cycle {currentCycle} Winner diff --git a/src/screens/profile/Profile.tsx b/src/screens/profile/Profile.tsx index fc7a82a..8334c6c 100644 --- a/src/screens/profile/Profile.tsx +++ b/src/screens/profile/Profile.tsx @@ -30,7 +30,7 @@ import { clearUser, setUserData } from "../../redux/userSlice"; import { StackNavigationProp } from "@react-navigation/stack"; import { RootStackParamList } from "../../navigation/AppNavigator"; import { firebase } from "@react-native-firebase/messaging"; -import FirebaseService, { deleteFcmToken } from "../../utils/firebase/firebaseServices"; +import FirebaseService, { deleteFcmToken, getFcmToken } from "../../utils/firebase/firebaseServices"; type UserProfile = { @@ -303,7 +303,15 @@ const Profile = () => { ToastAndroid.show('No user is currently logged in', ToastAndroid.SHORT); return; } - + const fcmToken = await getFcmToken(user?.userId?.toString()); + const res = await fetch(`${BASE_URL}token/remove?fcmToken=${fcmToken}`, { + method: "PUT", + headers: { + Accept: "*/*", + Authorization: `Bearer ${credentials.password}`, + }, + }); + console.log(" logout api response : ", res) await deleteFcmToken(user?.userId?.toString()); // Clear stored credentials @@ -353,25 +361,7 @@ const Profile = () => { }, 2000); // 2 seconds delay }; - - console.log("user image :", user?.filePath); - const getProfileImage = () => { - return require('../../assets/images/placeholder.png'); - if (user?.imageBlob) { - return { uri: `data:image/jpeg;base64,${user.imageBlob}` }; - } - if (user?.filePath) { - return { uri: user.filePath }; - } - // Return a require for local asset if nothing is available - return require('../../assets/images/placeholder.png'); -}; - - - - - - + return ( {/* Header */} @@ -433,11 +423,12 @@ const Profile = () => { console.log("Error loading image")} resizeMode='contain' /> + {user?.filePath} @@ -464,7 +455,7 @@ const Profile = () => { Become Organizer - + setEditing(true)} @@ -638,29 +629,29 @@ const Profile = () => { /> - Gender - - {["Male", "Female", "Other"].map((option) => ( - setUser({ ...user, gender: option })} - > - - {option} - - - ))} - - + Gender + + {["Male", "Female", "Other"].map((option) => ( + setUser({ ...user, gender: option })} + > + + {option} + + + ))} + + @@ -716,7 +707,7 @@ const styles = StyleSheet.create({ borderBottomRightRadius: 20, }, headerTitle: { - fontSize: 22, fontWeight: "600", color: colors.black + fontSize: 22, fontWeight: "600", color: colors.black }, refreshButton: { padding: 4, @@ -887,33 +878,33 @@ const styles = StyleSheet.create({ color: "#6366f1", }, genderRow: { - flexDirection: "row", - justifyContent: "space-between", - marginTop: 8, - marginBottom: 16, - gap: 12, -}, -genderButton: { - flex: 1, - paddingVertical: 12, - backgroundColor: "#f1f5f9", - borderRadius: 12, - alignItems: "center", - borderWidth: 1, - borderColor: "#e2e8f0", -}, -genderButtonActive: { - backgroundColor: colors.pastelBlue, -}, -genderButtonText: { - color: "#64748b", - fontWeight: "500", - fontSize: 16, -}, -genderButtonTextActive: { - color: colors.black, - fontWeight: "700" -}, + flexDirection: "row", + justifyContent: "space-between", + marginTop: 8, + marginBottom: 16, + gap: 12, + }, + genderButton: { + flex: 1, + paddingVertical: 12, + backgroundColor: "#f1f5f9", + borderRadius: 12, + alignItems: "center", + borderWidth: 1, + borderColor: "#e2e8f0", + }, + genderButtonActive: { + backgroundColor: colors.pastelBlue, + }, + genderButtonText: { + color: "#64748b", + fontWeight: "500", + fontSize: 16, + }, + genderButtonTextActive: { + color: colors.black, + fontWeight: "700" + }, buttonIcon: { marginRight: 8, diff --git a/src/screens/transaction/TransactionList.tsx b/src/screens/transaction/TransactionList.tsx index cebc60c..42bdc85 100644 --- a/src/screens/transaction/TransactionList.tsx +++ b/src/screens/transaction/TransactionList.tsx @@ -69,9 +69,20 @@ const StatusBadge: React.FC<{ status?: string }> = ({ status }) => { }; const TransactionItem: React.FC<{ item: Transaction }> = ({ item }) => { - const date = useMemo(() => parseTransactionDate(item.transactionDate), [item.transactionDate]); - const dateStr = date ? date.toLocaleString("en-IN") : "-"; + const formatDate = (dateStr: string | null): string => { + if (!dateStr) return 'N/A'; + const date = new Date(dateStr); + const day = String(date.getDate()).padStart(2, '0'); + const month = String(date.getMonth() + 1).padStart(2, '0'); + const year = date.getFullYear(); + + return `${day}-${month}-${year}`; + }; + + const dateStr = item.transactionDate ? formatDate(item.transactionDate) : "N/A"; + + console.log("item of the transaction : ", item) return ( @@ -130,7 +141,7 @@ const TransactionsList: React.FC = () => { return ( -
+
{message} diff --git a/src/utils/ApiUrls.tsx b/src/utils/ApiUrls.tsx index 9570ecb..ede19f8 100644 --- a/src/utils/ApiUrls.tsx +++ b/src/utils/ApiUrls.tsx @@ -1,6 +1,6 @@ -export const BASE_URL = "https://api.godemo.in/FundCollect/api/" -// export const BASE_URL = "http://192.168.1.5:9060/api/" +// export const BASE_URL = "https://11.godemo.in/FundCollect/api/" +export const BASE_URL = "http://192.168.1.8:9060/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`