# SIMCO: OPERACIONES MOBILE (React Native/TypeScript) **Versión:** 1.0.0 **Fecha:** 2025-12-08 **Aplica a:** Todo agente que trabaje con código móvil React Native **Prioridad:** OBLIGATORIA para operaciones mobile --- ## RESUMEN EJECUTIVO > **Types alineados + Store configurado + Componentes optimizados + Navegación funcional = Mobile completo.** --- ## PRINCIPIO FUNDAMENTAL ``` ╔══════════════════════════════════════════════════════════════════════╗ ║ MOBILE-FIRST PERFORMANCE ║ ║ ║ ║ • Componentes optimizados (memoización) ║ ║ • Listas virtualizadas (FlatList) ║ ║ • Imágenes optimizadas ║ ║ • Offline-first cuando aplique ║ ║ • Navegación fluida (<16ms por frame) ║ ╚══════════════════════════════════════════════════════════════════════╝ ``` --- ## ESTRUCTURA DE PROYECTO ``` mobile/ ├── src/ │ ├── app/ # Entry point y configuración │ │ ├── App.tsx # Root component │ │ ├── providers/ │ │ │ ├── index.tsx # Provider composer │ │ │ ├── QueryProvider.tsx # TanStack Query │ │ │ └── ThemeProvider.tsx │ │ └── linking.ts # Deep linking config │ ├── screens/ # Pantallas │ │ ├── auth/ │ │ │ ├── LoginScreen.tsx │ │ │ └── RegisterScreen.tsx │ │ ├── home/ │ │ │ └── HomeScreen.tsx │ │ └── {module}/ │ │ ├── {Module}Screen.tsx │ │ └── {Module}DetailScreen.tsx │ ├── components/ # Componentes │ │ ├── common/ # Compartidos │ │ │ ├── Button.tsx │ │ │ ├── Input.tsx │ │ │ ├── Card.tsx │ │ │ └── Loading.tsx │ │ ├── forms/ │ │ │ └── FormField.tsx │ │ └── {module}/ │ │ └── {Component}.tsx │ ├── navigation/ # Navegación │ │ ├── RootNavigator.tsx # Navigator principal │ │ ├── AuthNavigator.tsx │ │ ├── MainNavigator.tsx │ │ └── types.ts # Navigation types │ ├── hooks/ # Hooks personalizados │ │ ├── useAuth.ts │ │ ├── useApi.ts │ │ └── use{Module}.ts │ ├── services/ # API services │ │ ├── api.ts # Axios instance │ │ ├── auth.service.ts │ │ └── {module}.service.ts │ ├── stores/ # State management │ │ ├── auth.store.ts │ │ └── {module}.store.ts │ ├── types/ # TypeScript types │ │ ├── index.ts │ │ ├── api.types.ts │ │ └── {module}.types.ts │ ├── utils/ # Utilidades │ │ ├── storage.ts # AsyncStorage helpers │ │ ├── validation.ts │ │ └── formatting.ts │ ├── constants/ # Constantes │ │ ├── colors.ts │ │ ├── spacing.ts │ │ └── config.ts │ └── theme/ # Tema global │ ├── index.ts │ ├── colors.ts │ └── typography.ts ├── android/ # Proyecto Android nativo ├── ios/ # Proyecto iOS nativo ├── __tests__/ ├── app.json ├── metro.config.js ├── babel.config.js ├── tsconfig.json └── package.json ``` --- ## CONVENCIONES DE NOMENCLATURA ### Archivos ```typescript // Screens: PascalCase + Screen suffix HomeScreen.tsx ProductDetailScreen.tsx UserProfileScreen.tsx // Components: PascalCase Button.tsx ProductCard.tsx UserAvatar.tsx // Hooks: camelCase con prefijo use useAuth.ts useProducts.ts useNavigation.ts // Services: camelCase + .service suffix auth.service.ts products.service.ts // Stores: camelCase + .store suffix auth.store.ts cart.store.ts // Types: camelCase + .types suffix user.types.ts product.types.ts ``` ### Clases y Tipos ```typescript // Interfaces: PascalCase con prefijo I (opcional) interface User {} interface IAuthState {} // Types: PascalCase type NavigationProps = {} type ThemeColors = {} // Enums: PascalCase enum OrderStatus { PENDING = 'pending', COMPLETED = 'completed', } ``` ### Funciones y Variables ```typescript // Componentes: PascalCase const ProductCard: React.FC = () => {} // Funciones: camelCase con verbo const fetchProducts = async () => {} const handleSubmit = () => {} const formatPrice = (price: number) => {} // Variables: camelCase const isLoading = true const productList = [] const currentUser = null // Constantes: UPPER_SNAKE_CASE const API_URL = '' const MAX_ITEMS = 50 ``` --- ## TEMPLATES ### Screen Component ```typescript // screens/{module}/{Module}Screen.tsx import React, { useCallback, useMemo } from 'react'; import { View, StyleSheet, FlatList, RefreshControl } from 'react-native'; import { SafeAreaView } from 'react-native-safe-area-context'; import { NativeStackScreenProps } from '@react-navigation/native-stack'; import { RootStackParamList } from '@/navigation/types'; import { useProducts } from '@/hooks/useProducts'; import { ProductCard, Loading, EmptyState } from '@/components'; import { Product } from '@/types'; type Props = NativeStackScreenProps; /** * ProductsScreen - Lista de productos * * Muestra productos con pull-to-refresh y navegación a detalle. */ export const ProductsScreen: React.FC = ({ navigation }) => { const { products, isLoading, isRefreshing, refresh } = useProducts(); const handleProductPress = useCallback((product: Product) => { navigation.navigate('ProductDetail', { productId: product.id }); }, [navigation]); const renderItem = useCallback(({ item }: { item: Product }) => ( handleProductPress(item)} /> ), [handleProductPress]); const keyExtractor = useCallback((item: Product) => item.id, []); const ListEmptyComponent = useMemo(() => ( ), []); if (isLoading && !products.length) { return ; } return ( } // Optimizaciones de rendimiento removeClippedSubviews maxToRenderPerBatch={10} windowSize={5} initialNumToRender={10} getItemLayout={(_, index) => ({ length: ITEM_HEIGHT, offset: ITEM_HEIGHT * index, index, })} /> ); }; const ITEM_HEIGHT = 120; const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#fff', }, list: { padding: 16, gap: 12, }, }); ``` ### Component (Reusable) ```typescript // components/common/Button.tsx import React, { memo } from 'react'; import { TouchableOpacity, Text, StyleSheet, ActivityIndicator, ViewStyle, TextStyle, } from 'react-native'; import { colors, spacing } from '@/theme'; interface ButtonProps { title: string; onPress: () => void; variant?: 'primary' | 'secondary' | 'outline'; size?: 'small' | 'medium' | 'large'; disabled?: boolean; loading?: boolean; style?: ViewStyle; textStyle?: TextStyle; } /** * Button - Botón reutilizable * * @example *