@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.
- package/package.json +1 -1
- package/templates/app/(app)/_layout.tsx +0 -216
- package/templates/app/(app)/customer/[id].tsx +0 -68
- package/templates/app/(app)/customer/create.tsx +0 -24
- package/templates/app/(app)/customers.tsx +0 -164
- package/templates/app/(app)/index.tsx +0 -310
- package/templates/app/(app)/notifications.tsx +0 -242
- package/templates/app/(app)/profile.tsx +0 -254
- package/templates/app/(app)/settings.tsx +0 -241
- package/templates/app/(app)/task/[id].tsx +0 -70
- package/templates/app/(app)/task/create.tsx +0 -24
- package/templates/app/(app)/tasks.tsx +0 -164
- package/templates/app/_layout.tsx +0 -54
- package/templates/app/index.tsx +0 -35
- package/templates/app/login.tsx +0 -179
|
@@ -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
|
-
}
|
package/templates/app/index.tsx
DELETED
|
@@ -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
|
-
})
|
package/templates/app/login.tsx
DELETED
|
@@ -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
|
-
})
|