create-ern-boilerplate 0.0.39 → 0.0.40
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/templates/agent-generator/app/(auth)/login.tsx +2 -4
- package/templates/agent-generator/app/(auth)/register.tsx +2 -4
- package/templates/agent-generator/app/(tabs)/index.tsx +2 -4
- package/templates/agent-generator/examples/component.example.tsx +2 -3
- package/templates/agent-generator/examples/screens/detail-screen.example.tsx +2 -3
- package/templates/agent-generator/examples/screens/form-screen.example.tsx +2 -3
- package/templates/agent-generator/examples/screens/list-screen-no-auth.example.tsx +2 -3
- package/templates/agent-generator/examples/screens/list-screen-with-auth.example.tsx +2 -3
- package/templates/agent-generator/src/components/shared/ConfirmDialog.tsx +37 -84
- package/templates/agent-generator/src/components/shared/FormInput.tsx +12 -35
- package/templates/agent-generator/src/components/shared/RoleSelector.tsx +16 -35
package/package.json
CHANGED
|
@@ -2,19 +2,17 @@ import React, { useState } from 'react';
|
|
|
2
2
|
import { View, Text, TextInput, TouchableOpacity, KeyboardAvoidingView, Platform } from 'react-native';
|
|
3
3
|
import { Link } from 'expo-router';
|
|
4
4
|
import { useAuthStore } from '@/store/authStore';
|
|
5
|
-
import {
|
|
5
|
+
import { useTheme } from '@/hooks/useTheme';
|
|
6
6
|
import { Button } from '@/components/common/Button';
|
|
7
7
|
|
|
8
8
|
export default function LoginScreen() {
|
|
9
9
|
const login = useAuthStore((state) => state.login);
|
|
10
|
-
const
|
|
10
|
+
const { colors, isDark } = useTheme();
|
|
11
11
|
|
|
12
12
|
const [email, setEmail] = useState('');
|
|
13
13
|
const [password, setPassword] = useState('');
|
|
14
14
|
const [loading, setLoading] = useState(false);
|
|
15
15
|
|
|
16
|
-
const isDark = colorScheme === 'dark';
|
|
17
|
-
|
|
18
16
|
const handleLogin = async () => {
|
|
19
17
|
if (!email || !password) return;
|
|
20
18
|
|
|
@@ -1,20 +1,18 @@
|
|
|
1
1
|
import React, { useState } from 'react';
|
|
2
2
|
import { View, Text, TextInput, TouchableOpacity, KeyboardAvoidingView, Platform } from 'react-native';
|
|
3
3
|
import { Link, useRouter } from 'expo-router';
|
|
4
|
-
import {
|
|
4
|
+
import { useTheme } from '@/hooks/useTheme';
|
|
5
5
|
import { Button } from '@/components/common/Button';
|
|
6
6
|
|
|
7
7
|
export default function RegisterScreen() {
|
|
8
8
|
const router = useRouter();
|
|
9
|
-
const
|
|
9
|
+
const { colors, isDark } = useTheme();
|
|
10
10
|
|
|
11
11
|
const [name, setName] = useState('');
|
|
12
12
|
const [email, setEmail] = useState('');
|
|
13
13
|
const [password, setPassword] = useState('');
|
|
14
14
|
const [loading, setLoading] = useState(false);
|
|
15
15
|
|
|
16
|
-
const isDark = colorScheme === 'dark';
|
|
17
|
-
|
|
18
16
|
const handleRegister = async () => {
|
|
19
17
|
if (!name || !email || !password) return;
|
|
20
18
|
|
|
@@ -1,15 +1,13 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { View, Text, ScrollView } from 'react-native';
|
|
3
|
-
import {
|
|
3
|
+
import { useTheme } from '@/hooks/useTheme';
|
|
4
4
|
import { useAuthStore } from '@/store/authStore';
|
|
5
5
|
import { Card } from '@/components/common/Card';
|
|
6
6
|
|
|
7
7
|
export default function HomeScreen() {
|
|
8
|
-
const
|
|
8
|
+
const { colors, isDark } = useTheme();
|
|
9
9
|
const user = useAuthStore((state) => state.user);
|
|
10
10
|
|
|
11
|
-
const isDark = colorScheme === 'dark';
|
|
12
|
-
|
|
13
11
|
return (
|
|
14
12
|
<ScrollView
|
|
15
13
|
className="flex-1"
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
|
|
12
12
|
import React from 'react';
|
|
13
13
|
import { View, Text, TouchableOpacity } from 'react-native';
|
|
14
|
-
import {
|
|
14
|
+
import { useTheme } from '@/hooks/useTheme';
|
|
15
15
|
|
|
16
16
|
// Example: Item Card Component
|
|
17
17
|
interface ItemCardProps {
|
|
@@ -31,8 +31,7 @@ export function ItemCard({
|
|
|
31
31
|
variant = 'default',
|
|
32
32
|
className = '',
|
|
33
33
|
}: ItemCardProps) {
|
|
34
|
-
const
|
|
35
|
-
const isDark = colorScheme === 'dark';
|
|
34
|
+
const { colors, isDark } = useTheme();
|
|
36
35
|
|
|
37
36
|
const baseClasses = `rounded-lg p-4 ${className}`;
|
|
38
37
|
const variantClasses = variant === 'highlighted'
|
|
@@ -25,7 +25,7 @@ import {
|
|
|
25
25
|
Image,
|
|
26
26
|
Alert,
|
|
27
27
|
} from 'react-native';
|
|
28
|
-
import {
|
|
28
|
+
import { useTheme } from '@/hooks/useTheme';
|
|
29
29
|
import { useRouter, useLocalSearchParams } from 'expo-router';
|
|
30
30
|
import Toast from 'react-native-toast-message';
|
|
31
31
|
|
|
@@ -62,10 +62,9 @@ const mockProductService = {
|
|
|
62
62
|
};
|
|
63
63
|
|
|
64
64
|
export default function ProductDetailScreen() {
|
|
65
|
-
const
|
|
65
|
+
const { colors, isDark } = useTheme();
|
|
66
66
|
const router = useRouter();
|
|
67
67
|
const params = useLocalSearchParams();
|
|
68
|
-
const isDark = colorScheme === 'dark';
|
|
69
68
|
|
|
70
69
|
// Get product ID from params
|
|
71
70
|
const productId = params.id as string;
|
|
@@ -26,7 +26,7 @@ import {
|
|
|
26
26
|
ScrollView,
|
|
27
27
|
ActivityIndicator,
|
|
28
28
|
} from 'react-native';
|
|
29
|
-
import {
|
|
29
|
+
import { useTheme } from '@/hooks/useTheme';
|
|
30
30
|
import { useRouter, useLocalSearchParams } from 'expo-router';
|
|
31
31
|
import Toast from 'react-native-toast-message';
|
|
32
32
|
|
|
@@ -67,10 +67,9 @@ const mockProductService = {
|
|
|
67
67
|
};
|
|
68
68
|
|
|
69
69
|
export default function ProductFormScreen() {
|
|
70
|
-
const
|
|
70
|
+
const { colors, isDark } = useTheme();
|
|
71
71
|
const router = useRouter();
|
|
72
72
|
const params = useLocalSearchParams();
|
|
73
|
-
const isDark = colorScheme === 'dark';
|
|
74
73
|
|
|
75
74
|
// Check if we're in edit mode
|
|
76
75
|
const isEditMode = !!params.id;
|
|
@@ -24,7 +24,7 @@ import {
|
|
|
24
24
|
TouchableOpacity,
|
|
25
25
|
Image,
|
|
26
26
|
} from 'react-native';
|
|
27
|
-
import {
|
|
27
|
+
import { useTheme } from '@/hooks/useTheme';
|
|
28
28
|
import { useRouter } from 'expo-router';
|
|
29
29
|
|
|
30
30
|
// Example: News interface
|
|
@@ -61,9 +61,8 @@ const mockNewsService = {
|
|
|
61
61
|
};
|
|
62
62
|
|
|
63
63
|
export default function NewsListScreen() {
|
|
64
|
-
const
|
|
64
|
+
const { colors, isDark } = useTheme();
|
|
65
65
|
const router = useRouter();
|
|
66
|
-
const isDark = colorScheme === 'dark';
|
|
67
66
|
|
|
68
67
|
// State management
|
|
69
68
|
const [news, setNews] = useState<NewsItem[]>([]);
|
|
@@ -24,7 +24,7 @@ import {
|
|
|
24
24
|
RefreshControl,
|
|
25
25
|
TouchableOpacity,
|
|
26
26
|
} from 'react-native';
|
|
27
|
-
import {
|
|
27
|
+
import { useTheme } from '@/hooks/useTheme';
|
|
28
28
|
import { useAuthStore } from '@/store/authStore';
|
|
29
29
|
import { useRouter } from 'expo-router';
|
|
30
30
|
|
|
@@ -65,10 +65,9 @@ const mockTaskService = {
|
|
|
65
65
|
};
|
|
66
66
|
|
|
67
67
|
export default function TaskListScreen() {
|
|
68
|
-
const
|
|
68
|
+
const { colors, isDark } = useTheme();
|
|
69
69
|
const { user, isAuthenticated } = useAuthStore();
|
|
70
70
|
const router = useRouter();
|
|
71
|
-
const isDark = colorScheme === 'dark';
|
|
72
71
|
|
|
73
72
|
// State management
|
|
74
73
|
const [tasks, setTasks] = useState<Task[]>([]);
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
// components/shared/ConfirmDialog.tsx
|
|
2
2
|
import React from 'react';
|
|
3
|
-
import { View, Text, Modal, TouchableOpacity,
|
|
3
|
+
import { View, Text, Modal, TouchableOpacity, ActivityIndicator } from 'react-native';
|
|
4
4
|
import { AlertTriangle } from 'lucide-react-native';
|
|
5
|
+
import { useTheme } from '@/hooks/useTheme';
|
|
5
6
|
|
|
6
7
|
interface ConfirmDialogProps {
|
|
7
8
|
visible: boolean;
|
|
@@ -12,7 +13,6 @@ interface ConfirmDialogProps {
|
|
|
12
13
|
onConfirm: () => void;
|
|
13
14
|
onCancel: () => void;
|
|
14
15
|
loading?: boolean;
|
|
15
|
-
colors: any;
|
|
16
16
|
destructive?: boolean;
|
|
17
17
|
}
|
|
18
18
|
|
|
@@ -25,9 +25,10 @@ export const ConfirmDialog: React.FC<ConfirmDialogProps> = ({
|
|
|
25
25
|
onConfirm,
|
|
26
26
|
onCancel,
|
|
27
27
|
loading = false,
|
|
28
|
-
colors,
|
|
29
28
|
destructive = false,
|
|
30
29
|
}) => {
|
|
30
|
+
const { colors } = useTheme();
|
|
31
|
+
|
|
31
32
|
return (
|
|
32
33
|
<Modal
|
|
33
34
|
visible={visible}
|
|
@@ -35,39 +36,54 @@ export const ConfirmDialog: React.FC<ConfirmDialogProps> = ({
|
|
|
35
36
|
animationType="fade"
|
|
36
37
|
onRequestClose={onCancel}
|
|
37
38
|
>
|
|
38
|
-
<View style={
|
|
39
|
-
<View
|
|
39
|
+
<View className="flex-1 justify-center items-center px-6" style={{ backgroundColor: 'rgba(0, 0, 0, 0.5)' }}>
|
|
40
|
+
<View
|
|
41
|
+
className="w-full max-w-[360px] rounded-2xl p-6 shadow-xl"
|
|
42
|
+
style={{
|
|
43
|
+
backgroundColor: colors.background,
|
|
44
|
+
shadowColor: '#000',
|
|
45
|
+
shadowOffset: { width: 0, height: 4 },
|
|
46
|
+
shadowOpacity: 0.2,
|
|
47
|
+
shadowRadius: 12,
|
|
48
|
+
elevation: 8,
|
|
49
|
+
}}
|
|
50
|
+
>
|
|
40
51
|
{destructive && (
|
|
41
|
-
<View
|
|
52
|
+
<View className="items-center mb-4">
|
|
42
53
|
<AlertTriangle size={48} color="#ef4444" />
|
|
43
54
|
</View>
|
|
44
55
|
)}
|
|
45
|
-
|
|
46
|
-
<Text style={
|
|
47
|
-
|
|
56
|
+
|
|
57
|
+
<Text className="text-xl font-extrabold mb-3 text-center" style={{ color: colors.text }}>
|
|
58
|
+
{title}
|
|
59
|
+
</Text>
|
|
60
|
+
<Text className="text-sm font-medium leading-5 text-center mb-6" style={{ color: colors.textSecondary }}>
|
|
48
61
|
{message}
|
|
49
62
|
</Text>
|
|
50
63
|
|
|
51
|
-
<View
|
|
64
|
+
<View className="flex-row gap-3">
|
|
52
65
|
<TouchableOpacity
|
|
53
|
-
|
|
66
|
+
className="flex-1 py-3.5 rounded-xl items-center justify-center border-2"
|
|
67
|
+
style={{ borderColor: colors.border }}
|
|
54
68
|
onPress={onCancel}
|
|
55
69
|
activeOpacity={0.8}
|
|
56
70
|
disabled={loading}
|
|
57
71
|
>
|
|
58
|
-
<Text style={
|
|
72
|
+
<Text className="text-base font-bold" style={{ color: colors.text }}>
|
|
59
73
|
{cancelText}
|
|
60
74
|
</Text>
|
|
61
75
|
</TouchableOpacity>
|
|
62
76
|
<TouchableOpacity
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
77
|
+
className="flex-1 py-3.5 rounded-xl items-center justify-center shadow-md"
|
|
78
|
+
style={{
|
|
79
|
+
backgroundColor: destructive ? '#ef4444' : colors.primary,
|
|
80
|
+
opacity: loading ? 0.7 : 1,
|
|
81
|
+
shadowColor: '#000',
|
|
82
|
+
shadowOffset: { width: 0, height: 2 },
|
|
83
|
+
shadowOpacity: 0.15,
|
|
84
|
+
shadowRadius: 4,
|
|
85
|
+
elevation: 3,
|
|
86
|
+
}}
|
|
71
87
|
onPress={onConfirm}
|
|
72
88
|
activeOpacity={0.8}
|
|
73
89
|
disabled={loading}
|
|
@@ -75,7 +91,7 @@ export const ConfirmDialog: React.FC<ConfirmDialogProps> = ({
|
|
|
75
91
|
{loading ? (
|
|
76
92
|
<ActivityIndicator size="small" color="#FFFFFF" />
|
|
77
93
|
) : (
|
|
78
|
-
<Text
|
|
94
|
+
<Text className="text-base font-bold text-white">
|
|
79
95
|
{confirmText}
|
|
80
96
|
</Text>
|
|
81
97
|
)}
|
|
@@ -86,66 +102,3 @@ export const ConfirmDialog: React.FC<ConfirmDialogProps> = ({
|
|
|
86
102
|
</Modal>
|
|
87
103
|
);
|
|
88
104
|
};
|
|
89
|
-
|
|
90
|
-
const styles = StyleSheet.create({
|
|
91
|
-
dialogOverlay: {
|
|
92
|
-
flex: 1,
|
|
93
|
-
backgroundColor: 'rgba(0, 0, 0, 0.5)',
|
|
94
|
-
justifyContent: 'center',
|
|
95
|
-
alignItems: 'center',
|
|
96
|
-
paddingHorizontal: 24,
|
|
97
|
-
},
|
|
98
|
-
dialogContent: {
|
|
99
|
-
width: '100%',
|
|
100
|
-
maxWidth: 360,
|
|
101
|
-
borderRadius: 20,
|
|
102
|
-
padding: 24,
|
|
103
|
-
elevation: 8,
|
|
104
|
-
shadowColor: '#000',
|
|
105
|
-
shadowOffset: { width: 0, height: 4 },
|
|
106
|
-
shadowOpacity: 0.2,
|
|
107
|
-
shadowRadius: 12,
|
|
108
|
-
},
|
|
109
|
-
iconContainer: {
|
|
110
|
-
alignItems: 'center',
|
|
111
|
-
marginBottom: 16,
|
|
112
|
-
},
|
|
113
|
-
dialogTitle: {
|
|
114
|
-
fontSize: 20,
|
|
115
|
-
fontWeight: '800',
|
|
116
|
-
marginBottom: 12,
|
|
117
|
-
textAlign: 'center',
|
|
118
|
-
},
|
|
119
|
-
dialogMessage: {
|
|
120
|
-
fontSize: 14,
|
|
121
|
-
fontWeight: '500',
|
|
122
|
-
lineHeight: 20,
|
|
123
|
-
textAlign: 'center',
|
|
124
|
-
marginBottom: 24,
|
|
125
|
-
},
|
|
126
|
-
dialogActions: {
|
|
127
|
-
flexDirection: 'row',
|
|
128
|
-
gap: 12,
|
|
129
|
-
},
|
|
130
|
-
dialogButton: {
|
|
131
|
-
flex: 1,
|
|
132
|
-
paddingVertical: 14,
|
|
133
|
-
borderRadius: 12,
|
|
134
|
-
alignItems: 'center',
|
|
135
|
-
justifyContent: 'center',
|
|
136
|
-
},
|
|
137
|
-
cancelButton: {
|
|
138
|
-
borderWidth: 2,
|
|
139
|
-
},
|
|
140
|
-
confirmButton: {
|
|
141
|
-
shadowColor: '#000',
|
|
142
|
-
shadowOffset: { width: 0, height: 2 },
|
|
143
|
-
shadowOpacity: 0.15,
|
|
144
|
-
shadowRadius: 4,
|
|
145
|
-
elevation: 3,
|
|
146
|
-
},
|
|
147
|
-
dialogButtonText: {
|
|
148
|
-
fontSize: 15,
|
|
149
|
-
fontWeight: '700',
|
|
150
|
-
},
|
|
151
|
-
});
|
|
@@ -1,33 +1,37 @@
|
|
|
1
1
|
// components/shared/FormInput.tsx
|
|
2
2
|
import React from 'react';
|
|
3
|
-
import { View, Text, TextInput,
|
|
3
|
+
import { View, Text, TextInput, TextInputProps } from 'react-native';
|
|
4
4
|
import { User, Mail, Lock } from 'lucide-react-native';
|
|
5
|
+
import { useTheme } from '@/hooks/useTheme';
|
|
5
6
|
|
|
6
7
|
interface FormInputProps extends TextInputProps {
|
|
7
8
|
label: string;
|
|
8
9
|
icon?: 'user' | 'mail' | 'lock';
|
|
9
|
-
colors: any;
|
|
10
10
|
required?: boolean;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
export const FormInput: React.FC<FormInputProps> = ({
|
|
14
14
|
label,
|
|
15
15
|
icon,
|
|
16
|
-
colors,
|
|
17
16
|
required = false,
|
|
18
17
|
...textInputProps
|
|
19
18
|
}) => {
|
|
19
|
+
const { colors } = useTheme();
|
|
20
20
|
const IconComponent = icon === 'user' ? User : icon === 'mail' ? Mail : Lock;
|
|
21
21
|
|
|
22
22
|
return (
|
|
23
|
-
<View
|
|
24
|
-
<Text style={
|
|
25
|
-
{label} {required && <Text
|
|
23
|
+
<View className="gap-2">
|
|
24
|
+
<Text className="text-sm font-semibold mb-1" style={{ color: colors.text }}>
|
|
25
|
+
{label} {required && <Text className="text-red-500">*</Text>}
|
|
26
26
|
</Text>
|
|
27
|
-
<View
|
|
27
|
+
<View
|
|
28
|
+
className="flex-row items-center px-4 py-3 rounded-xl gap-2.5"
|
|
29
|
+
style={{ backgroundColor: `${colors.primary}08` }}
|
|
30
|
+
>
|
|
28
31
|
{icon && <IconComponent size={18} color={colors.textSecondary} />}
|
|
29
32
|
<TextInput
|
|
30
|
-
|
|
33
|
+
className="flex-1 text-base font-medium"
|
|
34
|
+
style={{ color: colors.text }}
|
|
31
35
|
placeholderTextColor={colors.textSecondary}
|
|
32
36
|
{...textInputProps}
|
|
33
37
|
/>
|
|
@@ -36,32 +40,5 @@ export const FormInput: React.FC<FormInputProps> = ({
|
|
|
36
40
|
);
|
|
37
41
|
};
|
|
38
42
|
|
|
39
|
-
const styles = StyleSheet.create({
|
|
40
|
-
inputGroup: {
|
|
41
|
-
gap: 8,
|
|
42
|
-
},
|
|
43
|
-
inputLabel: {
|
|
44
|
-
fontSize: 14,
|
|
45
|
-
fontWeight: '600',
|
|
46
|
-
marginBottom: 4,
|
|
47
|
-
},
|
|
48
|
-
required: {
|
|
49
|
-
color: '#ef4444',
|
|
50
|
-
},
|
|
51
|
-
inputContainer: {
|
|
52
|
-
flexDirection: 'row',
|
|
53
|
-
alignItems: 'center',
|
|
54
|
-
paddingHorizontal: 16,
|
|
55
|
-
paddingVertical: 12,
|
|
56
|
-
borderRadius: 12,
|
|
57
|
-
gap: 10,
|
|
58
|
-
},
|
|
59
|
-
input: {
|
|
60
|
-
flex: 1,
|
|
61
|
-
fontSize: 15,
|
|
62
|
-
fontWeight: '500',
|
|
63
|
-
},
|
|
64
|
-
});
|
|
65
|
-
|
|
66
43
|
|
|
67
44
|
|
|
@@ -1,42 +1,39 @@
|
|
|
1
1
|
// components/shared/RoleSelector.tsx
|
|
2
2
|
import React from 'react';
|
|
3
|
-
import { View, Text, TouchableOpacity
|
|
3
|
+
import { View, Text, TouchableOpacity } from 'react-native';
|
|
4
|
+
import { useTheme } from '@/hooks/useTheme';
|
|
4
5
|
|
|
5
6
|
interface RoleSelectorProps {
|
|
6
7
|
selectedRole: 'admin' | 'user' | any;
|
|
7
8
|
onSelectRole: (role: 'admin' | 'user') => void;
|
|
8
|
-
colors: any;
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
export const RoleSelector: React.FC<RoleSelectorProps> = ({
|
|
12
12
|
selectedRole,
|
|
13
13
|
onSelectRole,
|
|
14
|
-
colors,
|
|
15
14
|
}) => {
|
|
15
|
+
const { colors } = useTheme();
|
|
16
|
+
|
|
16
17
|
return (
|
|
17
|
-
<View
|
|
18
|
+
<View className="flex-row gap-3">
|
|
18
19
|
{(['user', 'admin'] as const).map((role) => (
|
|
19
20
|
<TouchableOpacity
|
|
20
21
|
key={role}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
},
|
|
28
|
-
]}
|
|
22
|
+
className="flex-1 py-3 rounded-xl items-center"
|
|
23
|
+
style={{
|
|
24
|
+
backgroundColor: selectedRole === role
|
|
25
|
+
? colors.primary
|
|
26
|
+
: `${colors.primary}10`,
|
|
27
|
+
}}
|
|
29
28
|
onPress={() => onSelectRole(role)}
|
|
30
29
|
activeOpacity={0.7}
|
|
31
30
|
>
|
|
32
31
|
<Text
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
},
|
|
39
|
-
]}
|
|
32
|
+
className="text-sm"
|
|
33
|
+
style={{
|
|
34
|
+
color: selectedRole === role ? '#FFFFFF' : colors.text,
|
|
35
|
+
fontWeight: selectedRole === role ? '700' : '500',
|
|
36
|
+
}}
|
|
40
37
|
>
|
|
41
38
|
{role.charAt(0).toUpperCase() + role.slice(1)}
|
|
42
39
|
</Text>
|
|
@@ -45,19 +42,3 @@ export const RoleSelector: React.FC<RoleSelectorProps> = ({
|
|
|
45
42
|
</View>
|
|
46
43
|
);
|
|
47
44
|
};
|
|
48
|
-
|
|
49
|
-
const styles = StyleSheet.create({
|
|
50
|
-
roleSelector: {
|
|
51
|
-
flexDirection: 'row',
|
|
52
|
-
gap: 12,
|
|
53
|
-
},
|
|
54
|
-
roleOption: {
|
|
55
|
-
flex: 1,
|
|
56
|
-
paddingVertical: 12,
|
|
57
|
-
borderRadius: 12,
|
|
58
|
-
alignItems: 'center',
|
|
59
|
-
},
|
|
60
|
-
roleOptionText: {
|
|
61
|
-
fontSize: 14,
|
|
62
|
-
},
|
|
63
|
-
});
|