create-gufran-expo-app 2.0.4 → 2.0.6

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 (43) hide show
  1. package/README.md +60 -321
  2. package/bin/cli.js +0 -1
  3. package/package.json +4 -3
  4. package/template/src/navigation/AuthStack.tsx +6 -25
  5. package/template/src/navigation/MainStack.tsx +0 -148
  6. package/template/src/navigation/RootNavigator.tsx +4 -26
  7. package/template/src/navigation/index.ts +0 -1
  8. package/template/src/navigation/navigationRef.ts +1 -1
  9. package/template/src/screens/HomeScreen.tsx +3 -215
  10. package/template/src/screens/auth/LoginScreen.tsx +13 -13
  11. package/template/src/screens/auth/index.ts +1 -6
  12. package/template/src/screens/index.ts +0 -35
  13. package/template/src/services/api.ts +5 -5
  14. package/template/src/services/authService.ts +3 -299
  15. package/template/src/services/mainServices.ts +19 -1914
  16. package/template/src/types/navigation.ts +5 -155
  17. package/template/src/utils/index.ts +5 -8
  18. package/template/src/navigation/MiddleStack.tsx +0 -35
  19. package/template/src/screens/auth/AddMamber.tsx +0 -428
  20. package/template/src/screens/auth/ForgotPasswordScreen.tsx +0 -176
  21. package/template/src/screens/auth/OTPVerifyScreen.tsx +0 -359
  22. package/template/src/screens/auth/RegisterScreen.tsx +0 -430
  23. package/template/src/screens/auth/SuccessScreen.tsx +0 -201
  24. package/template/src/screens/chat/ChatScreen.tsx +0 -1819
  25. package/template/src/screens/chat/ChatThreadsScreen.tsx +0 -360
  26. package/template/src/screens/chat/ReportMessageScreen.tsx +0 -238
  27. package/template/src/screens/clubs/Announcements.tsx +0 -426
  28. package/template/src/screens/clubs/BuyRaffleTicketsScreen.tsx +0 -568
  29. package/template/src/screens/clubs/ClubDeteils.tsx +0 -497
  30. package/template/src/screens/clubs/JoinClub.tsx +0 -841
  31. package/template/src/screens/events/EventScreen.tsx +0 -460
  32. package/template/src/screens/raffles/MyReferralMembersScreen.tsx +0 -758
  33. package/template/src/screens/raffles/RaffleDetailsScreen.tsx +0 -762
  34. package/template/src/screens/raffles/RafflesScreen.tsx +0 -495
  35. package/template/src/screens/raffles/SetRaffleReminderScreen.tsx +0 -390
  36. package/template/src/screens/teams/JoinTeamScreen.tsx +0 -464
  37. package/template/src/screens/teams/MyTeamDetailsScreen.tsx +0 -979
  38. package/template/src/screens/teams/MyTeamScreen.tsx +0 -568
  39. package/template/src/screens/teams/PendingRequestsScreen.tsx +0 -426
  40. package/template/src/screens/volunteerOpportunities/SetReminderScreen.tsx +0 -631
  41. package/template/src/screens/volunteerOpportunities/VolunteerOpportunitiesDetailsScreen.tsx +0 -1049
  42. package/template/src/screens/volunteerOpportunities/VolunteerOpportunitiesScreen.tsx +0 -608
  43. package/template/src/utils/ClubSearchManager.ts +0 -222
