@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,164 +0,0 @@
1
- /**
2
- * Tasks List Screen
3
- */
4
-
5
- import { useCallback, useState } from 'react'
6
- import {
7
- View,
8
- Text,
9
- FlatList,
10
- RefreshControl,
11
- StyleSheet,
12
- } from 'react-native'
13
- import { router } from 'expo-router'
14
- import { useTasks, type Task } from '@/src/entities/tasks'
15
- import { TaskCard } from '@/src/components/entities/tasks'
16
- import { Button } from '@/src/components/ui'
17
- import { Colors } from '@/src/constants/colors'
18
-
19
- export default function TasksScreen() {
20
- const { data, isLoading, error, refetch } = useTasks()
21
- const [refreshing, setRefreshing] = useState(false)
22
-
23
- const onRefresh = useCallback(async () => {
24
- setRefreshing(true)
25
- try {
26
- await refetch()
27
- } finally {
28
- setRefreshing(false)
29
- }
30
- }, [refetch])
31
-
32
- const handleTaskPress = (task: Task) => {
33
- router.push(`/(app)/task/${task.id}`)
34
- }
35
-
36
- const renderTask = ({ item }: { item: Task }) => (
37
- <TaskCard task={item} onPress={() => handleTaskPress(item)} />
38
- )
39
-
40
- const renderEmpty = () => {
41
- if (isLoading) return null
42
-
43
- return (
44
- <View style={styles.emptyContainer}>
45
- <Text style={styles.emptyIcon}>☑</Text>
46
- <Text style={styles.emptyTitle}>Sin tareas</Text>
47
- <Text style={styles.emptyText}>
48
- Toca el botón Crear para agregar tu primera tarea
49
- </Text>
50
- </View>
51
- )
52
- }
53
-
54
- const renderError = () => (
55
- <View style={styles.errorContainer}>
56
- <Text style={styles.errorTitle}>Algo salió mal</Text>
57
- <Text style={styles.errorText}>
58
- {error instanceof Error ? error.message : 'Error al cargar tareas'}
59
- </Text>
60
- <Button onPress={() => refetch()}>
61
- Reintentar
62
- </Button>
63
- </View>
64
- )
65
-
66
- return (
67
- <View style={styles.container}>
68
- {/* Page Header */}
69
- <View style={styles.header}>
70
- <Text style={styles.pageTitle}>Tareas</Text>
71
- <Text style={styles.pageSubtitle}>
72
- Gestiona y organiza tus tareas pendientes
73
- </Text>
74
- </View>
75
-
76
- {/* Error State */}
77
- {error && renderError()}
78
-
79
- {/* Tasks List */}
80
- {!error && (
81
- <FlatList
82
- data={data?.data || []}
83
- renderItem={renderTask}
84
- keyExtractor={(item) => item.id}
85
- contentContainerStyle={styles.listContent}
86
- refreshControl={
87
- <RefreshControl
88
- refreshing={refreshing}
89
- onRefresh={onRefresh}
90
- tintColor={Colors.primary}
91
- />
92
- }
93
- ListEmptyComponent={renderEmpty}
94
- showsVerticalScrollIndicator={false}
95
- />
96
- )}
97
- </View>
98
- )
99
- }
100
-
101
- const styles = StyleSheet.create({
102
- container: {
103
- flex: 1,
104
- backgroundColor: Colors.backgroundSecondary,
105
- },
106
- header: {
107
- padding: 20,
108
- paddingBottom: 12,
109
- },
110
- pageTitle: {
111
- fontSize: 28,
112
- fontWeight: '700',
113
- color: Colors.foreground,
114
- marginBottom: 4,
115
- },
116
- pageSubtitle: {
117
- fontSize: 15,
118
- color: Colors.foregroundSecondary,
119
- },
120
- listContent: {
121
- paddingBottom: 12,
122
- flexGrow: 1,
123
- },
124
- emptyContainer: {
125
- flex: 1,
126
- justifyContent: 'center',
127
- alignItems: 'center',
128
- paddingHorizontal: 32,
129
- },
130
- emptyIcon: {
131
- fontSize: 48,
132
- marginBottom: 16,
133
- opacity: 0.5,
134
- },
135
- emptyTitle: {
136
- fontSize: 18,
137
- fontWeight: '600',
138
- color: Colors.foreground,
139
- marginBottom: 8,
140
- },
141
- emptyText: {
142
- fontSize: 14,
143
- color: Colors.foregroundSecondary,
144
- textAlign: 'center',
145
- },
146
- errorContainer: {
147
- flex: 1,
148
- justifyContent: 'center',
149
- alignItems: 'center',
150
- paddingHorizontal: 32,
151
- },
152
- errorTitle: {
153
- fontSize: 18,
154
- fontWeight: '600',
155
- color: Colors.destructive,
156
- marginBottom: 8,
157
- },
158
- errorText: {
159
- fontSize: 14,
160
- color: Colors.foregroundSecondary,
161
- textAlign: 'center',
162
- marginBottom: 16,
163
- },
164
- })
@@ -1,54 +0,0 @@
1
- /**
2
- * Root Layout - Sets up providers
3
- */
4
-
5
- import "../src/styles/globals.css";
6
-
7
- import { Stack } from "expo-router";
8
- import { StatusBar } from "expo-status-bar";
9
- import { QueryProvider, AuthProvider } from "@nextsparkjs/mobile";
10
- import { ThemeProvider } from "@nextsparkjs/ui";
11
-
12
- /**
13
- * Custom colors demo - Override any color from ThemeColors
14
- * These match the web app's default design system.
15
- * Uncomment and modify to customize your app's theme.
16
- */
17
- const customColors = {
18
- // Primary: Dark neutral (matches web)
19
- primary: "#171717",
20
- primaryForeground: "#fafafa",
21
-
22
- // Secondary: Light gray
23
- secondary: "#f5f5f5",
24
- secondaryForeground: "#1a1a1a",
25
-
26
- // Destructive: Red for errors/danger
27
- destructive: "#ef4444",
28
- destructiveForeground: "#FFFFFF",
29
-
30
- // Success: Green for confirmations
31
- success: "#22c55e",
32
- successForeground: "#FFFFFF",
33
- };
34
-
35
- export default function RootLayout() {
36
- return (
37
- <QueryProvider>
38
- <AuthProvider>
39
- <ThemeProvider colors={customColors}>
40
- <StatusBar style="auto" />
41
- <Stack
42
- screenOptions={{
43
- headerShown: false,
44
- }}
45
- >
46
- <Stack.Screen name="index" />
47
- <Stack.Screen name="login" />
48
- <Stack.Screen name="(app)" />
49
- </Stack>
50
- </ThemeProvider>
51
- </AuthProvider>
52
- </QueryProvider>
53
- );
54
- }
@@ -1,35 +0,0 @@
1
- /**
2
- * Entry point - Redirects based on auth state
3
- */
4
-
5
- import { useEffect } from 'react'
6
- import { View, ActivityIndicator, StyleSheet } from 'react-native'
7
- import { Redirect } from 'expo-router'
8
- import { useAuth } from '@nextsparkjs/mobile'
9
-
10
- export default function Index() {
11
- const { isAuthenticated, isLoading } = useAuth()
12
-
13
- if (isLoading) {
14
- return (
15
- <View style={styles.container}>
16
- <ActivityIndicator size="large" color="#3B82F6" />
17
- </View>
18
- )
19
- }
20
-
21
- if (isAuthenticated) {
22
- return <Redirect href="/(app)" />
23
- }
24
-
25
- return <Redirect href="/login" />
26
- }
27
-
28
- const styles = StyleSheet.create({
29
- container: {
30
- flex: 1,
31
- justifyContent: 'center',
32
- alignItems: 'center',
33
- backgroundColor: '#F9FAFB',
34
- },
35
- })
@@ -1,179 +0,0 @@
1
- /**
2
- * Login Screen
3
- */
4
-
5
- import { useState } from 'react'
6
- import {
7
- View,
8
- Text,
9
- TextInput,
10
- StyleSheet,
11
- KeyboardAvoidingView,
12
- Platform,
13
- } from 'react-native'
14
- import { SafeAreaView } from 'react-native-safe-area-context'
15
- import { router } from 'expo-router'
16
- import { useAuth } from '@nextsparkjs/mobile'
17
- import { Colors } from '@/src/constants/colors'
18
- import { Button } from '@/src/components/ui'
19
-
20
- export default function LoginScreen() {
21
- const { login, isLoading } = useAuth()
22
- const [email, setEmail] = useState('')
23
- const [password, setPassword] = useState('')
24
- const [error, setError] = useState<string | null>(null)
25
-
26
- const handleLogin = async () => {
27
- setError(null)
28
-
29
- if (!email.trim() || !password.trim()) {
30
- setError('Por favor ingresa tu email y contraseña')
31
- return
32
- }
33
-
34
- try {
35
- await login(email.trim(), password)
36
- router.replace('/(app)')
37
- } catch (err) {
38
- setError(err instanceof Error ? err.message : 'Error al iniciar sesión. Por favor intenta de nuevo.')
39
- }
40
- }
41
-
42
- return (
43
- <SafeAreaView style={styles.safeArea}>
44
- <KeyboardAvoidingView
45
- behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
46
- style={styles.container}
47
- >
48
- <View style={styles.content}>
49
- {/* Header */}
50
- <View style={styles.header}>
51
- <Text style={styles.logo}>NextSpark</Text>
52
- <Text style={styles.subtitle}>Inicia sesión en tu cuenta</Text>
53
- </View>
54
-
55
- {/* Error */}
56
- {error && (
57
- <View style={styles.errorContainer}>
58
- <Text style={styles.errorText}>{error}</Text>
59
- </View>
60
- )}
61
-
62
- {/* Form */}
63
- <View style={styles.form}>
64
- <View style={styles.inputContainer}>
65
- <Text style={styles.label}>Email</Text>
66
- <TextInput
67
- style={styles.input}
68
- value={email}
69
- onChangeText={setEmail}
70
- placeholder="Ingresa tu email"
71
- placeholderTextColor={Colors.foregroundMuted}
72
- keyboardType="email-address"
73
- autoCapitalize="none"
74
- autoCorrect={false}
75
- editable={!isLoading}
76
- />
77
- </View>
78
-
79
- <View style={styles.inputContainer}>
80
- <Text style={styles.label}>Contraseña</Text>
81
- <TextInput
82
- style={styles.input}
83
- value={password}
84
- onChangeText={setPassword}
85
- placeholder="Ingresa tu contraseña"
86
- placeholderTextColor={Colors.foregroundMuted}
87
- secureTextEntry
88
- editable={!isLoading}
89
- />
90
- </View>
91
-
92
- <Button
93
- onPress={handleLogin}
94
- isLoading={isLoading}
95
- style={{ marginTop: 8 }}
96
- >
97
- Iniciar Sesión
98
- </Button>
99
- </View>
100
-
101
- {/* Dev Hint */}
102
- <View style={styles.hint}>
103
- <Text style={styles.hintText}>
104
- Dev: carlos.mendoza@nextspark.dev / Test1234
105
- </Text>
106
- </View>
107
- </View>
108
- </KeyboardAvoidingView>
109
- </SafeAreaView>
110
- )
111
- }
112
-
113
- const styles = StyleSheet.create({
114
- safeArea: {
115
- flex: 1,
116
- backgroundColor: Colors.backgroundSecondary,
117
- },
118
- container: {
119
- flex: 1,
120
- },
121
- content: {
122
- flex: 1,
123
- justifyContent: 'center',
124
- padding: 24,
125
- },
126
- header: {
127
- alignItems: 'center',
128
- marginBottom: 32,
129
- },
130
- logo: {
131
- fontSize: 32,
132
- fontWeight: '700',
133
- color: Colors.foreground,
134
- },
135
- subtitle: {
136
- fontSize: 16,
137
- color: Colors.foregroundSecondary,
138
- marginTop: 8,
139
- },
140
- errorContainer: {
141
- backgroundColor: '#FEE2E2',
142
- padding: 12,
143
- borderRadius: 8,
144
- marginBottom: 16,
145
- },
146
- errorText: {
147
- color: Colors.destructive,
148
- fontSize: 14,
149
- textAlign: 'center',
150
- },
151
- form: {
152
- gap: 16,
153
- },
154
- inputContainer: {
155
- gap: 6,
156
- },
157
- label: {
158
- fontSize: 14,
159
- fontWeight: '500',
160
- color: Colors.foreground,
161
- },
162
- input: {
163
- backgroundColor: Colors.card,
164
- borderWidth: 1,
165
- borderColor: Colors.border,
166
- borderRadius: 8,
167
- padding: 14,
168
- fontSize: 16,
169
- color: Colors.foreground,
170
- },
171
- hint: {
172
- marginTop: 24,
173
- alignItems: 'center',
174
- },
175
- hintText: {
176
- fontSize: 12,
177
- color: Colors.foregroundMuted,
178
- },
179
- })