# FarmaFinder Mobile - Especificación de Diseño **Fecha**: 2026-07-06 **Estado**: Aprobado **Versión**: 1.0 --- ## 1. Resumen Crear un segundo frontend en **React Native (Expo)** para FarmaFinder, manteniendo el frontend actual (React + Vite) para Desktop/PWA. El objetivo es lograr una experiencia móvil nativa que permita publicar en App Store y Google Play con mejor rendimiento, UX y mantenibilidad. --- ## 2. Arquitectura ### 2.1 Estructura del Proyecto ``` FarmaFinder/ ├── frontend/ ← React + Vite (Desktop/PWA, mantiene Capacitor) ├── frontend-mobile/ ← Expo + React Native (NUEVO) │ ├── app/ ← Expo Router (file-based routing) │ │ ├── _layout.tsx ← Layout raíz │ │ ├── (tabs)/ ← Bottom tabs │ │ │ ├── _layout.tsx ← Tab navigator │ │ │ ├── index.tsx ← Home (búsqueda) │ │ │ ├── map.tsx ← Mapa de farmacias │ │ │ └── profile.tsx ← Perfil de usuario │ │ ├── medicine/[id].tsx ← Detalle de medicamento │ │ ├── pharmacy/[id].tsx ← Detalle de farmacia │ │ └── auth/ ← Auth flow │ ├── components/ ← Componentes React Native │ ├── services/ ← Lógica de negocio y llamadas API │ ├── hooks/ ← Custom hooks │ ├── constants/ ← Colores, tipos, config │ └── assets/ ← Imágenes, fuentes ├── backend/ ← API compartida (sin cambios) └── package.json ← Scripts para ambos frontends ``` ### 2.2 Stack Tecnológico | Componente | Tecnología | Justificación | |------------|------------|---------------| | Framework | Expo SDK 52+ | Setup rápido, OTA updates, fácil publicación | | Routing | Expo Router v4 | File-based routing, similar a Next.js | | Navegación | React Navigation | Bottom tabs + stack navigation | | State | Zustand | Ligero, sin boilerplate, fácil de usar | | HTTP Client | Axios | Interceptors, cancelación de requests | | Cache | TanStack Query | Cache automático, optimistic updates | | Mapas | react-native-maps | Google Maps provider nativo | | Barcode | expo-camera | Escaneo de código de barras nativo | | Storage | AsyncStorage + expo-secure-store | Datos offline + tokens seguros | | Animaciones | React Native Reanimated 3 | Animaciones fluidas en 60fps | --- ## 3. Estructura de Navegación ### 3.1 Navegación Principal ``` Bottom Tabs ├── Home (🔍) → Búsqueda de medicamentos ├── Mapa (📍) → Mapa de farmacias └── Perfil (👤) → Perfil de usuario + Admin ``` ### 3.2 Navegación Detallada ``` Home Tab (Stack) ├── index.tsx ← Lista de resultados de búsqueda └── medicine/[id].tsx ← Detalle de medicamento Mapa Tab (Stack) ├── map.tsx ← Mapa con marcadores de farmacias └── pharmacy/[id].tsx ← Detalle de farmacia Perfil Tab (Stack) ├── profile.tsx ← Info de usuario + opciones ├── auth/login.tsx ← Login (si no autenticado) ├── auth/register.tsx ← Registro └── admin/ ← Panel admin (solo si auth + admin) ``` ### 3.3 Flujos de Navegación - **Auth Flow**: Si no hay token → redirigir a login - **Admin Flow**: Si usuario es admin → mostrar acceso a admin - **Deep Linking**: URLs como `farmafinder://medicine/123` abren pantalla específica --- ## 4. Funcionalidades ### 4.1 MVP (Paridad con Web) | Funcionalidad | Descripción | |---------------|-------------| | **Búsqueda** | Búsqueda en tiempo real de medicamentos vía API CIMA | | **Resultados** | Lista de resultados con nombre, principio activo | | **Detalle medicamento** | Precio, stock, farmacias que lo tienen | | **Mapa farmacias** | Marcadores en mapa con ubicación | | **Detalle farmacia** | Dirección, teléfono, medicamentos disponibles | | **Auth** | Login/registro de usuarios | ### 4.2 Extras Nativos (NUEVO) | Funcionalidad | Descripción | |---------------|-------------| | **Push Notifications** | Alertas de disponibilidad de medicamentos favoritos | | **Escáner código barras** | Escanear medicamentos directamente con cámara | | **Biometría** | Face ID / Touch ID para login rápido | | **Deep Links** | Compartir medicamentos/farmacias via URL | | **Offline Cache** | Medicamentos favoritos accesibles sin conexión | --- ## 5. Integración con la API ### 5.1 Cliente API ```typescript // frontend-mobile/services/api.ts import axios from 'axios'; const API_BASE = __DEV__ ? 'http://localhost:3001/api' : 'https://tu-dominio.com/api'; export const api = axios.create({ baseURL: API_BASE, timeout: 10000, headers: { 'Content-Type': 'application/json' } }); // Request interceptor para auth token api.interceptors.request.use((config) => { const token = getToken(); if (token) config.headers.Authorization = `Bearer ${token}`; return config; }); ``` ### 5.2 Endpoints **Públicos:** - `GET /api/medicines/search?q=` - Búsqueda de medicamentos - `GET /api/medicines/:nregistro` - Detalle de medicamento - `GET /api/medicines/:nregistro/pharmacies` - Farmacias con medicamento - `GET /api/pharmacies` - Todas las farmacias **Autenticados:** - `POST /api/auth/login` - Login - `POST /api/auth/logout` - Logout - `GET /api/auth/check` - Verificar auth **Admin:** - CRUD de farmacias - Búsqueda de medicamentos para admin - Vincular medicamentos a farmacias ### 5.3 Estrategia de Cache ```typescript // Con TanStack Query const { data, isLoading } = useQuery({ queryKey: ['medicines', searchQuery], queryFn: () => searchMedicines(searchQuery), staleTime: 5 * 60 * 1000, // 5 minutos cacheTime: 30 * 60 * 1000, // 30 minutos }); ``` **Persistencia offline:** - AsyncStorage para datos no sensibles - expo-secure-store para tokens y credenciales - React Query persistor para cache de queries --- ## 6. Diseño Visual ### 6.1 Design Tokens ```typescript // frontend-mobile/constants/theme.ts export const colors = { // Primary primary: '#007AFF', primaryLight: '#4DA3FF', // Semantic success: '#34C759', // Disponible danger: '#FF3B30', // Sin stock warning: '#FF9500', // Stock bajo // Neutral background: '#F2F2F7', card: '#FFFFFF', border: '#E5E5EA', // Text text: '#1C1C1E', textSecondary: '#8E8E93', textInverse: '#FFFFFF', }; export const spacing = { xs: 4, sm: 8, md: 16, lg: 24, xl: 32, }; export const borderRadius = { sm: 8, md: 12, lg: 16, }; ``` ### 6.2 Componentes Principales | Componente | Descripción | |------------|-------------| | **SearchBar** | Input con debounce (300ms) + dropdown de resultados | | **MedicineCard** | Card con nombre, principio activo, precio, badge de stock | | **PharmacyMarker** | Marcador personalizado en mapa con info window | | **StockBadge** | Badge verde (disponible) / rojo (sin stock) | | **LoadingSpinner** | Spinner nativo durante cargas | | **ErrorToast** | Toast de error con retry | ### 6.3 Patrones de Diseño - **Cards**: Sombra sutil, border-radius 12px - **Tipografía**: Sistema nativo (SF Pro en iOS, Roboto en Android) - **Espaciado**: Escala de 4px base (4, 8, 12, 16, 24, 32) - **Animaciones**: Reanimated 3 para transiciones y gestos --- ## 7. Extras Nativos (Detalles) ### 7.1 Push Notifications ```typescript // Expo Notifications import * as Notifications from 'expo-notifications'; // Registrar para notificaciones const registerForPushNotifications = async () => { const { status } = await Notifications.requestPermissionsAsync(); if (status !== 'granted') return; const token = await Notifications.getExpoPushToken(); return token.data; }; // Escuchar notificaciones Notifications.addNotificationReceivedListener((notification) => { // Mostrar alerta de disponibilidad }); ``` ### 7.2 Escáner de Código de Barras ```typescript // expo-camera + barcode scanning import { CameraView } from 'expo-camera'; { // Buscar medicamento por código de barras searchMedicineByBarcode(data.data); }} /> ``` ### 7.3 Biometría ```typescript // expo-local-authentication import * as LocalAuthentication from 'expo-local-authentication'; const authenticateWithBiometrics = async () => { const hasHardware = await LocalAuthentication.hasHardwareAsync(); const isEnrolled = await LocalAuthentication.isEnrolledAsync(); if (hasHardware && isEnrolled) { return await LocalAuthentication.authenticateAsync(); } return false; }; ``` --- ## 8. Workflow de Desarrollo ### 8.1 Scripts ```json { "scripts": { "dev:mobile": "cd frontend-mobile && npx expo start", "dev:mobile:android": "cd frontend-mobile && npx expo start --android", "dev:mobile:ios": "cd frontend-mobile && npx expo start --ios", "build:mobile:dev": "cd frontend-mobile && eas build --profile development", "build:mobile:preview": "cd frontend-mobile && eas build --profile preview", "build:mobile:prod": "cd frontend-mobile && eas build --profile production", "submit:android": "cd frontend-mobile && eas submit --platform android", "submit:ios": "cd frontend-mobile && eas submit --platform ios" } } ``` ### 8.2 EAS Build Profiles ```json // frontend-mobile/eas.json { "build": { "development": { "developmentClient": true, "distribution": "internal" }, "preview": { "distribution": "internal" }, "production": {} } } ``` ### 8.3 CI/CD - **Desarrollo**: Expo Go + hot reload - **Testing**: EAS Build (preview) → APK/IPA para testing - **Producción**: EAS Build (production) → Submit a tiendas - **OTA Updates**: Expo Updates para fixes sin pasar por tienda --- ## 9. Dependencias Principales ```json { "dependencies": { "expo": "~52.0.0", "expo-router": "~4.0.0", "expo-camera": "~16.0.0", "expo-notifications": "~0.29.0", "expo-local-authentication": "~15.0.0", "expo-secure-store": "~14.0.0", "react-native": "0.76.0", "react-native-maps": "1.18.0", "react-native-reanimated": "~3.16.0", "react-native-gesture-handler": "~2.20.0", "@react-navigation/native": "^7.0.0", "@react-navigation/bottom-tabs": "^7.0.0", "zustand": "^5.0.0", "axios": "^1.7.0", "@tanstack/react-query": "^5.0.0", "@react-native-async-storage/async-storage": "^2.0.0" } } ``` --- ## 10. Criterios de Aceptación ### MVP - [ ] Búsqueda de medicamentos funcional - [ ] Mapa con farmacias mostrando marcadores - [ ] Detalle de medicamento con precio y stock - [ ] Detalle de farmacia con ubicación - [ ] Login/registro funcional - [ ] Navegación entre pantallas fluida - [ ] Build de desarrollo funcionando en Expo Go ### Extras Nativos - [ ] Push notifications configuradas - [ ] Escáner de código de barras funcional - [ ] Biometría para login rápido - [ ] Deep links configurados - [ ] Offline cache para favoritos ### Publicación - [ ] Build de producción optimizado - [ ] App Store listing configurado - [ ] Google Play listing configurado - [ ] Screenshots y descripción preparados --- ## 11. Riesgos y Mitigaciones | Riesgo | Mitigación | |--------|------------| | API del backend no preparada para móvil | Revisar endpoints, agregar si es necesario | | Performance en dispositivos antiguos | Testing en dispositivos低端, optimizar renders | | Diferencias iOS/Android | Usar componentes nativos, testing en ambas plataformas | | Mantenimiento de dos frontends | Documentar bien, compartir types cuando sea posible | --- ## 12. Próximos Pasos 1. Crear estructura del proyecto Expo 2. Configurar routing con Expo Router 3. Implementar cliente API 4. Crear pantallas MVP 5. Implementar extras nativos 6. Testing y optimización 7. Build y publicación en tiendas