@modhamanish/rn-mm-template 1.0.1 → 1.0.3
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/MMTemplate/App.tsx +15 -2
- package/MMTemplate/package.json +3 -0
- package/MMTemplate/src/components/AppText.tsx +125 -0
- package/MMTemplate/src/components/CustomToast.tsx +8 -6
- package/MMTemplate/src/components/FeatureItem.tsx +11 -8
- package/MMTemplate/src/components/InfoCard.tsx +10 -6
- package/MMTemplate/src/components/LanguageSwitcher.tsx +8 -7
- package/MMTemplate/src/components/TextInput.tsx +214 -23
- package/MMTemplate/src/components/ThemeSwitcher.tsx +12 -7
- package/MMTemplate/src/context/ThemeContext.tsx +15 -1
- package/MMTemplate/src/locales/en.json +19 -2
- package/MMTemplate/src/locales/hi.json +19 -2
- package/MMTemplate/src/navigation/AppStack.tsx +2 -0
- package/MMTemplate/src/navigation/MainTab.tsx +15 -4
- package/MMTemplate/src/navigation/routes.ts +2 -0
- package/MMTemplate/src/screens/AddNoteScreen.tsx +155 -0
- package/MMTemplate/src/screens/HomeScreen.tsx +60 -33
- package/MMTemplate/src/screens/LoginScreen.tsx +67 -25
- package/MMTemplate/src/screens/NoteScreen.tsx +241 -0
- package/MMTemplate/src/screens/ProfileScreen.tsx +26 -25
- package/MMTemplate/src/screens/SettingsScreen.tsx +17 -16
- package/MMTemplate/src/screens/WelcomeScreen.tsx +23 -23
- package/MMTemplate/src/services/axiosInstance.ts +41 -0
- package/MMTemplate/src/services/note.query.ts +40 -0
- package/MMTemplate/src/services/queryKeys.ts +4 -0
- package/MMTemplate/src/types/components.types.ts +47 -1
- package/MMTemplate/src/types/navigation.types.ts +2 -0
- package/MMTemplate/src/types/services.types.ts +6 -0
- package/MMTemplate/src/utils/storageHelper.ts +2 -0
- package/MMTemplate/src/utils/validationSchemas.ts +6 -0
- package/README.md +1 -1
- package/package.json +1 -1
|
@@ -1,11 +1,6 @@
|
|
|
1
1
|
import React, { FC } from 'react';
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
Text,
|
|
5
|
-
TouchableOpacity,
|
|
6
|
-
StyleSheet,
|
|
7
|
-
ScrollView,
|
|
8
|
-
} from 'react-native';
|
|
2
|
+
import { View, TouchableOpacity, StyleSheet, ScrollView } from 'react-native';
|
|
3
|
+
import AppText from '../components/AppText';
|
|
9
4
|
import { useFormik } from 'formik';
|
|
10
5
|
import { useTranslation } from 'react-i18next';
|
|
11
6
|
import { useTheme } from '../context/ThemeContext';
|
|
@@ -65,13 +60,40 @@ const LoginScreen: FC = () => {
|
|
|
65
60
|
>
|
|
66
61
|
<AnimationView animType="FadeIn" duration={800}>
|
|
67
62
|
<View style={styles.header}>
|
|
68
|
-
<
|
|
69
|
-
|
|
63
|
+
<AppText variant="h1" style={styles.title}>
|
|
64
|
+
{t('auth.welcomeBack')}
|
|
65
|
+
</AppText>
|
|
66
|
+
<AppText size="body" style={styles.subtitle}>
|
|
67
|
+
{t('auth.signInToContinue')}
|
|
68
|
+
</AppText>
|
|
70
69
|
</View>
|
|
71
70
|
</AnimationView>
|
|
72
71
|
|
|
73
72
|
<AnimationView delay={200} animType="FadeIn" duration={800}>
|
|
74
73
|
<View style={styles.formContainer}>
|
|
74
|
+
{/* Hint Banner */}
|
|
75
|
+
<View style={styles.hintBanner}>
|
|
76
|
+
<AppText variant="bold" style={styles.hintTitle}>
|
|
77
|
+
{t('auth.mockCredentialsHint')}
|
|
78
|
+
</AppText>
|
|
79
|
+
<View style={styles.hintContent}>
|
|
80
|
+
<AppText variant="semiBold" size={13} style={styles.hintLabel}>
|
|
81
|
+
{t('auth.email')}:{' '}
|
|
82
|
+
</AppText>
|
|
83
|
+
<AppText size={13} style={styles.hintValue}>
|
|
84
|
+
{userMockData.email}
|
|
85
|
+
</AppText>
|
|
86
|
+
</View>
|
|
87
|
+
<View style={styles.hintContent}>
|
|
88
|
+
<AppText variant="semiBold" size={13} style={styles.hintLabel}>
|
|
89
|
+
{t('auth.password')}:{' '}
|
|
90
|
+
</AppText>
|
|
91
|
+
<AppText size={13} style={styles.hintValue}>
|
|
92
|
+
{userMockData.password}
|
|
93
|
+
</AppText>
|
|
94
|
+
</View>
|
|
95
|
+
</View>
|
|
96
|
+
|
|
75
97
|
{/* Email Input */}
|
|
76
98
|
<TextInput
|
|
77
99
|
label={t('auth.email')}
|
|
@@ -102,9 +124,9 @@ const LoginScreen: FC = () => {
|
|
|
102
124
|
|
|
103
125
|
{/* Forgot Password */}
|
|
104
126
|
<TouchableOpacity style={styles.forgotPassword}>
|
|
105
|
-
<
|
|
127
|
+
<AppText variant="semiBold" style={styles.forgotPasswordText}>
|
|
106
128
|
{t('auth.forgotPassword')}
|
|
107
|
-
</
|
|
129
|
+
</AppText>
|
|
108
130
|
</TouchableOpacity>
|
|
109
131
|
|
|
110
132
|
{/* Login Button */}
|
|
@@ -112,16 +134,24 @@ const LoginScreen: FC = () => {
|
|
|
112
134
|
style={styles.loginButton}
|
|
113
135
|
onPress={() => formik.handleSubmit()}
|
|
114
136
|
>
|
|
115
|
-
<
|
|
137
|
+
<AppText
|
|
138
|
+
variant="bold"
|
|
139
|
+
size="body"
|
|
140
|
+
style={styles.loginButtonText}
|
|
141
|
+
>
|
|
142
|
+
{t('auth.login')}
|
|
143
|
+
</AppText>
|
|
116
144
|
</TouchableOpacity>
|
|
117
145
|
|
|
118
146
|
{/* Sign Up Link */}
|
|
119
147
|
<View style={styles.signupContainer}>
|
|
120
|
-
<
|
|
148
|
+
<AppText style={styles.signupText}>
|
|
121
149
|
{t('auth.dontHaveAccount')}{' '}
|
|
122
|
-
</
|
|
150
|
+
</AppText>
|
|
123
151
|
<TouchableOpacity>
|
|
124
|
-
<
|
|
152
|
+
<AppText variant="semiBold" style={styles.signupLink}>
|
|
153
|
+
{t('auth.signUp')}
|
|
154
|
+
</AppText>
|
|
125
155
|
</TouchableOpacity>
|
|
126
156
|
</View>
|
|
127
157
|
</View>
|
|
@@ -149,26 +179,43 @@ const getStyles = ({ colors }: ThemeType) =>
|
|
|
149
179
|
alignItems: 'center',
|
|
150
180
|
},
|
|
151
181
|
title: {
|
|
152
|
-
fontSize: 32,
|
|
153
|
-
fontWeight: '700',
|
|
154
182
|
color: colors.textColor,
|
|
155
183
|
marginBottom: 8,
|
|
156
184
|
},
|
|
157
185
|
subtitle: {
|
|
158
|
-
fontSize: 16,
|
|
159
186
|
color: colors.textColor + 'CC',
|
|
160
187
|
},
|
|
161
188
|
formContainer: {
|
|
162
189
|
width: '100%',
|
|
163
190
|
},
|
|
191
|
+
hintBanner: {
|
|
192
|
+
backgroundColor: colors.primary + '10',
|
|
193
|
+
padding: 16,
|
|
194
|
+
borderRadius: 12,
|
|
195
|
+
borderWidth: 1,
|
|
196
|
+
borderColor: colors.primary + '30',
|
|
197
|
+
marginBottom: 24,
|
|
198
|
+
},
|
|
199
|
+
hintTitle: {
|
|
200
|
+
color: colors.primary,
|
|
201
|
+
marginBottom: 8,
|
|
202
|
+
},
|
|
203
|
+
hintContent: {
|
|
204
|
+
flexDirection: 'row',
|
|
205
|
+
marginBottom: 4,
|
|
206
|
+
},
|
|
207
|
+
hintLabel: {
|
|
208
|
+
color: colors.textColor,
|
|
209
|
+
},
|
|
210
|
+
hintValue: {
|
|
211
|
+
color: colors.textColor + 'CC',
|
|
212
|
+
},
|
|
164
213
|
forgotPassword: {
|
|
165
214
|
alignSelf: 'flex-end',
|
|
166
215
|
marginBottom: 24,
|
|
167
216
|
},
|
|
168
217
|
forgotPasswordText: {
|
|
169
218
|
color: colors.primary,
|
|
170
|
-
fontSize: 14,
|
|
171
|
-
fontWeight: '600',
|
|
172
219
|
},
|
|
173
220
|
loginButton: {
|
|
174
221
|
backgroundColor: colors.primary,
|
|
@@ -179,8 +226,6 @@ const getStyles = ({ colors }: ThemeType) =>
|
|
|
179
226
|
},
|
|
180
227
|
loginButtonText: {
|
|
181
228
|
color: colors.white,
|
|
182
|
-
fontSize: 16,
|
|
183
|
-
fontWeight: '700',
|
|
184
229
|
},
|
|
185
230
|
signupContainer: {
|
|
186
231
|
flexDirection: 'row',
|
|
@@ -189,11 +234,8 @@ const getStyles = ({ colors }: ThemeType) =>
|
|
|
189
234
|
},
|
|
190
235
|
signupText: {
|
|
191
236
|
color: colors.textColor + 'CC',
|
|
192
|
-
fontSize: 14,
|
|
193
237
|
},
|
|
194
238
|
signupLink: {
|
|
195
239
|
color: colors.primary,
|
|
196
|
-
fontSize: 14,
|
|
197
|
-
fontWeight: '600',
|
|
198
240
|
},
|
|
199
241
|
});
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
import {
|
|
2
|
+
StyleSheet,
|
|
3
|
+
FlatList,
|
|
4
|
+
View,
|
|
5
|
+
TouchableOpacity,
|
|
6
|
+
ActivityIndicator,
|
|
7
|
+
RefreshControl,
|
|
8
|
+
} from 'react-native';
|
|
9
|
+
import AppText from '../components/AppText';
|
|
10
|
+
import React, { FC, useMemo } from 'react';
|
|
11
|
+
import FullScreenContainer from '../components/FullScreenContainer';
|
|
12
|
+
import { useTheme } from '../context/ThemeContext';
|
|
13
|
+
import { useTranslation } from 'react-i18next';
|
|
14
|
+
import { ThemeType } from '../theme/Colors';
|
|
15
|
+
import { useGetNotesQuery } from '../services/note.query';
|
|
16
|
+
import { Note } from '../types/services.types';
|
|
17
|
+
import AnimationView from '../components/AnimationView';
|
|
18
|
+
|
|
19
|
+
import { navigate } from '../utils/navigationUtils';
|
|
20
|
+
import Routes from '../navigation/routes';
|
|
21
|
+
|
|
22
|
+
const NoteScreen: FC = () => {
|
|
23
|
+
const { t } = useTranslation();
|
|
24
|
+
const theme = useTheme();
|
|
25
|
+
const styles = getStyles(theme);
|
|
26
|
+
|
|
27
|
+
const { data: notes, isLoading, refetch, isRefetching } = useGetNotesQuery();
|
|
28
|
+
|
|
29
|
+
const renderNoteItem = ({ item, index }: { item: Note; index: number }) => (
|
|
30
|
+
<AnimationView delay={index * 100} animType="FadeIn" duration={500}>
|
|
31
|
+
<TouchableOpacity style={styles.noteCard} activeOpacity={0.7}>
|
|
32
|
+
<View style={styles.noteHeader}>
|
|
33
|
+
<AppText
|
|
34
|
+
variant="bold"
|
|
35
|
+
size={18}
|
|
36
|
+
style={styles.noteTitle}
|
|
37
|
+
numberOfLines={1}
|
|
38
|
+
>
|
|
39
|
+
{item.title}
|
|
40
|
+
</AppText>
|
|
41
|
+
<View style={styles.noteTag}>
|
|
42
|
+
<AppText
|
|
43
|
+
variant="semiBold"
|
|
44
|
+
size="xsmall"
|
|
45
|
+
style={styles.noteTagText}
|
|
46
|
+
>
|
|
47
|
+
#{index + 1}
|
|
48
|
+
</AppText>
|
|
49
|
+
</View>
|
|
50
|
+
</View>
|
|
51
|
+
<AppText style={styles.noteContent} numberOfLines={3}>
|
|
52
|
+
{item.description}
|
|
53
|
+
</AppText>
|
|
54
|
+
</TouchableOpacity>
|
|
55
|
+
</AnimationView>
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
const listHeader = useMemo(
|
|
59
|
+
() => (
|
|
60
|
+
<View style={styles.headerContainer}>
|
|
61
|
+
<AppText variant="h1" style={styles.headerTitle}>
|
|
62
|
+
{t('common.notes')}
|
|
63
|
+
</AppText>
|
|
64
|
+
<AppText style={styles.headerSubtitle}>
|
|
65
|
+
{notes?.length || 0} {t('common.notes').toLowerCase()}
|
|
66
|
+
</AppText>
|
|
67
|
+
</View>
|
|
68
|
+
),
|
|
69
|
+
[notes?.length, styles, t],
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
const emptyComponent = () => (
|
|
73
|
+
<View style={styles.emptyContainer}>
|
|
74
|
+
<AppText size={60} style={styles.emptyIcon}>
|
|
75
|
+
📝
|
|
76
|
+
</AppText>
|
|
77
|
+
<AppText size={18} style={styles.emptyText}>
|
|
78
|
+
{t('common.noNotesFound')}
|
|
79
|
+
</AppText>
|
|
80
|
+
<TouchableOpacity
|
|
81
|
+
style={styles.addNoteButtonSmall}
|
|
82
|
+
activeOpacity={0.8}
|
|
83
|
+
onPress={() => navigate(Routes.AddNoteScreen)}
|
|
84
|
+
>
|
|
85
|
+
<AppText
|
|
86
|
+
variant="bold"
|
|
87
|
+
size="body"
|
|
88
|
+
style={styles.addNoteButtonTextSmall}
|
|
89
|
+
>
|
|
90
|
+
{t('common.addNote')}
|
|
91
|
+
</AppText>
|
|
92
|
+
</TouchableOpacity>
|
|
93
|
+
</View>
|
|
94
|
+
);
|
|
95
|
+
|
|
96
|
+
return (
|
|
97
|
+
<FullScreenContainer style={styles.container}>
|
|
98
|
+
{isLoading && !isRefetching ? (
|
|
99
|
+
<View style={styles.loadingContainer}>
|
|
100
|
+
<ActivityIndicator size="large" color={theme.colors.primary} />
|
|
101
|
+
</View>
|
|
102
|
+
) : (
|
|
103
|
+
<FlatList
|
|
104
|
+
data={notes}
|
|
105
|
+
keyExtractor={(_, index) => index.toString()}
|
|
106
|
+
renderItem={renderNoteItem}
|
|
107
|
+
ListHeaderComponent={listHeader}
|
|
108
|
+
ListEmptyComponent={emptyComponent}
|
|
109
|
+
contentContainerStyle={styles.listContent}
|
|
110
|
+
refreshControl={
|
|
111
|
+
<RefreshControl
|
|
112
|
+
refreshing={isRefetching}
|
|
113
|
+
onRefresh={refetch}
|
|
114
|
+
tintColor={theme.colors.primary}
|
|
115
|
+
colors={[theme.colors.primary]}
|
|
116
|
+
/>
|
|
117
|
+
}
|
|
118
|
+
/>
|
|
119
|
+
)}
|
|
120
|
+
<TouchableOpacity
|
|
121
|
+
style={styles.fab}
|
|
122
|
+
activeOpacity={0.8}
|
|
123
|
+
onPress={() => navigate(Routes.AddNoteScreen)}
|
|
124
|
+
>
|
|
125
|
+
<AppText size="xxlarge" style={styles.fabIcon}>
|
|
126
|
+
+
|
|
127
|
+
</AppText>
|
|
128
|
+
</TouchableOpacity>
|
|
129
|
+
</FullScreenContainer>
|
|
130
|
+
);
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
export default NoteScreen;
|
|
134
|
+
|
|
135
|
+
const getStyles = ({ colors }: ThemeType) =>
|
|
136
|
+
StyleSheet.create({
|
|
137
|
+
container: {
|
|
138
|
+
flex: 1,
|
|
139
|
+
backgroundColor: colors.backgroundColor,
|
|
140
|
+
},
|
|
141
|
+
loadingContainer: {
|
|
142
|
+
flex: 1,
|
|
143
|
+
justifyContent: 'center',
|
|
144
|
+
alignItems: 'center',
|
|
145
|
+
},
|
|
146
|
+
listContent: {
|
|
147
|
+
padding: 20,
|
|
148
|
+
paddingBottom: 100,
|
|
149
|
+
},
|
|
150
|
+
headerContainer: {
|
|
151
|
+
marginBottom: 24,
|
|
152
|
+
marginTop: 20,
|
|
153
|
+
},
|
|
154
|
+
headerTitle: {
|
|
155
|
+
color: colors.textColor,
|
|
156
|
+
letterSpacing: -0.5,
|
|
157
|
+
},
|
|
158
|
+
headerSubtitle: {
|
|
159
|
+
color: colors.textColor + '80',
|
|
160
|
+
marginTop: 4,
|
|
161
|
+
},
|
|
162
|
+
noteCard: {
|
|
163
|
+
backgroundColor: colors.backgroundColor,
|
|
164
|
+
borderRadius: 16,
|
|
165
|
+
padding: 16,
|
|
166
|
+
marginBottom: 16,
|
|
167
|
+
borderWidth: 1,
|
|
168
|
+
borderColor: colors.textColor + '15',
|
|
169
|
+
shadowColor: colors.black,
|
|
170
|
+
shadowOffset: { width: 0, height: 2 },
|
|
171
|
+
shadowOpacity: 0.05,
|
|
172
|
+
shadowRadius: 10,
|
|
173
|
+
elevation: 2,
|
|
174
|
+
},
|
|
175
|
+
noteHeader: {
|
|
176
|
+
flexDirection: 'row',
|
|
177
|
+
justifyContent: 'space-between',
|
|
178
|
+
alignItems: 'center',
|
|
179
|
+
marginBottom: 8,
|
|
180
|
+
},
|
|
181
|
+
noteTitle: {
|
|
182
|
+
color: colors.textColor,
|
|
183
|
+
flex: 1,
|
|
184
|
+
marginRight: 8,
|
|
185
|
+
},
|
|
186
|
+
noteTag: {
|
|
187
|
+
backgroundColor: colors.primary + '15',
|
|
188
|
+
paddingHorizontal: 8,
|
|
189
|
+
paddingVertical: 4,
|
|
190
|
+
borderRadius: 8,
|
|
191
|
+
},
|
|
192
|
+
noteTagText: {
|
|
193
|
+
color: colors.primary,
|
|
194
|
+
textTransform: 'uppercase',
|
|
195
|
+
},
|
|
196
|
+
noteContent: {
|
|
197
|
+
color: colors.textColor + 'B3',
|
|
198
|
+
lineHeight: 20,
|
|
199
|
+
},
|
|
200
|
+
emptyContainer: {
|
|
201
|
+
flex: 1,
|
|
202
|
+
alignItems: 'center',
|
|
203
|
+
justifyContent: 'center',
|
|
204
|
+
marginTop: 100,
|
|
205
|
+
},
|
|
206
|
+
emptyIcon: {
|
|
207
|
+
marginBottom: 16,
|
|
208
|
+
},
|
|
209
|
+
emptyText: {
|
|
210
|
+
color: colors.textColor + '80',
|
|
211
|
+
marginBottom: 24,
|
|
212
|
+
},
|
|
213
|
+
addNoteButtonSmall: {
|
|
214
|
+
backgroundColor: colors.primary,
|
|
215
|
+
paddingHorizontal: 24,
|
|
216
|
+
paddingVertical: 12,
|
|
217
|
+
borderRadius: 12,
|
|
218
|
+
},
|
|
219
|
+
addNoteButtonTextSmall: {
|
|
220
|
+
color: colors.white,
|
|
221
|
+
},
|
|
222
|
+
fab: {
|
|
223
|
+
position: 'absolute',
|
|
224
|
+
right: 20,
|
|
225
|
+
bottom: 20,
|
|
226
|
+
width: 60,
|
|
227
|
+
height: 60,
|
|
228
|
+
borderRadius: 30,
|
|
229
|
+
backgroundColor: colors.primary,
|
|
230
|
+
justifyContent: 'center',
|
|
231
|
+
alignItems: 'center',
|
|
232
|
+
elevation: 5,
|
|
233
|
+
shadowColor: colors.black,
|
|
234
|
+
shadowOffset: { width: 0, height: 4 },
|
|
235
|
+
shadowOpacity: 0.3,
|
|
236
|
+
shadowRadius: 6,
|
|
237
|
+
},
|
|
238
|
+
fabIcon: {
|
|
239
|
+
color: colors.white,
|
|
240
|
+
},
|
|
241
|
+
});
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React, { FC } from 'react';
|
|
2
|
-
import { View,
|
|
2
|
+
import { View, TouchableOpacity, StyleSheet, Alert } from 'react-native';
|
|
3
|
+
import AppText from '../components/AppText';
|
|
3
4
|
import { useTranslation } from 'react-i18next';
|
|
4
5
|
import { useTheme } from '../context/ThemeContext';
|
|
5
6
|
import { ThemeType } from '../theme/Colors';
|
|
@@ -41,26 +42,32 @@ const ProfileScreen: FC = () => {
|
|
|
41
42
|
<AnimationView animType="FadeIn" duration={800}>
|
|
42
43
|
<View style={styles.header}>
|
|
43
44
|
<View style={styles.avatarContainer}>
|
|
44
|
-
<
|
|
45
|
+
<AppText variant="bold" size={40} style={styles.avatarText}>
|
|
45
46
|
{user?.name?.charAt(0).toUpperCase() || 'U'}
|
|
46
|
-
</
|
|
47
|
+
</AppText>
|
|
47
48
|
</View>
|
|
48
|
-
<
|
|
49
|
-
|
|
49
|
+
<AppText variant="bold" style={styles.name}>
|
|
50
|
+
{user?.name || 'User'}
|
|
51
|
+
</AppText>
|
|
52
|
+
<AppText style={styles.email}>
|
|
50
53
|
{user?.email || 'user@example.com'}
|
|
51
|
-
</
|
|
54
|
+
</AppText>
|
|
52
55
|
</View>
|
|
53
56
|
</AnimationView>
|
|
54
57
|
|
|
55
58
|
<AnimationView delay={300} animType="FadeIn" duration={800}>
|
|
56
59
|
<InfoCard title={t('profile.accountInformation')} icon="👤">
|
|
57
60
|
<View style={styles.infoRow}>
|
|
58
|
-
<
|
|
59
|
-
|
|
61
|
+
<AppText variant="semiBold" style={styles.infoLabel}>
|
|
62
|
+
{t('profile.name')}:
|
|
63
|
+
</AppText>
|
|
64
|
+
<AppText style={styles.infoValue}>{user?.name || 'N/A'}</AppText>
|
|
60
65
|
</View>
|
|
61
66
|
<View style={styles.infoRow}>
|
|
62
|
-
<
|
|
63
|
-
|
|
67
|
+
<AppText variant="semiBold" style={styles.infoLabel}>
|
|
68
|
+
{t('profile.email')}:
|
|
69
|
+
</AppText>
|
|
70
|
+
<AppText style={styles.infoValue}>{user?.email || 'N/A'}</AppText>
|
|
64
71
|
</View>
|
|
65
72
|
</InfoCard>
|
|
66
73
|
</AnimationView>
|
|
@@ -70,15 +77,21 @@ const ProfileScreen: FC = () => {
|
|
|
70
77
|
style={styles.settingsButton}
|
|
71
78
|
onPress={() => navigate(Routes.SettingsScreen)}
|
|
72
79
|
>
|
|
73
|
-
<
|
|
80
|
+
<AppText
|
|
81
|
+
variant="bold"
|
|
82
|
+
size="body"
|
|
83
|
+
style={styles.settingsButtonText}
|
|
84
|
+
>
|
|
74
85
|
⚙️ {t('settings.settings')}
|
|
75
|
-
</
|
|
86
|
+
</AppText>
|
|
76
87
|
</TouchableOpacity>
|
|
77
88
|
</AnimationView>
|
|
78
89
|
|
|
79
90
|
<AnimationView delay={600} animType="FadeIn" duration={800}>
|
|
80
91
|
<TouchableOpacity style={styles.logoutButton} onPress={confirmLogout}>
|
|
81
|
-
<
|
|
92
|
+
<AppText variant="bold" size="body" style={styles.logoutButtonText}>
|
|
93
|
+
{t('common.logout')}
|
|
94
|
+
</AppText>
|
|
82
95
|
</TouchableOpacity>
|
|
83
96
|
</AnimationView>
|
|
84
97
|
</View>
|
|
@@ -113,18 +126,13 @@ const getStyles = ({ colors }: ThemeType) =>
|
|
|
113
126
|
marginBottom: 16,
|
|
114
127
|
},
|
|
115
128
|
avatarText: {
|
|
116
|
-
fontSize: 40,
|
|
117
|
-
fontWeight: '700',
|
|
118
129
|
color: colors.white,
|
|
119
130
|
},
|
|
120
131
|
name: {
|
|
121
|
-
fontSize: 24,
|
|
122
|
-
fontWeight: '700',
|
|
123
132
|
color: colors.textColor,
|
|
124
133
|
marginBottom: 4,
|
|
125
134
|
},
|
|
126
135
|
email: {
|
|
127
|
-
fontSize: 14,
|
|
128
136
|
color: colors.textColor + 'CC',
|
|
129
137
|
},
|
|
130
138
|
infoRow: {
|
|
@@ -134,12 +142,9 @@ const getStyles = ({ colors }: ThemeType) =>
|
|
|
134
142
|
paddingVertical: 8,
|
|
135
143
|
},
|
|
136
144
|
infoLabel: {
|
|
137
|
-
fontSize: 14,
|
|
138
|
-
fontWeight: '600',
|
|
139
145
|
color: colors.textColor,
|
|
140
146
|
},
|
|
141
147
|
infoValue: {
|
|
142
|
-
fontSize: 14,
|
|
143
148
|
color: colors.textColor + 'CC',
|
|
144
149
|
},
|
|
145
150
|
logoutButton: {
|
|
@@ -151,8 +156,6 @@ const getStyles = ({ colors }: ThemeType) =>
|
|
|
151
156
|
},
|
|
152
157
|
logoutButtonText: {
|
|
153
158
|
color: colors.white,
|
|
154
|
-
fontSize: 16,
|
|
155
|
-
fontWeight: '700',
|
|
156
159
|
},
|
|
157
160
|
settingsButton: {
|
|
158
161
|
backgroundColor: colors.backgroundColor,
|
|
@@ -165,7 +168,5 @@ const getStyles = ({ colors }: ThemeType) =>
|
|
|
165
168
|
},
|
|
166
169
|
settingsButtonText: {
|
|
167
170
|
color: colors.primary,
|
|
168
|
-
fontSize: 16,
|
|
169
|
-
fontWeight: '700',
|
|
170
171
|
},
|
|
171
172
|
});
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React, { FC } from 'react';
|
|
2
|
-
import { View,
|
|
2
|
+
import { View, StyleSheet, ScrollView } from 'react-native';
|
|
3
|
+
import AppText from '../components/AppText';
|
|
3
4
|
import { useTranslation } from 'react-i18next';
|
|
4
5
|
import { useTheme } from '../context/ThemeContext';
|
|
5
6
|
import { ThemeType } from '../theme/Colors';
|
|
@@ -21,20 +22,24 @@ const SettingsScreen: FC = () => {
|
|
|
21
22
|
>
|
|
22
23
|
<AnimationView animType="FadeIn" duration={800}>
|
|
23
24
|
<View style={styles.header}>
|
|
24
|
-
<
|
|
25
|
-
|
|
25
|
+
<AppText variant="h1" style={styles.title}>
|
|
26
|
+
{t('settings.settings')}
|
|
27
|
+
</AppText>
|
|
28
|
+
<AppText size="body" style={styles.subtitle}>
|
|
26
29
|
{t('settings.customizeYourExperience')}
|
|
27
|
-
</
|
|
30
|
+
</AppText>
|
|
28
31
|
</View>
|
|
29
32
|
</AnimationView>
|
|
30
33
|
|
|
31
34
|
{/* Language Section */}
|
|
32
35
|
<AnimationView delay={200} animType="FadeIn" duration={800}>
|
|
33
36
|
<View style={styles.section}>
|
|
34
|
-
<
|
|
35
|
-
|
|
37
|
+
<AppText variant="semiBold" size={18} style={styles.sectionTitle}>
|
|
38
|
+
{t('settings.language')}
|
|
39
|
+
</AppText>
|
|
40
|
+
<AppText style={styles.sectionDescription}>
|
|
36
41
|
{t('settings.chooseYourPreferredLanguage')}
|
|
37
|
-
</
|
|
42
|
+
</AppText>
|
|
38
43
|
<LanguageSwitcher />
|
|
39
44
|
</View>
|
|
40
45
|
</AnimationView>
|
|
@@ -42,10 +47,12 @@ const SettingsScreen: FC = () => {
|
|
|
42
47
|
{/* Theme Section */}
|
|
43
48
|
<AnimationView delay={400} animType="FadeIn" duration={800}>
|
|
44
49
|
<View style={styles.section}>
|
|
45
|
-
<
|
|
46
|
-
|
|
50
|
+
<AppText variant="semiBold" size={18} style={styles.sectionTitle}>
|
|
51
|
+
{t('settings.theme')}
|
|
52
|
+
</AppText>
|
|
53
|
+
<AppText style={styles.sectionDescription}>
|
|
47
54
|
{t('settings.switchBetweenLightAndDark')}
|
|
48
|
-
</
|
|
55
|
+
</AppText>
|
|
49
56
|
<ThemeSwitcher />
|
|
50
57
|
</View>
|
|
51
58
|
</AnimationView>
|
|
@@ -70,26 +77,20 @@ const getStyles = ({ colors }: ThemeType) =>
|
|
|
70
77
|
marginBottom: 32,
|
|
71
78
|
},
|
|
72
79
|
title: {
|
|
73
|
-
fontSize: 32,
|
|
74
|
-
fontWeight: '700',
|
|
75
80
|
color: colors.textColor,
|
|
76
81
|
marginBottom: 8,
|
|
77
82
|
},
|
|
78
83
|
subtitle: {
|
|
79
|
-
fontSize: 16,
|
|
80
84
|
color: colors.textColor + 'CC',
|
|
81
85
|
},
|
|
82
86
|
section: {
|
|
83
87
|
marginBottom: 32,
|
|
84
88
|
},
|
|
85
89
|
sectionTitle: {
|
|
86
|
-
fontSize: 18,
|
|
87
|
-
fontWeight: '600',
|
|
88
90
|
color: colors.textColor,
|
|
89
91
|
marginBottom: 8,
|
|
90
92
|
},
|
|
91
93
|
sectionDescription: {
|
|
92
|
-
fontSize: 14,
|
|
93
94
|
color: colors.textColor + 'CC',
|
|
94
95
|
marginBottom: 16,
|
|
95
96
|
},
|