@fadyshawky/react-native-magic 2.0.4 → 2.0.5
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/src/common/ImageResources.g.ts +33 -1
- package/template/src/common/components/Background.tsx +3 -1
- package/template/src/common/components/Container.tsx +1 -1
- 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/localization.ts +10 -0
- package/template/src/common/localization/translations/commonLocalization.ts +97 -0
- package/template/src/common/localization/translations/homeLocalization.ts +24 -0
- package/template/src/common/localization/translations/loginLocalization.ts +28 -2
- 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/otpLocalization.ts +28 -0
- package/template/src/common/localization/translations/passwordLocalization.ts +54 -0
- package/template/src/common/localization/translations/posLocalization.ts +196 -0
- 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/components/PrinterExample.js +226 -0
- 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 +70 -94
- package/template/src/core/theme/commonConsts.ts +1 -1
- package/template/src/core/theme/commonSizes.ts +94 -119
- package/template/src/core/theme/commonStyles.ts +22 -22
- package/template/src/core/theme/fonts.ts +14 -13
- package/template/src/core/theme/themes.ts +75 -386
- package/template/src/core/theme/types.ts +15 -201
- package/template/src/core/utils/stringUtils.ts +114 -0
- package/template/src/modules/SunmiCard.js +212 -0
- package/template/src/modules/SunmiPrepaid.ts +122 -0
- package/template/src/navigation/AuthStack.tsx +8 -0
- package/template/src/navigation/HeaderComponents.tsx +76 -1
- package/template/src/navigation/MainNavigation.tsx +3 -1
- package/template/src/navigation/MainStack.tsx +130 -56
- package/template/src/navigation/TabBar.tsx +111 -59
- package/template/src/navigation/types.ts +24 -0
- package/template/src/screens/Categories/Categories.tsx +141 -0
- package/template/src/screens/Categories/hooks/useCategoriesData.ts +33 -0
- package/template/src/screens/Categories/types.ts +7 -0
- package/template/src/screens/Favorites/Favorites.tsx +130 -0
- package/template/src/screens/ForceChangePassword/ForceChangePasswordScreen.tsx +155 -0
- package/template/src/screens/History/History.tsx +430 -0
- package/template/src/screens/History/hooks/useHistoryData.ts +49 -0
- package/template/src/screens/History/types.ts +7 -0
- package/template/src/screens/InquiredBill/InquiredBill.tsx +443 -0
- package/template/src/screens/InquiredBill/hooks/useInquiredData.ts +91 -0
- package/template/src/screens/Login/Login.tsx +85 -85
- package/template/src/screens/OTP/OTPScreen.tsx +170 -0
- package/template/src/screens/PaymentConfirmation/PaymentConfirmation.tsx +326 -0
- package/template/src/screens/Providers/Providers.tsx +166 -0
- package/template/src/screens/Providers/hooks/useProvidersData.ts +33 -0
- package/template/src/screens/Providers/types.ts +7 -0
- package/template/src/screens/ReceiptScreen/ReceiptScreen.tsx +181 -0
- package/template/src/screens/ReceiptScreen/hooks/useReceiptData.ts +46 -0
- package/template/src/screens/ReceiptScreen/utils/utils.tsx +156 -0
- package/template/src/screens/Services/Services.tsx +144 -0
- package/template/src/screens/Services/hooks/useServicesData.ts +41 -0
- package/template/src/screens/SingleService/Components/FawryInputs.tsx +446 -0
- package/template/src/screens/SingleService/SingleService.tsx +229 -0
- package/template/src/screens/SingleService/hooks/useServiceData.ts +164 -0
- package/template/src/screens/home/Components/PayByCode.tsx +129 -0
- package/template/src/screens/home/HomeScreen.tsx +268 -77
- package/template/src/screens/home/hooks/useHomeData.ts +32 -38
- package/template/src/screens/index.tsx +24 -0
- package/template/src/screens/profile/Profile.tsx +290 -2
- package/template/src/services/SunmiPrinterInternal.js +268 -0
- package/template/src/types/sunmiPrepaid.d.ts +20 -0
- package/template/src/utils/SunmiPrinter.ts +442 -0
- package/template/src/utils/feesCalculator.ts +92 -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/localization/intlFormatter.ts +0 -37
- 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/core/theme/shadows.ts +0 -135
- 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
|
@@ -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,37 +0,0 @@
|
|
|
1
|
-
import Intl from 'intl';
|
|
2
|
-
import {getLanguage} from './localization';
|
|
3
|
-
// eslint-disable-next-line import/no-unassigned-import
|
|
4
|
-
import 'intl/locale-data/jsonp/en';
|
|
5
|
-
|
|
6
|
-
export function formatPercent(percent: number | string): string {
|
|
7
|
-
const formatter = new Intl.NumberFormat(getLanguage(), {
|
|
8
|
-
style: 'percent',
|
|
9
|
-
minimumFractionDigits: 0,
|
|
10
|
-
maximumFractionDigits: 2,
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
return formatter.format(Number(percent) / 100);
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export function formatCurrency(
|
|
17
|
-
price: number | string,
|
|
18
|
-
currency?: string,
|
|
19
|
-
): string {
|
|
20
|
-
const formatter = new Intl.NumberFormat(getLanguage(), {
|
|
21
|
-
style: 'currency',
|
|
22
|
-
minimumFractionDigits: 0,
|
|
23
|
-
maximumFractionDigits: 2,
|
|
24
|
-
currency: currency || 'USD',
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
return formatter.format(Number(price));
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export function formatDecimal(value: number | string): string {
|
|
31
|
-
const formatter = new Intl.NumberFormat(getLanguage(), {
|
|
32
|
-
style: 'decimal',
|
|
33
|
-
minimumFractionDigits: 0,
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
return formatter.format(Number(value));
|
|
37
|
-
}
|
|
@@ -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
|
-
}
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import {emptyValidation} from './commonValidations';
|
|
2
|
-
import {isEmail} from '../helpers/regexHelpers';
|
|
3
|
-
import {validationConstants} from './validationConstants';
|
|
4
|
-
import {localization} from '../localization/localization';
|
|
5
|
-
|
|
6
|
-
export function emailValidations(checkValue: string): string | null {
|
|
7
|
-
const isEmpty = emptyValidation(checkValue);
|
|
8
|
-
|
|
9
|
-
if (isEmpty != null) {
|
|
10
|
-
return isEmpty;
|
|
11
|
-
} else if (!isEmail(checkValue)) {
|
|
12
|
-
return localization.errors.invalidEmail;
|
|
13
|
-
} else {
|
|
14
|
-
return null;
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export function fullNameValidations(checkValue: string): string | null {
|
|
19
|
-
const isEmpty = emptyValidation(checkValue);
|
|
20
|
-
|
|
21
|
-
if (isEmpty != null) {
|
|
22
|
-
return isEmpty;
|
|
23
|
-
} else if (
|
|
24
|
-
checkValue.trim().length < validationConstants.fullName.minLength
|
|
25
|
-
) {
|
|
26
|
-
return localization.errors.invalidFullName;
|
|
27
|
-
} else {
|
|
28
|
-
return null;
|
|
29
|
-
}
|
|
30
|
-
}
|
|
@@ -1,135 +0,0 @@
|
|
|
1
|
-
export interface ShadowConfig {
|
|
2
|
-
shadowColor: string;
|
|
3
|
-
shadowOffset: {
|
|
4
|
-
width: number;
|
|
5
|
-
height: number;
|
|
6
|
-
};
|
|
7
|
-
shadowOpacity: number;
|
|
8
|
-
shadowRadius: number;
|
|
9
|
-
elevation?: number; // For Android
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export interface ElevationShadow {
|
|
13
|
-
primary: ShadowConfig;
|
|
14
|
-
secondary: ShadowConfig;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export const Shadows: Record<number, ElevationShadow> = {
|
|
18
|
-
1: {
|
|
19
|
-
primary: {
|
|
20
|
-
shadowColor: '#000000',
|
|
21
|
-
shadowOffset: {
|
|
22
|
-
width: 0,
|
|
23
|
-
height: 1,
|
|
24
|
-
},
|
|
25
|
-
shadowOpacity: 0.02, // 2%
|
|
26
|
-
shadowRadius: 1,
|
|
27
|
-
elevation: 1,
|
|
28
|
-
},
|
|
29
|
-
secondary: {
|
|
30
|
-
shadowColor: '#000000',
|
|
31
|
-
shadowOffset: {
|
|
32
|
-
width: 0,
|
|
33
|
-
height: 2,
|
|
34
|
-
},
|
|
35
|
-
shadowOpacity: 0.04, // 4%
|
|
36
|
-
shadowRadius: 4,
|
|
37
|
-
elevation: 1,
|
|
38
|
-
},
|
|
39
|
-
},
|
|
40
|
-
2: {
|
|
41
|
-
primary: {
|
|
42
|
-
shadowColor: '#000000',
|
|
43
|
-
shadowOffset: {
|
|
44
|
-
width: 0,
|
|
45
|
-
height: 1,
|
|
46
|
-
},
|
|
47
|
-
shadowOpacity: 0.04, // 4%
|
|
48
|
-
shadowRadius: 4,
|
|
49
|
-
elevation: 2,
|
|
50
|
-
},
|
|
51
|
-
secondary: {
|
|
52
|
-
shadowColor: '#000000',
|
|
53
|
-
shadowOffset: {
|
|
54
|
-
width: 0,
|
|
55
|
-
height: 4,
|
|
56
|
-
},
|
|
57
|
-
shadowOpacity: 0.08, // 8%
|
|
58
|
-
shadowRadius: 10,
|
|
59
|
-
elevation: 2,
|
|
60
|
-
},
|
|
61
|
-
},
|
|
62
|
-
3: {
|
|
63
|
-
primary: {
|
|
64
|
-
shadowColor: '#000000',
|
|
65
|
-
shadowOffset: {
|
|
66
|
-
width: 0,
|
|
67
|
-
height: 2,
|
|
68
|
-
},
|
|
69
|
-
shadowOpacity: 0.04, // 4%
|
|
70
|
-
shadowRadius: 20,
|
|
71
|
-
elevation: 3,
|
|
72
|
-
},
|
|
73
|
-
secondary: {
|
|
74
|
-
shadowColor: '#000000',
|
|
75
|
-
shadowOffset: {
|
|
76
|
-
width: 0,
|
|
77
|
-
height: 8,
|
|
78
|
-
},
|
|
79
|
-
shadowOpacity: 0.08, // 8%
|
|
80
|
-
shadowRadius: 32,
|
|
81
|
-
elevation: 3,
|
|
82
|
-
},
|
|
83
|
-
},
|
|
84
|
-
4: {
|
|
85
|
-
primary: {
|
|
86
|
-
shadowColor: '#000000',
|
|
87
|
-
shadowOffset: {
|
|
88
|
-
width: 0,
|
|
89
|
-
height: 8,
|
|
90
|
-
},
|
|
91
|
-
shadowOpacity: 0.06, // 6%
|
|
92
|
-
shadowRadius: 20,
|
|
93
|
-
elevation: 4,
|
|
94
|
-
},
|
|
95
|
-
secondary: {
|
|
96
|
-
shadowColor: '#000000',
|
|
97
|
-
shadowOffset: {
|
|
98
|
-
width: 0,
|
|
99
|
-
height: 24,
|
|
100
|
-
},
|
|
101
|
-
shadowOpacity: 0.12, // 12%
|
|
102
|
-
shadowRadius: 60,
|
|
103
|
-
elevation: 4,
|
|
104
|
-
},
|
|
105
|
-
},
|
|
106
|
-
};
|
|
107
|
-
|
|
108
|
-
// Helper function to get shadow styles for a specific elevation
|
|
109
|
-
export const getShadowStyle = (
|
|
110
|
-
elevation: number,
|
|
111
|
-
useSecondary = false,
|
|
112
|
-
): ShadowConfig => {
|
|
113
|
-
const shadow = Shadows[elevation];
|
|
114
|
-
if (!shadow) {
|
|
115
|
-
throw new Error(
|
|
116
|
-
`Elevation ${elevation} is not defined. Available elevations: ${Object.keys(
|
|
117
|
-
Shadows,
|
|
118
|
-
).join(', ')}`,
|
|
119
|
-
);
|
|
120
|
-
}
|
|
121
|
-
return useSecondary ? shadow.secondary : shadow.primary;
|
|
122
|
-
};
|
|
123
|
-
|
|
124
|
-
// Helper function to get both primary and secondary shadows for an elevation
|
|
125
|
-
export const getElevationShadows = (elevation: number): ElevationShadow => {
|
|
126
|
-
const shadow = Shadows[elevation];
|
|
127
|
-
if (!shadow) {
|
|
128
|
-
throw new Error(
|
|
129
|
-
`Elevation ${elevation} is not defined. Available elevations: ${Object.keys(
|
|
130
|
-
Shadows,
|
|
131
|
-
).join(', ')}`,
|
|
132
|
-
);
|
|
133
|
-
}
|
|
134
|
-
return shadow;
|
|
135
|
-
};
|
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
import {Animated, View, TouchableOpacity} from 'react-native';
|
|
2
|
-
import {CommonStyles, screenWidth} from '../core/theme/commonStyles';
|
|
3
|
-
import {NaturalColors} from '../core/theme/colors';
|
|
4
|
-
|
|
5
|
-
export function TopBar({state, descriptors, navigation, position}: any) {
|
|
6
|
-
return (
|
|
7
|
-
<View
|
|
8
|
-
style={{
|
|
9
|
-
flexDirection: 'row',
|
|
10
|
-
backgroundColor: NaturalColors.grayScale_50,
|
|
11
|
-
width: screenWidth - 60,
|
|
12
|
-
alignSelf: 'center',
|
|
13
|
-
height: 40,
|
|
14
|
-
borderRadius: 20,
|
|
15
|
-
marginBottom: 24,
|
|
16
|
-
}}>
|
|
17
|
-
{state.routes.map((route: any, index: any) => {
|
|
18
|
-
const {options} = descriptors[route.key];
|
|
19
|
-
const label =
|
|
20
|
-
options.tabBarLabel !== undefined
|
|
21
|
-
? options.tabBarLabel
|
|
22
|
-
: options.title !== undefined
|
|
23
|
-
? options.title
|
|
24
|
-
: route.name;
|
|
25
|
-
|
|
26
|
-
const isFocused = state.index === index;
|
|
27
|
-
|
|
28
|
-
const onPress = () => {
|
|
29
|
-
const event = navigation.emit({
|
|
30
|
-
type: 'tabPress',
|
|
31
|
-
target: route.key,
|
|
32
|
-
canPreventDefault: true,
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
if (!isFocused && !event.defaultPrevented) {
|
|
36
|
-
navigation.navigate(route.name, route.params);
|
|
37
|
-
}
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
const onLongPress = () => {
|
|
41
|
-
navigation.emit({
|
|
42
|
-
type: 'tabLongPress',
|
|
43
|
-
target: route.key,
|
|
44
|
-
});
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
return (
|
|
48
|
-
<TouchableOpacity
|
|
49
|
-
accessibilityRole="button"
|
|
50
|
-
accessibilityState={isFocused ? {selected: true} : {}}
|
|
51
|
-
accessibilityLabel={options.tabBarAccessibilityLabel}
|
|
52
|
-
testID={options.tabBarTestID}
|
|
53
|
-
onPress={onPress}
|
|
54
|
-
onLongPress={onLongPress}
|
|
55
|
-
style={{
|
|
56
|
-
flex: 1,
|
|
57
|
-
alignItems: 'center',
|
|
58
|
-
justifyContent: 'center',
|
|
59
|
-
backgroundColor: isFocused
|
|
60
|
-
? NaturalColors.grayScale_0
|
|
61
|
-
: NaturalColors.grayScale_50,
|
|
62
|
-
borderRadius: 20,
|
|
63
|
-
}}>
|
|
64
|
-
<Animated.Text
|
|
65
|
-
style={
|
|
66
|
-
isFocused
|
|
67
|
-
? {...CommonStyles.h4_bold, fontWeight: 'bold'}
|
|
68
|
-
: CommonStyles.h4_regular
|
|
69
|
-
}>
|
|
70
|
-
{label}
|
|
71
|
-
</Animated.Text>
|
|
72
|
-
</TouchableOpacity>
|
|
73
|
-
);
|
|
74
|
-
})}
|
|
75
|
-
</View>
|
|
76
|
-
);
|
|
77
|
-
}
|