@nextsparkjs/mobile 0.1.0-beta.1

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.
Files changed (123) hide show
  1. package/README.md +339 -0
  2. package/dist/api/client.d.ts +102 -0
  3. package/dist/api/client.js +189 -0
  4. package/dist/api/client.js.map +1 -0
  5. package/dist/api/client.types.d.ts +39 -0
  6. package/dist/api/client.types.js +12 -0
  7. package/dist/api/client.types.js.map +1 -0
  8. package/dist/api/core/auth.d.ts +26 -0
  9. package/dist/api/core/auth.js +52 -0
  10. package/dist/api/core/auth.js.map +1 -0
  11. package/dist/api/core/index.d.ts +4 -0
  12. package/dist/api/core/index.js +5 -0
  13. package/dist/api/core/index.js.map +1 -0
  14. package/dist/api/core/teams.d.ts +20 -0
  15. package/dist/api/core/teams.js +19 -0
  16. package/dist/api/core/teams.js.map +1 -0
  17. package/dist/api/core/types.d.ts +58 -0
  18. package/dist/api/core/types.js +1 -0
  19. package/dist/api/core/types.js.map +1 -0
  20. package/dist/api/core/users.d.ts +43 -0
  21. package/dist/api/core/users.js +41 -0
  22. package/dist/api/core/users.js.map +1 -0
  23. package/dist/api/entities/factory.d.ts +43 -0
  24. package/dist/api/entities/factory.js +31 -0
  25. package/dist/api/entities/factory.js.map +1 -0
  26. package/dist/api/entities/index.d.ts +3 -0
  27. package/dist/api/entities/index.js +3 -0
  28. package/dist/api/entities/index.js.map +1 -0
  29. package/dist/api/entities/types.d.ts +32 -0
  30. package/dist/api/entities/types.js +1 -0
  31. package/dist/api/entities/types.js.map +1 -0
  32. package/dist/api/index.d.ts +7 -0
  33. package/dist/api/index.js +15 -0
  34. package/dist/api/index.js.map +1 -0
  35. package/dist/hooks/index.d.ts +4 -0
  36. package/dist/hooks/index.js +5 -0
  37. package/dist/hooks/index.js.map +1 -0
  38. package/dist/index.d.ts +14 -0
  39. package/dist/index.js +28 -0
  40. package/dist/index.js.map +1 -0
  41. package/dist/lib/alert.d.ts +34 -0
  42. package/dist/lib/alert.js +73 -0
  43. package/dist/lib/alert.js.map +1 -0
  44. package/dist/lib/index.d.ts +2 -0
  45. package/dist/lib/index.js +10 -0
  46. package/dist/lib/index.js.map +1 -0
  47. package/dist/lib/storage.d.ts +1 -0
  48. package/dist/lib/storage.js +29 -0
  49. package/dist/lib/storage.js.map +1 -0
  50. package/dist/providers/AuthProvider.d.ts +21 -0
  51. package/dist/providers/AuthProvider.js +113 -0
  52. package/dist/providers/AuthProvider.js.map +1 -0
  53. package/dist/providers/QueryProvider.d.ts +11 -0
  54. package/dist/providers/QueryProvider.js +23 -0
  55. package/dist/providers/QueryProvider.js.map +1 -0
  56. package/dist/providers/index.d.ts +6 -0
  57. package/dist/providers/index.js +9 -0
  58. package/dist/providers/index.js.map +1 -0
  59. package/dist/storage-BaRppHUz.d.ts +22 -0
  60. package/package.json +99 -0
  61. package/templates/app/(app)/_layout.tsx +216 -0
  62. package/templates/app/(app)/customer/[id].tsx +68 -0
  63. package/templates/app/(app)/customer/create.tsx +24 -0
  64. package/templates/app/(app)/customers.tsx +164 -0
  65. package/templates/app/(app)/index.tsx +310 -0
  66. package/templates/app/(app)/notifications.tsx +242 -0
  67. package/templates/app/(app)/profile.tsx +254 -0
  68. package/templates/app/(app)/settings.tsx +241 -0
  69. package/templates/app/(app)/task/[id].tsx +70 -0
  70. package/templates/app/(app)/task/create.tsx +24 -0
  71. package/templates/app/(app)/tasks.tsx +164 -0
  72. package/templates/app/_layout.tsx +54 -0
  73. package/templates/app/index.tsx +35 -0
  74. package/templates/app/login.tsx +179 -0
  75. package/templates/app.config.ts +39 -0
  76. package/templates/babel.config.js +9 -0
  77. package/templates/eas.json +18 -0
  78. package/templates/jest.config.js +12 -0
  79. package/templates/metro.config.js +23 -0
  80. package/templates/package.json.template +52 -0
  81. package/templates/src/components/entities/customers/CustomerCard.tsx +59 -0
  82. package/templates/src/components/entities/customers/CustomerForm.tsx +194 -0
  83. package/templates/src/components/entities/customers/index.ts +6 -0
  84. package/templates/src/components/entities/index.ts +9 -0
  85. package/templates/src/components/entities/tasks/TaskCard.tsx +89 -0
  86. package/templates/src/components/entities/tasks/TaskForm.tsx +231 -0
  87. package/templates/src/components/entities/tasks/index.ts +6 -0
  88. package/templates/src/components/features/index.ts +6 -0
  89. package/templates/src/components/navigation/BottomTabBar.tsx +80 -0
  90. package/templates/src/components/navigation/CreateSheet.tsx +108 -0
  91. package/templates/src/components/navigation/MoreSheet.tsx +403 -0
  92. package/templates/src/components/navigation/TopBar.tsx +74 -0
  93. package/templates/src/components/navigation/index.ts +8 -0
  94. package/templates/src/components/ui/index.ts +89 -0
  95. package/templates/src/components/ui/text.tsx +64 -0
  96. package/templates/src/config/api.config.ts +26 -0
  97. package/templates/src/config/app.config.ts +15 -0
  98. package/templates/src/config/hooks.ts +58 -0
  99. package/templates/src/config/permissions.config.ts +119 -0
  100. package/templates/src/constants/colors.ts +55 -0
  101. package/templates/src/data/notifications.mock.json +100 -0
  102. package/templates/src/entities/customers/api.ts +10 -0
  103. package/templates/src/entities/customers/constants.internal.ts +6 -0
  104. package/templates/src/entities/customers/constants.ts +14 -0
  105. package/templates/src/entities/customers/index.ts +9 -0
  106. package/templates/src/entities/customers/mutations.ts +58 -0
  107. package/templates/src/entities/customers/queries.ts +40 -0
  108. package/templates/src/entities/customers/types.ts +43 -0
  109. package/templates/src/entities/index.ts +8 -0
  110. package/templates/src/entities/tasks/api.ts +10 -0
  111. package/templates/src/entities/tasks/constants.internal.ts +6 -0
  112. package/templates/src/entities/tasks/constants.ts +39 -0
  113. package/templates/src/entities/tasks/index.ts +9 -0
  114. package/templates/src/entities/tasks/mutations.ts +108 -0
  115. package/templates/src/entities/tasks/queries.ts +42 -0
  116. package/templates/src/entities/tasks/types.ts +52 -0
  117. package/templates/src/hooks/useCustomers.ts +17 -0
  118. package/templates/src/hooks/useTasks.ts +18 -0
  119. package/templates/src/lib/utils.ts +10 -0
  120. package/templates/src/styles/globals.css +103 -0
  121. package/templates/src/types/index.ts +45 -0
  122. package/templates/tailwind.config.js +108 -0
  123. package/templates/tsconfig.json +15 -0
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Permission hooks for mobile
3
+ */
4
+
5
+ import { useMemo } from 'react'
6
+ import { useAuth } from '@nextsparkjs/mobile'
7
+ import { canDoAction, PERMISSIONS_CONFIG } from './permissions.config'
8
+
9
+ /**
10
+ * Check if current user has permission to perform an action
11
+ */
12
+ export function usePermission(action: string): boolean {
13
+ const { team } = useAuth()
14
+
15
+ return useMemo(() => {
16
+ if (!team?.role) return false
17
+ return canDoAction(team.role, action)
18
+ }, [team?.role, action])
19
+ }
20
+
21
+ /**
22
+ * Check multiple permissions at once
23
+ */
24
+ export function usePermissions<T extends Record<string, string>>(
25
+ permissions: T
26
+ ): Record<keyof T, boolean> {
27
+ const { team } = useAuth()
28
+
29
+ return useMemo(() => {
30
+ const result = {} as Record<keyof T, boolean>
31
+ for (const [key, action] of Object.entries(permissions)) {
32
+ result[key as keyof T] = team?.role ? canDoAction(team.role, action) : false
33
+ }
34
+ return result
35
+ }, [team?.role, permissions])
36
+ }
37
+
38
+ /**
39
+ * Get current team role
40
+ */
41
+ export function useTeamRole(): string | null {
42
+ const { team } = useAuth()
43
+ return team?.role ?? null
44
+ }
45
+
46
+ /**
47
+ * Check if user can perform entity action
48
+ */
49
+ export function useEntityPermission(entity: 'tasks' | 'customers', action: string): boolean {
50
+ const { team } = useAuth()
51
+
52
+ return useMemo(() => {
53
+ if (!team?.role) return false
54
+ const entityPerms = PERMISSIONS_CONFIG.entities[entity]
55
+ const perm = entityPerms.find(p => p.action === action)
56
+ return perm ? perm.roles.includes(team.role) : false
57
+ }, [team?.role, entity, action])
58
+ }
@@ -0,0 +1,119 @@
1
+ /**
2
+ * Mobile App - Permissions Configuration
3
+ *
4
+ * SINGLE SOURCE OF TRUTH for all permissions and roles.
5
+ * Structure matches web theme: teams, entities, features
6
+ */
7
+
8
+ // Types (simplified for mobile - no ThemePermissionsConfig import)
9
+ interface Permission {
10
+ action: string
11
+ label: string
12
+ description: string
13
+ roles: string[]
14
+ dangerous?: boolean
15
+ category?: string
16
+ }
17
+
18
+ interface PermissionsConfig {
19
+ teams: Permission[]
20
+ entities: {
21
+ tasks: Permission[]
22
+ customers: Permission[]
23
+ }
24
+ features: Permission[]
25
+ }
26
+
27
+ export const PERMISSIONS_CONFIG: PermissionsConfig = {
28
+ // ==========================================
29
+ // TEAM PERMISSIONS
30
+ // ==========================================
31
+ teams: [
32
+ // View permissions
33
+ { action: 'team.view', label: 'View Team', description: 'Can view team details', roles: ['owner', 'admin', 'member', 'viewer'] },
34
+ { action: 'team.members.view', label: 'View Members', description: 'Can see team member list', roles: ['owner', 'admin', 'member', 'viewer'] },
35
+ { action: 'team.settings.view', label: 'View Settings', description: 'Can view team settings', roles: ['owner', 'admin', 'member'] },
36
+
37
+ // Edit permissions
38
+ { action: 'team.edit', label: 'Edit Team', description: 'Can modify team name and details', roles: ['owner', 'admin'] },
39
+ { action: 'team.settings.edit', label: 'Edit Settings', description: 'Can modify team settings', roles: ['owner', 'admin'] },
40
+
41
+ // Member management
42
+ { action: 'team.members.invite', label: 'Invite Members', description: 'Can invite new team members', roles: ['owner', 'admin'] },
43
+ { action: 'team.members.remove', label: 'Remove Members', description: 'Can remove team members', roles: ['owner', 'admin'] },
44
+ ],
45
+
46
+ // ==========================================
47
+ // ENTITY PERMISSIONS
48
+ // ==========================================
49
+ entities: {
50
+ // TASKS
51
+ tasks: [
52
+ { action: 'create', label: 'Create tasks', description: 'Can create new tasks', roles: ['owner', 'admin', 'member'] },
53
+ { action: 'read', label: 'View tasks', description: 'Can view task details', roles: ['owner', 'admin', 'member'] },
54
+ { action: 'list', label: 'List tasks', description: 'Can see the tasks list', roles: ['owner', 'admin', 'member'] },
55
+ { action: 'update', label: 'Edit tasks', description: 'Can modify task information', roles: ['owner', 'admin', 'member'] },
56
+ { action: 'delete', label: 'Delete tasks', description: 'Can delete tasks', roles: ['owner', 'admin'], dangerous: true },
57
+ ],
58
+
59
+ // CUSTOMERS
60
+ customers: [
61
+ { action: 'create', label: 'Create customers', description: 'Can create new customers', roles: ['owner', 'admin'] },
62
+ { action: 'read', label: 'View customers', description: 'Can view customer details', roles: ['owner', 'admin', 'member'] },
63
+ { action: 'list', label: 'List customers', description: 'Can see the customers list', roles: ['owner', 'admin', 'member'] },
64
+ { action: 'update', label: 'Edit customers', description: 'Can modify customer information', roles: ['owner', 'admin'] },
65
+ { action: 'delete', label: 'Delete customers', description: 'Can delete customers', roles: ['owner'], dangerous: true },
66
+ ],
67
+ },
68
+
69
+ // ==========================================
70
+ // FEATURE PERMISSIONS
71
+ // ==========================================
72
+ features: [
73
+ // Offline Mode
74
+ {
75
+ action: 'offline.access',
76
+ label: 'Offline Mode',
77
+ description: 'Can use the app in offline mode',
78
+ category: 'Mobile',
79
+ roles: ['owner', 'admin', 'member'],
80
+ },
81
+ // Push Notifications
82
+ {
83
+ action: 'notifications.receive',
84
+ label: 'Push Notifications',
85
+ description: 'Can receive push notifications',
86
+ category: 'Mobile',
87
+ roles: ['owner', 'admin', 'member', 'viewer'],
88
+ },
89
+ // Quick Create
90
+ {
91
+ action: 'quick-create.access',
92
+ label: 'Quick Create',
93
+ description: 'Can use quick create from bottom nav',
94
+ category: 'Mobile',
95
+ roles: ['owner', 'admin', 'member'],
96
+ },
97
+ ],
98
+ }
99
+
100
+ // Helper function (optional - for future use)
101
+ export function canDoAction(role: string, action: string): boolean {
102
+ // Check teams
103
+ const teamPerm = PERMISSIONS_CONFIG.teams.find(p => p.action === action)
104
+ if (teamPerm) return teamPerm.roles.includes(role)
105
+
106
+ // Check entities
107
+ for (const [entity, perms] of Object.entries(PERMISSIONS_CONFIG.entities)) {
108
+ const entityPerm = perms.find(p => `${entity}.${p.action}` === action)
109
+ if (entityPerm) return entityPerm.roles.includes(role)
110
+ }
111
+
112
+ // Check features
113
+ const featurePerm = PERMISSIONS_CONFIG.features.find(p => p.action === action)
114
+ if (featurePerm) return featurePerm.roles.includes(role)
115
+
116
+ return false
117
+ }
118
+
119
+ export default PERMISSIONS_CONFIG
@@ -0,0 +1,55 @@
1
+ /**
2
+ * NextSpark Mobile Color Palette
3
+ * Black/White theme matching default NextSpark theme
4
+ */
5
+
6
+ export const Colors = {
7
+ // Primary
8
+ primary: '#000000',
9
+ primaryForeground: '#FFFFFF',
10
+
11
+ // Background
12
+ background: '#FFFFFF',
13
+ backgroundSecondary: '#F9FAFB',
14
+ backgroundTertiary: '#F3F4F6',
15
+
16
+ // Foreground
17
+ foreground: '#111827',
18
+ foregroundSecondary: '#6B7280',
19
+ foregroundMuted: '#9CA3AF',
20
+
21
+ // Border
22
+ border: '#E5E7EB',
23
+ borderSecondary: '#D1D5DB',
24
+
25
+ // Accent
26
+ accent: '#F59E0B', // Orange for avatar
27
+ accentForeground: '#FFFFFF',
28
+
29
+ // Destructive
30
+ destructive: '#DC2626',
31
+ destructiveForeground: '#FFFFFF',
32
+
33
+ // Success
34
+ success: '#10B981',
35
+ successForeground: '#FFFFFF',
36
+
37
+ // Card
38
+ card: '#FFFFFF',
39
+ cardForeground: '#111827',
40
+
41
+ // Status colors
42
+ statusTodo: '#6B7280',
43
+ statusInProgress: '#3B82F6',
44
+ statusReview: '#F59E0B',
45
+ statusDone: '#10B981',
46
+ statusBlocked: '#DC2626',
47
+
48
+ // Priority colors
49
+ priorityLow: '#6B7280',
50
+ priorityMedium: '#F59E0B',
51
+ priorityHigh: '#F97316',
52
+ priorityUrgent: '#DC2626',
53
+ }
54
+
55
+ export default Colors
@@ -0,0 +1,100 @@
1
+ {
2
+ "notifications": [
3
+ {
4
+ "id": "notif-001",
5
+ "type": "task_assigned",
6
+ "title": "Nueva tarea asignada",
7
+ "message": "Se te ha asignado la tarea 'Revisar propuesta de diseño'",
8
+ "read": false,
9
+ "createdAt": "2025-01-24T10:30:00Z",
10
+ "data": {
11
+ "taskId": "task-123",
12
+ "taskTitle": "Revisar propuesta de diseño"
13
+ }
14
+ },
15
+ {
16
+ "id": "notif-002",
17
+ "type": "task_completed",
18
+ "title": "Tarea completada",
19
+ "message": "La tarea 'Implementar autenticación' ha sido marcada como completada",
20
+ "read": false,
21
+ "createdAt": "2025-01-24T09:15:00Z",
22
+ "data": {
23
+ "taskId": "task-456",
24
+ "taskTitle": "Implementar autenticación"
25
+ }
26
+ },
27
+ {
28
+ "id": "notif-003",
29
+ "type": "customer_added",
30
+ "title": "Nuevo cliente agregado",
31
+ "message": "Se ha agregado el cliente 'Acme Corporation' al sistema",
32
+ "read": true,
33
+ "createdAt": "2025-01-23T16:45:00Z",
34
+ "data": {
35
+ "customerId": "cust-789",
36
+ "customerName": "Acme Corporation"
37
+ }
38
+ },
39
+ {
40
+ "id": "notif-004",
41
+ "type": "task_due_soon",
42
+ "title": "Tarea por vencer",
43
+ "message": "La tarea 'Entregar reporte mensual' vence mañana",
44
+ "read": false,
45
+ "createdAt": "2025-01-23T14:00:00Z",
46
+ "data": {
47
+ "taskId": "task-101",
48
+ "taskTitle": "Entregar reporte mensual",
49
+ "dueDate": "2025-01-25T23:59:59Z"
50
+ }
51
+ },
52
+ {
53
+ "id": "notif-005",
54
+ "type": "team_invite",
55
+ "title": "Invitación a equipo",
56
+ "message": "Has sido invitado a unirte al equipo 'Marketing Digital'",
57
+ "read": true,
58
+ "createdAt": "2025-01-22T11:20:00Z",
59
+ "data": {
60
+ "teamId": "team-202",
61
+ "teamName": "Marketing Digital"
62
+ }
63
+ },
64
+ {
65
+ "id": "notif-006",
66
+ "type": "task_comment",
67
+ "title": "Nuevo comentario",
68
+ "message": "Carlos Mendoza comentó en 'Planificación Q1'",
69
+ "read": true,
70
+ "createdAt": "2025-01-22T08:30:00Z",
71
+ "data": {
72
+ "taskId": "task-303",
73
+ "taskTitle": "Planificación Q1",
74
+ "commentBy": "Carlos Mendoza"
75
+ }
76
+ },
77
+ {
78
+ "id": "notif-007",
79
+ "type": "system",
80
+ "title": "Actualización del sistema",
81
+ "message": "Se han realizado mejoras de rendimiento en la plataforma",
82
+ "read": true,
83
+ "createdAt": "2025-01-21T12:00:00Z",
84
+ "data": {}
85
+ },
86
+ {
87
+ "id": "notif-008",
88
+ "type": "task_overdue",
89
+ "title": "Tarea vencida",
90
+ "message": "La tarea 'Actualizar documentación' está vencida desde hace 2 días",
91
+ "read": false,
92
+ "createdAt": "2025-01-20T09:00:00Z",
93
+ "data": {
94
+ "taskId": "task-404",
95
+ "taskTitle": "Actualizar documentación",
96
+ "dueDate": "2025-01-18T23:59:59Z"
97
+ }
98
+ }
99
+ ]
100
+ }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Customers API Client
3
+ *
4
+ * Auto-generated entity API using createEntityApi factory.
5
+ */
6
+
7
+ import { createEntityApi } from '@nextsparkjs/mobile'
8
+ import type { Customer, CreateCustomerInput, UpdateCustomerInput } from './types'
9
+
10
+ export const customersApi = createEntityApi<Customer, CreateCustomerInput, UpdateCustomerInput>('customers')
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Internal constants for customers module
3
+ * (Query keys and other internal values)
4
+ */
5
+
6
+ export const CUSTOMERS_QUERY_KEY = ['customers'] as const
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Customer Entity Constants
3
+ */
4
+
5
+ import type { DayOption } from './types'
6
+
7
+ // Day labels for display
8
+ export const DAY_LABELS: Record<DayOption, string> = {
9
+ lun: 'Lunes',
10
+ mar: 'Martes',
11
+ mie: 'Miércoles',
12
+ jue: 'Jueves',
13
+ vie: 'Viernes',
14
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Customers Entity Module
3
+ */
4
+
5
+ export * from './types'
6
+ export * from './api'
7
+ export * from './queries'
8
+ export * from './mutations'
9
+ export * from './constants'
@@ -0,0 +1,58 @@
1
+ /**
2
+ * TanStack Query mutations for Customers
3
+ */
4
+
5
+ import { useMutation, useQueryClient } from '@tanstack/react-query'
6
+ import { customersApi } from './api'
7
+ import { CUSTOMERS_QUERY_KEY } from './constants.internal'
8
+ import type { CreateCustomerInput, UpdateCustomerInput } from './types'
9
+
10
+ /**
11
+ * Hook to create a new customer
12
+ */
13
+ export function useCreateCustomer() {
14
+ const queryClient = useQueryClient()
15
+
16
+ return useMutation({
17
+ mutationFn: (data: CreateCustomerInput) => customersApi.create(data),
18
+ onSuccess: () => {
19
+ // Invalidate customers list to refetch
20
+ queryClient.invalidateQueries({ queryKey: CUSTOMERS_QUERY_KEY })
21
+ },
22
+ })
23
+ }
24
+
25
+ /**
26
+ * Hook to update an existing customer
27
+ */
28
+ export function useUpdateCustomer() {
29
+ const queryClient = useQueryClient()
30
+
31
+ return useMutation({
32
+ mutationFn: ({ id, data }: { id: string; data: UpdateCustomerInput }) =>
33
+ customersApi.update(id, data),
34
+ onSuccess: (response) => {
35
+ // Update the specific customer in cache
36
+ queryClient.setQueryData([...CUSTOMERS_QUERY_KEY, response.data.id], response)
37
+ // Invalidate list to refetch
38
+ queryClient.invalidateQueries({ queryKey: CUSTOMERS_QUERY_KEY })
39
+ },
40
+ })
41
+ }
42
+
43
+ /**
44
+ * Hook to delete a customer
45
+ */
46
+ export function useDeleteCustomer() {
47
+ const queryClient = useQueryClient()
48
+
49
+ return useMutation({
50
+ mutationFn: (id: string) => customersApi.delete(id),
51
+ onSuccess: (_, deletedId) => {
52
+ // Remove from cache
53
+ queryClient.removeQueries({ queryKey: [...CUSTOMERS_QUERY_KEY, deletedId] })
54
+ // Invalidate list to refetch
55
+ queryClient.invalidateQueries({ queryKey: CUSTOMERS_QUERY_KEY })
56
+ },
57
+ })
58
+ }
@@ -0,0 +1,40 @@
1
+ /**
2
+ * TanStack Query hooks for Customers
3
+ */
4
+
5
+ import { useQuery } from '@tanstack/react-query'
6
+ import { customersApi } from './api'
7
+ import { CUSTOMERS_QUERY_KEY } from './constants.internal'
8
+
9
+ export { CUSTOMERS_QUERY_KEY }
10
+
11
+ interface UseCustomersOptions {
12
+ page?: number
13
+ limit?: number
14
+ search?: string
15
+ enabled?: boolean
16
+ }
17
+
18
+ /**
19
+ * Hook to fetch paginated customers list
20
+ */
21
+ export function useCustomers(options: UseCustomersOptions = {}) {
22
+ const { page = 1, limit = 20, search, enabled = true } = options
23
+
24
+ return useQuery({
25
+ queryKey: [...CUSTOMERS_QUERY_KEY, { page, limit, search }],
26
+ queryFn: () => customersApi.list({ page, limit, search }),
27
+ enabled,
28
+ })
29
+ }
30
+
31
+ /**
32
+ * Hook to fetch a single customer by ID
33
+ */
34
+ export function useCustomer(id: string | undefined) {
35
+ return useQuery({
36
+ queryKey: [...CUSTOMERS_QUERY_KEY, id],
37
+ queryFn: () => customersApi.get(id!),
38
+ enabled: !!id,
39
+ })
40
+ }
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Customer Entity Types
3
+ */
4
+
5
+ // Day options for visit/contact days
6
+ export type DayOption = 'lun' | 'mar' | 'mie' | 'jue' | 'vie'
7
+
8
+ // Customer entity
9
+ export interface Customer {
10
+ id: string
11
+ name: string
12
+ account: number
13
+ office: string
14
+ phone?: string | null
15
+ salesRep?: string | null
16
+ visitDays?: DayOption[] | null
17
+ contactDays?: DayOption[] | null
18
+ teamId: string
19
+ createdAt: string
20
+ updatedAt: string
21
+ }
22
+
23
+ // Create customer payload
24
+ export interface CreateCustomerInput {
25
+ name: string
26
+ account: number
27
+ office: string
28
+ phone?: string
29
+ salesRep?: string
30
+ visitDays?: DayOption[]
31
+ contactDays?: DayOption[]
32
+ }
33
+
34
+ // Update customer payload
35
+ export interface UpdateCustomerInput {
36
+ name?: string
37
+ account?: number
38
+ office?: string
39
+ phone?: string | null
40
+ salesRep?: string | null
41
+ visitDays?: DayOption[] | null
42
+ contactDays?: DayOption[] | null
43
+ }
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Entities Module
3
+ *
4
+ * Central export for all entity types and APIs.
5
+ */
6
+
7
+ export * from './tasks'
8
+ export * from './customers'
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Tasks API Client
3
+ *
4
+ * Auto-generated entity API using createEntityApi factory.
5
+ */
6
+
7
+ import { createEntityApi } from '@nextsparkjs/mobile'
8
+ import type { Task, CreateTaskInput, UpdateTaskInput } from './types'
9
+
10
+ export const tasksApi = createEntityApi<Task, CreateTaskInput, UpdateTaskInput>('tasks')
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Internal constants for tasks module
3
+ * (Query keys and other internal values)
4
+ */
5
+
6
+ export const TASKS_QUERY_KEY = ['tasks'] as const
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Task Entity Constants
3
+ */
4
+
5
+ import type { TaskStatus, TaskPriority } from './types'
6
+
7
+ // Status display labels
8
+ export const STATUS_LABELS: Record<TaskStatus, string> = {
9
+ 'todo': 'To Do',
10
+ 'in-progress': 'In Progress',
11
+ 'review': 'In Review',
12
+ 'done': 'Done',
13
+ 'blocked': 'Blocked',
14
+ }
15
+
16
+ // Priority display labels
17
+ export const PRIORITY_LABELS: Record<TaskPriority, string> = {
18
+ low: 'Low',
19
+ medium: 'Medium',
20
+ high: 'High',
21
+ urgent: 'Urgent',
22
+ }
23
+
24
+ // Status colors
25
+ export const STATUS_COLORS: Record<TaskStatus, string> = {
26
+ 'todo': '#6B7280',
27
+ 'in-progress': '#3B82F6',
28
+ 'review': '#F59E0B',
29
+ 'done': '#10B981',
30
+ 'blocked': '#EF4444',
31
+ }
32
+
33
+ // Priority colors
34
+ export const PRIORITY_COLORS: Record<TaskPriority, string> = {
35
+ low: '#6B7280',
36
+ medium: '#3B82F6',
37
+ high: '#F59E0B',
38
+ urgent: '#EF4444',
39
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Tasks Entity Module
3
+ */
4
+
5
+ export * from './types'
6
+ export * from './api'
7
+ export * from './queries'
8
+ export * from './mutations'
9
+ export * from './constants'