Last active
April 8, 2023 03:35
-
-
Save kevincarpdev/691121880969df0edd34c84e2a63cce2 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, { useState, useEffect, useRef } from 'react'; | |
import { useNavigation } from '@react-navigation/native'; | |
import { | |
View, | |
TouchableOpacity, | |
ScrollView, | |
StyleSheet, | |
NativeSyntheticEvent, | |
NativeScrollEvent, | |
Animated, | |
Easing, | |
} from 'react-native'; | |
import { Text } from 'react-native-paper'; | |
import { | |
CONSTANT_COLOR as CC, | |
CONSTANT_SIZE, | |
GLOBAL_STYLE as GS, | |
icons, | |
} from '../../../../assets'; | |
import { | |
BButton, | |
BIcon, | |
BInput, | |
BSwitch, | |
KYCAlert, | |
SizedBox, | |
} from '../../../../components'; | |
import { useAuthContext } from '../../../../context/auth/auth.context'; | |
import { useAppContext } from '../../../../context/auth/app.context'; | |
import { DRAWER_ROUTES_NAMES } from '../../../../router/DrawerNavigator'; | |
import { | |
AccountLayout, | |
AccountListItem, | |
AccountLoggedHeader, | |
AccountPromotions, | |
} from '../components'; | |
import mobxStore from '../../../../store/RootStore'; | |
import { observer } from 'mobx-react'; | |
import { useKycUrl } from '../../../../hooks/useKycUrl'; | |
import moment from 'moment'; | |
import AsyncStorage from '@react-native-async-storage/async-storage'; | |
import { useMyPromotions } from '../../../../hooks/useMyPromotions'; | |
type TAB_PROPS = | |
| 'wallet' | |
| 'account_details' | |
| 'responsible_gaming' | |
| 'promotion_bonuses' | |
| 'preferences'; | |
const TABS = [ | |
{ | |
title: 'Wallet', | |
key: 'wallet', | |
}, | |
{ | |
title: 'Account Details', | |
key: 'account_details', | |
}, | |
{ | |
title: 'Responsible Gaming', | |
key: 'responsible_gaming', | |
}, | |
{ | |
title: 'Promotion & Bonuses', | |
key: 'promotion_bonuses', | |
}, | |
{ title: 'Preferences', key: 'preferences' }, | |
]; | |
const TabView = ({ | |
routes, | |
}: { | |
routes: Array<{ title: string; route: string | null }>; | |
}) => { | |
const navigation = useNavigation(); | |
return ( | |
<View> | |
{routes.map((r, k) => { | |
const isLast = k === routes.length - 1; | |
return ( | |
<AccountListItem | |
key={k} | |
title={r.title} | |
onPress={() => { | |
if (r.route != null) { | |
navigation.navigate(r.route as never); | |
} | |
}} | |
isLast={isLast} | |
/> | |
); | |
})} | |
</View> | |
); | |
}; | |
const PersonalInfoView = () => { | |
const navigation = useNavigation(); | |
const { userInfo } = useAuthContext(); | |
const profile = React.useMemo( | |
() => userInfo?.profile || null, | |
[userInfo?.profile], | |
); | |
const dateOfBirth = React.useMemo( | |
() => | |
profile?.dateOfBirth ? moment(profile?.dateOfBirth).format('L') : '', | |
[profile?.dateOfBirth], | |
); | |
return ( | |
<View | |
style={{ | |
padding: CONSTANT_SIZE.padding, | |
backgroundColor: 'rgba(0,0,0,0.25)', | |
marginTop: CONSTANT_SIZE.SPACE_LG, | |
borderRadius: 20, | |
}}> | |
<View style={[GS.row, GS.alignCenter]}> | |
<BIcon | |
icon={icons.lock_icon_symbol} | |
style={{ height: 18, width: 18, resizeMode: 'contain' }} | |
/> | |
<SizedBox width={10} /> | |
<Text | |
style={{ | |
...GS.FF_PoppinsSemiBold, | |
fontSize: 18, | |
lineHeight: 24, | |
textTransform: 'uppercase', | |
color: 'white', | |
}}> | |
Personal details | |
</Text> | |
</View> | |
<Text | |
style={[ | |
GS.txtUpper, | |
GS.txtWhite, | |
GS.txtSm, | |
{ opacity: 0.8, marginTop: 15 }, | |
]}> | |
TO EDIT THESE DETAILS, PLEASE CONTACT CUSTOMER SERVICE ON 406-528-3926. | |
YOU WIL HAVE TO RE-VERIFY ANY UPDATES YOU MAKE FOR SECURITY REASONS. | |
</Text> | |
<View | |
style={{ | |
marginTop: 15, | |
marginBottom: 20, | |
backgroundColor: 'white', | |
opacity: 0.25, | |
height: 2, | |
width: '100%', | |
}} | |
/> | |
{/* GENDER */} | |
<BInput | |
label="Title" | |
value={profile?.titleName} | |
style={GS.mb3} | |
editable={false} | |
readonly | |
textUpper | |
/> | |
{/* */} | |
<View style={[GS.row, GS.mb3]}> | |
<View style={GS.flex1}> | |
<BInput | |
label="First name" | |
value={profile?.firstName} | |
editable={false} | |
readonly | |
textUpper | |
/> | |
</View> | |
<SizedBox width={10} /> | |
<View style={GS.flex1}> | |
<BInput | |
label="Last name" | |
value={profile?.lastName} | |
editable={false} | |
readonly | |
textUpper | |
/> | |
</View> | |
</View> | |
{/* GENDER */} | |
<BInput | |
label="Date of birth" | |
value={dateOfBirth} | |
editable={false} | |
readonly | |
/> | |
{/* */} | |
<View style={{ marginTop: 25 }}> | |
<BButton | |
title="View more" | |
onPress={() => | |
navigation.navigate( | |
DRAWER_ROUTES_NAMES.ACCOUNT__CHANGE_PERSONAL_INFORMATION as never, | |
) | |
} | |
mode="primary" | |
/> | |
</View> | |
</View> | |
); | |
}; | |
const LoggedInScreeen = () => { | |
const navigation = useNavigation(); | |
const [currentIndex, setCurrentIndex] = React.useState(0); | |
const [currentTab, setCurrentTab] = React.useState<TAB_PROPS>('wallet'); | |
const { userInfo, supportedBiometry, isAuthDataLoading } = useAuthContext(); | |
const { reAuthorize, walletData, refetchWallet } = useAuthContext(); | |
const { isAppDataLoading, appData } = useAppContext(); | |
const [isWalletLoading, setIsWalletLoading] = React.useState(false); | |
const [isWithdrawDisabled, setIsWithdrawDisabled] = React.useState(false); | |
const [isDepositDisabled, setIsDepositDisabled] = React.useState(false); | |
const [spinAnim, setSpinAnim] = useState(new Animated.Value(0)); | |
const { data: kycUrl, fetch: getKycUrl } = useKycUrl({ | |
key: `${userInfo?.profile.username}_kyc_url`, | |
config: { enabled: false }, | |
}); | |
// Set up our initial parameters for the promotions query | |
let promotionsParams: any = { | |
pagination: { | |
pageNumber: 1, | |
itemsPerPage: 50, | |
totalItems: 0, | |
totalPages: 0, | |
}, | |
}; | |
// push our status filter to the filters array | |
promotionsParams?.filters?.push({ | |
name: 'status', | |
value: [ | |
{ | |
condition: 'INCLUDE', | |
logic: 'INCLUDE', | |
value: 'available', | |
}, | |
], | |
}); | |
// get total number of available promotions via useMyPromotions hook | |
const { data, isLoading } = useMyPromotions('available', promotionsParams); | |
// If it is not loading get the data | |
var totalAvailablePromotions = data?.response?.promotions?.length || 0; | |
if (!isLoading) { | |
totalAvailablePromotions = data?.response?.promotions?.length || 0; | |
} | |
// get | |
const WALLET_ROUTES = [ | |
{ | |
title: 'Gaming history', | |
route: DRAWER_ROUTES_NAMES.ACCOUNT__GAMING_HISTORY_STEP_1, | |
}, | |
{ | |
title: 'Transaction history', | |
route: DRAWER_ROUTES_NAMES.ACCOUNT__TRANSACTION_HISTORY, | |
}, | |
{ | |
title: 'Deposit', | |
route: DRAWER_ROUTES_NAMES.WALLET__DEPOSIT, | |
}, | |
{ | |
title: 'Withdraw', | |
route: DRAWER_ROUTES_NAMES.WALLET__WITHDRAW, | |
}, | |
{ | |
title: 'Manage Payment Method', | |
route: DRAWER_ROUTES_NAMES.WALLET__MANAGE_PAYMENT_METHODS, | |
} | |
]; | |
const ACCOUNT_DETAILS_ROUTES = [ | |
{ | |
title: 'Change Username', | |
route: DRAWER_ROUTES_NAMES.ACCOUNT__CHANGE_USERNAME, | |
}, | |
{ | |
title: 'Change Password', | |
route: DRAWER_ROUTES_NAMES.ACCOUNT__CHANGE_PASSWORD, | |
}, | |
{ | |
title: 'Change Address', | |
route: DRAWER_ROUTES_NAMES.ACCOUNT__CHANGE_ADDRESS, | |
}, | |
{ | |
title: 'Change Email', | |
route: DRAWER_ROUTES_NAMES.ACCOUNT__CHANGE_EMAIL, | |
}, | |
// { | |
// title: 'Change Security Question', | |
// route: DRAWER_ROUTES_NAMES.ACCOUNT__CHANGE_SECURITY_QUESTIONS, | |
// }, | |
{ | |
title: 'Change Mobile Number', | |
route: DRAWER_ROUTES_NAMES.ACCOUNT__CHANGE_MOBILE_NUMBER, | |
}, | |
// { | |
// title: 'Edit Communication Preferences', | |
// route: DRAWER_ROUTES_NAMES.ACCOUNT__EDIT_COMMUNICATION_PREFERENCES, | |
// }, | |
]; | |
const RESPONSIBLE_GAMING_ROUTES = [ | |
{ | |
title: 'Deposit Limits', | |
route: DRAWER_ROUTES_NAMES.ACCOUNT__CHANGE_DEPOSIT_LIMIT_STEP_1, | |
}, | |
{ | |
title: 'Withdraw Limits', | |
route: DRAWER_ROUTES_NAMES.ACCOUNT__CHANGE_WITHDRAW_LIMIT_STEP_1, | |
}, | |
{ | |
title: 'Session Limits', | |
route: DRAWER_ROUTES_NAMES.ACCOUNT__SESSION_LIMIT_STEP_1, | |
}, | |
{ | |
title: 'Cool Off period', | |
route: DRAWER_ROUTES_NAMES.ACCOUNT__COOL_OFF, | |
}, | |
{ | |
title: 'Self Exclude', | |
route: DRAWER_ROUTES_NAMES.ACCOUNT__SELF_EXCLUSION, | |
}, | |
{ | |
title: 'Reality Check', | |
route: DRAWER_ROUTES_NAMES.ACCOUNT__REALITY_CHECK_STEP_1, | |
}, | |
{ | |
title: 'Loss Limits', | |
route: DRAWER_ROUTES_NAMES.ACCOUNT__CHANGE_LOSS_LIMIT_STEP_1, | |
}, | |
{ | |
title: 'Play Limits', | |
route: DRAWER_ROUTES_NAMES.ACCOUNT__CHANGE_PLAY_LIMIT_STEP_1, | |
}, | |
]; | |
const PROMOTION_BONUSES_ROUTES = [ | |
{ | |
title: 'List of Active/Open/Expired', | |
route: DRAWER_ROUTES_NAMES.ACCOUNT__MY_PROMOTIONS, | |
}, | |
]; | |
const PREFERENCES_ROUTES = [ | |
{ | |
title: 'My Favorites', | |
route: DRAWER_ROUTES_NAMES.ACCOUNT__MY_FAVORITES, | |
}, | |
{ | |
title: 'My Messages', | |
route: DRAWER_ROUTES_NAMES.ACCOUNT__MESSAGES, | |
}, | |
{ | |
title: 'Communication Preferences', | |
route: DRAWER_ROUTES_NAMES.ACCOUNT__EDIT_COMMUNICATION_PREFERENCES, | |
}, | |
]; | |
if (supportedBiometry) { | |
PREFERENCES_ROUTES.push({ | |
title: 'QUICK LOGIN', | |
route: DRAWER_ROUTES_NAMES.ACCOUNT__ENABLE_QUICK_LOGIN, | |
}); | |
} | |
const dynamicTabs = (tab: TAB_PROPS) => { | |
switch (tab) { | |
case 'wallet': | |
return <TabView routes={WALLET_ROUTES} />; | |
case 'account_details': | |
return ( | |
<View> | |
<TabView routes={ACCOUNT_DETAILS_ROUTES} /> | |
<SizedBox height={5} /> | |
<PersonalInfoView /> | |
</View> | |
); | |
case 'preferences': | |
return <TabView routes={PREFERENCES_ROUTES} />; | |
case 'promotion_bonuses': | |
return <TabView routes={PROMOTION_BONUSES_ROUTES} />; | |
case 'responsible_gaming': | |
return <TabView routes={RESPONSIBLE_GAMING_ROUTES} />; | |
} | |
}; | |
React.useEffect(() => { | |
return navigation.addListener('focus', () => { | |
setCurrentTab('wallet'); | |
setCurrentIndex(0); | |
}); | |
}, [navigation]); | |
const BalanceObserver = observer((props) => { | |
const showBalance = props.mobxStore.showBalance; | |
return ( | |
<View | |
style={{ | |
backgroundColor: 'rgba(0,0,0,0.3)', | |
padding: 15, | |
borderRadius: 10, | |
}}> | |
<BSwitch | |
label={'Hide balance'} | |
value={!showBalance} | |
onValueChange={(_v: boolean) => mobxStore.handleShowBalance()} | |
/> | |
{showBalance && ( | |
<View> | |
<View | |
style={{ | |
height: 2, | |
width: '100%', | |
marginVertical: 10, | |
backgroundColor: 'rgba(255,255,255,0.3)', | |
}} | |
/> | |
<View style={[GS.row, GS.alignCenter]}> | |
<View style={GS.flex1}> | |
<Text style={[GS.txtUpper, GS.FF_PoppinsSemiBold, GS.txtWhite]}> | |
Cash balance | |
</Text> | |
</View> | |
<View style={[GS.row, GS.alignCenter]}> | |
<View | |
style={{ | |
height: 28, | |
width: 28, | |
flexDirection: 'row', | |
alignItems: 'center', | |
justifyContent: 'center', | |
borderRadius: 50, | |
backgroundColor: CC.primary, | |
marginRight: 10, | |
}}> | |
<TouchableOpacity | |
onPress={() => { | |
spin(() => { | |
refetchWallet() | |
}); | |
}} | |
> | |
<Animated.Image | |
source={icons.refresh_symbol} | |
style={{ | |
height: 16, | |
width: 16, | |
resizeMode: 'contain' | |
}} | |
/> | |
</TouchableOpacity> | |
</View> | |
{userInfo && | |
walletData?.response?.cashBalance !== undefined && ( | |
<Text style={{ color: 'white' }}> | |
{`$${walletData?.response?.cashBalance | |
?.toFixed(2) | |
.replace(/(\d)(?=(\d{3})+(?!\d))/g, '$1,')}`} | |
</Text> | |
)} | |
</View> | |
</View> | |
<View style={[GS.row, GS.alignCenter]}> | |
<View style={GS.flex1}> | |
<Text style={[GS.txtUpper, GS.FF_PoppinsSemiBold, GS.txtWhite]}> | |
Bonus balance | |
</Text> | |
</View> | |
<View style={[GS.row, GS.alignCenter]}> | |
{userInfo && walletData?.response?.bonusMoney !== undefined && ( | |
<Text style={{ color: 'white' }}> | |
{`$${walletData?.response?.bonusMoney | |
?.toFixed(2) | |
?.replace(/(\d)(?=(\d{3})+(?!\d))/g, '$1,')}`} | |
</Text> | |
)} | |
</View> | |
</View> | |
</View> | |
)} | |
</View> | |
); | |
}); | |
React.useEffect(() => { | |
if ( | |
!isAuthDataLoading && | |
userInfo && | |
userInfo?.kycCheckedData && | |
!userInfo.kycCheckedData.kycChecked | |
) { | |
getKycUrl(); | |
} | |
}, [getKycUrl, isAuthDataLoading, userInfo]); | |
const [scrollViewWidth, setScrollViewWidth] = React.useState(0); | |
const [currentXOffset, setCurrentXOffset] = React.useState(0); | |
const [layoutWidth, setLayoutWidth] = React.useState(0); | |
const scrollViewRef = useRef<ScrollView>(null); | |
const _handleScroll = (event: NativeSyntheticEvent<NativeScrollEvent>) => { | |
const newXOffset = event.nativeEvent.contentOffset.x; | |
setCurrentXOffset(newXOffset); | |
}; | |
const handleLeftArrow = () => { | |
const eachItemOffset = scrollViewWidth / 6; | |
const _currentXOffset = currentXOffset - eachItemOffset; | |
scrollViewRef.current?.scrollTo({ | |
x: _currentXOffset, | |
y: 0, | |
animated: true, | |
}); | |
}; | |
const handleRightArrow = () => { | |
const eachItemOffset = scrollViewWidth / 6; | |
const _currentXOffset = currentXOffset + eachItemOffset; | |
scrollViewRef.current?.scrollTo({ | |
x: _currentXOffset, | |
y: 0, | |
animated: true, | |
}); | |
}; | |
const handleClick = async (item) => { | |
setCurrentTab(item.key as any) | |
await AsyncStorage.setItem('activeTab', item.key); | |
} | |
const getActiveTab = async () => { | |
try { | |
const activeTab = await AsyncStorage.getItem('activeTab'); | |
if (activeTab !== null && activeTab !== undefined) { | |
setCurrentTab(activeTab as any) | |
return activeTab; | |
} | |
} catch (error) { | |
// Error retrieving data | |
} | |
}; | |
React.useEffect(() => { | |
(async () => { | |
await getActiveTab(); | |
})(); | |
return () => { | |
// Component unmount code. | |
}; | |
}, [currentTab]); | |
// Define the spinValue variable with an initial value of 0 | |
const spinValue = new Animated.Value(0); | |
// Set up the animation to rotate from 0 to 1 over 3 seconds using the linear easing function | |
Animated.timing(spinValue, { | |
toValue: 1, | |
duration: 3000, | |
easing: Easing.linear, | |
useNativeDriver: true, | |
}).start(); | |
const spin = (callback) => { | |
Animated.timing(spinAnim, { | |
toValue: 1, | |
duration: 1000, | |
easing: Easing.linear, | |
useNativeDriver: true, | |
}).start(() => { | |
setSpinAnim(new Animated.Value(0)); | |
if (callback) { | |
callback(); | |
} | |
}); | |
}; | |
// anytime walletData is updated, setIsWalletLoading to true | |
React.useEffect(() => { | |
if (isAppDataLoading) { | |
setIsWalletLoading(true); | |
Animated.timing(spinValue, { | |
toValue: 1, | |
duration: 1000, | |
easing: Easing.linear, | |
useNativeDriver: true, | |
}).start(() => { | |
spinValue.setValue(0); | |
setIsWalletLoading(false); // Set isWalletLoading to false after animation completes | |
}); | |
} | |
}, [walletData]); | |
return ( | |
<AccountLayout hasHeader={false}> | |
<View> | |
{/* Header */} | |
<AccountLoggedHeader /> | |
{/* ALERT */} | |
{ | |
(userInfo && | |
userInfo?.kycCheckedData && | |
!userInfo.kycCheckedData.kycChecked && | |
userInfo.kycCheckedData.remainingDays | |
) ? ( | |
<KYCAlert | |
url={kycUrl?.response?.scanUrl ?? ""} | |
remainingDays={userInfo.kycCheckedData.remainingDays} | |
/> | |
) : | |
(<></>) | |
} | |
<View style={GS.row}> | |
<BButton | |
title="Deposit" | |
onPress={() => { | |
navigation.navigate(DRAWER_ROUTES_NAMES.WALLET__DEPOSIT as never); | |
}} | |
mode="danger" | |
disabled={isDepositDisabled} | |
/> | |
<SizedBox width={10} /> | |
<BButton | |
title="Withdraw" | |
onPress={() => { | |
navigation.navigate( | |
DRAWER_ROUTES_NAMES.WALLET__WITHDRAW as never, | |
); | |
}} | |
mode="primary" | |
disabled={!userInfo?.kycCheckedData.kycChecked || isWithdrawDisabled} | |
/> | |
</View> | |
{/* */} | |
<SizedBox height={20} /> | |
{/* */} | |
<BalanceObserver mobxStore={mobxStore} /> | |
{/* PROMOTIONS */} | |
<AccountPromotions availablePromotions={totalAvailablePromotions} /> | |
{/* */} | |
<SizedBox height={20} /> | |
{/* */} | |
<View | |
style={{ | |
backgroundColor: 'rgba(0,0,0,0.3)', | |
borderRadius: 15, | |
padding: 10, | |
paddingRight: 30, | |
position: 'relative', | |
flexDirection: 'row', | |
alignItems: 'center', | |
height: 45, | |
}}> | |
<TouchableOpacity | |
style={{ position: 'relative', right: 1 }} | |
onPress={handleLeftArrow}> | |
<BIcon | |
icon={icons.left_arrow} | |
style={{ | |
height: 15, | |
width: 11, | |
resizeMode: 'contain', | |
tintColor: CC.primary, | |
}} | |
/> | |
</TouchableOpacity> | |
<ScrollView | |
ref={scrollViewRef} | |
fadingEdgeLength={80} | |
onLayout={(event) => setLayoutWidth(event.nativeEvent.layout.width)} | |
onContentSizeChange={(width) => | |
setScrollViewWidth(width - layoutWidth) | |
} | |
onScroll={_handleScroll} | |
horizontal | |
showsHorizontalScrollIndicator={false} | |
bounces={false} | |
pagingEnabled | |
snapToInterval={120} | |
centerContent | |
scrollEventThrottle={32} | |
contentContainerStyle={{ | |
paddingHorizontal: 15, | |
}} | |
style={{ | |
flex: 1, | |
}}> | |
<View | |
style={{ | |
flex: 1, | |
flexDirection: 'row', | |
alignItems: 'center', | |
justifyContent: 'center', | |
}}> | |
{TABS.map((item, key) => { | |
const isLast = key === TABS.length - 1; | |
return ( | |
<TouchableOpacity | |
onPress={() => handleClick(item)} | |
key={key} | |
style={ | |
isLast ? styles.horizontalItemLast : styles.horizontalItem | |
}> | |
<Text | |
style={[ | |
GS.txtUpper, | |
GS.txtSm, | |
GS.FF_PoppinsSemiBold, | |
{ | |
color: currentTab === item.key ? CC.primary : 'white', | |
}, | |
]}> | |
{item.title} | |
</Text> | |
</TouchableOpacity> | |
); | |
})} | |
</View> | |
</ScrollView> | |
<TouchableOpacity | |
style={{ position: 'absolute', right: 10 }} | |
onPress={handleRightArrow}> | |
<BIcon | |
icon={icons.right_arrow} | |
style={{ | |
height: 15, | |
width: 11, | |
resizeMode: 'contain', | |
tintColor: CC.primary, | |
}} | |
/> | |
</TouchableOpacity> | |
</View> | |
{/* */} | |
<SizedBox height={20} /> | |
{/* TABS */} | |
{dynamicTabs(currentTab)} | |
</View> | |
</AccountLayout> | |
); | |
}; | |
export default LoggedInScreeen; | |
const styles = StyleSheet.create({ | |
alert: { | |
borderColor: CC.secondary, | |
borderWidth: 1, | |
borderRadius: 20, | |
paddingHorizontal: 12.5, | |
paddingVertical: 17.5, | |
marginBottom: 25, | |
marginTop: 10, | |
flexDirection: 'row', | |
alignItems: 'center', | |
backgroundColor: 'rgba(0,0,0,0.3)', | |
}, | |
alertText: { | |
...GS.txtSm, | |
opacity: 0.9, | |
textTransform: 'uppercase', | |
color: 'white', | |
}, | |
horizontalItem: { | |
flexGrow: 1, | |
marginRight: 15, | |
borderRightColor: 'rgba(255,255,255,0.2)', | |
paddingRight: 15, | |
borderRightWidth: 2, | |
}, | |
horizontalItemLast: { | |
flexGrow: 1, | |
marginRight: 0, | |
}, | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment