@fadyshawky/react-native-magic 2.0.5 → 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 (66) hide show
  1. package/package.json +1 -1
  2. package/template/App.tsx +28 -19
  3. package/template/ios/reactnativemagic/AppDelegate.mm +5 -0
  4. package/template/src/common/ImageResources.g.ts +1 -33
  5. package/template/src/common/components/Background.tsx +7 -7
  6. package/template/src/common/components/Container.tsx +7 -10
  7. package/template/src/common/localization/LocalizationProvider.tsx +14 -17
  8. package/template/src/common/localization/RTLInitializer.tsx +90 -0
  9. package/template/src/common/localization/intlFormatter.ts +37 -0
  10. package/template/src/common/localization/localization.ts +1 -3
  11. package/template/src/common/localization/translations/commonLocalization.ts +11 -81
  12. package/template/src/common/localization/translations/emptyLocalization.ts +6 -2
  13. package/template/src/common/localization/translations/errorsLocalization.ts +33 -13
  14. package/template/src/common/localization/translations/homeLocalization.ts +4 -24
  15. package/template/src/common/localization/translations/loginLocalization.ts +26 -29
  16. package/template/src/common/localization/translations/mainNavigationLocalization.ts +2 -2
  17. package/template/src/common/localization/translations/onboardingLocalization.ts +40 -9
  18. package/template/src/common/localization/translations/otpLocalization.ts +8 -8
  19. package/template/src/common/localization/translations/pagesLocalization.ts +13 -1
  20. package/template/src/common/localization/translations/passwordLocalization.ts +3 -3
  21. package/template/src/common/localization/translations/profileLocalization.ts +4 -4
  22. package/template/src/core/store/app/appState.ts +2 -2
  23. package/template/src/core/theme/colors.ts +106 -70
  24. package/template/src/core/theme/commonConsts.ts +1 -1
  25. package/template/src/core/theme/commonSizes.ts +119 -94
  26. package/template/src/core/theme/commonStyles.ts +22 -22
  27. package/template/src/core/theme/fonts.ts +13 -14
  28. package/template/src/core/theme/shadows.ts +135 -0
  29. package/template/src/core/theme/themes.ts +386 -75
  30. package/template/src/core/theme/types.ts +201 -15
  31. package/template/src/navigation/HeaderComponents.tsx +6 -30
  32. package/template/src/navigation/MainStack.tsx +6 -97
  33. package/template/src/screens/Login/Login.tsx +5 -7
  34. package/template/src/screens/OTP/OTPScreen.tsx +12 -13
  35. package/template/src/screens/home/HomeScreen.tsx +2 -295
  36. package/template/src/screens/profile/Profile.tsx +2 -290
  37. package/template/src/common/localization/translations/posLocalization.ts +0 -196
  38. package/template/src/components/PrinterExample.js +0 -226
  39. package/template/src/modules/SunmiCard.js +0 -212
  40. package/template/src/modules/SunmiPrepaid.ts +0 -122
  41. package/template/src/screens/Categories/Categories.tsx +0 -141
  42. package/template/src/screens/Categories/hooks/useCategoriesData.ts +0 -33
  43. package/template/src/screens/Categories/types.ts +0 -7
  44. package/template/src/screens/Favorites/Favorites.tsx +0 -130
  45. package/template/src/screens/ForceChangePassword/ForceChangePasswordScreen.tsx +0 -155
  46. package/template/src/screens/History/History.tsx +0 -430
  47. package/template/src/screens/History/hooks/useHistoryData.ts +0 -49
  48. package/template/src/screens/History/types.ts +0 -7
  49. package/template/src/screens/InquiredBill/InquiredBill.tsx +0 -443
  50. package/template/src/screens/InquiredBill/hooks/useInquiredData.ts +0 -91
  51. package/template/src/screens/PaymentConfirmation/PaymentConfirmation.tsx +0 -326
  52. package/template/src/screens/Providers/Providers.tsx +0 -166
  53. package/template/src/screens/Providers/hooks/useProvidersData.ts +0 -33
  54. package/template/src/screens/Providers/types.ts +0 -7
  55. package/template/src/screens/ReceiptScreen/ReceiptScreen.tsx +0 -181
  56. package/template/src/screens/ReceiptScreen/hooks/useReceiptData.ts +0 -46
  57. package/template/src/screens/ReceiptScreen/utils/utils.tsx +0 -156
  58. package/template/src/screens/Services/Services.tsx +0 -144
  59. package/template/src/screens/Services/hooks/useServicesData.ts +0 -41
  60. package/template/src/screens/SingleService/Components/FawryInputs.tsx +0 -446
  61. package/template/src/screens/SingleService/SingleService.tsx +0 -229
  62. package/template/src/screens/SingleService/hooks/useServiceData.ts +0 -164
  63. package/template/src/services/SunmiPrinterInternal.js +0 -268
  64. package/template/src/types/sunmiPrepaid.d.ts +0 -20
  65. package/template/src/utils/SunmiPrinter.ts +0 -442
  66. package/template/src/utils/feesCalculator.ts +0 -92
