create-gufran-expo-app 2.0.0 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (266) hide show
  1. package/lib/createApp.js +7 -2
  2. package/package.json +1 -1
  3. package/template/App.tsx +118 -0
  4. package/template/ReactotronConfig.js +5 -0
  5. package/template/android/app/build.gradle +184 -0
  6. package/template/android/app/debug.keystore +0 -0
  7. package/template/android/app/google-services.json +29 -0
  8. package/template/android/app/proguard-rules.pro +14 -0
  9. package/template/android/app/src/debug/AndroidManifest.xml +7 -0
  10. package/template/android/app/src/debugOptimized/AndroidManifest.xml +7 -0
  11. package/template/android/app/src/main/AndroidManifest.xml +28 -0
  12. package/template/android/app/src/main/assets/fonts/Outfit-Bold.ttf +0 -0
  13. package/template/android/app/src/main/assets/fonts/Outfit-Light.ttf +0 -0
  14. package/template/android/app/src/main/assets/fonts/Outfit-Medium.ttf +0 -0
  15. package/template/android/app/src/main/assets/fonts/Outfit-Regular.ttf +0 -0
  16. package/template/android/app/src/main/assets/fonts/Outfit-SemiBold.ttf +0 -0
  17. package/template/android/app/src/main/java/com/club/yakka/MainActivity.kt +61 -0
  18. package/template/android/app/src/main/java/com/club/yakka/MainApplication.kt +60 -0
  19. package/template/android/app/src/main/res/drawable/ic_launcher_background.xml +6 -0
  20. package/template/android/app/src/main/res/drawable/rn_edit_text_material.xml +37 -0
  21. package/template/android/app/src/main/res/drawable-hdpi/splashscreen_logo.png +0 -0
  22. package/template/android/app/src/main/res/drawable-mdpi/splashscreen_logo.png +0 -0
  23. package/template/android/app/src/main/res/drawable-xhdpi/splashscreen_logo.png +0 -0
  24. package/template/android/app/src/main/res/drawable-xxhdpi/splashscreen_logo.png +0 -0
  25. package/template/android/app/src/main/res/drawable-xxxhdpi/splashscreen_logo.png +0 -0
  26. package/template/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +5 -0
  27. package/template/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +5 -0
  28. package/template/android/app/src/main/res/mipmap-hdpi/ic_launcher.webp +0 -0
  29. package/template/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.webp +0 -0
  30. package/template/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp +0 -0
  31. package/template/android/app/src/main/res/mipmap-mdpi/ic_launcher.webp +0 -0
  32. package/template/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.webp +0 -0
  33. package/template/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp +0 -0
  34. package/template/android/app/src/main/res/mipmap-xhdpi/ic_launcher.webp +0 -0
  35. package/template/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.webp +0 -0
  36. package/template/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp +0 -0
  37. package/template/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp +0 -0
  38. package/template/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.webp +0 -0
  39. package/template/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp +0 -0
  40. package/template/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp +0 -0
  41. package/template/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.webp +0 -0
  42. package/template/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp +0 -0
  43. package/template/android/app/src/main/res/values/colors.xml +6 -0
  44. package/template/android/app/src/main/res/values/strings.xml +5 -0
  45. package/template/android/app/src/main/res/values/styles.xml +14 -0
  46. package/template/android/app/src/main/res/values-night/colors.xml +1 -0
  47. package/template/android/build.gradle +33 -0
  48. package/template/android/gradle/wrapper/gradle-wrapper.jar +0 -0
  49. package/template/android/gradle/wrapper/gradle-wrapper.properties +7 -0
  50. package/template/android/gradle.properties +65 -0
  51. package/template/android/gradlew +251 -0
  52. package/template/android/gradlew.bat +94 -0
  53. package/template/android/settings.gradle +39 -0
  54. package/template/app.json +69 -0
  55. package/template/assets/adaptive-icon.png +0 -0
  56. package/template/assets/adaptive-icon1.png +0 -0
  57. package/template/assets/app_icon.png +0 -0
  58. package/template/assets/favicon.png +0 -0
  59. package/template/assets/icon.png +0 -0
  60. package/template/assets/splash-icon.png +0 -0
  61. package/template/babel-plugin-disable-font-scaling.js +41 -0
  62. package/template/babel.config.js +28 -0
  63. package/template/firebase.json +5 -0
  64. package/template/index.ts +24 -0
  65. package/template/ios/.xcode.env +11 -0
  66. package/template/ios/ClubYakka/AppDelegate.swift +74 -0
  67. package/template/ios/ClubYakka/ClubYakka-Bridging-Header.h +3 -0
  68. package/template/ios/ClubYakka/ClubYakka.entitlements +8 -0
  69. package/template/ios/ClubYakka/GoogleService-Info.plist +30 -0
  70. package/template/ios/ClubYakka/Images.xcassets/AppIcon.appiconset/App-Icon-1024x1024@1x.png +0 -0
  71. package/template/ios/ClubYakka/Images.xcassets/AppIcon.appiconset/Contents.json +14 -0
  72. package/template/ios/ClubYakka/Images.xcassets/Contents.json +6 -0
  73. package/template/ios/ClubYakka/Images.xcassets/SplashScreenBackground.colorset/Contents.json +20 -0
  74. package/template/ios/ClubYakka/Images.xcassets/SplashScreenLegacy.imageset/Contents.json +23 -0
  75. package/template/ios/ClubYakka/Images.xcassets/SplashScreenLegacy.imageset/image.png +0 -0
  76. package/template/ios/ClubYakka/Images.xcassets/SplashScreenLegacy.imageset/image@2x.png +0 -0
  77. package/template/ios/ClubYakka/Images.xcassets/SplashScreenLegacy.imageset/image@3x.png +0 -0
  78. package/template/ios/ClubYakka/Info.plist +101 -0
  79. package/template/ios/ClubYakka/PrivacyInfo.xcprivacy +50 -0
  80. package/template/ios/ClubYakka/SplashScreen.storyboard +48 -0
  81. package/template/ios/ClubYakka/Supporting/Expo.plist +12 -0
  82. package/template/ios/ClubYakka.xcodeproj/project.pbxproj +669 -0
  83. package/template/ios/ClubYakka.xcodeproj/xcshareddata/xcschemes/ClubYakka.xcscheme +88 -0
  84. package/template/ios/ClubYakka.xcworkspace/contents.xcworkspacedata +10 -0
  85. package/template/ios/ClubYakka.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings +5 -0
  86. package/template/ios/Podfile +84 -0
  87. package/template/ios/Podfile.lock +2698 -0
  88. package/template/ios/Podfile.properties.json +8 -0
  89. package/template/metro.config.js +17 -0
  90. package/template/package.json +70 -0
  91. package/template/patches/react-native-background-upload+6.6.0.patch +704 -0
  92. package/template/react-native.config.js +7 -0
  93. package/template/src/assets/fonts/Outfit-Bold.ttf +0 -0
  94. package/template/src/assets/fonts/Outfit-Light.ttf +0 -0
  95. package/template/src/assets/fonts/Outfit-Medium.ttf +0 -0
  96. package/template/src/assets/fonts/Outfit-Regular.ttf +0 -0
  97. package/template/src/assets/fonts/Outfit-SemiBold.ttf +0 -0
  98. package/template/src/assets/icons/BG.svg +33 -0
  99. package/template/src/assets/icons/Ic_Users.svg +6 -0
  100. package/template/src/assets/icons/arrow-left-white.svg +4 -0
  101. package/template/src/assets/icons/arrow-left.svg +4 -0
  102. package/template/src/assets/icons/bell.svg +4 -0
  103. package/template/src/assets/icons/bottomSheetIcone.svg +3 -0
  104. package/template/src/assets/icons/call.svg +4 -0
  105. package/template/src/assets/icons/camera.svg +0 -0
  106. package/template/src/assets/icons/chatAppleGreenBG.svg +22 -0
  107. package/template/src/assets/icons/check.svg +4 -0
  108. package/template/src/assets/icons/check_Radio.svg +4 -0
  109. package/template/src/assets/icons/chevron-right.svg +3 -0
  110. package/template/src/assets/icons/clubDefauldImage.png +0 -0
  111. package/template/src/assets/icons/curvBackgroundView.svg +3 -0
  112. package/template/src/assets/icons/defaultClub.png +0 -0
  113. package/template/src/assets/icons/email.svg +3 -0
  114. package/template/src/assets/icons/emptyUser.svg +5 -0
  115. package/template/src/assets/icons/eye-Hide.svg +8 -0
  116. package/template/src/assets/icons/eye.svg +4 -0
  117. package/template/src/assets/icons/gallery.svg +4 -0
  118. package/template/src/assets/icons/home.svg +4 -0
  119. package/template/src/assets/icons/ic_Calendar.svg +14 -0
  120. package/template/src/assets/icons/ic_Calendar_blue.svg +12 -0
  121. package/template/src/assets/icons/ic_Calendar_white.svg +12 -0
  122. package/template/src/assets/icons/ic_Chat.svg +14 -0
  123. package/template/src/assets/icons/ic_ChatAppleGreen.svg +21 -0
  124. package/template/src/assets/icons/ic_ChatAppleWhite.svg +21 -0
  125. package/template/src/assets/icons/ic_Download.svg +6 -0
  126. package/template/src/assets/icons/ic_Events.svg +6 -0
  127. package/template/src/assets/icons/ic_HeadCoachIcon.svg +3 -0
  128. package/template/src/assets/icons/ic_Membership.svg +10 -0
  129. package/template/src/assets/icons/ic_Notification.svg +6 -0
  130. package/template/src/assets/icons/ic_Raffles.svg +14 -0
  131. package/template/src/assets/icons/ic_Referral_Members.svg +12 -0
  132. package/template/src/assets/icons/ic_Shop.svg +13 -0
  133. package/template/src/assets/icons/ic_Teams.svg +8 -0
  134. package/template/src/assets/icons/ic_Volunteer.svg +9 -0
  135. package/template/src/assets/icons/ic_add.svg +3 -0
  136. package/template/src/assets/icons/ic_addCircle.svg +5 -0
  137. package/template/src/assets/icons/ic_chatSend.svg +4 -0
  138. package/template/src/assets/icons/ic_chat_blue_bg.svg +22 -0
  139. package/template/src/assets/icons/ic_clock_blue.svg +4 -0
  140. package/template/src/assets/icons/ic_delete.svg +8 -0
  141. package/template/src/assets/icons/ic_more.svg +5 -0
  142. package/template/src/assets/icons/ic_mute.svg +10 -0
  143. package/template/src/assets/icons/ic_pdf.svg +3 -0
  144. package/template/src/assets/icons/ic_pending_AppleGreen.svg +11 -0
  145. package/template/src/assets/icons/ic_right_appleGreen.svg +11 -0
  146. package/template/src/assets/icons/ic_unread_chat_blue_bg.svg +23 -0
  147. package/template/src/assets/icons/ic_volunteer_Member.svg +8 -0
  148. package/template/src/assets/icons/index.ts +144 -0
  149. package/template/src/assets/icons/location-blue.svg +4 -0
  150. package/template/src/assets/icons/location-white.svg +4 -0
  151. package/template/src/assets/icons/location.svg +4 -0
  152. package/template/src/assets/icons/lock.svg +5 -0
  153. package/template/src/assets/icons/log-out.svg +5 -0
  154. package/template/src/assets/icons/login_logo.svg +9 -0
  155. package/template/src/assets/icons/mail.svg +4 -0
  156. package/template/src/assets/icons/or_saprater.svg +5 -0
  157. package/template/src/assets/icons/password.svg +4 -0
  158. package/template/src/assets/icons/profile-appleGreen.svg +6 -0
  159. package/template/src/assets/icons/search.svg +3 -0
  160. package/template/src/assets/icons/settings.svg +4 -0
  161. package/template/src/assets/icons/success.svg +4 -0
  162. package/template/src/assets/icons/unCheck_Radio.svg +3 -0
  163. package/template/src/assets/icons/uncheck.svg +3 -0
  164. package/template/src/assets/icons/upload_Image.svg +6 -0
  165. package/template/src/assets/icons/upload_Image_Member.svg +6 -0
  166. package/template/src/assets/icons/user.svg +4 -0
  167. package/template/src/assets/icons/wifi.svg +1 -0
  168. package/template/src/assets/images/Splash.png +0 -0
  169. package/template/src/assets/images/SplashLogo.png +0 -0
  170. package/template/src/assets/images/background.png +0 -0
  171. package/template/src/assets/images/clubDefauldImage.png +0 -0
  172. package/template/src/assets/images/index.tsx +9 -0
  173. package/template/src/assets/index.ts +1 -0
  174. package/template/src/components/common/AddMemberModal.tsx +543 -0
  175. package/template/src/components/common/AppLoader.tsx +91 -0
  176. package/template/src/components/common/Button.tsx +173 -0
  177. package/template/src/components/common/ClubCard.tsx +248 -0
  178. package/template/src/components/common/Icon.tsx +93 -0
  179. package/template/src/components/common/IconAlt.tsx +65 -0
  180. package/template/src/components/common/IconButton.tsx +92 -0
  181. package/template/src/components/common/ImagePicker.tsx +451 -0
  182. package/template/src/components/common/LoadingSpinner.tsx +30 -0
  183. package/template/src/components/common/OTPInput.tsx +128 -0
  184. package/template/src/components/common/ReminderCalendar.tsx +129 -0
  185. package/template/src/components/common/ReminderCardItem.tsx +91 -0
  186. package/template/src/components/common/SafeAreaWrapper.tsx +27 -0
  187. package/template/src/components/common/SetReminderModal.tsx +308 -0
  188. package/template/src/components/common/SlowInternet.js +57 -0
  189. package/template/src/components/common/TeamCard.tsx +297 -0
  190. package/template/src/components/common/TextInput.tsx +227 -0
  191. package/template/src/components/common/ToastConfig.tsx +103 -0
  192. package/template/src/components/common/ToastManager.ts +86 -0
  193. package/template/src/components/common/UploadProgressModal.tsx +284 -0
  194. package/template/src/components/common/WrapperContainer.tsx +39 -0
  195. package/template/src/components/common/index.ts +19 -0
  196. package/template/src/constants/Constants.tsx +7 -0
  197. package/template/src/constants/Fonts.tsx +30 -0
  198. package/template/src/constants/index.ts +45 -0
  199. package/template/src/constants/strings.ts +211 -0
  200. package/template/src/constants/theme.ts +72 -0
  201. package/template/src/contexts/AuthContext.tsx +268 -0
  202. package/template/src/contexts/index.ts +2 -0
  203. package/template/src/hooks/index.ts +3 -0
  204. package/template/src/hooks/useImageUpload.ts +199 -0
  205. package/template/src/index.ts +8 -0
  206. package/template/src/navigation/AuthStack.tsx +67 -0
  207. package/template/src/navigation/MainStack.tsx +183 -0
  208. package/template/src/navigation/MiddleStack.tsx +35 -0
  209. package/template/src/navigation/RootNavigator.tsx +101 -0
  210. package/template/src/navigation/index.ts +5 -0
  211. package/template/src/navigation/navigationRef.ts +5 -0
  212. package/template/src/providers/QueryProvider.tsx +30 -0
  213. package/template/src/screens/DetailsScreen.tsx +271 -0
  214. package/template/src/screens/HomeScreen.tsx +736 -0
  215. package/template/src/screens/ProfileScreen.tsx +202 -0
  216. package/template/src/screens/SettingsScreen.tsx +253 -0
  217. package/template/src/screens/SportHubScreen.tsx +280 -0
  218. package/template/src/screens/auth/AddMamber.tsx +428 -0
  219. package/template/src/screens/auth/ForgotPasswordScreen.tsx +176 -0
  220. package/template/src/screens/auth/LoginScreen.tsx +286 -0
  221. package/template/src/screens/auth/OTPVerifyScreen.tsx +359 -0
  222. package/template/src/screens/auth/RegisterScreen.tsx +430 -0
  223. package/template/src/screens/auth/SuccessScreen.tsx +201 -0
  224. package/template/src/screens/auth/WalcomeScreen.tsx +274 -0
  225. package/template/src/screens/auth/index.ts +8 -0
  226. package/template/src/screens/chat/ChatScreen.tsx +1819 -0
  227. package/template/src/screens/chat/ChatThreadsScreen.tsx +360 -0
  228. package/template/src/screens/chat/ReportMessageScreen.tsx +238 -0
  229. package/template/src/screens/clubs/Announcements.tsx +426 -0
  230. package/template/src/screens/clubs/BuyRaffleTicketsScreen.tsx +568 -0
  231. package/template/src/screens/clubs/ClubDeteils.tsx +497 -0
  232. package/template/src/screens/clubs/JoinClub.tsx +841 -0
  233. package/template/src/screens/events/EventScreen.tsx +460 -0
  234. package/template/src/screens/index.ts +42 -0
  235. package/template/src/screens/raffles/MyReferralMembersScreen.tsx +758 -0
  236. package/template/src/screens/raffles/RaffleDetailsScreen.tsx +762 -0
  237. package/template/src/screens/raffles/RafflesScreen.tsx +495 -0
  238. package/template/src/screens/raffles/SetRaffleReminderScreen.tsx +390 -0
  239. package/template/src/screens/teams/JoinTeamScreen.tsx +464 -0
  240. package/template/src/screens/teams/MyTeamDetailsScreen.tsx +979 -0
  241. package/template/src/screens/teams/MyTeamScreen.tsx +568 -0
  242. package/template/src/screens/teams/PendingRequestsScreen.tsx +426 -0
  243. package/template/src/screens/volunteerOpportunities/SetReminderScreen.tsx +631 -0
  244. package/template/src/screens/volunteerOpportunities/VolunteerOpportunitiesDetailsScreen.tsx +1049 -0
  245. package/template/src/screens/volunteerOpportunities/VolunteerOpportunitiesScreen.tsx +608 -0
  246. package/template/src/services/api.ts +167 -0
  247. package/template/src/services/authService.ts +422 -0
  248. package/template/src/services/index.ts +5 -0
  249. package/template/src/services/mainServices.ts +1963 -0
  250. package/template/src/stores/authStore.ts +159 -0
  251. package/template/src/stores/index.ts +2 -0
  252. package/template/src/types/index.ts +85 -0
  253. package/template/src/types/navigation.ts +206 -0
  254. package/template/src/utils/AzureUploaderService.ts +371 -0
  255. package/template/src/utils/ClubSearchManager.ts +222 -0
  256. package/template/src/utils/NotificationManager.ts +503 -0
  257. package/template/src/utils/UploadDebugUtil.ts +107 -0
  258. package/template/src/utils/imagePicker.ts +321 -0
  259. package/template/src/utils/index.ts +111 -0
  260. package/template/src/utils/permissions.ts +277 -0
  261. package/template/src/utils/scaling.ts +14 -0
  262. package/template/src/utils/storage.ts +247 -0
  263. package/template/src/utils/usePermissions.ts +275 -0
  264. package/template/src/utils/validation.ts +340 -0
  265. package/template/tsconfig.json +50 -0
  266. package/template/types/svg.d.ts +6 -0
