@fadyshawky/react-native-magic 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.
- package/package.json +1 -1
- package/template/App.tsx +28 -19
- package/template/ios/reactnativemagic/AppDelegate.mm +5 -0
- package/template/src/common/components/Background.tsx +6 -4
- package/template/src/common/components/Container.tsx +6 -9
- package/template/src/common/components/OTPInput.tsx +3 -2
- package/template/src/common/components/PrimaryButton.tsx +23 -23
- package/template/src/common/components/PrimaryTextInput.tsx +189 -199
- package/template/src/common/components/RadioIcon.tsx +4 -4
- package/template/src/common/components/SafeText.tsx +41 -0
- package/template/src/common/components/SearchBar.tsx +19 -17
- package/template/src/common/components/TryAgain.tsx +3 -3
- package/template/src/common/localization/LocalizationProvider.tsx +14 -17
- package/template/src/common/localization/RTLInitializer.tsx +90 -0
- package/template/src/common/localization/localization.ts +8 -0
- package/template/src/common/localization/translations/commonLocalization.ts +33 -6
- package/template/src/common/localization/translations/emptyLocalization.ts +6 -2
- package/template/src/common/localization/translations/errorsLocalization.ts +33 -13
- package/template/src/common/localization/translations/homeLocalization.ts +6 -2
- package/template/src/common/localization/translations/loginLocalization.ts +32 -9
- package/template/src/common/localization/translations/mainNavigationLocalization.ts +30 -0
- package/template/src/common/localization/translations/navigationLocalization.ts +48 -0
- package/template/src/common/localization/translations/onboardingLocalization.ts +40 -9
- package/template/src/common/localization/translations/otpLocalization.ts +28 -0
- package/template/src/common/localization/translations/pagesLocalization.ts +13 -1
- package/template/src/common/localization/translations/passwordLocalization.ts +54 -0
- package/template/src/common/localization/translations/profileLocalization.ts +4 -4
- package/template/src/common/utils/FeesCaalculation.tsx +37 -0
- package/template/src/common/utils/index.tsx +11 -0
- package/template/src/common/utils/printData.tsx +161 -0
- package/template/src/common/validations/errorValidations.ts +3 -2
- package/template/src/core/api/serverHeaders.ts +62 -1
- package/template/src/core/store/Categories/categoryActions.ts +33 -0
- package/template/src/core/store/Categories/categorySlice.ts +75 -0
- package/template/src/core/store/Categories/categoryState.ts +41 -0
- package/template/src/core/store/Providers/providersActions.ts +102 -0
- package/template/src/core/store/Providers/providersSlice.ts +136 -0
- package/template/src/core/store/Providers/providersState.ts +37 -0
- package/template/src/core/store/Services/servicesActions.ts +191 -0
- package/template/src/core/store/Services/servicesSlice.ts +205 -0
- package/template/src/core/store/Services/servicesState.ts +466 -0
- package/template/src/core/store/app/appSlice.ts +13 -5
- package/template/src/core/store/app/appState.ts +10 -2
- package/template/src/core/store/rootReducer.ts +6 -1
- package/template/src/core/store/store.tsx +55 -2
- package/template/src/core/store/user/userActions.ts +164 -26
- package/template/src/core/store/user/userSlice.ts +193 -21
- package/template/src/core/store/user/userState.ts +148 -25
- package/template/src/core/theme/colors.ts +12 -0
- package/template/src/core/theme/themes.ts +1 -1
- package/template/src/core/utils/stringUtils.ts +114 -0
- package/template/src/navigation/AuthStack.tsx +8 -0
- package/template/src/navigation/HeaderComponents.tsx +52 -1
- package/template/src/navigation/MainNavigation.tsx +3 -1
- package/template/src/navigation/MainStack.tsx +39 -56
- package/template/src/navigation/TabBar.tsx +111 -59
- package/template/src/navigation/types.ts +24 -0
- package/template/src/screens/Login/Login.tsx +83 -85
- package/template/src/screens/OTP/OTPScreen.tsx +169 -0
- package/template/src/screens/home/Components/PayByCode.tsx +129 -0
- package/template/src/screens/home/HomeScreen.tsx +1 -103
- package/template/src/screens/home/hooks/useHomeData.ts +32 -38
- package/template/src/screens/index.tsx +24 -0
- package/template/src/common/components/Stepper.tsx +0 -153
- package/template/src/common/components/Svg.tsx +0 -25
- package/template/src/common/hooks/useDebounce.ts +0 -17
- package/template/src/common/hooks/usePrevious.ts +0 -11
- package/template/src/common/urls/emailUrl.ts +0 -20
- package/template/src/common/urls/mapUrl.ts +0 -22
- package/template/src/common/utils/listHandlers.ts +0 -30
- package/template/src/common/utils/serializeQueryParams.ts +0 -10
- package/template/src/common/validations/hooks/useDatesError.ts +0 -40
- package/template/src/common/validations/profileValidations.ts +0 -30
- package/template/src/navigation/TopTabBar.tsx +0 -77
- package/template/src/screens/Settings/Settings.tsx +0 -5
- package/template/src/screens/home/components/CarouselSection.tsx +0 -79
- package/template/src/screens/home/components/FeaturedCarousel.tsx +0 -128
- package/template/src/screens/main/Main.tsx +0 -5
- package/template/src/screens/registration/RegistrationScreen.tsx +0 -198
- package/template/src/screens/resetPassword/ForgotPasswordScreen.tsx +0 -129
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import React, {useState} from 'react';
|
|
2
|
+
import {Modal, StyleSheet, View} from 'react-native';
|
|
3
|
+
import {RTLAwareView} from '../../../common/components/RTLAwareView';
|
|
4
|
+
import {CommonSizes} from '../../../core/theme/commonSizes';
|
|
5
|
+
import {PrimaryTextInput} from '../../../common/components/PrimaryTextInput';
|
|
6
|
+
import {useTheme} from '../../../core/theme/ThemeProvider';
|
|
7
|
+
import {PrimaryButton} from '../../../common/components/PrimaryButton';
|
|
8
|
+
import {ButtonType} from '../../../../types';
|
|
9
|
+
import {useAppDispatch} from '../../../core/store/reduxHelpers';
|
|
10
|
+
import {getServiceById} from '../../../core/store/Services/servicesActions';
|
|
11
|
+
import {getProviderById} from '../../../core/store/Providers/providersActions';
|
|
12
|
+
import {useNavigation} from '@react-navigation/native';
|
|
13
|
+
import {NativeStackNavigationProp} from '@react-navigation/native-stack';
|
|
14
|
+
import {RootStackParamList} from '../../../navigation/types';
|
|
15
|
+
import {useTranslation} from '../../../common/localization/LocalizationProvider';
|
|
16
|
+
|
|
17
|
+
export function PayByCode({
|
|
18
|
+
isVisible,
|
|
19
|
+
onClose,
|
|
20
|
+
}: {
|
|
21
|
+
isVisible: boolean;
|
|
22
|
+
onClose: () => void;
|
|
23
|
+
}): JSX.Element {
|
|
24
|
+
const {theme} = useTheme();
|
|
25
|
+
const t = useTranslation();
|
|
26
|
+
const [code, setCode] = useState('');
|
|
27
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
28
|
+
const dispatch = useAppDispatch();
|
|
29
|
+
const navigation =
|
|
30
|
+
useNavigation<NativeStackNavigationProp<RootStackParamList>>();
|
|
31
|
+
|
|
32
|
+
const getService = async () => {
|
|
33
|
+
if (!code) {
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
try {
|
|
37
|
+
setIsLoading(true);
|
|
38
|
+
const response = await dispatch(
|
|
39
|
+
getServiceById({data: {BillTypeCode: code}}),
|
|
40
|
+
);
|
|
41
|
+
if (response.type.includes('fulfilled')) {
|
|
42
|
+
const providerResponse = await dispatch(
|
|
43
|
+
getProviderById({
|
|
44
|
+
data: {BillerId: response.payload.service.BillerId},
|
|
45
|
+
}),
|
|
46
|
+
);
|
|
47
|
+
if (providerResponse.type.includes('fulfilled')) {
|
|
48
|
+
setCode('');
|
|
49
|
+
onClose();
|
|
50
|
+
setTimeout(() => {
|
|
51
|
+
navigation.navigate('SingleService', {
|
|
52
|
+
serviceID: undefined,
|
|
53
|
+
});
|
|
54
|
+
}, 200);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
} catch (error) {
|
|
58
|
+
console.error(error);
|
|
59
|
+
} finally {
|
|
60
|
+
setIsLoading(false);
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
return (
|
|
65
|
+
<Modal
|
|
66
|
+
onRequestClose={onClose}
|
|
67
|
+
visible={isVisible}
|
|
68
|
+
transparent
|
|
69
|
+
style={styles.modal}>
|
|
70
|
+
<RTLAwareView
|
|
71
|
+
style={{
|
|
72
|
+
...styles.container,
|
|
73
|
+
backgroundColor: theme.colors.surface,
|
|
74
|
+
borderWidth: 1,
|
|
75
|
+
borderColor: theme.colors.indigoBlue,
|
|
76
|
+
}}>
|
|
77
|
+
<PrimaryTextInput
|
|
78
|
+
value={code}
|
|
79
|
+
onChangeText={setCode}
|
|
80
|
+
placeholder={t('enterCode', 'home')}
|
|
81
|
+
/>
|
|
82
|
+
<RTLAwareView
|
|
83
|
+
style={{
|
|
84
|
+
flexDirection: 'row',
|
|
85
|
+
alignItems: 'center',
|
|
86
|
+
justifyContent: 'space-between',
|
|
87
|
+
}}>
|
|
88
|
+
<PrimaryButton
|
|
89
|
+
disabled={isLoading}
|
|
90
|
+
isLoading={isLoading}
|
|
91
|
+
onPress={() => {
|
|
92
|
+
onClose();
|
|
93
|
+
setCode('');
|
|
94
|
+
}}
|
|
95
|
+
style={{width: '48%'}}
|
|
96
|
+
label={t('cancel', 'home')}
|
|
97
|
+
type={ButtonType.solid}
|
|
98
|
+
/>
|
|
99
|
+
<PrimaryButton
|
|
100
|
+
disabled={isLoading}
|
|
101
|
+
isLoading={isLoading}
|
|
102
|
+
onPress={getService}
|
|
103
|
+
style={{width: '48%'}}
|
|
104
|
+
label={t('search', 'home')}
|
|
105
|
+
type={ButtonType.solid}
|
|
106
|
+
/>
|
|
107
|
+
</RTLAwareView>
|
|
108
|
+
</RTLAwareView>
|
|
109
|
+
</Modal>
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const styles = StyleSheet.create({
|
|
114
|
+
modal: {
|
|
115
|
+
flex: 1,
|
|
116
|
+
backgroundColor: 'red',
|
|
117
|
+
alignItems: 'center',
|
|
118
|
+
justifyContent: 'center',
|
|
119
|
+
},
|
|
120
|
+
container: {
|
|
121
|
+
width: '95%',
|
|
122
|
+
// minHeight: '40%',
|
|
123
|
+
alignSelf: 'center',
|
|
124
|
+
borderRadius: CommonSizes.borderRadius.large,
|
|
125
|
+
padding: CommonSizes.spacing.large,
|
|
126
|
+
gap: CommonSizes.spacing.large,
|
|
127
|
+
marginTop: '45%',
|
|
128
|
+
},
|
|
129
|
+
});
|
|
@@ -1,107 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import {
|
|
3
|
-
Dimensions,
|
|
4
|
-
RefreshControl,
|
|
5
|
-
ScrollView,
|
|
6
|
-
StyleSheet,
|
|
7
|
-
Text,
|
|
8
|
-
View,
|
|
9
|
-
} from 'react-native';
|
|
10
|
-
import {NaturalColors} from '../../core/theme/colors';
|
|
11
|
-
import {CommonSizes} from '../../core/theme/commonSizes';
|
|
12
|
-
import {CommonStyles} from '../../core/theme/commonStyles';
|
|
13
|
-
import {CarouselSection} from './components/CarouselSection';
|
|
14
|
-
import {FeaturedCarousel} from './components/FeaturedCarousel';
|
|
15
|
-
import {useHomeData} from './hooks/useHomeData';
|
|
16
|
-
|
|
17
|
-
const {width} = Dimensions.get('window');
|
|
18
2
|
|
|
19
3
|
export function HomeScreen(): JSX.Element {
|
|
20
|
-
|
|
21
|
-
featuredItems,
|
|
22
|
-
trendingItems,
|
|
23
|
-
newItems,
|
|
24
|
-
recommendedItems,
|
|
25
|
-
isLoading,
|
|
26
|
-
refreshData,
|
|
27
|
-
} = useHomeData();
|
|
28
|
-
|
|
29
|
-
return (
|
|
30
|
-
<ScrollView
|
|
31
|
-
style={styles.container}
|
|
32
|
-
refreshControl={
|
|
33
|
-
<RefreshControl refreshing={isLoading} onRefresh={refreshData} />
|
|
34
|
-
}>
|
|
35
|
-
<View style={styles.content}>
|
|
36
|
-
{/* Featured Section */}
|
|
37
|
-
<View style={styles.featuredSection}>
|
|
38
|
-
<Text style={styles.sectionTitle}>Featured</Text>
|
|
39
|
-
<FeaturedCarousel items={featuredItems} />
|
|
40
|
-
</View>
|
|
41
|
-
|
|
42
|
-
{/* Trending Section */}
|
|
43
|
-
<View style={styles.carouselSection}>
|
|
44
|
-
<Text style={styles.sectionTitle}>Trending Now</Text>
|
|
45
|
-
<CarouselSection
|
|
46
|
-
items={trendingItems}
|
|
47
|
-
imageStyle={styles.trendingImage}
|
|
48
|
-
/>
|
|
49
|
-
</View>
|
|
50
|
-
|
|
51
|
-
{/* New Arrivals Section */}
|
|
52
|
-
<View style={styles.carouselSection}>
|
|
53
|
-
<Text style={styles.sectionTitle}>New Arrivals</Text>
|
|
54
|
-
<CarouselSection
|
|
55
|
-
items={newItems}
|
|
56
|
-
imageStyle={styles.newArrivalsImage}
|
|
57
|
-
/>
|
|
58
|
-
</View>
|
|
59
|
-
|
|
60
|
-
{/* Recommended Section */}
|
|
61
|
-
<View style={styles.carouselSection}>
|
|
62
|
-
<Text style={styles.sectionTitle}>Recommended for You</Text>
|
|
63
|
-
<CarouselSection
|
|
64
|
-
items={recommendedItems}
|
|
65
|
-
imageStyle={styles.recommendedImage}
|
|
66
|
-
/>
|
|
67
|
-
</View>
|
|
68
|
-
</View>
|
|
69
|
-
</ScrollView>
|
|
70
|
-
);
|
|
4
|
+
return <></>;
|
|
71
5
|
}
|
|
72
|
-
|
|
73
|
-
const styles = StyleSheet.create({
|
|
74
|
-
container: {
|
|
75
|
-
flex: 1,
|
|
76
|
-
backgroundColor: NaturalColors.grayScale_0,
|
|
77
|
-
},
|
|
78
|
-
content: {
|
|
79
|
-
paddingVertical: CommonSizes.spacing.medium,
|
|
80
|
-
},
|
|
81
|
-
featuredSection: {
|
|
82
|
-
marginBottom: CommonSizes.spacing.large,
|
|
83
|
-
},
|
|
84
|
-
carouselSection: {
|
|
85
|
-
marginBottom: CommonSizes.spacing.large,
|
|
86
|
-
},
|
|
87
|
-
sectionTitle: {
|
|
88
|
-
...CommonStyles.h2_semiBold,
|
|
89
|
-
marginHorizontal: CommonSizes.spacing.large,
|
|
90
|
-
marginBottom: CommonSizes.spacing.medium,
|
|
91
|
-
},
|
|
92
|
-
trendingImage: {
|
|
93
|
-
width: width * 0.7,
|
|
94
|
-
height: 200,
|
|
95
|
-
borderRadius: CommonSizes.borderRadius.medium,
|
|
96
|
-
},
|
|
97
|
-
newArrivalsImage: {
|
|
98
|
-
width: width * 0.5,
|
|
99
|
-
height: 180,
|
|
100
|
-
borderRadius: CommonSizes.borderRadius.medium,
|
|
101
|
-
},
|
|
102
|
-
recommendedImage: {
|
|
103
|
-
width: width * 0.6,
|
|
104
|
-
height: 160,
|
|
105
|
-
borderRadius: CommonSizes.borderRadius.medium,
|
|
106
|
-
},
|
|
107
|
-
});
|
|
@@ -1,39 +1,34 @@
|
|
|
1
|
-
import {useState
|
|
2
|
-
import {
|
|
3
|
-
|
|
1
|
+
import {useState} from 'react';
|
|
2
|
+
import {getCategories} from '../../../core/store/Categories/categoryActions';
|
|
3
|
+
import {clearSelectedCategory} from '../../../core/store/Categories/categorySlice';
|
|
4
|
+
import {getHomeProviders} from '../../../core/store/Providers/providersActions';
|
|
5
|
+
import {useAppDispatch, useAppSelector} from '../../../core/store/reduxHelpers';
|
|
6
|
+
import {RootState} from '../../../core/store/rootReducer';
|
|
7
|
+
import {getBalance} from '../../../core/store/user/userActions';
|
|
8
|
+
import {clearSelectedProvider} from '../../../core/store/Providers/providersSlice';
|
|
4
9
|
export function useHomeData() {
|
|
5
10
|
const [isLoading, setIsLoading] = useState(false);
|
|
6
|
-
const
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
11
|
+
const dispatch = useAppDispatch();
|
|
12
|
+
const {categories, loadState} = useAppSelector(
|
|
13
|
+
(state: RootState) => state.categories,
|
|
14
|
+
);
|
|
15
|
+
const [isPayByCodeModalVisible, setIsPayByCodeModalVisible] = useState(false);
|
|
16
|
+
const {homeProviders} = useAppSelector((state: RootState) => state.providers);
|
|
17
|
+
const {user} = useAppSelector((state: RootState) => state.user);
|
|
10
18
|
|
|
11
19
|
const fetchData = async () => {
|
|
12
20
|
setIsLoading(true);
|
|
13
21
|
try {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
]);
|
|
25
|
-
|
|
26
|
-
setTrendingItems([
|
|
27
|
-
{
|
|
28
|
-
id: '1',
|
|
29
|
-
title: 'Trending Item 1',
|
|
30
|
-
subtitle: 'Hot right now',
|
|
31
|
-
imageUrl: 'https://picsum.photos/700/400',
|
|
32
|
-
},
|
|
33
|
-
// Add more items...
|
|
34
|
-
]);
|
|
35
|
-
|
|
36
|
-
// Similar for newItems and recommendedItems...
|
|
22
|
+
const balance = await dispatch(getBalance());
|
|
23
|
+
if (balance.type.includes('fulfilled')) {
|
|
24
|
+
const categoryResponse = await dispatch(
|
|
25
|
+
getCategories({data: {limit: 30}}),
|
|
26
|
+
);
|
|
27
|
+
if (categoryResponse.type.includes('fulfilled')) {
|
|
28
|
+
const category_id = categoryResponse?.payload?.categories?.[0]?.id;
|
|
29
|
+
await dispatch(getHomeProviders({data: {category_id: category_id}}));
|
|
30
|
+
}
|
|
31
|
+
}
|
|
37
32
|
} catch (error) {
|
|
38
33
|
console.error('Error fetching home data:', error);
|
|
39
34
|
} finally {
|
|
@@ -45,16 +40,15 @@ export function useHomeData() {
|
|
|
45
40
|
fetchData();
|
|
46
41
|
};
|
|
47
42
|
|
|
48
|
-
useEffect(() => {
|
|
49
|
-
fetchData();
|
|
50
|
-
}, []);
|
|
51
|
-
|
|
52
43
|
return {
|
|
53
44
|
isLoading,
|
|
54
|
-
featuredItems,
|
|
55
|
-
trendingItems,
|
|
56
|
-
newItems,
|
|
57
|
-
recommendedItems,
|
|
58
45
|
refreshData,
|
|
46
|
+
fetchData,
|
|
47
|
+
categories,
|
|
48
|
+
user,
|
|
49
|
+
homeProviders,
|
|
50
|
+
loadState,
|
|
51
|
+
isPayByCodeModalVisible,
|
|
52
|
+
setIsPayByCodeModalVisible,
|
|
59
53
|
};
|
|
60
54
|
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// Authentication Screens
|
|
2
|
+
export {Login} from './Login/Login';
|
|
3
|
+
export {OTPScreen as OTP} from './OTP/OTPScreen';
|
|
4
|
+
export {ForceChangePasswordScreen as ForceChangePassword} from './ForceChangePassword/ForceChangePasswordScreen';
|
|
5
|
+
|
|
6
|
+
// Main Navigation Screens
|
|
7
|
+
export {HomeScreen as Home} from './home/HomeScreen';
|
|
8
|
+
export {Profile} from './profile/Profile';
|
|
9
|
+
export {Splash} from './splash/Splash';
|
|
10
|
+
|
|
11
|
+
// Service Related Screens
|
|
12
|
+
export {Categories} from './Categories/Categories';
|
|
13
|
+
export {Services} from './Services/Services';
|
|
14
|
+
export {SingleService} from './SingleService/SingleService';
|
|
15
|
+
export {Providers} from './Providers/Providers';
|
|
16
|
+
export {InquiredBill} from './InquiredBill/InquiredBill';
|
|
17
|
+
export {PaymentConfirmation} from './PaymentConfirmation/PaymentConfirmation';
|
|
18
|
+
|
|
19
|
+
// History and Receipt Screens
|
|
20
|
+
export {History} from './History/History';
|
|
21
|
+
export {Favorites} from './Favorites/Favorites';
|
|
22
|
+
|
|
23
|
+
// Device and Card Related Screens
|
|
24
|
+
export {ReceiptScreen} from './ReceiptScreen/ReceiptScreen';
|
|
@@ -1,153 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import {View, Text, StyleSheet, Image, Pressable} from 'react-native';
|
|
3
|
-
import {useTheme} from '../../core/theme/ThemeProvider';
|
|
4
|
-
import {Theme} from '../../core/theme/types';
|
|
5
|
-
import {PrimaryColors} from '../../core/theme/colors';
|
|
6
|
-
import {ImageResources} from '../ImageResources.g';
|
|
7
|
-
|
|
8
|
-
interface Step {
|
|
9
|
-
title: string;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
interface StepperProps {
|
|
13
|
-
steps: Step[];
|
|
14
|
-
currentStep: number;
|
|
15
|
-
orientation?: 'horizontal' | 'vertical';
|
|
16
|
-
onStepPress?: (index: number) => void;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
const STEP_SIZE = 64;
|
|
20
|
-
|
|
21
|
-
const Stepper: React.FC<StepperProps> = ({
|
|
22
|
-
steps,
|
|
23
|
-
currentStep,
|
|
24
|
-
orientation = 'horizontal',
|
|
25
|
-
onStepPress,
|
|
26
|
-
}) => {
|
|
27
|
-
const {theme} = useTheme();
|
|
28
|
-
const isDarkMode = theme.mode === 'dark';
|
|
29
|
-
const styles = createStyles(theme, orientation, isDarkMode);
|
|
30
|
-
|
|
31
|
-
return (
|
|
32
|
-
<View style={styles.container}>
|
|
33
|
-
{steps.map((step, index) => {
|
|
34
|
-
const isCompleted = index < currentStep;
|
|
35
|
-
const isActive = index === currentStep;
|
|
36
|
-
const isLastStep = index === steps.length - 1;
|
|
37
|
-
|
|
38
|
-
const connectorStyle = [
|
|
39
|
-
styles.connector,
|
|
40
|
-
(isCompleted || isActive) && styles.connectorCompleted,
|
|
41
|
-
];
|
|
42
|
-
|
|
43
|
-
return (
|
|
44
|
-
<React.Fragment key={index}>
|
|
45
|
-
<Pressable
|
|
46
|
-
style={styles.stepContainer}
|
|
47
|
-
onPress={() => onStepPress?.(index)}>
|
|
48
|
-
<View
|
|
49
|
-
style={[
|
|
50
|
-
styles.circle,
|
|
51
|
-
isCompleted && styles.circleCompleted,
|
|
52
|
-
isActive && styles.circleActive,
|
|
53
|
-
]}>
|
|
54
|
-
{isCompleted ? (
|
|
55
|
-
<Image source={0} style={styles.icon} />
|
|
56
|
-
) : (
|
|
57
|
-
<Text style={styles.stepNumber}>{index + 1}</Text>
|
|
58
|
-
)}
|
|
59
|
-
</View>
|
|
60
|
-
<Text
|
|
61
|
-
style={[
|
|
62
|
-
styles.title,
|
|
63
|
-
(isCompleted || isActive) && styles.titleActive,
|
|
64
|
-
]}>
|
|
65
|
-
{step.title}
|
|
66
|
-
</Text>
|
|
67
|
-
</Pressable>
|
|
68
|
-
{!isLastStep && <View style={connectorStyle} />}
|
|
69
|
-
</React.Fragment>
|
|
70
|
-
);
|
|
71
|
-
})}
|
|
72
|
-
</View>
|
|
73
|
-
);
|
|
74
|
-
};
|
|
75
|
-
|
|
76
|
-
const createStyles = (
|
|
77
|
-
theme: Theme,
|
|
78
|
-
orientation: 'horizontal' | 'vertical',
|
|
79
|
-
isDarkMode: boolean,
|
|
80
|
-
) =>
|
|
81
|
-
StyleSheet.create({
|
|
82
|
-
container: {
|
|
83
|
-
flexDirection: orientation === 'horizontal' ? 'row' : 'column',
|
|
84
|
-
alignItems: orientation === 'horizontal' ? 'flex-start' : 'stretch',
|
|
85
|
-
},
|
|
86
|
-
stepContainer: {
|
|
87
|
-
alignItems: 'center',
|
|
88
|
-
flex: orientation === 'horizontal' ? 1 : undefined,
|
|
89
|
-
},
|
|
90
|
-
circle: {
|
|
91
|
-
width: STEP_SIZE,
|
|
92
|
-
height: STEP_SIZE,
|
|
93
|
-
borderRadius: STEP_SIZE / 2,
|
|
94
|
-
borderWidth: 1,
|
|
95
|
-
borderColor: isDarkMode
|
|
96
|
-
? theme.colors.grayScale_400
|
|
97
|
-
: theme.colors.grayScale_50,
|
|
98
|
-
justifyContent: 'center',
|
|
99
|
-
alignItems: 'center',
|
|
100
|
-
backgroundColor: 'transparent',
|
|
101
|
-
},
|
|
102
|
-
circleCompleted: {
|
|
103
|
-
backgroundColor: PrimaryColors.PlatinateBlue_400,
|
|
104
|
-
borderColor: PrimaryColors.PlatinateBlue_400,
|
|
105
|
-
},
|
|
106
|
-
circleActive: {
|
|
107
|
-
borderColor: PrimaryColors.PlatinateBlue_400,
|
|
108
|
-
},
|
|
109
|
-
icon: {
|
|
110
|
-
width: STEP_SIZE / 2,
|
|
111
|
-
height: STEP_SIZE / 2,
|
|
112
|
-
tintColor: theme.colors.grayScale_0,
|
|
113
|
-
},
|
|
114
|
-
stepNumber: {
|
|
115
|
-
...theme.text.bodyXLargeRegular,
|
|
116
|
-
color: isDarkMode
|
|
117
|
-
? theme.colors.grayScale_400
|
|
118
|
-
: theme.colors.grayScale_50,
|
|
119
|
-
},
|
|
120
|
-
title: {
|
|
121
|
-
...theme.text.bodyMediumRegular,
|
|
122
|
-
marginTop: theme.spacing.small,
|
|
123
|
-
color: isDarkMode
|
|
124
|
-
? theme.colors.grayScale_400
|
|
125
|
-
: theme.colors.grayScale_50,
|
|
126
|
-
},
|
|
127
|
-
titleActive: {
|
|
128
|
-
color: theme.colors.cetaceanBlue_700,
|
|
129
|
-
},
|
|
130
|
-
connector: {
|
|
131
|
-
backgroundColor: isDarkMode
|
|
132
|
-
? theme.colors.grayScale_400
|
|
133
|
-
: theme.colors.grayScale_50,
|
|
134
|
-
...(orientation === 'horizontal'
|
|
135
|
-
? {
|
|
136
|
-
height: 1,
|
|
137
|
-
flex: 1,
|
|
138
|
-
marginHorizontal: -STEP_SIZE / 4,
|
|
139
|
-
top: STEP_SIZE / 2,
|
|
140
|
-
}
|
|
141
|
-
: {
|
|
142
|
-
width: 1,
|
|
143
|
-
flex: 1,
|
|
144
|
-
marginVertical: -STEP_SIZE / 4,
|
|
145
|
-
left: '50%',
|
|
146
|
-
}),
|
|
147
|
-
},
|
|
148
|
-
connectorCompleted: {
|
|
149
|
-
backgroundColor: PrimaryColors.PlatinateBlue_400,
|
|
150
|
-
},
|
|
151
|
-
});
|
|
152
|
-
|
|
153
|
-
export default Stepper;
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import * as React from 'react';
|
|
2
|
-
import Svg, {G, Path, Defs, ClipPath, SvgProps} from 'react-native-svg';
|
|
3
|
-
|
|
4
|
-
const SvgComponent: React.FC<SvgProps> = props => (
|
|
5
|
-
<Svg width={'100%'} height={'100%'} fill="none" {...props}>
|
|
6
|
-
<G clipPath="url(#a)">
|
|
7
|
-
<Path fill="#F9FCFF" d="M0 0h428v925H0z" />
|
|
8
|
-
<Path
|
|
9
|
-
fill="#F3F2FF"
|
|
10
|
-
d="M293.588 913.49c-11.664-7.299-22.732-17.683-25.003-31.28-1.327-8.116.619-16.401.321-24.632-1.302-34.39-41.04-60.387-36.303-94.477 3.225-23.054 26.005-38.157 48.084-45.307 22.079-7.15 46.135-9.803 65.558-22.544 11.677-7.647 20.94-18.492 32.704-26.016 31.368-20.054 78.287-8.983 97.328 23.023 13.438 22.55 13.203 50.707 8.916 76.621-7.313 43.969-24.299 113.518-59.201 144.845-32.956 29.629-98.321 21.076-132.404-.233Z"
|
|
11
|
-
/>
|
|
12
|
-
<Path
|
|
13
|
-
fill="#EEF8FF"
|
|
14
|
-
d="M80.103-35.495c11.658 7.31 22.718 17.702 24.977 31.301 1.32 8.117-.633 16.4-.342 24.631 1.274 34.392 40.991 60.422 36.225 94.508-3.244 23.051-26.037 38.135-48.122 45.267-22.085 7.132-46.143 9.764-65.577 22.489-11.683 7.638-20.955 18.474-32.725 25.989-31.385 20.028-78.294 8.917-97.31-23.105-13.419-22.56-13.16-50.717-8.852-76.628C-104.272 64.994-87.228-4.54-52.301-35.838c32.98-29.602 98.34-20.994 132.404.343Z"
|
|
15
|
-
/>
|
|
16
|
-
</G>
|
|
17
|
-
<Defs>
|
|
18
|
-
<ClipPath id="a">
|
|
19
|
-
<Path fill="#fff" d="M0 0h428v925H0z" />
|
|
20
|
-
</ClipPath>
|
|
21
|
-
</Defs>
|
|
22
|
-
</Svg>
|
|
23
|
-
);
|
|
24
|
-
|
|
25
|
-
export default SvgComponent;
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import {useEffect, useState} from 'react';
|
|
2
|
-
|
|
3
|
-
export function useDebounce<T>(value: T, delay: number): T {
|
|
4
|
-
const [debouncedValue, setDebouncedValue] = useState<T>(value);
|
|
5
|
-
|
|
6
|
-
useEffect(() => {
|
|
7
|
-
const handler = setTimeout(() => {
|
|
8
|
-
setDebouncedValue(value);
|
|
9
|
-
}, delay);
|
|
10
|
-
|
|
11
|
-
return () => {
|
|
12
|
-
clearTimeout(handler);
|
|
13
|
-
};
|
|
14
|
-
}, [value, delay]);
|
|
15
|
-
|
|
16
|
-
return debouncedValue;
|
|
17
|
-
}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import {BaseUrlOpener} from './baseUrlOpener';
|
|
2
|
-
|
|
3
|
-
export class EmailUrl extends BaseUrlOpener {
|
|
4
|
-
constructor(private email: string | null) {
|
|
5
|
-
super();
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
protected generateUrl(): string | null {
|
|
9
|
-
if (this.email == null) {
|
|
10
|
-
return null;
|
|
11
|
-
} else {
|
|
12
|
-
let url = this.email;
|
|
13
|
-
if (!url.startsWith('mailto')) {
|
|
14
|
-
url = 'mailto://' + url;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
return url;
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import {isIos} from '../../core/theme/commonConsts';
|
|
2
|
-
import {BaseUrlOpener} from './baseUrlOpener';
|
|
3
|
-
|
|
4
|
-
export class MapUrl extends BaseUrlOpener {
|
|
5
|
-
constructor(
|
|
6
|
-
private latitude: number,
|
|
7
|
-
private longitude: number,
|
|
8
|
-
private address: string,
|
|
9
|
-
) {
|
|
10
|
-
super();
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
protected generateUrl(): string | null {
|
|
14
|
-
if (isIos) {
|
|
15
|
-
return `https://maps.apple.com/?q=${encodeURIComponent(
|
|
16
|
-
this.address,
|
|
17
|
-
)}&sll=${this.latitude},${this.longitude}`;
|
|
18
|
-
} else {
|
|
19
|
-
return `geo:${this.latitude}, ${this.longitude}`;
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
}
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import {LoadState} from '../../../types';
|
|
2
|
-
import {DEFAULT_PAGE_SIZE} from '../helpers/calculatePage';
|
|
3
|
-
|
|
4
|
-
export function commonListFulfilledHandler<T>(
|
|
5
|
-
loadState: LoadState,
|
|
6
|
-
payloadList: T[],
|
|
7
|
-
storedList: T[],
|
|
8
|
-
) {
|
|
9
|
-
const newLoadState =
|
|
10
|
-
payloadList.length >= DEFAULT_PAGE_SIZE
|
|
11
|
-
? LoadState.idle
|
|
12
|
-
: LoadState.allIsLoaded;
|
|
13
|
-
|
|
14
|
-
let newData: T[] = [];
|
|
15
|
-
|
|
16
|
-
switch (loadState) {
|
|
17
|
-
case LoadState.firstLoad:
|
|
18
|
-
case LoadState.pullToRefresh:
|
|
19
|
-
case LoadState.refreshing:
|
|
20
|
-
newData = [...payloadList];
|
|
21
|
-
break;
|
|
22
|
-
case LoadState.loadingMore:
|
|
23
|
-
newData = [...storedList].concat(payloadList);
|
|
24
|
-
break;
|
|
25
|
-
default:
|
|
26
|
-
throw new Error(`LoadState ${loadState} is not valid in this context.`);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
return {data: newData, error: null, loadState: newLoadState};
|
|
30
|
-
}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
export function serializeQueryParams(obj: any): string {
|
|
2
|
-
const str = [];
|
|
3
|
-
for (const key in obj) {
|
|
4
|
-
if (obj.hasOwnProperty(key) && obj[key] !== undefined) {
|
|
5
|
-
str.push(encodeURIComponent(key) + '=' + encodeURIComponent(obj[key]));
|
|
6
|
-
}
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
return str.join('&');
|
|
10
|
-
}
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import {useCallback, useEffect, useRef, useState} from 'react';
|
|
2
|
-
import {datesValidation} from '../commonValidations';
|
|
3
|
-
|
|
4
|
-
export function useDatesError(
|
|
5
|
-
fromDate: Date,
|
|
6
|
-
toDate: Date,
|
|
7
|
-
fromLabel: string,
|
|
8
|
-
toLabel: string,
|
|
9
|
-
currentField: 'from' | 'to',
|
|
10
|
-
) {
|
|
11
|
-
const [error, setError] = useState<string | null>(null);
|
|
12
|
-
const didMountRef = useRef(false);
|
|
13
|
-
|
|
14
|
-
const recheckValue = useCallback(() => {
|
|
15
|
-
const result = datesValidation(
|
|
16
|
-
fromDate,
|
|
17
|
-
toDate,
|
|
18
|
-
fromLabel,
|
|
19
|
-
toLabel,
|
|
20
|
-
currentField,
|
|
21
|
-
);
|
|
22
|
-
setError(result);
|
|
23
|
-
|
|
24
|
-
return result;
|
|
25
|
-
}, [currentField, fromDate, fromLabel, toDate, toLabel]);
|
|
26
|
-
|
|
27
|
-
useEffect(() => {
|
|
28
|
-
if (didMountRef.current) {
|
|
29
|
-
recheckValue();
|
|
30
|
-
} else {
|
|
31
|
-
didMountRef.current = true;
|
|
32
|
-
}
|
|
33
|
-
}, [recheckValue]);
|
|
34
|
-
|
|
35
|
-
return {
|
|
36
|
-
error,
|
|
37
|
-
setError,
|
|
38
|
-
recheckValue,
|
|
39
|
-
};
|
|
40
|
-
}
|