@@ -1,568 +0,0 @@
1
- import React, { useState, useEffect, useRef } from 'react';
2
- import {
3
- View,
4
- Text,
5
- StyleSheet,
6
- StatusBar,
7
- Platform,
8
- TouchableOpacity,
9
- Alert,
10
- ActivityIndicator,
11
- Image,
12
- Keyboard,
13
- } from 'react-native';
14
- import { SafeAreaView } from 'react-native-safe-area-context';
15
- import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view';
16
- import { NativeStackScreenProps } from '@react-navigation/native-stack';
17
- import { theme } from '@constants';
18
- import { moderateScale } from '@utils/scaling';
19
- import { Fonts } from '@constants/Fonts';
20
- import SVG from '@assets/icons';
21
- import { MainStackParamList } from '@navigation';
22
- import { useVerifyReferralCode } from '@services/mainServices';
23
- import { getApiErrorInfo } from '@services';
24
- import { TextInput } from '@components/common';
25
-
26
- // Helper function to format currency
27
- const formatCurrency = (amount: number): string => {
28
- return new Intl.NumberFormat('en-US', {
29
- style: 'currency',
30
- currency: 'USD',
31
- }).format(amount);
32
- };
33
-
34
- type BuyRaffleTicketsScreenProps = NativeStackScreenProps<MainStackParamList, 'BuyRaffleTickets'>;
35
-
36
- interface TicketOption {
37
- id: number;
38
- raffleId: number;
39
- ticketCount: number;
40
- totalAmount: number;
41
- perTicketAmount: number;
42
- }
43
-
44
- export const BuyRaffleTicketsScreen: React.FC<BuyRaffleTicketsScreenProps> = ({ navigation, route }) => {
45
-
46
- const {
47
- selectedClub,
48
- selectedMember,
49
- raffleId,
50
- raffleTitle,
51
- ticketOptions,
52
- } = route.params;
53
-
54
- const [selectedTicket, setSelectedTicket] = useState<TicketOption | null>(null);
55
- const [referralCode, setReferralCode] = useState('');
56
- const [isProcessing, setIsProcessing] = useState(false);
57
- const [referralError, setReferralError] = useState<string | null>(null);
58
- const scrollViewRef = useRef<KeyboardAwareScrollView>(null);
59
-
60
- const verifyReferralCodeMutation = useVerifyReferralCode();
61
-
62
- useEffect(() => {
63
- // Set first ticket as default selection
64
- if (ticketOptions && ticketOptions.length > 0) {
65
- setSelectedTicket(ticketOptions[0]);
66
- }
67
- }, []);
68
-
69
- const handleSelectTicket = (ticket: TicketOption) => {
70
- setSelectedTicket(ticket);
71
- };
72
-
73
- const handlePlaceOrder = async () => {
74
- Keyboard.dismiss();
75
- setReferralError(null);
76
- if (!selectedTicket) {
77
- Alert.alert('Select Tickets', 'Please select a ticket package first.');
78
- return;
79
- }
80
-
81
- Alert.alert(
82
- 'Payment Integration Required',
83
- 'Payment processing functionality needs to be implemented. Please integrate your preferred payment gateway.',
84
- [{ text: 'OK' }]
85
- );
86
-
87
- /*
88
- // TODO: Implement payment processing logic here
89
- // Example implementation structure:
90
-
91
- setIsProcessing(true);
92
-
93
- try {
94
- // Verify referral code if present
95
- if (referralCode.trim()) {
96
- try {
97
- const verifyResult = await verifyReferralCodeMutation.mutateAsync({
98
- raffleId: raffleId,
99
- clubId: selectedClub?.id || 0,
100
- memberId: selectedMember?.id || 0,
101
- referralCode: referralCode.trim()
102
- });
103
- console.log("verifyResult====?", verifyResult);
104
-
105
- } catch (error: any) {
106
- const errorInfo = getApiErrorInfo(error);
107
- console.error('[BuyRaffleTicketsScreen]', errorInfo);
108
- setReferralError(errorInfo?.message || 'Invalid referral code');
109
- setIsProcessing(false);
110
- setTimeout(() => {
111
- scrollViewRef.current?.scrollToEnd(true);
112
- }, 100);
113
- return;
114
- }
115
- }
116
-
117
- // Process payment with your payment gateway
118
- // const paymentResult = await yourPaymentService.processPayment({
119
- // amount: selectedTicket.totalAmount,
120
- // ticketInfo: selectedTicket,
121
- // referralCode: referralCode
122
- // });
123
-
124
- // if (paymentResult.success) {
125
- // Alert.alert(
126
- // 'Purchase Successful',
127
- // `You've purchased ${selectedTicket.ticketCount} raffle ticket${selectedTicket.ticketCount > 1 ? 's' : ''} for ${raffleTitle}!\n\nGood luck! 🍀`,
128
- // [
129
- // {
130
- // text: 'OK',
131
- // onPress: () => {
132
- // navigation.navigate('ClubDetails', {
133
- // selectedClub,
134
- // selectedMember
135
- // });
136
- // },
137
- // },
138
- // ]
139
- // );
140
- // }
141
- } catch (error: any) {
142
- console.error('[BuyRaffleTicketsScreen] Payment error:', error);
143
- Alert.alert(
144
- 'Payment Failed',
145
- error?.message || 'Unable to process payment. Please try again.',
146
- [{ text: 'OK' }]
147
- );
148
- } finally {
149
- setIsProcessing(false);
150
- }
151
- */
152
- };
153
-
154
- const renderTicketOption = ({ item }: { item: TicketOption }) => {
155
- const isSelected = selectedTicket?.id === item.id;
156
-
157
- return (
158
- <TouchableOpacity
159
- style={[styles.ticketOption, isSelected && styles.ticketOptionSelected]}
160
- onPress={() => handleSelectTicket(item)}
161
- activeOpacity={0.7}
162
- >
163
- <View style={[styles.radioButton, isSelected && styles.radioButtonSelected]}>
164
- {isSelected && <View style={styles.radioButtonInner} />}
165
- </View>
166
- <View style={styles.ticketInfo}>
167
- <Text style={styles.ticketText}>
168
- {item.ticketCount} ticket{item.ticketCount > 1 ? 's' : ''} for{' '}
169
- <Text style={styles.ticketPrice}>{formatCurrency(item.totalAmount)}</Text>
170
- {' '}
171
- <Text style={styles.ticketPricePerUnit}>
172
- ({formatCurrency(item.perTicketAmount)} ea)
173
- </Text>
174
- </Text>
175
- </View>
176
- </TouchableOpacity>
177
- );
178
- };
179
-
180
- const renderFooter = () => (
181
- <View style={styles.footerContainer}>
182
- <View style={styles.totalContainer}>
183
- <Text style={styles.totalLabel}>Total Amount:</Text>
184
- <Text style={styles.totalAmount}>
185
- {selectedTicket ? formatCurrency(selectedTicket.totalAmount) : '$0.00'}
186
- </Text>
187
- </View>
188
-
189
- <View style={styles.inputContainer}>
190
- {/* <TextInput
191
- style={[styles.input, !!referralError && styles.inputError]}
192
- placeholder="Enter referral code"
193
- placeholderTextColor={theme.colors.textSecondary}
194
- value={referralCode}
195
- onChangeText={(text) => {
196
- setReferralCode(text);
197
- if (referralError) setReferralError(null);
198
- }}
199
- autoCapitalize="characters"
200
- /> */}
201
-
202
- <TextInput
203
- style={styles.input}
204
- placeholder="Enter referral code"
205
- placeholderTextColor={theme.colors.textSecondary}
206
- value={referralCode}
207
- maxLength={10}
208
- textAlign='center'
209
- onChangeText={(text) => {
210
- setReferralCode(text);
211
- if (referralError) setReferralError(null);
212
- }}
213
- autoCapitalize="characters"
214
- />
215
- {!!referralError && (
216
- <Text style={styles.errorText}>{referralError}</Text>
217
- )}
218
- </View>
219
-
220
- <TouchableOpacity
221
- style={[styles.placeOrderButton, (!selectedTicket || isProcessing) && styles.placeOrderButtonDisabled]}
222
- onPress={handlePlaceOrder}
223
- disabled={!selectedTicket || isProcessing}
224
- activeOpacity={0.8}
225
- >
226
- {isProcessing ? (
227
- <>
228
- <ActivityIndicator color="#fff" style={{ marginRight: 10 }} />
229
- <Text style={styles.placeOrderButtonText}>Processing...</Text>
230
- </>
231
- ) : (
232
- <Text style={styles.placeOrderButtonText}>Place Order</Text>
233
- )}
234
- </TouchableOpacity>
235
-
236
- <View style={styles.paymentMethodsContainer}>
237
- <Text style={styles.paymentMethodsText}>💳 Payment Gateway Not Configured</Text>
238
- </View>
239
- </View>
240
- );
241
-
242
- return (
243
- <View style={styles.container}>
244
- <StatusBar
245
- barStyle="light-content"
246
- backgroundColor={theme.colors.blue}
247
- translucent={Platform.OS === 'android' ? true : false}
248
- />
249
- {Platform.OS === 'ios' && <View style={styles.statusBarBackground} />}
250
-
251
- <SafeAreaView style={styles.header}>
252
- <View style={{ flexDirection: 'row', paddingHorizontal: theme.spacing.lg }}>
253
- <TouchableOpacity onPress={() => navigation.goBack()}>
254
- <SVG.arrowLeft_white width={moderateScale(25)} height={moderateScale(25)} />
255
- </TouchableOpacity>
256
- <View style={{ flexDirection: 'row' }}>
257
- <View style={styles.userConSty}>
258
- {!!selectedClub?.clubImage ? (
259
- <Image
260
- source={{ uri: selectedClub?.clubImage }}
261
- resizeMode='cover'
262
- style={styles.userDetailsSty}
263
- />
264
- ) : (
265
- <View style={styles.placeholderLogoHeader}>
266
- <SVG.UsersIcon width={moderateScale(20)} height={moderateScale(20)} />
267
- </View>
268
- )}
269
- </View>
270
- <Text style={styles.userNameSty}>{selectedClub?.clubName || 'Club'}</Text>
271
- </View>
272
- </View>
273
-
274
- <View style={styles.content}>
275
- <KeyboardAwareScrollView
276
- ref={scrollViewRef}
277
- showsVerticalScrollIndicator={false}
278
- keyboardShouldPersistTaps="handled"
279
- enableOnAndroid={true}
280
- enableAutomaticScroll={true}
281
- extraScrollHeight={moderateScale(100)}
282
- keyboardOpeningTime={250}
283
- contentContainerStyle={styles.scrollContent}
284
- >
285
- <Text style={styles.questionTitle}>How Many Tickets?</Text>
286
-
287
- <View style={styles.listContent}>
288
- {ticketOptions.map((item) => (
289
- <View key={item.id}>
290
- {renderTicketOption({ item })}
291
- </View>
292
- ))}
293
-
294
- {/* {renderFooter()} */}
295
- <View style={styles.footerContainer}>
296
- <View style={styles.totalContainer}>
297
- <Text style={styles.totalLabel}>Total Amount:</Text>
298
- <Text style={styles.totalAmount}>
299
- {selectedTicket ? formatCurrency(selectedTicket.totalAmount) : '$0.00'}
300
- </Text>
301
- </View>
302
-
303
- <View style={styles.inputContainer}>
304
- <TextInput
305
- style={styles.input}
306
- placeholder="Enter referral code"
307
- placeholderTextColor={theme.colors.textSecondary}
308
- value={referralCode}
309
- maxLength={10}
310
- textAlign='center'
311
- onChangeText={(text) => {
312
- setReferralCode(text);
313
- if (referralError) setReferralError(null);
314
- }}
315
- autoCapitalize="characters"
316
- />
317
- {!!referralError && (
318
- <Text style={styles.errorText}>{referralError}</Text>
319
- )}
320
- </View>
321
-
322
- <TouchableOpacity
323
- style={[styles.placeOrderButton, (!selectedTicket || isProcessing) && styles.placeOrderButtonDisabled]}
324
- onPress={handlePlaceOrder}
325
- disabled={!selectedTicket || isProcessing}
326
- activeOpacity={0.8}
327
- >
328
- {isProcessing ? (
329
- <>
330
- <ActivityIndicator color="#fff" style={{ marginRight: 10 }} />
331
- <Text style={styles.placeOrderButtonText}>Processing...</Text>
332
- </>
333
- ) : (
334
- <Text style={styles.placeOrderButtonText}>Place Order</Text>
335
- )}
336
- </TouchableOpacity>
337
-
338
-
339
- </View>
340
- </View>
341
- </KeyboardAwareScrollView>
342
- </View>
343
- </SafeAreaView>
344
-
345
- {/* Full-screen loader during payment processing */}
346
- {isProcessing && (
347
- <View style={styles.loaderOverlay}><ActivityIndicator size="large" color={theme.colors.blue} /></View>
348
- )}
349
- </View>
350
- );
351
- };
352
-
353
- const styles = StyleSheet.create({
354
- container: {
355
- flex: 1,
356
- backgroundColor: theme.colors.blue,
357
- },
358
- statusBarBackground: {
359
- position: 'absolute',
360
- top: 0,
361
- left: 0,
362
- right: 0,
363
- height: Platform.OS === 'ios' ? 44 : 0,
364
- backgroundColor: theme.colors.blue,
365
- zIndex: 1000,
366
- },
367
- header: {
368
- flex: 1,
369
- backgroundColor: theme.colors.blue,
370
- paddingVertical: theme.spacing.xs,
371
- paddingTop: Platform.OS === 'android' ? theme.spacing.lg : theme.spacing.xs,
372
- },
373
- userConSty: {
374
- marginHorizontal: moderateScale(10),
375
- width: moderateScale(30),
376
- height: moderateScale(30),
377
- borderRadius: moderateScale(15),
378
- borderWidth: 1.5,
379
- borderColor: theme.colors.imageBorder,
380
- backgroundColor: theme.colors.background,
381
- alignItems: 'center',
382
- justifyContent: 'center',
383
- },
384
- userNameSty: {
385
- marginTop: moderateScale(5),
386
- color: theme.colors.white,
387
- fontFamily: Fonts.outfitMedium,
388
- fontSize: moderateScale(15),
389
- },
390
- userDetailsSty: {
391
- width: moderateScale(30),
392
- height: moderateScale(30),
393
- borderRadius: moderateScale(15),
394
- },
395
- placeholderLogoHeader: {
396
- width: moderateScale(20),
397
- height: moderateScale(20),
398
- borderRadius: moderateScale(10),
399
- alignItems: 'center',
400
- justifyContent: 'center',
401
- },
402
- headerTitle: {
403
- marginTop: moderateScale(20),
404
- fontFamily: Fonts.outfitMedium,
405
- fontSize: moderateScale(22),
406
- color: theme.colors.white,
407
- paddingHorizontal: theme.spacing.lg,
408
- marginBottom: theme.spacing.sm,
409
- },
410
- content: {
411
- flex: 1,
412
- backgroundColor: theme.colors.white,
413
- paddingHorizontal: theme.spacing.lg,
414
- paddingTop: theme.spacing.md,
415
- borderTopLeftRadius: moderateScale(30),
416
- borderTopRightRadius: moderateScale(30),
417
- marginTop: theme.spacing.md,
418
- },
419
- scrollContent: {
420
- flexGrow: 1,
421
- },
422
- questionTitle: {
423
- fontFamily: Fonts.outfitMedium,
424
- fontSize: moderateScale(16),
425
- color: theme.colors.black,
426
- marginBottom: theme.spacing.md,
427
- letterSpacing: 0.5,
428
- },
429
- listContent: {
430
- paddingBottom: theme.spacing.xl,
431
- },
432
- ticketOption: {
433
- flexDirection: 'row',
434
- alignItems: 'center',
435
- backgroundColor: theme.colors.lightLavenderGray,
436
- borderRadius: moderateScale(12),
437
- borderWidth: 2,
438
- borderColor: theme.colors.border,
439
- padding: theme.spacing.md,
440
- marginBottom: theme.spacing.sm,
441
- },
442
- ticketOptionSelected: {
443
- borderColor: theme.colors.blue,
444
- backgroundColor: theme.colors.lightLavenderGray,
445
- },
446
- radioButton: {
447
- width: moderateScale(24),
448
- height: moderateScale(24),
449
- borderRadius: moderateScale(12),
450
- borderWidth: 2,
451
- borderColor: theme.colors.border,
452
- alignItems: 'center',
453
- justifyContent: 'center',
454
- marginRight: theme.spacing.md,
455
- },
456
- radioButtonSelected: {
457
- borderColor: theme.colors.blue,
458
- },
459
- radioButtonInner: {
460
- width: moderateScale(12),
461
- height: moderateScale(12),
462
- borderRadius: moderateScale(6),
463
- backgroundColor: theme.colors.blue,
464
- },
465
- ticketInfo: {
466
- flex: 1,
467
- },
468
- ticketText: {
469
- fontFamily: Fonts.outfitRegular,
470
- fontSize: moderateScale(15),
471
- color: theme.colors.text,
472
- },
473
- ticketPrice: {
474
- fontFamily: Fonts.outfitBold,
475
- color: theme.colors.text,
476
- },
477
- ticketPricePerUnit: {
478
- fontFamily: Fonts.outfitRegular,
479
- fontSize: moderateScale(14),
480
- color: theme.colors.blue,
481
- },
482
- footerContainer: {
483
- marginTop: theme.spacing.lg,
484
- },
485
- totalContainer: {
486
- flexDirection: 'row',
487
- alignItems: 'center',
488
- justifyContent: 'center',
489
- marginBottom: theme.spacing.lg,
490
- },
491
- totalLabel: {
492
- fontFamily: Fonts.outfitRegular,
493
- fontSize: moderateScale(16),
494
- color: theme.colors.text,
495
- marginRight: theme.spacing.sm,
496
- },
497
- totalAmount: {
498
- fontFamily: Fonts.outfitBold,
499
- fontSize: moderateScale(20),
500
- color: theme.colors.appleGreen,
501
- },
502
- inputContainer: {
503
- marginBottom: theme.spacing.lg,
504
- },
505
- input: {
506
- backgroundColor: theme.colors.background,
507
- borderRadius: theme.borderRadius.xxl,
508
- borderWidth: 1,
509
- borderColor: theme.colors.border,
510
- paddingHorizontal: theme.spacing.md,
511
- paddingVertical: theme.spacing.md,
512
- fontFamily: Fonts.outfitRegular,
513
- fontSize: moderateScale(14),
514
- color: theme.colors.text,
515
- textAlign: 'center',
516
- },
517
- inputError: {
518
- borderColor: theme.colors.error,
519
- },
520
- errorText: {
521
- color: theme.colors.error,
522
- fontSize: moderateScale(12),
523
- fontFamily: Fonts.outfitRegular,
524
- marginTop: theme.spacing.xs,
525
- textAlign: 'center',
526
- },
527
- placeOrderButton: {
528
- backgroundColor: theme.colors.blue,
529
- borderRadius: moderateScale(25),
530
- paddingVertical: moderateScale(16),
531
- alignItems: 'center',
532
- justifyContent: 'center',
533
- flexDirection: 'row',
534
- marginBottom: theme.spacing.md,
535
- },
536
- placeOrderButtonDisabled: {
537
- backgroundColor: theme.colors.textSecondary,
538
- opacity: 0.7,
539
- },
540
- placeOrderButtonText: {
541
- fontFamily: Fonts.outfitBold,
542
- fontSize: moderateScale(16),
543
- color: theme.colors.white,
544
- },
545
- paymentMethodsContainer: {
546
- flexDirection: 'row',
547
- alignItems: 'center',
548
- justifyContent: 'center',
549
- gap: moderateScale(12),
550
- paddingVertical: theme.spacing.sm,
551
- },
552
- paymentMethodsText: {
553
- fontSize: moderateScale(13),
554
- color: '#666',
555
- fontFamily: Fonts.outfitRegular,
556
- },
557
- loaderOverlay: {
558
- position: 'absolute',
559
- top: 0,
560
- left: 0,
561
- right: 0,
562
- bottom: 0,
563
- backgroundColor: 'rgba(0, 0, 0, 0.5)',
564
- justifyContent: 'center',
565
- alignItems: 'center',
566
- zIndex: 9999,
567
- },
568
- });