@@ -1,122 +0,0 @@
1
- import {NativeModules} from 'react-native';
2
-
3
- const {SunmiPrepaid} = NativeModules;
4
-
5
- export interface PrepaidResponse {
6
- success: boolean;
7
- message: string;
8
- billingAcct: string;
9
- extraBillingAcctKey: any[];
10
- customProperties: any[];
11
- }
12
-
13
- export interface ServiceStatus {
14
- isInitialized: boolean;
15
- }
16
-
17
- function checkMeeterFeedBack(response: any): {Key: string; Value: string}[] {
18
- let chunksNum;
19
- if (response.meterFeedback.length % 1024 == 0)
20
- chunksNum = response.meterFeedback.length / 1024;
21
- else {
22
- chunksNum = response.meterFeedback.length / 1024 + 1;
23
- }
24
-
25
- let tmp = [];
26
-
27
- for (let i = 1; i <= chunksNum; i++) {
28
- let meterFeedbackKey = 'ESCFBT0';
29
- meterFeedbackKey += i;
30
- let chunkLength = i * 1024;
31
- let previousChunkLength = (i - 1) * 1024;
32
- if (chunkLength > response.meterFeedback.length)
33
- chunkLength = response.meterFeedback.length;
34
- let chunkData = response.meterFeedback.substring(
35
- previousChunkLength,
36
- chunkLength,
37
- );
38
- tmp.push({Key: meterFeedbackKey, Value: chunkData});
39
- }
40
- return tmp;
41
- }
42
-
43
- class SunmiPrepaidModule {
44
- async initializePrepaid(): Promise<PrepaidResponse> {
45
- try {
46
- return await SunmiPrepaid.initializePrepaid();
47
- } catch (error) {
48
- throw new Error(`Failed to initialize prepaid service: ${error}`);
49
- }
50
- }
51
-
52
- async forceCardFacadeDetection(): Promise<PrepaidResponse> {
53
- try {
54
- return await SunmiPrepaid.forceCardFacadeDetection();
55
- } catch (error) {
56
- throw new Error(`Failed to force card facade detection: ${error}`);
57
- }
58
- }
59
-
60
- async readCardMetadata(
61
- extraKeys: any,
62
- type: string,
63
- ): Promise<PrepaidResponse> {
64
- try {
65
- const response = await SunmiPrepaid.readCardMetadata(type);
66
-
67
- let keysArray = [
68
- {Key: 'Key1', Value: response.vendor},
69
- {Key: 'Key2', Value: response.sectorIdentifier},
70
- {Key: 'Key3', Value: response.meterIdentifier},
71
- ];
72
-
73
- let propertiesArray = [
74
- {
75
- Key:
76
- type === 'SC' || type === 'GASSC'
77
- ? 'ElectrictyCompany'
78
- : 'WaterCompany',
79
- Value: response.companyIdentifier,
80
- },
81
- {Key: 'ClientIdentifier', Value: response.clientIdentifier},
82
- {Key: 'CardMetadata', Value: response.metaData},
83
- ];
84
-
85
- if (response.meterFeedback.length < 1024) {
86
- propertiesArray.push({
87
- Key: 'ESCFBT01',
88
- Value: response.meterFeedback,
89
- });
90
- } else {
91
- propertiesArray.push(...checkMeeterFeedBack(response));
92
- }
93
-
94
- if (response.metaData) {
95
- propertiesArray.push({Key: 'CardMetadata', Value: response.metaData});
96
- }
97
-
98
- return {
99
- success: true,
100
- message: 'success',
101
- billingAcct: response.identifier,
102
- extraBillingAcctKey: keysArray,
103
- customProperties: propertiesArray,
104
- };
105
- } catch (error) {
106
- throw new Error(`Failed to read card metadata: ${error}`);
107
- }
108
- }
109
-
110
- async writeCardCharge(
111
- billEncryptInfo: string,
112
- cardMetadata: string,
113
- ): Promise<PrepaidResponse> {
114
- try {
115
- return await SunmiPrepaid.writeCardCharge(billEncryptInfo, cardMetadata);
116
- } catch (error) {
117
- throw new Error(`Failed to write card charge: ${error}`);
118
- }
119
- }
120
- }
121
-
122
- export default new SunmiPrepaidModule();
@@ -1,141 +0,0 @@
1
- import {useIsFocused, useNavigation} from '@react-navigation/native';
2
- import {NativeStackNavigationProp} from '@react-navigation/native-stack';
3
- import React, {useEffect, useRef} from 'react';
4
- import {StyleSheet, View} from 'react-native';
5
- import {SkypeIndicator} from 'react-native-indicators';
6
- import {KeyboardAwareScrollView} from 'react-native-keyboard-aware-scroll-view';
7
- import {LoadState} from '../../../types';
8
- import {Card} from '../../common/components/Cards';
9
- import {Container} from '../../common/components/Container';
10
- import {FlatListWrapper} from '../../common/components/FlatListWrapper';
11
- import {ImageResources} from '../../common/ImageResources.g';
12
- import {useTranslation} from '../../common/localization/LocalizationProvider';
13
- import {CommonSizes} from '../../core/theme/commonSizes';
14
- import {scaleHeight, scaleWidth} from '../../core/theme/scaling';
15
- import {useTheme} from '../../core/theme/ThemeProvider';
16
- import {HeaderBack} from '../../navigation/HeaderComponents';
17
- import {RootStackParamList} from '../../navigation/types';
18
- import {useCategoriesData} from './hooks/useCategoriesData';
19
- import {setSelectedCategory} from '../../core/store/Categories/categorySlice';
20
- import {useAppDispatch} from '../../core/store/reduxHelpers';
21
-
22
- export function Categories(): JSX.Element {
23
- const {isLoading, fetchData, categories} = useCategoriesData();
24
- const t = useTranslation();
25
- const navigation =
26
- useNavigation<NativeStackNavigationProp<RootStackParamList>>();
27
- const {theme} = useTheme();
28
- const scroll = useRef<KeyboardAwareScrollView>(null);
29
- const isFocused = useIsFocused();
30
- const dispatch = useAppDispatch();
31
-
32
- useEffect(() => {
33
- if (isFocused && categories.length === 0) {
34
- fetchData();
35
- }
36
- }, [isFocused]);
37
-
38
- return (
39
- <Container
40
- ref={scroll}
41
- testID={'CategoriesScreenID'}
42
- contentContainerStyle={styles.contentContainer}
43
- style={styles.container}
44
- backgroundImage={ImageResources[`${theme.mode}_background_1`]}
45
- withoutPadding
46
- withoutScroll
47
- backgroundColor={theme.colors.background}>
48
- {isLoading ? (
49
- <SkypeIndicator size={80} color={theme.colors.mutedLavender} />
50
- ) : (
51
- <>
52
- <HeaderBack onPress={navigation.goBack} />
53
- <FlatListWrapper
54
- contentContainerStyle={{
55
- alignItems: 'center',
56
- paddingBottom: scaleHeight(50),
57
- }}
58
- style={{
59
- flex: 1,
60
- alignSelf: 'center',
61
- }}
62
- ItemSeparatorComponent={() => (
63
- <View style={{height: CommonSizes.spacing.large}} />
64
- )}
65
- keyExtractor={(item, index) => `${item.id}-${index}`}
66
- loadState={
67
- isLoading ? LoadState['loadingMore'] : LoadState['pullToRefresh']
68
- }
69
- data={categories}
70
- numColumns={3}
71
- renderItem={({item, index}) => (
72
- <Card
73
- cardStyle={{
74
- width: scaleWidth(187),
75
- height: scaleHeight(260),
76
- }}
77
- key={item.id}
78
- icon={{uri: item.img_url}}
79
- title={item.name}
80
- onPress={() => {
81
- dispatch(setSelectedCategory(item));
82
- navigation.navigate('Providers', {
83
- categoryID: item?.id?.toString(),
84
- });
85
- }}
86
- marginRight={
87
- (index % 3) + 1 !== 3 ? CommonSizes.spacing.medium : undefined
88
- }
89
- />
90
- )}
91
- />
92
- </>
93
- )}
94
- </Container>
95
- );
96
- }
97
-
98
- const styles = StyleSheet.create({
99
- container: {
100
- flexGrow: 1,
101
- borderTopRightRadius: CommonSizes.spacing.large,
102
- borderTopLeftRadius: CommonSizes.spacing.large,
103
- gap: CommonSizes.spacing.large,
104
- justifyContent: 'flex-start',
105
- alignItems: 'center',
106
- },
107
- contentContainer: {
108
- flexGrow: 1,
109
- },
110
- searchBar: {
111
- width: '90%',
112
- alignSelf: 'center',
113
- marginTop: CommonSizes.spacing.medium,
114
- },
115
- formContainer: {
116
- alignItems: 'center',
117
- paddingHorizontal: CommonSizes.spacing.large,
118
- gap: CommonSizes.spacing.large,
119
- },
120
- balanceSection: {
121
- alignItems: 'center',
122
- justifyContent: 'space-evenly',
123
- gap: CommonSizes.spacing.large,
124
- },
125
- seeMoreSection: {
126
- alignItems: 'center',
127
- gap: CommonSizes.spacing.large,
128
- alignSelf: 'center',
129
- },
130
- sectionImage: {
131
- width: scaleWidth(120),
132
- height: scaleHeight(70),
133
- },
134
- amountText: {
135
- textAlign: 'left',
136
- },
137
- balanceCard: {
138
- width: '100%',
139
- borderRadius: CommonSizes.spacing.huge,
140
- },
141
- });
@@ -1,33 +0,0 @@
1
- import {useEffect, useState} from 'react';
2
- import {getCategories} from '../../../core/store/Categories/categoryActions';
3
- import {getProviders} from '../../../core/store/Providers/providersActions';
4
- import {useAppDispatch, useAppSelector} from '../../../core/store/reduxHelpers';
5
- import {RootState} from '../../../core/store/rootReducer';
6
- export function useCategoriesData() {
7
- const [isLoading, setIsLoading] = useState(false);
8
-
9
- const dispatch = useAppDispatch();
10
- const {categories} = useAppSelector((state: RootState) => state.categories);
11
-
12
- const fetchData = async () => {
13
- setIsLoading(true);
14
- try {
15
- const categories = await dispatch(getCategories({data: {limit: 30}}));
16
- } catch (error) {
17
- console.error('Error fetching home data:', error);
18
- } finally {
19
- setIsLoading(false);
20
- }
21
- };
22
-
23
- const refreshData = () => {
24
- fetchData();
25
- };
26
-
27
- return {
28
- isLoading,
29
- refreshData,
30
- fetchData,
31
- categories,
32
- };
33
- }
@@ -1,7 +0,0 @@
1
- export interface CarouselItem {
2
- id: string;
3
- title: string;
4
- subtitle?: string;
5
- imageUrl: string;
6
- onPress?: (item: CarouselItem) => void;
7
- }
@@ -1,130 +0,0 @@
1
- import {useNavigation} from '@react-navigation/native';
2
- import {NativeStackNavigationProp} from '@react-navigation/native-stack';
3
- import React, {useCallback, useRef} from 'react';
4
- import {StyleSheet} from 'react-native';
5
- import {KeyboardAwareScrollView} from 'react-native-keyboard-aware-scroll-view';
6
- import {Container} from '../../common/components/Container';
7
- import {RTLAwareText} from '../../common/components/RTLAwareText';
8
- import {RTLAwareView} from '../../common/components/RTLAwareView';
9
- import {ImageResources} from '../../common/ImageResources.g';
10
- import {
11
- useRTL,
12
- useTranslation,
13
- } from '../../common/localization/LocalizationProvider';
14
- import {setSelectedProvider} from '../../core/store/Providers/providersSlice';
15
- import {ServiceProvider} from '../../core/store/Providers/providersState';
16
- import {useAppDispatch, useAppSelector} from '../../core/store/reduxHelpers';
17
- import {RootState} from '../../core/store/rootReducer';
18
- import {CommonSizes} from '../../core/theme/commonSizes';
19
- import {scaleHeight} from '../../core/theme/scaling';
20
- import {useTheme} from '../../core/theme/ThemeProvider';
21
- import {Header} from '../../navigation/HeaderComponents';
22
- import {RootStackParamList} from '../../navigation/types';
23
-
24
- export function Favorites(): JSX.Element {
25
- const dispatch = useAppDispatch();
26
- const {favoriteProviders = []} = useAppSelector(
27
- (state: RootState) => state.user,
28
- );
29
- const {favoriteCategories = []} = useAppSelector(
30
- (state: RootState) => state.user,
31
- );
32
- const {providers} = useAppSelector((state: RootState) => state.providers);
33
- const {categories} = useAppSelector((state: RootState) => state.categories);
34
- const t = useTranslation();
35
- const isRTL = useRTL();
36
- const navigation =
37
- useNavigation<NativeStackNavigationProp<RootStackParamList>>();
38
- const {theme} = useTheme();
39
- const scroll = useRef<KeyboardAwareScrollView>(null);
40
-
41
- const navigateToServices = useCallback(
42
- (provider: ServiceProvider) => {
43
- dispatch(setSelectedProvider(provider));
44
- navigation.navigate('Services', {
45
- providerID: provider?.id?.toString() as string,
46
- });
47
- },
48
- [dispatch, navigation],
49
- );
50
-
51
- return (
52
- <Container
53
- ref={scroll}
54
- testID={'FavoritesScreenID'}
55
- contentContainerStyle={styles.contentContainer}
56
- style={styles.container}
57
- backgroundImage={ImageResources[`${theme.mode}_background_1`]}
58
- withoutPadding
59
- backgroundColor={theme.colors.background}>
60
- <Header />
61
-
62
- <RTLAwareView style={styles.sectionHeader}>
63
- <RTLAwareText style={theme.text.header2}>
64
- {t('favoriteCategories', 'common')}
65
- </RTLAwareText>
66
- </RTLAwareView>
67
- </Container>
68
- );
69
- }
70
-
71
- const styles = StyleSheet.create({
72
- container: {
73
- flexGrow: 1,
74
- paddingBottom: scaleHeight(150),
75
- borderTopRightRadius: CommonSizes.spacing.large,
76
- borderTopLeftRadius: CommonSizes.spacing.large,
77
- gap: CommonSizes.spacing.medium,
78
- justifyContent: 'flex-start',
79
- alignItems: 'center',
80
- },
81
- contentContainer: {
82
- flexGrow: 1,
83
- },
84
- searchBar: {
85
- width: '90%',
86
- alignSelf: 'center',
87
- marginTop: CommonSizes.spacing.medium,
88
- },
89
- sectionHeader: {
90
- width: '90%',
91
- marginVertical: CommonSizes.spacing.medium,
92
- },
93
- carouselContainer: {
94
- height: scaleHeight(570),
95
- width: '100%',
96
- },
97
- gridPage: {
98
- flexDirection: 'row',
99
- flexWrap: 'wrap',
100
- justifyContent: 'flex-start',
101
- alignItems: 'center',
102
- paddingHorizontal: CommonSizes.spacing.large,
103
- overflow: 'hidden',
104
- },
105
- paginationContainer: {
106
- flexDirection: 'row',
107
- justifyContent: 'center',
108
- alignItems: 'center',
109
- marginTop: CommonSizes.spacing.small,
110
- },
111
- paginationDot: {
112
- width: 8,
113
- height: 8,
114
- borderRadius: 4,
115
- backgroundColor: '#cccccc',
116
- marginHorizontal: 4,
117
- },
118
- paginationDotActive: {
119
- backgroundColor: '#666666',
120
- width: 10,
121
- height: 10,
122
- borderRadius: 5,
123
- },
124
- emptyContainer: {
125
- height: scaleHeight(150),
126
- width: '100%',
127
- justifyContent: 'center',
128
- alignItems: 'center',
129
- },
130
- });
@@ -1,155 +0,0 @@
1
- import {useNavigation} from '@react-navigation/native';
2
- import type {NativeStackNavigationProp} from '@react-navigation/native-stack';
3
- import React, {useRef, useState} from 'react';
4
- import {StyleSheet, Text} from 'react-native';
5
- import {KeyboardAwareScrollView} from 'react-native-keyboard-aware-scroll-view';
6
- import {ButtonType} from '../../../types';
7
- import {Container} from '../../common/components/Container';
8
- import {PrimaryButton} from '../../common/components/PrimaryButton';
9
- import {PrimaryTextInput} from '../../common/components/PrimaryTextInput';
10
- import {ImageResources} from '../../common/ImageResources.g';
11
- import {useInputError} from '../../common/validations/hooks/useInputError';
12
- import {useAppDispatch} from '../../core/store/reduxHelpers';
13
- import {CommonSizes} from '../../core/theme/commonSizes';
14
- import {useTheme} from '../../core/theme/ThemeProvider';
15
- import {Header} from '../../navigation/HeaderComponents';
16
- import type {RootStackParamList} from '../../navigation/types';
17
- import {resetPassword} from '../../core/store/user/userActions';
18
- import {
19
- useTranslation,
20
- useRTL,
21
- } from '../../common/localization/LocalizationProvider';
22
- import {RTLAwareText} from '../../common/components/RTLAwareText';
23
- import {RTLAwareView} from '../../common/components/RTLAwareView';
24
-
25
- export function ForceChangePasswordScreen(): JSX.Element {
26
- const dispatch = useAppDispatch();
27
- const [currentPassword, setCurrentPassword] = useState('');
28
- const [newPassword, setNewPassword] = useState('');
29
- const [confirmPassword, setConfirmPassword] = useState('');
30
- const [loading, setLoading] = useState(false);
31
- const navigation =
32
- useNavigation<NativeStackNavigationProp<RootStackParamList>>();
33
- const scroll = useRef<KeyboardAwareScrollView>(null);
34
- const {theme} = useTheme();
35
- const t = useTranslation();
36
- const isRTL = useRTL();
37
-
38
- const {error: currentPasswordError, recheckValue: recheckCurrentPassword} =
39
- useInputError(currentPassword, value =>
40
- value.length < 6 ? 'Password must be at least 6 characters' : null,
41
- );
42
-
43
- const {error: newPasswordError, recheckValue: recheckNewPassword} =
44
- useInputError(newPassword, value => {
45
- if (value.length < 6) return 'Password must be at least 6 characters';
46
- if (value === currentPassword)
47
- return 'New password must be different from current password';
48
- return null;
49
- });
50
-
51
- const {error: confirmPasswordError, recheckValue: recheckConfirmPassword} =
52
- useInputError(confirmPassword, value =>
53
- value !== newPassword ? 'Passwords do not match' : null,
54
- );
55
-
56
- async function handleChangePassword() {
57
- const currentPasswordValid = recheckCurrentPassword() === null;
58
- const newPasswordValid = recheckNewPassword() === null;
59
- const confirmPasswordValid = recheckConfirmPassword() === null;
60
-
61
- if (!currentPasswordValid || !newPasswordValid || !confirmPasswordValid) {
62
- return;
63
- }
64
-
65
- setLoading(true);
66
- try {
67
- // Add your change password logic here
68
- const response = await dispatch(
69
- resetPassword({
70
- mpin: currentPassword,
71
- new_mpin: newPassword,
72
- confirm_mpin: confirmPassword,
73
- }),
74
- );
75
-
76
- if (resetPassword.fulfilled.match(response)) {
77
- navigation.goBack();
78
- }
79
- } catch (error) {
80
- console.error(error);
81
- } finally {
82
- setLoading(false);
83
- }
84
- }
85
-
86
- return (
87
- <Container
88
- ref={scroll}
89
- testID={'ForceChangePasswordID'}
90
- contentContainerStyle={styles.contentContainer}
91
- style={styles.container}
92
- backgroundImage={ImageResources.background_2}
93
- withoutPadding
94
- extendedBackground
95
- backgroundColor={theme.colors.background}>
96
- <Header />
97
- <RTLAwareText style={{...theme.text.body2, textAlign: 'center'}}>
98
- {t('forceChange.subtitle', 'password')}
99
- </RTLAwareText>
100
- <PrimaryTextInput
101
- label={t('forceChange.currentPassword', 'password')}
102
- value={currentPassword}
103
- onChangeText={setCurrentPassword}
104
- error={currentPasswordError}
105
- placeholder={t('forceChange.enterCurrentPassword', 'password')}
106
- secureTextEntry={true}
107
- keyboardType="numeric"
108
- />
109
- <PrimaryTextInput
110
- label={t('forceChange.newPassword', 'password')}
111
- value={newPassword}
112
- onChangeText={setNewPassword}
113
- error={newPasswordError}
114
- placeholder={t('forceChange.enterNewPassword', 'password')}
115
- secureTextEntry={true}
116
- keyboardType="numeric"
117
- />
118
- <PrimaryTextInput
119
- label={t('forceChange.confirmPassword', 'password')}
120
- value={confirmPassword}
121
- onChangeText={setConfirmPassword}
122
- error={confirmPasswordError}
123
- placeholder={t('forceChange.confirmNewPassword', 'password')}
124
- secureTextEntry={true}
125
- keyboardType="numeric"
126
- />
127
- <PrimaryButton
128
- label={t('forceChange.changePassword', 'password')}
129
- onPressIn={handleChangePassword}
130
- isLoading={loading}
131
- disabled={loading}
132
- type={ButtonType.solid}
133
- />
134
- </Container>
135
- );
136
- }
137
-
138
- const styles = StyleSheet.create({
139
- container: {
140
- flexGrow: 1,
141
- borderTopRightRadius: CommonSizes.spacing.large,
142
- borderTopLeftRadius: CommonSizes.spacing.large,
143
- paddingHorizontal: CommonSizes.spacing.large,
144
- justifyContent: 'flex-start',
145
- gap: CommonSizes.spacing.large,
146
- },
147
- contentContainer: {
148
- flexGrow: 1,
149
- },
150
- formContainer: {
151
- width: '100%',
152
- marginTop: CommonSizes.spacing.large,
153
- gap: CommonSizes.spacing.medium,
154
- },
155
- });