@@ -0,0 +1,758 @@
1
+ import React, { useMemo, useCallback, useState, useRef } from 'react';
2
+ import {
3
+ View,
4
+ Text,
5
+ StyleSheet,
6
+ StatusBar,
7
+ Platform,
8
+ TouchableOpacity,
9
+ Image,
10
+ FlatList,
11
+ ListRenderItem,
12
+ Share,
13
+ ActivityIndicator,
14
+ RefreshControl,
15
+ Modal,
16
+ Animated,
17
+ Dimensions,
18
+ PanResponder,
19
+ } from 'react-native';
20
+ import { MyReferralMembersScreenProps } from '@navigation';
21
+ import { theme } from '@constants';
22
+ import { moderateScale } from '@utils/scaling';
23
+ import { Fonts } from '@constants/Fonts';
24
+ import SVG from '@assets/icons';
25
+ import { SafeAreaView } from 'react-native-safe-area-context';
26
+ import { Button } from '@components/common';
27
+ import { useInfiniteReferrerMemberSales, ReferrerMember, mainService } from '@services/mainServices';
28
+
29
+
30
+ export const MyReferralMembersScreen: React.FC<MyReferralMembersScreenProps> = ({ navigation, route }) => {
31
+ const { selectedClub, selectedMember: initialSelectedMember, raffleId, raffleTitle } = route?.params ?? {};
32
+
33
+ const memberId = initialSelectedMember?.id;
34
+ const pageSize = 10;
35
+
36
+ // Fetch referral members with pagination
37
+ const {
38
+ data,
39
+ isLoading,
40
+ isError,
41
+ error,
42
+ fetchNextPage,
43
+ hasNextPage,
44
+ isFetchingNextPage,
45
+ refetch,
46
+ isRefetching,
47
+ } = useInfiniteReferrerMemberSales(raffleId, memberId, pageSize);
48
+
49
+ // Modal state
50
+ const [ticketModalVisible, setTicketModalVisible] = useState(false);
51
+ const [ticketDetailsLoading, setTicketDetailsLoading] = useState(false);
52
+ const [ticketNumbers, setTicketNumbers] = useState<any>([]);
53
+ const translateY = useRef(new Animated.Value(0)).current;
54
+ const screenHeight = Dimensions.get('window').height;
55
+ const bottomSheetHeight = screenHeight * 0.5; // 50% of screen height
56
+
57
+
58
+ // Flatten paginated data
59
+ const referralMembers = useMemo(() => {
60
+ if (!data?.pages) return [];
61
+
62
+ return data.pages.flatMap((page) => {
63
+ // Access the correct nested structure: data.data.data.salesList
64
+ const responseData = page?.data?.data;
65
+
66
+ if (responseData && typeof responseData === 'object') {
67
+ // Check for nested data.data.salesList structure
68
+ if ('data' in responseData && responseData.data && typeof responseData.data === 'object') {
69
+ const nestedData = responseData.data as any;
70
+ if ('salesList' in nestedData && Array.isArray(nestedData.salesList)) {
71
+ return nestedData.salesList;
72
+ }
73
+ }
74
+ // Direct salesList
75
+ if ('salesList' in responseData && Array.isArray(responseData.salesList)) {
76
+ return responseData.salesList;
77
+ }
78
+ // Fallback to other possible structures
79
+ if ('members' in responseData && Array.isArray(responseData.members)) {
80
+ return responseData.members;
81
+ } else if ('referralMembers' in responseData && Array.isArray(responseData.referralMembers)) {
82
+ return responseData.referralMembers;
83
+ } else if (Array.isArray(responseData)) {
84
+ return responseData;
85
+ }
86
+ } else if (Array.isArray(page?.data?.data)) {
87
+ return page.data.data;
88
+ }
89
+
90
+ return [];
91
+ });
92
+ }, [data]);
93
+
94
+ // Calculate total sales from API response
95
+ const totalSales = useMemo(() => {
96
+ if (!data?.pages?.[0]) return 0;
97
+
98
+ const firstPage = data.pages[0];
99
+ const responseData = firstPage?.data?.data;
100
+
101
+ // Try to get totalPurchasedTicketCount from nested data structure
102
+ if (responseData && typeof responseData === 'object') {
103
+ if ('data' in responseData && responseData.data && typeof responseData.data === 'object') {
104
+ const nestedData = responseData.data as any;
105
+ if (typeof nestedData.totalPurchasedTicketCount === 'number') {
106
+ return nestedData.totalPurchasedTicketCount;
107
+ }
108
+ }
109
+ // Try direct totalPurchasedTicketCount
110
+ if ('totalPurchasedTicketCount' in responseData && typeof responseData.totalPurchasedTicketCount === 'number') {
111
+ return responseData.totalPurchasedTicketCount;
112
+ }
113
+ }
114
+
115
+ // Fallback: calculate from member data
116
+ return referralMembers.reduce((sum, member) => {
117
+ const tickets = member.purchasedTicketCount ?? member.ticketCount ?? member.ticketsSold ?? member.totalTickets ?? 0;
118
+ return sum + tickets;
119
+ }, 0);
120
+ }, [data, referralMembers]);
121
+
122
+ const handleReferToFriends = async () => {
123
+ try {
124
+ const response = await mainService.getReferralCode({
125
+ raffleId: raffleId || 0,
126
+ memberId: memberId || 0,
127
+ });
128
+
129
+ const responseData = response?.data?.data;
130
+ const referralCode = responseData?.referralCode || '';
131
+ const clubCode = responseData?.clubCode || '';
132
+ const clubName = responseData?.clubName || 'ClubYakka';
133
+
134
+ const appLink = '(App Link)';
135
+ const shareMessage =
136
+ `Join the *${raffleTitle}* raffle on ClubYakka app!
137
+
138
+ Use my referral code: *${referralCode}* when buying tickets
139
+
140
+ Steps to buy:
141
+ 1. Ensure you have ${clubName} club already joined or if not, find it with club code: #${clubCode} to join it
142
+ 2. Continue as desired member in Club Dashboard
143
+ 3. Click Raffle section and find raffle: *${raffleTitle}*
144
+ 4. When buying raffle tickets, apply my code: *${referralCode}*
145
+ 5. Purchase raffle tickets and WIN!
146
+
147
+ Click the link to open the app ${appLink}`;
148
+
149
+ Share.share({
150
+ message: shareMessage,
151
+ title: `${clubName} Raffle on ClubYakka`
152
+ });
153
+ } catch (error) {
154
+ console.error('Failed to get referral code:', error);
155
+ }
156
+ };
157
+
158
+ // Handle load more for pagination
159
+ const handleLoadMore = useCallback(() => {
160
+ if (hasNextPage && !isFetchingNextPage) {
161
+ fetchNextPage();
162
+ }
163
+ }, [hasNextPage, isFetchingNextPage, fetchNextPage]);
164
+
165
+ // Handle pull to refresh
166
+ const handleRefresh = useCallback(() => {
167
+ refetch();
168
+ }, [refetch]);
169
+
170
+ // Bottom sheet animation functions
171
+ const showBottomSheet = () => {
172
+ setTicketModalVisible(true);
173
+ Animated.spring(translateY, {
174
+ toValue: 0,
175
+ useNativeDriver: true,
176
+ tension: 100,
177
+ friction: 8,
178
+ }).start();
179
+ };
180
+
181
+ const hideBottomSheet = () => {
182
+ Animated.timing(translateY, {
183
+ toValue: bottomSheetHeight,
184
+ duration: 300,
185
+ useNativeDriver: true,
186
+ }).start(() => {
187
+ setTicketModalVisible(false);
188
+ translateY.setValue(bottomSheetHeight);
189
+ setTicketNumbers([]);
190
+ });
191
+ };
192
+
193
+ // PanResponder for swipe gestures
194
+ const panResponder = useRef(
195
+ PanResponder.create({
196
+ onMoveShouldSetPanResponder: (_, gestureState) => {
197
+ return Math.abs(gestureState.dy) > 5;
198
+ },
199
+ onPanResponderGrant: () => {
200
+ translateY.setOffset((translateY as any)._value);
201
+ translateY.setValue(0);
202
+ },
203
+ onPanResponderMove: (_, gestureState) => {
204
+ // Only allow downward movement
205
+ if (gestureState.dy > 0) {
206
+ translateY.setValue(gestureState.dy);
207
+ }
208
+ },
209
+ onPanResponderRelease: (_, gestureState) => {
210
+ translateY.flattenOffset();
211
+
212
+ // If swiped down more than 100px or with high velocity, close the modal
213
+ if (gestureState.dy > 100 || gestureState.vy > 0.5) {
214
+ hideBottomSheet();
215
+ } else {
216
+ // Snap back to original position
217
+ Animated.spring(translateY, {
218
+ toValue: 0,
219
+ useNativeDriver: true,
220
+ tension: 100,
221
+ friction: 8,
222
+ }).start();
223
+ }
224
+ },
225
+ })
226
+ ).current;
227
+
228
+ // Handle ticket badge press
229
+ const handleTicketPress = async (member: ReferrerMember) => {
230
+ try {
231
+ setTicketDetailsLoading(true);
232
+
233
+ const response = await mainService.getTicketDetails({
234
+ raffleId: raffleId || 0,
235
+ memberId: member?.memberId || 0,
236
+ purchasedMemberId: member.memberId || member.id || 0,
237
+ });
238
+ console.log("data===>>>", JSON.stringify(response));
239
+
240
+
241
+ if (response?.data?.data) {
242
+ setTicketNumbers(response?.data?.data || []);
243
+ showBottomSheet();
244
+ }
245
+ } catch (error) {
246
+ console.error('Failed to fetch ticket details:', error);
247
+ } finally {
248
+ setTicketDetailsLoading(false);
249
+ }
250
+ };
251
+
252
+
253
+ // Render individual member item
254
+ const renderMemberItem: ListRenderItem<ReferrerMember> = ({ item }) => {
255
+ const displayName = item.memberName || item.name || 'Unknown';
256
+ const profileImg = item.profileImage || item.profileImageUrl;
257
+ const tickets = item.purchasedTicketCount ?? item.ticketCount ?? item.ticketsSold ?? item.totalTickets ?? 0;
258
+
259
+ return (
260
+ <View style={styles.memberRow}>
261
+ <View style={styles.memberInfo}>
262
+ <View style={styles.memberAvatar}>
263
+ {profileImg ? (
264
+ <Image source={{ uri: profileImg }} style={styles.avatarImage} resizeMode="cover" />
265
+ ) : (
266
+ <View style={styles.avatarPlaceholder}>
267
+ <SVG.UsersIcon width={moderateScale(24)} height={moderateScale(24)} />
268
+ </View>
269
+ )}
270
+ </View>
271
+ <Text style={styles.memberName}>{displayName}</Text>
272
+ </View>
273
+ <TouchableOpacity
274
+ style={styles.ticketBadge}
275
+ onPress={() => handleTicketPress(item)}
276
+ disabled={ticketDetailsLoading}
277
+ >
278
+ {ticketDetailsLoading ? (
279
+ <ActivityIndicator size="small" color={theme.colors.blue} />
280
+ ) : (
281
+ <Text style={styles.ticketCount}>{tickets} Ticket{tickets !== 1 ? 's' : ''}</Text>
282
+ )}
283
+ </TouchableOpacity>
284
+ </View>
285
+ );
286
+ };
287
+
288
+ // Render footer loader
289
+ const renderFooter = () => {
290
+ if (!isFetchingNextPage) return null;
291
+ return (
292
+ <View style={styles.footerLoader}>
293
+ <ActivityIndicator size="small" color={theme.colors.blue} />
294
+ </View>
295
+ );
296
+ };
297
+
298
+ // Render empty state
299
+ const renderEmptyComponent = () => {
300
+ if (isLoading) {
301
+ return (
302
+ <View style={styles.emptyContainer}>
303
+ <ActivityIndicator size="large" color={theme.colors.blue} />
304
+ <Text style={styles.emptyText}>Loading referral members...</Text>
305
+ </View>
306
+ );
307
+ }
308
+
309
+ if (isError) {
310
+ return (
311
+ <View style={styles.emptyContainer}>
312
+ <Text style={styles.errorText}>Failed to load referral members</Text>
313
+ <Text style={styles.errorSubText}>{error?.message || 'Please try again'}</Text>
314
+ <TouchableOpacity onPress={handleRefresh} style={styles.retryButton}>
315
+ <Text style={styles.retryButtonText}>Retry</Text>
316
+ </TouchableOpacity>
317
+ </View>
318
+ );
319
+ }
320
+
321
+ return (
322
+ <View style={styles.emptyContainer}>
323
+ <Text style={styles.emptyText}>No referral members found</Text>
324
+ <Text style={styles.emptySubText}>Start referring friends to see them here</Text>
325
+ </View>
326
+ );
327
+ };
328
+
329
+ return (
330
+
331
+ console.log("hhhh", ticketNumbers),
332
+
333
+ <View style={styles.container}>
334
+ <StatusBar
335
+ barStyle="light-content"
336
+ backgroundColor={theme.colors.blue}
337
+ translucent={Platform.OS === 'android' ? true : false}
338
+ />
339
+ {Platform.OS === 'ios' && <View style={styles.statusBarBackground} />}
340
+ <SafeAreaView style={styles.header}>
341
+ <View style={styles.headerTopRow}>
342
+ <TouchableOpacity onPress={() => navigation.goBack()}>
343
+ <SVG.arrowLeft_white width={moderateScale(25)} height={moderateScale(25)} />
344
+ </TouchableOpacity>
345
+ <View style={styles.clubInfoWrapper}>
346
+ <View style={styles.userConSty}>
347
+ {!!selectedClub?.clubImage ? (
348
+ <Image source={{ uri: selectedClub?.clubImage }} style={styles.userDetailsSty} resizeMode="cover" />
349
+ ) : (
350
+ <View style={styles.placeholderLogoHeader}>
351
+ <SVG.UsersIcon width={moderateScale(20)} height={moderateScale(20)} />
352
+ </View>
353
+ )}
354
+ </View>
355
+ <Text style={styles.userNameSty}>{selectedClub?.clubName || 'Unknown Club'}</Text>
356
+ </View>
357
+ </View>
358
+ <View style={styles.titleWrapper}>
359
+ <Text style={styles.headerTitle}>My Referral Members Sales</Text>
360
+ </View>
361
+ <View style={styles.addMemberContainer} />
362
+ <View style={styles.content}>
363
+ <View style={{ paddingHorizontal: theme.spacing.lg }}>
364
+
365
+ <View style={styles.headerCard}>
366
+ <Text style={styles.totalSalesLabel}>Total Sales</Text>
367
+ <View style={styles.totalSalesBadge}>
368
+ <Text style={styles.totalSalesCount}>{totalSales}</Text>
369
+ </View>
370
+ </View>
371
+ <View style={{ height: moderateScale(500) }}>
372
+ <FlatList
373
+ data={referralMembers}
374
+ keyExtractor={(item, index) => item.id?.toString() || item.memberId?.toString() || index.toString()}
375
+ renderItem={renderMemberItem}
376
+ contentContainerStyle={styles.listContent}
377
+ showsVerticalScrollIndicator={false}
378
+ onEndReached={handleLoadMore}
379
+ onEndReachedThreshold={0.3}
380
+ ListFooterComponent={renderFooter}
381
+ ListEmptyComponent={renderEmptyComponent}
382
+ refreshControl={
383
+ <RefreshControl
384
+ refreshing={isRefetching}
385
+ onRefresh={handleRefresh}
386
+ tintColor={theme.colors.blue}
387
+ colors={[theme.colors.blue]}
388
+ />
389
+ }
390
+ />
391
+ </View>
392
+ <Button
393
+ title="Refer to More Friends"
394
+ onPress={handleReferToFriends}
395
+ variant="outline"
396
+ textStyle={styles.referButtonText}
397
+ style={styles.referButton}
398
+ size="medium"
399
+ />
400
+ </View>
401
+ </View>
402
+ </SafeAreaView>
403
+
404
+ {/* Ticket Details Modal */}
405
+ <Modal
406
+ visible={ticketModalVisible}
407
+ animationType="fade"
408
+ transparent={true}
409
+ onRequestClose={hideBottomSheet}
410
+ >
411
+ <View style={styles.modalOverlay}>
412
+ <TouchableOpacity
413
+ style={styles.modalBackdrop}
414
+ activeOpacity={1}
415
+ onPress={hideBottomSheet}
416
+ />
417
+ <Animated.View
418
+ style={[
419
+ styles.modalContainer,
420
+ {
421
+ transform: [{ translateY }],
422
+ },
423
+ ]}
424
+ >
425
+ <View style={styles.dragHandle} {...panResponder.panHandlers} />
426
+ <View style={styles.modalHeader}>
427
+ <Text style={styles.modalTitle}>Ticket Details</Text>
428
+ </View>
429
+ <FlatList
430
+ data={ticketNumbers}
431
+ keyExtractor={(item, index) => `ticket-${item}-${index}`}
432
+ contentContainerStyle={styles.ticketListContent}
433
+ showsVerticalScrollIndicator={false}
434
+ renderItem={({ item }) => (
435
+ <View style={styles.ticketNumberBadge}>
436
+ <Text style={styles.ticketNumberText}>{item?.ticketNumber}</Text>
437
+ </View>
438
+ )}
439
+ ListEmptyComponent={() => (
440
+ <View style={styles.emptyTicketContainer}>
441
+ <Text style={styles.emptyTicketText}>No tickets found</Text>
442
+ </View>
443
+ )}
444
+ />
445
+ </Animated.View>
446
+ </View>
447
+ </Modal>
448
+ </View>
449
+ );
450
+ };
451
+
452
+ const styles = StyleSheet.create({
453
+ container: {
454
+ flex: 1,
455
+ backgroundColor: theme.colors.blue,
456
+ },
457
+ statusBarBackground: {
458
+ position: 'absolute',
459
+ top: 0,
460
+ left: 0,
461
+ right: 0,
462
+ height: Platform.OS === 'ios' ? 44 : 0,
463
+ backgroundColor: theme.colors.blue,
464
+ zIndex: 1000,
465
+ },
466
+ header: {
467
+ flex: 1,
468
+ backgroundColor: theme.colors.blue,
469
+ },
470
+ userConSty: {
471
+ marginHorizontal: moderateScale(10),
472
+ width: moderateScale(30),
473
+ height: moderateScale(30),
474
+ borderRadius: moderateScale(15),
475
+ borderWidth: 1.5,
476
+ borderColor: theme.colors.imageBorder,
477
+ backgroundColor: theme.colors.background,
478
+ alignItems: 'center',
479
+ justifyContent: 'center',
480
+ },
481
+ headerTopRow: {
482
+ flexDirection: 'row',
483
+ alignItems: 'center',
484
+ paddingHorizontal: theme.spacing.lg,
485
+ },
486
+ clubInfoWrapper: {
487
+ flexDirection: 'row',
488
+ alignItems: 'center',
489
+ },
490
+ headerTitle: {
491
+ marginTop: moderateScale(10),
492
+ fontFamily: Fonts.outfitMedium,
493
+ fontSize: moderateScale(22),
494
+ color: theme.colors.white,
495
+ },
496
+ titleWrapper: {
497
+ paddingHorizontal: theme.spacing.lg,
498
+ },
499
+ content: {
500
+ flex: 1,
501
+ backgroundColor: theme.colors.background,
502
+ paddingTop: theme.spacing.md,
503
+ borderTopLeftRadius: moderateScale(30),
504
+ borderTopRightRadius: moderateScale(30),
505
+ },
506
+ userDetailsSty: {
507
+ width: moderateScale(30),
508
+ height: moderateScale(30),
509
+ borderRadius: moderateScale(15),
510
+ },
511
+ placeholderLogoHeader: {
512
+ width: moderateScale(20),
513
+ height: moderateScale(20),
514
+ borderRadius: moderateScale(10),
515
+ alignItems: 'center',
516
+ justifyContent: 'center',
517
+ },
518
+ userNameSty: {
519
+ marginTop: moderateScale(5),
520
+ color: theme.colors.white,
521
+ fontFamily: Fonts.outfitMedium,
522
+ fontSize: moderateScale(15),
523
+ },
524
+ addMemberContainer: {
525
+ backgroundColor: theme.colors.blue,
526
+ paddingHorizontal: theme.spacing.lg,
527
+ paddingBottom: theme.spacing.md,
528
+ },
529
+ listContent: {
530
+ paddingTop: theme.spacing.md,
531
+ paddingBottom: theme.spacing.xl,
532
+ },
533
+ // Header card with total sales
534
+ headerCard: {
535
+ backgroundColor: theme.colors.lightLavenderGray,
536
+ borderRadius: theme.borderRadius.lg,
537
+ paddingHorizontal: theme.spacing.lg,
538
+ paddingVertical: theme.spacing.sm,
539
+ flexDirection: 'row',
540
+ justifyContent: 'space-between',
541
+ alignItems: 'center',
542
+ marginBottom: theme.spacing.xs
543
+ },
544
+ totalSalesLabel: {
545
+ fontFamily: Fonts.outfitMedium,
546
+ fontSize: theme.typography.fontSize.md,
547
+ color: theme.colors.blue,
548
+ },
549
+ totalSalesBadge: {
550
+ width: moderateScale(25),
551
+ height: moderateScale(25),
552
+ borderRadius: moderateScale(12.5),
553
+ backgroundColor: theme.colors.appleGreen,
554
+ alignItems: 'center',
555
+ justifyContent: 'center',
556
+ },
557
+ totalSalesCount: {
558
+ fontFamily: Fonts.outfitMedium,
559
+ fontSize: theme.typography.fontSize.xs,
560
+ color: theme.colors.blue,
561
+ },
562
+ // Member row
563
+ memberRow: {
564
+ flexDirection: 'row',
565
+ alignItems: 'center',
566
+ justifyContent: 'space-between',
567
+ backgroundColor: theme.colors.background,
568
+ paddingVertical: moderateScale(10),
569
+ borderBottomWidth: 0.5,
570
+ borderBottomColor: theme.colors.border,
571
+ },
572
+ memberInfo: {
573
+ flexDirection: 'row',
574
+ alignItems: 'center',
575
+ flex: 1,
576
+ },
577
+ memberAvatar: {
578
+ width: moderateScale(45),
579
+ height: moderateScale(45),
580
+ borderRadius: moderateScale(22.5),
581
+ marginRight: theme.spacing.md,
582
+ overflow: 'hidden',
583
+ },
584
+ avatarImage: {
585
+ width: '100%',
586
+ height: '100%',
587
+ resizeMode: 'cover',
588
+ },
589
+ avatarPlaceholder: {
590
+ width: '100%',
591
+ height: '100%',
592
+ backgroundColor: theme.colors.surface,
593
+ alignItems: 'center',
594
+ justifyContent: 'center',
595
+ },
596
+ memberName: {
597
+ fontFamily: Fonts.outfitRegular,
598
+ fontSize: moderateScale(16),
599
+ color: theme.colors.text,
600
+ },
601
+ ticketBadge: {
602
+ paddingHorizontal: theme.spacing.sm,
603
+ paddingVertical: theme.spacing.xs,
604
+ },
605
+ ticketCount: {
606
+ fontFamily: Fonts.outfitMedium,
607
+ fontSize: moderateScale(14),
608
+ color: theme.colors.blue,
609
+ },
610
+ // Footer
611
+ footerContainer: {
612
+ paddingHorizontal: theme.spacing.lg,
613
+ paddingTop: theme.spacing.lg,
614
+ paddingBottom: theme.spacing.md,
615
+ },
616
+ referButton: {
617
+ borderColor: theme.colors.blue,
618
+ backgroundColor: 'transparent',
619
+ marginTop: theme.spacing.sm,
620
+ },
621
+ referButtonText: {
622
+ color: theme.colors.blue,
623
+ fontFamily: Fonts.outfitMedium,
624
+ },
625
+ // Loading and error states
626
+ footerLoader: {
627
+ paddingVertical: theme.spacing.md,
628
+ alignItems: 'center',
629
+ justifyContent: 'center',
630
+ },
631
+ emptyContainer: {
632
+ flex: 1,
633
+ alignItems: 'center',
634
+ justifyContent: 'center',
635
+ paddingVertical: moderateScale(60),
636
+ paddingHorizontal: theme.spacing.xl,
637
+ },
638
+ emptyText: {
639
+ fontFamily: Fonts.outfitMedium,
640
+ fontSize: moderateScale(16),
641
+ color: theme.colors.text,
642
+ textAlign: 'center',
643
+ marginBottom: theme.spacing.xs,
644
+ },
645
+ emptySubText: {
646
+ fontFamily: Fonts.outfitRegular,
647
+ fontSize: moderateScale(14),
648
+ color: theme.colors.textSecondary,
649
+ textAlign: 'center',
650
+ },
651
+ errorText: {
652
+ fontFamily: Fonts.outfitMedium,
653
+ fontSize: moderateScale(16),
654
+ color: theme.colors.error,
655
+ textAlign: 'center',
656
+ marginBottom: theme.spacing.xs,
657
+ },
658
+ errorSubText: {
659
+ fontFamily: Fonts.outfitRegular,
660
+ fontSize: moderateScale(14),
661
+ color: theme.colors.textSecondary,
662
+ textAlign: 'center',
663
+ marginBottom: theme.spacing.md,
664
+ },
665
+ retryButton: {
666
+ paddingHorizontal: theme.spacing.lg,
667
+ paddingVertical: theme.spacing.sm,
668
+ backgroundColor: theme.colors.blue,
669
+ borderRadius: theme.borderRadius.md,
670
+ marginTop: theme.spacing.sm,
671
+ },
672
+ retryButtonText: {
673
+ fontFamily: Fonts.outfitMedium,
674
+ fontSize: moderateScale(14),
675
+ color: theme.colors.white,
676
+ },
677
+ // Modal styles
678
+ modalOverlay: {
679
+ flex: 1,
680
+ justifyContent: 'flex-end',
681
+ },
682
+ modalBackdrop: {
683
+ position: 'absolute',
684
+ top: 0,
685
+ left: 0,
686
+ right: 0,
687
+ bottom: 0,
688
+ backgroundColor: 'rgba(0, 0, 0, 0.5)',
689
+ },
690
+ modalContainer: {
691
+ backgroundColor: theme.colors.white,
692
+ borderTopLeftRadius: moderateScale(20),
693
+ borderTopRightRadius: moderateScale(20),
694
+ paddingHorizontal: theme.spacing.lg,
695
+ paddingTop: theme.spacing.sm,
696
+ paddingBottom: theme.spacing.xl,
697
+ height: '60%',
698
+ maxHeight: '60%',
699
+ },
700
+ dragHandle: {
701
+ width: moderateScale(40),
702
+ height: moderateScale(4),
703
+ backgroundColor: theme.colors.border,
704
+ borderRadius: moderateScale(2),
705
+ alignSelf: 'center',
706
+ marginBottom: theme.spacing.sm,
707
+ },
708
+ modalHeader: {
709
+ paddingVertical: theme.spacing.md,
710
+ borderBottomColor: theme.colors.border,
711
+ },
712
+ modalTitle: {
713
+ fontFamily: Fonts.outfitSemiBold,
714
+ fontSize: moderateScale(18),
715
+ color: theme.colors.text,
716
+ },
717
+ modalSubtitle: {
718
+ fontFamily: Fonts.outfitRegular,
719
+ fontSize: moderateScale(14),
720
+ color: theme.colors.textSecondary,
721
+ textAlign: 'center',
722
+ marginTop: theme.spacing.xs,
723
+ },
724
+ ticketListContent: {
725
+ paddingVertical: theme.spacing.sm,
726
+ },
727
+ ticketNumberBadge: {
728
+ flex: 1,
729
+ margin: moderateScale(5),
730
+ paddingVertical: moderateScale(12),
731
+ paddingHorizontal: moderateScale(8),
732
+ backgroundColor: theme.colors.lightLavenderGray,
733
+ borderRadius: theme.borderRadius.md,
734
+ alignItems: 'center',
735
+ justifyContent: 'center',
736
+ minWidth: moderateScale(90),
737
+ },
738
+ ticketNumberText: {
739
+ fontFamily: Fonts.outfitMedium,
740
+ fontSize: moderateScale(16),
741
+ color: theme.colors.blue,
742
+ },
743
+ emptyTicketContainer: {
744
+ flex: 1,
745
+ alignItems: 'center',
746
+ justifyContent: 'center',
747
+ paddingVertical: moderateScale(40),
748
+ },
749
+ emptyTicketText: {
750
+ fontFamily: Fonts.outfitMedium,
751
+ fontSize: moderateScale(14),
752
+ color: theme.colors.textSecondary,
753
+ textAlign: 'center',
754
+ },
755
+ closeButton: {
756
+ marginTop: theme.spacing.md,
757
+ },
758
+ });