@nextsparkjs/mobile 0.1.0-beta.147 → 0.1.0-beta.148

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.
@@ -1,254 +0,0 @@
1
- /**
2
- * Profile Screen - User information and settings
3
- */
4
-
5
- import { View, Text, TextInput, ScrollView, StyleSheet } from 'react-native'
6
- import { useAuth } from '@nextsparkjs/mobile'
7
- import { Colors } from '@/src/constants/colors'
8
-
9
- export default function ProfileScreen() {
10
- const { user } = useAuth()
11
-
12
- // Split name into first and last name
13
- const nameParts = user?.name?.split(' ') || ['', '']
14
- const firstName = nameParts[0] || ''
15
- const lastName = nameParts.slice(1).join(' ') || ''
16
-
17
- return (
18
- <ScrollView style={styles.container}>
19
- {/* Page Header */}
20
- <View style={styles.header}>
21
- <Text style={styles.pageTitle}>Información Personal</Text>
22
- <Text style={styles.pageSubtitle}>
23
- Gestiona tu información personal y preferencias básicas de tu cuenta.
24
- </Text>
25
- </View>
26
-
27
- {/* Personal Data Card */}
28
- <View style={styles.card}>
29
- <View style={styles.cardHeader}>
30
- <Text style={styles.cardIcon}>👤</Text>
31
- <View>
32
- <Text style={styles.cardTitle}>Datos Personales</Text>
33
- <Text style={styles.cardSubtitle}>
34
- Actualiza tu nombre, país, zona horaria e idioma preferido
35
- </Text>
36
- </View>
37
- </View>
38
-
39
- {/* Name Field */}
40
- <View style={styles.field}>
41
- <Text style={styles.label}>Nombre</Text>
42
- <TextInput
43
- style={styles.input}
44
- value={firstName}
45
- editable={false}
46
- placeholder="Tu nombre"
47
- placeholderTextColor={Colors.foregroundMuted}
48
- />
49
- </View>
50
-
51
- {/* Last Name Field */}
52
- <View style={styles.field}>
53
- <Text style={styles.label}>Apellido</Text>
54
- <TextInput
55
- style={styles.input}
56
- value={lastName}
57
- editable={false}
58
- placeholder="Tu apellido"
59
- placeholderTextColor={Colors.foregroundMuted}
60
- />
61
- </View>
62
-
63
- {/* Email Field */}
64
- <View style={styles.field}>
65
- <Text style={styles.label}>Email</Text>
66
- <View style={styles.emailInputWrapper}>
67
- <Text style={styles.emailIcon}>✉</Text>
68
- <TextInput
69
- style={[styles.input, styles.emailInput]}
70
- value={user?.email || ''}
71
- editable={false}
72
- placeholder="Tu email"
73
- placeholderTextColor={Colors.foregroundMuted}
74
- />
75
- </View>
76
- <Text style={styles.hint}>No se puede cambiar</Text>
77
- </View>
78
-
79
- {/* Auth Method */}
80
- <View style={styles.field}>
81
- <Text style={styles.label}>Método de Autenticación</Text>
82
- <View style={styles.readOnlyRow}>
83
- <Text style={styles.readOnlyIcon}>✉</Text>
84
- <Text style={styles.readOnlyText}>Email</Text>
85
- </View>
86
- </View>
87
-
88
- {/* Verification Status */}
89
- <View style={styles.field}>
90
- <Text style={styles.label}>Estado de Verificación</Text>
91
- <View style={styles.readOnlyRow}>
92
- <Text style={styles.verifiedIcon}>✓</Text>
93
- <Text style={styles.verifiedText}>Verificado</Text>
94
- </View>
95
- </View>
96
-
97
- {/* Language */}
98
- <View style={styles.field}>
99
- <Text style={styles.label}>Idioma</Text>
100
- <View style={styles.selectWrapper}>
101
- <Text style={styles.selectIcon}>文</Text>
102
- <Text style={styles.selectText}>Español</Text>
103
- <Text style={styles.selectChevron}>⌄</Text>
104
- </View>
105
- </View>
106
- </View>
107
-
108
- <View style={styles.spacer} />
109
- </ScrollView>
110
- )
111
- }
112
-
113
- const styles = StyleSheet.create({
114
- container: {
115
- flex: 1,
116
- backgroundColor: Colors.backgroundSecondary,
117
- },
118
- header: {
119
- padding: 20,
120
- },
121
- pageTitle: {
122
- fontSize: 28,
123
- fontWeight: '700',
124
- color: Colors.foreground,
125
- marginBottom: 8,
126
- },
127
- pageSubtitle: {
128
- fontSize: 15,
129
- color: Colors.foregroundSecondary,
130
- lineHeight: 22,
131
- },
132
- card: {
133
- backgroundColor: Colors.card,
134
- marginHorizontal: 16,
135
- borderRadius: 12,
136
- padding: 20,
137
- borderWidth: 1,
138
- borderColor: Colors.border,
139
- },
140
- cardHeader: {
141
- flexDirection: 'row',
142
- alignItems: 'flex-start',
143
- gap: 12,
144
- marginBottom: 24,
145
- },
146
- cardIcon: {
147
- fontSize: 20,
148
- marginTop: 2,
149
- },
150
- cardTitle: {
151
- fontSize: 18,
152
- fontWeight: '600',
153
- color: Colors.foreground,
154
- },
155
- cardSubtitle: {
156
- fontSize: 14,
157
- color: Colors.foregroundSecondary,
158
- marginTop: 4,
159
- lineHeight: 20,
160
- },
161
- field: {
162
- marginBottom: 20,
163
- },
164
- label: {
165
- fontSize: 14,
166
- fontWeight: '500',
167
- color: Colors.foreground,
168
- marginBottom: 8,
169
- },
170
- input: {
171
- backgroundColor: Colors.backgroundSecondary,
172
- borderWidth: 1,
173
- borderColor: Colors.border,
174
- borderRadius: 8,
175
- paddingHorizontal: 14,
176
- paddingVertical: 12,
177
- fontSize: 15,
178
- color: Colors.foreground,
179
- },
180
- emailInputWrapper: {
181
- flexDirection: 'row',
182
- alignItems: 'center',
183
- backgroundColor: Colors.backgroundSecondary,
184
- borderWidth: 1,
185
- borderColor: Colors.border,
186
- borderRadius: 8,
187
- paddingHorizontal: 14,
188
- },
189
- emailIcon: {
190
- fontSize: 16,
191
- color: Colors.foregroundMuted,
192
- marginRight: 10,
193
- },
194
- emailInput: {
195
- flex: 1,
196
- borderWidth: 0,
197
- paddingHorizontal: 0,
198
- backgroundColor: 'transparent',
199
- },
200
- hint: {
201
- fontSize: 12,
202
- color: Colors.foregroundMuted,
203
- marginTop: 6,
204
- },
205
- readOnlyRow: {
206
- flexDirection: 'row',
207
- alignItems: 'center',
208
- gap: 8,
209
- },
210
- readOnlyIcon: {
211
- fontSize: 16,
212
- color: Colors.foregroundSecondary,
213
- },
214
- readOnlyText: {
215
- fontSize: 15,
216
- color: Colors.foreground,
217
- },
218
- verifiedIcon: {
219
- fontSize: 16,
220
- color: Colors.success,
221
- },
222
- verifiedText: {
223
- fontSize: 15,
224
- color: Colors.success,
225
- fontWeight: '500',
226
- },
227
- selectWrapper: {
228
- flexDirection: 'row',
229
- alignItems: 'center',
230
- backgroundColor: Colors.backgroundSecondary,
231
- borderWidth: 1,
232
- borderColor: Colors.border,
233
- borderRadius: 8,
234
- paddingHorizontal: 14,
235
- paddingVertical: 12,
236
- },
237
- selectIcon: {
238
- fontSize: 16,
239
- color: Colors.foregroundSecondary,
240
- marginRight: 10,
241
- },
242
- selectText: {
243
- flex: 1,
244
- fontSize: 15,
245
- color: Colors.foreground,
246
- },
247
- selectChevron: {
248
- fontSize: 16,
249
- color: Colors.foregroundSecondary,
250
- },
251
- spacer: {
252
- height: 40,
253
- },
254
- })
@@ -1,241 +0,0 @@
1
- /**
2
- * Settings Screen
3
- */
4
-
5
- import { View, Text, TouchableOpacity, ScrollView, StyleSheet, Switch } from 'react-native'
6
- import { useState } from 'react'
7
- import { router } from 'expo-router'
8
- import { Colors } from '@/src/constants/colors'
9
-
10
- interface SettingItem {
11
- key: string
12
- label: string
13
- description?: string
14
- icon: string
15
- type: 'navigation' | 'toggle'
16
- screen?: string
17
- }
18
-
19
- const SETTINGS_SECTIONS = [
20
- {
21
- title: 'Cuenta',
22
- items: [
23
- {
24
- key: 'profile',
25
- label: 'Información Personal',
26
- description: 'Nombre, email, idioma',
27
- icon: '👤',
28
- type: 'navigation' as const,
29
- screen: 'profile',
30
- },
31
- {
32
- key: 'security',
33
- label: 'Seguridad',
34
- description: 'Contraseña, autenticación',
35
- icon: '🔒',
36
- type: 'navigation' as const,
37
- },
38
- ],
39
- },
40
- {
41
- title: 'Preferencias',
42
- items: [
43
- {
44
- key: 'notifications',
45
- label: 'Notificaciones',
46
- icon: '🔔',
47
- type: 'toggle' as const,
48
- },
49
- {
50
- key: 'darkMode',
51
- label: 'Modo Oscuro',
52
- icon: '🌙',
53
- type: 'toggle' as const,
54
- },
55
- ],
56
- },
57
- {
58
- title: 'Soporte',
59
- items: [
60
- {
61
- key: 'help',
62
- label: 'Centro de Ayuda',
63
- icon: '❓',
64
- type: 'navigation' as const,
65
- },
66
- {
67
- key: 'feedback',
68
- label: 'Enviar Comentarios',
69
- icon: '💬',
70
- type: 'navigation' as const,
71
- },
72
- ],
73
- },
74
- ]
75
-
76
- export default function SettingsScreen() {
77
- const [toggleStates, setToggleStates] = useState<Record<string, boolean>>({
78
- notifications: true,
79
- darkMode: false,
80
- })
81
-
82
- const handleToggle = (key: string) => {
83
- setToggleStates((prev) => ({ ...prev, [key]: !prev[key] }))
84
- }
85
-
86
- const handleNavigation = (item: SettingItem) => {
87
- if (item.screen) {
88
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
89
- router.push(`/(app)/${item.screen}` as any)
90
- }
91
- }
92
-
93
- return (
94
- <ScrollView style={styles.container}>
95
- {/* Page Header */}
96
- <View style={styles.header}>
97
- <Text style={styles.pageTitle}>Ajustes</Text>
98
- <Text style={styles.pageSubtitle}>
99
- Configura tu cuenta y preferencias
100
- </Text>
101
- </View>
102
-
103
- {/* Settings Sections */}
104
- {SETTINGS_SECTIONS.map((section) => (
105
- <View key={section.title} style={styles.section}>
106
- <Text style={styles.sectionTitle}>{section.title}</Text>
107
- <View style={styles.sectionContent}>
108
- {section.items.map((item, index) => (
109
- <TouchableOpacity
110
- key={item.key}
111
- style={[
112
- styles.settingItem,
113
- index < section.items.length - 1 && styles.settingItemBorder,
114
- ]}
115
- onPress={() =>
116
- item.type === 'navigation'
117
- ? handleNavigation(item)
118
- : handleToggle(item.key)
119
- }
120
- activeOpacity={0.7}
121
- >
122
- <Text style={styles.settingIcon}>{item.icon}</Text>
123
- <View style={styles.settingInfo}>
124
- <Text style={styles.settingLabel}>{item.label}</Text>
125
- {'description' in item && item.description && (
126
- <Text style={styles.settingDescription}>
127
- {item.description}
128
- </Text>
129
- )}
130
- </View>
131
- {item.type === 'navigation' ? (
132
- <Text style={styles.chevron}>›</Text>
133
- ) : (
134
- <Switch
135
- value={toggleStates[item.key]}
136
- onValueChange={() => handleToggle(item.key)}
137
- trackColor={{
138
- false: Colors.border,
139
- true: Colors.primary,
140
- }}
141
- thumbColor={Colors.background}
142
- />
143
- )}
144
- </TouchableOpacity>
145
- ))}
146
- </View>
147
- </View>
148
- ))}
149
-
150
- {/* App Version */}
151
- <View style={styles.footer}>
152
- <Text style={styles.versionText}>NextSpark Mobile v1.0.0</Text>
153
- </View>
154
-
155
- <View style={styles.spacer} />
156
- </ScrollView>
157
- )
158
- }
159
-
160
- const styles = StyleSheet.create({
161
- container: {
162
- flex: 1,
163
- backgroundColor: Colors.backgroundSecondary,
164
- },
165
- header: {
166
- padding: 20,
167
- paddingBottom: 12,
168
- },
169
- pageTitle: {
170
- fontSize: 28,
171
- fontWeight: '700',
172
- color: Colors.foreground,
173
- marginBottom: 4,
174
- },
175
- pageSubtitle: {
176
- fontSize: 15,
177
- color: Colors.foregroundSecondary,
178
- },
179
- section: {
180
- marginBottom: 24,
181
- },
182
- sectionTitle: {
183
- fontSize: 13,
184
- fontWeight: '600',
185
- color: Colors.foregroundSecondary,
186
- textTransform: 'uppercase',
187
- letterSpacing: 0.5,
188
- marginHorizontal: 20,
189
- marginBottom: 8,
190
- },
191
- sectionContent: {
192
- backgroundColor: Colors.card,
193
- marginHorizontal: 16,
194
- borderRadius: 12,
195
- borderWidth: 1,
196
- borderColor: Colors.border,
197
- },
198
- settingItem: {
199
- flexDirection: 'row',
200
- alignItems: 'center',
201
- paddingVertical: 14,
202
- paddingHorizontal: 16,
203
- },
204
- settingItemBorder: {
205
- borderBottomWidth: 1,
206
- borderBottomColor: Colors.border,
207
- },
208
- settingIcon: {
209
- fontSize: 20,
210
- width: 32,
211
- },
212
- settingInfo: {
213
- flex: 1,
214
- },
215
- settingLabel: {
216
- fontSize: 16,
217
- color: Colors.foreground,
218
- fontWeight: '400',
219
- },
220
- settingDescription: {
221
- fontSize: 13,
222
- color: Colors.foregroundSecondary,
223
- marginTop: 2,
224
- },
225
- chevron: {
226
- fontSize: 24,
227
- color: Colors.foregroundMuted,
228
- fontWeight: '300',
229
- },
230
- footer: {
231
- alignItems: 'center',
232
- paddingVertical: 20,
233
- },
234
- versionText: {
235
- fontSize: 13,
236
- color: Colors.foregroundMuted,
237
- },
238
- spacer: {
239
- height: 40,
240
- },
241
- })
@@ -1,70 +0,0 @@
1
- /**
2
- * Edit Task Screen
3
- */
4
-
5
- import { View, Text, ActivityIndicator, StyleSheet } from 'react-native'
6
- import { useLocalSearchParams, router } from 'expo-router'
7
- import { TaskForm } from '@/src/components/entities/tasks'
8
- import { useTask, useUpdateTask, useDeleteTask, type UpdateTaskInput } from '@/src/entities/tasks'
9
-
10
- export default function EditTaskScreen() {
11
- const { id } = useLocalSearchParams<{ id: string }>()
12
- const { data, isLoading, error } = useTask(id)
13
- const updateTask = useUpdateTask()
14
- const deleteTask = useDeleteTask()
15
-
16
- const handleSubmit = async (formData: UpdateTaskInput) => {
17
- if (!id) return
18
- await updateTask.mutateAsync({ id, data: formData })
19
- router.back()
20
- }
21
-
22
- const handleDelete = async () => {
23
- if (!id) return
24
- await deleteTask.mutateAsync(id)
25
- router.back()
26
- }
27
-
28
- if (isLoading) {
29
- return (
30
- <View style={styles.centerContainer}>
31
- <ActivityIndicator size="large" color="#3B82F6" />
32
- </View>
33
- )
34
- }
35
-
36
- if (error || !data) {
37
- return (
38
- <View style={styles.centerContainer}>
39
- <Text style={styles.errorText}>
40
- {error instanceof Error ? error.message : 'Task not found'}
41
- </Text>
42
- </View>
43
- )
44
- }
45
-
46
- return (
47
- <TaskForm
48
- mode="edit"
49
- initialData={data.data}
50
- onSubmit={handleSubmit}
51
- onDelete={handleDelete}
52
- isLoading={updateTask.isPending || deleteTask.isPending}
53
- />
54
- )
55
- }
56
-
57
- const styles = StyleSheet.create({
58
- centerContainer: {
59
- flex: 1,
60
- justifyContent: 'center',
61
- alignItems: 'center',
62
- backgroundColor: '#F9FAFB',
63
- },
64
- errorText: {
65
- fontSize: 16,
66
- color: '#DC2626',
67
- textAlign: 'center',
68
- paddingHorizontal: 32,
69
- },
70
- })
@@ -1,24 +0,0 @@
1
- /**
2
- * Create Task Screen
3
- */
4
-
5
- import { router } from 'expo-router'
6
- import { TaskForm } from '@/src/components/entities/tasks'
7
- import { useCreateTask, type CreateTaskInput } from '@/src/entities/tasks'
8
-
9
- export default function CreateTaskScreen() {
10
- const createTask = useCreateTask()
11
-
12
- const handleSubmit = async (data: CreateTaskInput) => {
13
- await createTask.mutateAsync(data)
14
- router.back()
15
- }
16
-
17
- return (
18
- <TaskForm
19
- mode="create"
20
- onSubmit={handleSubmit}
21
- isLoading={createTask.isPending}
22
- />
23
- )
24
- }