# 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=<query>` - 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';

<CameraView
  onBarcodeScanned={(data) => {
    // 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
