# 🛠️ TRD - RUTAS DE SOLIDARIDAD
## Technical Requirements Document - Blueprint Técnico

**Versión:** 1.0
**Fecha:** 26/06/2024
**Autor:** Equipo Técnico - Rutas de Solidaridad
**Estado:** Aprobado para Desarrollo

---

## 📋 ÍNDICE

1. [Visión Técnica General](#visión-técnica-general)
2. [Stack Tecnológico](#stack-tecnológico)
3. [Arquitectura de la Aplicación](#arquitectura-de-la-aplicación)
4. [Frontend - Especificaciones Técnicas](#frontend---especificaciones-técnicas)
5. [Backend - Especificaciones Técnicas](#backend---especificaciones-técnicas)
6. [Base de Datos - Diseño Detallado](#base-de-datos---diseño-detallado)
7. [API - Diseño y Endpoints](#api---diseño-y-endpoints)
8. [PWA - Configuración y Estrategia](#pwa---configuración-y-estrategia)
9. [Seguridad - Implementación](#seguridad---implementación)
10. [Despliegue - Estrategia](#despliegue---estrategia)
11. [Rendimiento - Optimizaciones](#rendimiento---optimizaciones)
12. [Testing - Estrategia](#testing---estrategia)
13. [Monitoreo - Herramientas](#monitoreo---herramientas)
14. [Documentación - Plan](#documentación---plan)
15. [Roadmap Técnico](#roadmap-técnico)

---

## 1. VISIÓN TÉCNICA GENERAL

### 1.1 Objetivo Técnico
Construir una Progressive Web App (PWA) robusta, escalable y offline-first para la gestión de ayuda humanitaria en situaciones de emergencia.

### 1.2 Principios Técnicos
- **Offline First**: Funcionalidad sin conexión a internet
- **Real Time**: Actualizaciones en tiempo real de inventario
- **Mobile First**: Diseño prioritario para dispositivos móviles
- **Seguridad**: Protección de datos sensibles con RLS
- **Escalabilidad**: Preparado para crecer a más zonas
- **Simplicidad**: Código limpio y mantenible

### 1.3 Restricciones Técnicas
- Hosting: cPanel con recursos limitados
- Equipo: Voluntarios sin experiencia técnica
- Tiempo: Implementación urgente (días, no meses)
- Presupuesto: Cero ($0) - Todo debe ser gratuito o open source

---

## 2. STACK TECNOLÓGICO

### 2.1 Frontend

| Tecnología | Versión | Propósito | Razón |
|------------|---------|-----------|-------|
| **React** | 18.3.1 | Framework principal | Componentes reutilizables, gran comunidad |
| **Vite** | 5.0.0 | Build tool | Más rápido que Webpack, HMR instantáneo |
| **Tailwind CSS** | 3.4.0 | Estilos | Rápido de implementar, sin archivos CSS grandes |
| **React Router** | 6.23.0 | Routing | Navegación SPA, rutas dinámicas |
| **Leaflet** | 1.9.4 | Mapas interactivos | Gratuito, ligero, sin límites de uso |
| **React Leaflet** | 4.2.1 | Wrapper de Leaflet | Integración nativa con React |
| **Radix UI** | 1.0.0 | Componentes accesibles | Componentes base sin estilos, accesibles |
| **Lucide React** | 0.400.0 | Iconos | Íconos consistentes y ligeros |
| **React Hook Form** | 7.51.0 | Formularios | Validación eficiente, rendimiento |
| **Zod** | 3.23.0 | Validación | TypeScript-first, validación en runtime |
| **React Query** | 5.40.0 | Estado y caché | Manejo de datos, caché inteligente |
| **Date-fns** | 3.6.0 | Manejo de fechas | Ligero, funciones puras |
| **UUID** | 9.0.0 | Generación de IDs | IDs únicos para registros offline |

**Dependencias de Desarrollo:**
- ESLint: Linting de código
- Prettier: Formateo automático
- Husky: Git hooks
- Jest + React Testing Library: Testing

---

### 2.2 Backend (BaaS - Backend as a Service)

| Tecnología | Propósito | Razón |
|------------|-----------|-------|
| **Supabase** | Backend completo | Postgres + Auth + Storage + Realtime |
| **PostgreSQL** | Base de datos | Relacional, confiable, soporte GIS |
| **Supabase Auth** | Autenticación | Múltiples métodos, RLS integrado |
| **Supabase Realtime** | Datos en tiempo real | WebSockets para inventario y alertas |
| **Supabase Storage** | Almacenamiento de archivos | Fotos de afectados y entregas |
| **Row Level Security** | Seguridad | Control de acceso a nivel de fila |

---

### 2.3 APIs y Servicios Externos

| Servicio | Propósito | Costo | Límites |
|----------|-----------|-------|---------|
| **Leaflet + OpenStreetMap** | Mapas | Gratuito | Sin límites |
| **Nominatim** | Geocodificación | Gratuito | 1 request/segundo |
| **Geolocation API** | Ubicación automática | Gratuito | Navegador |
| **Service Workers** | PWA y offline | Gratuito | Navegador |
| **Cache API** | Almacenamiento offline | Gratuito | Navegador |

**Nota:** Google Maps es una alternativa, pero Leaflet es preferible por ser gratuito y sin límites.

---

## 3. ARQUITECTURA DE LA APLICACIÓN

### 3.1 Diagrama de Arquitectura
```
┌─────────────────────────────────────────────────────────────┐
│                    CLIENTE (PWA)                            │
│  ┌────────────────────────────────────────────────────────┐ │
│  │                   React SPA - Vite Build               │ │
│  │  ┌──────────┐  ┌──────────┐  ┌──────────┐  ┌──────┐  │ │
│  │  │Dashboard │  │Inventario│  │  Mapa    │  │Report│  │ │
│  │  └──────────┘  └──────────┘  └──────────┘  └──────┘  │ │
│  │  ┌──────────┐  ┌──────────┐  ┌──────────┐  ┌──────┐  │ │
│  │  │Afectados │  │Donaciones│  │Voluntarios│  │ Ayuda│  │ │
│  │  └──────────┘  └──────────┘  └──────────┘  └──────┘  │ │
│  └────────────────────────────────────────────────────────┘ │
│                            │                                 │
│                            ▼                                 │
│  ┌────────────────────────────────────────────────────────┐ │
│  │              React Query (Caché y Estado)              │ │
│  │  - Datos en caché  - Sincronización offline            │ │
│  │  - Mutaciones optimistas                               │ │
│  └────────────────────────────────────────────────────────┘ │
│                            │                                 │
│                            ▼                                 │
│  ┌────────────────────────────────────────────────────────┐ │
│  │                  Supabase Client (API)                  │ │
│  │  - RESTful API   - Realtime Subscriptions               │ │
│  │  - Storage (Fotos)                                     │ │
│  └────────────────────────────────────────────────────────┘ │
└──────────────────────────┼──────────────────────────────────┘
                           │
                           ▼
┌─────────────────────────────────────────────────────────────┐
│                      SUPABASE (Backend)                     │
│  ┌────────────────────────────────────────────────────────┐ │
│  │              PostgreSQL Database                       │ │
│  │  - Tablas: afectados, voluntarios, inventario, etc.    │ │
│  │  - RLS (Row Level Security)                            │ │
│  │  - Funciones y Triggers                                │ │
│  └────────────────────────────────────────────────────────┘ │
│  ┌────────────────────────────────────────────────────────┐ │
│  │                  Supabase Auth                         │ │
│  │  - Email/Password   - JWT Tokens                       │ │
│  └────────────────────────────────────────────────────────┘ │
│  ┌────────────────────────────────────────────────────────┐ │
│  │                Supabase Storage                        │ │
│  │  - Buckets: fotos_afectados, fotos_entregas            │ │
│  └────────────────────────────────────────────────────────┘ │
│  ┌────────────────────────────────────────────────────────┐ │
│  │               Supabase Realtime                        │ │
│  │  - WebSockets para actualizaciones                     │ │
│  │  - Broadcast para notificaciones                      │ │
│  └────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
```

### 3.2 Patrón de Diseño

**Tipos de Componentes:**
- **Presentacionales**: Solo UI, reciben datos por props
- **Contenedores**: Lógica de negocio, conectan con Supabase
- **Hooks Custom**: Lógica reutilizable
- **Context**: Estado global (usuario autenticado, tema)

**Estructura de Carpetas:**
```
src/
├── components/
│   ├── ui/           # Componentes UI reutilizables
│   ├── layout/       # Layouts (Navbar, Sidebar, Footer)
│   ├── dashboard/    # Dashboard y widgets
│   ├── inventario/   # Gestión de inventario
│   ├── afectados/    # Registro y gestión de afectados
│   ├── donaciones/   # Gestión de donaciones
│   ├── voluntarios/  # Gestión de voluntarios
│   ├── asignaciones/ # Asignación de ayudas
│   └── mapas/        # Componentes de mapas
├── lib/
│   ├── supabase.js   # Cliente Supabase
│   ├── queries.js    # Consultas a Supabase
│   ├── mutations.js  # Mutaciones a Supabase
│   └── helpers.js    # Funciones auxiliares
├── hooks/
│   ├── useAuth.js
│   ├── useInventario.js
│   └── useGeolocation.js
├── pages/
│   ├── Dashboard.jsx
│   ├── Afectados.jsx
│   ├── Inventario.jsx
│   ├── Donaciones.jsx
│   ├── Voluntarios.jsx
│   ├── Asignaciones.jsx
│   ├── Mapa.jsx
│   ├── Perfil.jsx
│   └── Login.jsx
├── context/
│   └── AuthContext.jsx
├── utils/
│   ├── validations.js  # Validaciones Zod
│   ├── formats.js      # Formateo de datos
│   └── constants.js    # Constantes
├── styles/
│   └── index.css       # Tailwind + custom
└── App.jsx
```

---

## 4. FRONTEND - ESPECIFICACIONES TÉCNICAS

### 4.1 Configuración de Vite

```javascript
// vite.config.js
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

export default defineConfig({
  plugins: [react()],
  build: {
    outDir: 'dist',
    sourcemap: true,
    rollupOptions: {
      output: {
        manualChunks: {
          vendor: ['react', 'react-dom', 'react-router-dom'],
          supabase: ['@supabase/supabase-js'],
          maps: ['leaflet', 'react-leaflet']
        }
      }
    }
  },
  server: {
    port: 5173,
    host: true
  }
})
```

### 4.2 Configuración de Tailwind

```javascript
// tailwind.config.js
export default {
  content: ['./index.html', './src/**/*.{js,ts,jsx,tsx}'],
  theme: {
    extend: {
      colors: {
        primary: {
          DEFAULT: '#EF4444',
          light: '#FCA5A5',
          dark: '#B91C1C'
        },
        success: '#10B981',
        warning: '#F59E0B',
        danger: '#EF4444'
      },
      fontFamily: {
        sans: ['Inter', 'sans-serif']
      }
    }
  },
  plugins: []
}
```

### 4.3 Cliente Supabase

```javascript
// lib/supabase.js
import { createClient } from '@supabase/supabase-js'

const supabaseUrl = import.meta.env.VITE_SUPABASE_URL
const supabaseAnonKey = import.meta.env.VITE_SUPABASE_PUBLISHABLE_KEY

export const supabase = createClient(supabaseUrl, supabaseAnonKey, {
  auth: {
    persistSession: true,
    autoRefreshToken: true
  },
  realtime: {
    params: {
      eventsPerSecond: 10
    }
  }
})

export const getCurrentUser = async () => {
  const { data: { user } } = await supabase.auth.getUser()
  return user
}

export const isVoluntario = async () => {
  const user = await getCurrentUser()
  if (!user) return false
  const { data } = await supabase
    .from('voluntarios')
    .select('activo')
    .eq('email', user.email)
    .single()
  return data?.activo || false
}
```

---

## 5. BACKEND - ESPECIFICACIONES TÉCNICAS

### 5.1 Configuración de Supabase
- **Proyecto:** voluntariado@foresve.com's Project
- **URL:** https://nvxgygnrgjnddrtboskr.supabase.co
- **Región:** Americas (us-east-1)

### 5.2 Autenticación

**Configuración:**
- Proveedores: Email/Password
- Confirmación de email: Desactivada (para rapidez en emergencia)
- Duración de sesión: 7 días
- Refresh tokens: Activado

**Roles:**
| Rol | Acceso |
|-----|--------|
| admin | Acceso total |
| voluntario | Acceso a datos operativos |
| public | Solo registro de afectados |

### 5.3 Row Level Security (RLS)

**Políticas Principales:**
```sql
-- Voluntarios pueden ver todos los afectados
CREATE POLICY "Voluntarios ver afectados" ON afectados
  FOR SELECT USING (auth.role() IN ('admin', 'voluntario'));

-- Cualquiera puede registrar afectados
CREATE POLICY "Publico registrar afectados" ON afectados
  FOR INSERT WITH CHECK (true);

-- Solo admins pueden modificar voluntarios
CREATE POLICY "Admins gestionar voluntarios" ON voluntarios
  FOR ALL USING (auth.role() = 'admin');

-- Voluntarios pueden modificar inventario
CREATE POLICY "Voluntarios gestionar inventario" ON inventario_ubicacion
  FOR ALL USING (auth.role() IN ('admin', 'voluntario'));
```

---

## 6. BASE DE DATOS - DISEÑO DETALLADO

### 6.1 Esquema Completo

```sql
-- Tabla: ubicaciones (Centros de Acopio)
CREATE TABLE ubicaciones (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  nombre VARCHAR(100) NOT NULL,
  direccion TEXT,
  latitud DECIMAL(10,8),
  longitud DECIMAL(11,8),
  tipo VARCHAR(20) DEFAULT 'centro_acopio',
  activo BOOLEAN DEFAULT true,
  created_at TIMESTAMP DEFAULT NOW()
);

-- Tabla: categorias_productos
CREATE TABLE categorias_productos (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  nombre VARCHAR(50) UNIQUE NOT NULL,
  descripcion TEXT,
  unidad_medida VARCHAR(20) NOT NULL,
  icono VARCHAR(50),
  created_at TIMESTAMP DEFAULT NOW()
);

-- Tabla: productos
CREATE TABLE productos (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  nombre VARCHAR(100) NOT NULL,
  categoria_id UUID REFERENCES categorias_productos(id),
  unidad_medida VARCHAR(20) NOT NULL,
  stock_minimo INTEGER DEFAULT 20,
  stock_critico INTEGER DEFAULT 10,
  descripcion TEXT,
  activo BOOLEAN DEFAULT true,
  created_at TIMESTAMP DEFAULT NOW()
);

-- Tabla: voluntarios
CREATE TABLE voluntarios (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  auth_id UUID REFERENCES auth.users(id),
  nombre VARCHAR(100) NOT NULL,
  email VARCHAR(100) UNIQUE NOT NULL,
  telefono VARCHAR(20),
  cedula VARCHAR(20) UNIQUE,
  zona_operativa VARCHAR(100),
  disponibilidad TEXT,
  vehiculo BOOLEAN DEFAULT false,
  activo BOOLEAN DEFAULT true,
  created_at TIMESTAMP DEFAULT NOW(),
  ultimo_acceso TIMESTAMP
);

-- Tabla: afectados
CREATE TABLE afectados (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  cedula VARCHAR(20) UNIQUE NOT NULL,
  nombre VARCHAR(100) NOT NULL,
  telefono VARCHAR(20),
  direccion TEXT,
  latitud DECIMAL(10,8),
  longitud DECIMAL(11,8),
  adultos INTEGER DEFAULT 0,
  ninos INTEGER DEFAULT 0,
  mayores INTEGER DEFAULT 0,
  prioridad VARCHAR(10) DEFAULT 'media',
  necesidades TEXT[],
  estado VARCHAR(20) DEFAULT 'activo',
  fecha_registro TIMESTAMP DEFAULT NOW(),
  ultimo_seguimiento TIMESTAMP,
  voluntario_asignado_id UUID REFERENCES voluntarios(id)
);

-- Tabla: donaciones
CREATE TABLE donaciones (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  tipo VARCHAR(20) NOT NULL,
  donante_nombre VARCHAR(100),
  donante_email VARCHAR(100),
  donante_telefono VARCHAR(20),
  descripcion TEXT,
  cantidad DECIMAL(10,2),
  unidad VARCHAR(20),
  ubicacion VARCHAR(100),
  latitud DECIMAL(10,8),
  longitud DECIMAL(11,8),
  estado VARCHAR(20) DEFAULT 'pendiente',
  foto_url TEXT,
  fecha_registro TIMESTAMP DEFAULT NOW(),
  voluntario_registro_id UUID REFERENCES voluntarios(id)
);

-- Tabla: inventario_ubicacion
CREATE TABLE inventario_ubicacion (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  producto_id UUID REFERENCES productos(id) ON DELETE CASCADE,
  ubicacion_id UUID REFERENCES ubicaciones(id) ON DELETE CASCADE,
  cantidad INTEGER DEFAULT 0,
  lote VARCHAR(50),
  fecha_vencimiento DATE,
  ultima_actualizacion TIMESTAMP DEFAULT NOW(),
  UNIQUE(producto_id, ubicacion_id, lote)
);

-- Tabla: movimientos_inventario
CREATE TABLE movimientos_inventario (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  producto_id UUID REFERENCES productos(id),
  ubicacion_origen_id UUID REFERENCES ubicaciones(id),
  ubicacion_destino_id UUID REFERENCES ubicaciones(id),
  tipo_movimiento VARCHAR(20) NOT NULL,
  cantidad INTEGER NOT NULL,
  fecha_movimiento TIMESTAMP DEFAULT NOW(),
  voluntario_id UUID REFERENCES voluntarios(id),
  donacion_id UUID REFERENCES donaciones(id),
  afectado_id UUID REFERENCES afectados(id),
  observaciones TEXT
);

-- Tabla: asignaciones
CREATE TABLE asignaciones (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  afectado_id UUID REFERENCES afectados(id) ON DELETE CASCADE,
  movimiento_id UUID REFERENCES movimientos_inventario(id),
  voluntario_id UUID REFERENCES voluntarios(id),
  fecha_asignacion TIMESTAMP DEFAULT NOW(),
  fecha_entrega TIMESTAMP,
  estado VARCHAR(20) DEFAULT 'asignado',
  observaciones TEXT,
  foto_entrega TEXT
);

-- Tabla: alertas_inventario
CREATE TABLE alertas_inventario (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  producto_id UUID REFERENCES productos(id),
  ubicacion_id UUID REFERENCES ubicaciones(id),
  tipo_alerta VARCHAR(20) NOT NULL,
  mensaje TEXT NOT NULL,
  fecha_alerta TIMESTAMP DEFAULT NOW(),
  resuelta BOOLEAN DEFAULT false,
  resuelta_por UUID REFERENCES voluntarios(id)
);

-- Tabla: seguimiento_afectados
CREATE TABLE seguimiento_afectados (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  afectado_id UUID REFERENCES afectados(id) ON DELETE CASCADE,
  fecha TIMESTAMP DEFAULT NOW(),
  tipo VARCHAR(20),
  descripcion TEXT,
  voluntario_id UUID REFERENCES voluntarios(id),
  proximo_seguimiento TIMESTAMP
);

-- Índices para rendimiento
CREATE INDEX idx_afectados_prioridad ON afectados(prioridad);
CREATE INDEX idx_afectados_estado ON afectados(estado);
CREATE INDEX idx_inventario_ubicacion ON inventario_ubicacion(producto_id, ubicacion_id);
CREATE INDEX idx_movimientos_fecha ON movimientos_inventario(fecha_movimiento);
```

### 6.2 Funciones y Triggers

```sql
-- Función: Actualizar inventario automáticamente
CREATE OR REPLACE FUNCTION actualizar_inventario()
RETURNS TRIGGER AS $$
BEGIN
  IF NEW.tipo_movimiento = 'ingreso' THEN
    INSERT INTO inventario_ubicacion (producto_id, ubicacion_id, cantidad)
    VALUES (NEW.producto_id, NEW.ubicacion_destino_id, NEW.cantidad)
    ON CONFLICT (producto_id, ubicacion_id) 
    DO UPDATE SET cantidad = inventario_ubicacion.cantidad + EXCLUDED.cantidad;
  ELSIF NEW.tipo_movimiento = 'salida' THEN
    UPDATE inventario_ubicacion
    SET cantidad = cantidad - NEW.cantidad
    WHERE producto_id = NEW.producto_id 
    AND ubicacion_id = NEW.ubicacion_origen_id;
  END IF;
  RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER trigger_actualizar_inventario
AFTER INSERT ON movimientos_inventario
FOR EACH ROW EXECUTE FUNCTION actualizar_inventario();

-- Función: Verificar alertas de stock
CREATE OR REPLACE FUNCTION verificar_alertas()
RETURNS TRIGGER AS $$
DECLARE
  v_minimo INTEGER;
  v_critico INTEGER;
BEGIN
  SELECT stock_minimo, stock_critico INTO v_minimo, v_critico
  FROM productos WHERE id = NEW.producto_id;
  
  IF NEW.cantidad <= v_critico THEN
    INSERT INTO alertas_inventario (producto_id, ubicacion_id, tipo_alerta, mensaje)
    VALUES (NEW.producto_id, NEW.ubicacion_id, 'stock_critico',
      'Stock crítico: ' || (SELECT nombre FROM productos WHERE id = NEW.producto_id));
  ELSIF NEW.cantidad <= v_minimo THEN
    INSERT INTO alertas_inventario (producto_id, ubicacion_id, tipo_alerta, mensaje)
    VALUES (NEW.producto_id, NEW.ubicacion_id, 'stock_bajo',
      'Stock bajo: ' || (SELECT nombre FROM productos WHERE id = NEW.producto_id));
  END IF;
  RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER trigger_verificar_alertas
AFTER UPDATE ON inventario_ubicacion
FOR EACH ROW
WHEN (OLD.cantidad IS DISTINCT FROM NEW.cantidad)
EXECUTE FUNCTION verificar_alertas();
```

### 6.3 Datos Iniciales (Seed)

```sql
-- Insertar categorías
INSERT INTO categorias_productos (nombre, descripcion, unidad_medida, icono) VALUES
('Alimentos', 'Alimentos no perecederos', 'kg', '🥫'),
('Agua', 'Agua potable', 'litros', '💧'),
('Medicinas', 'Medicamentos', 'unidades', '💊'),
('Ropa', 'Ropa y calzado', 'prendas', '👕'),
('Higiene', 'Higiene personal', 'unidades', '🧴'),
('Bebés', 'Productos infantiles', 'unidades', '🍼');

-- Insertar ubicaciones
INSERT INTO ubicaciones (nombre, direccion, tipo) VALUES
('Catia La Mar', 'Catia La Mar, La Guaira', 'centro_acopio'),
('Caraballeda', 'Caraballeda, La Guaira', 'centro_acopio'),
('Maiquetía', 'Maiquetía, La Guaira', 'centro_acopio');
```

---

## 7. API - DISEÑO Y ENDPOINTS

### 7.1 Convenciones
- **Base URL:** `https://nvxgygnrgjnddrtboskr.supabase.co/rest/v1`
- **Headers:**
```json
{
  "apikey": "sb_publishable_...",
  "Authorization": "Bearer {JWT}",
  "Content-Type": "application/json"
}
```

### 7.2 Endpoints Principales

| Método | Endpoint | Propósito |
|--------|----------|-----------|
| GET | /afectados | Listar afectados |
| POST | /afectados | Registrar afectado |
| GET | /afectados?id=eq.{id} | Ver afectado específico |
| PATCH | /afectados?id=eq.{id} | Actualizar afectado |
| GET | /inventario_ubicacion | Ver inventario |
| POST | /movimientos_inventario | Registrar movimiento |
| GET | /voluntarios | Listar voluntarios |
| POST | /donaciones | Registrar donación |
| GET | /asignaciones | Ver asignaciones |
| POST | /asignaciones | Crear asignación |

### 7.3 Ejemplos de API Calls

```javascript
// Registrar afectado
const registrarAfectado = async (data) => {
  const { data: result, error } = await supabase
    .from('afectados')
    .insert([{
      cedula: data.cedula,
      nombre: data.nombre,
      telefono: data.telefono,
      latitud: data.latitud,
      longitud: data.longitud,
      adultos: data.adultos,
      ninos: data.ninos,
      necesidades: data.necesidades
    }])
    .select()
  return { result, error }
}

// Registrar movimiento de inventario
const registrarMovimiento = async (movimiento) => {
  const { data, error } = await supabase
    .from('movimientos_inventario')
    .insert([movimiento])
    .select()
  return { data, error }
}

// Obtener inventario en tiempo real
const subscribeInventario = (callback) => {
  return supabase
    .channel('inventario')
    .on('postgres_changes', 
      { event: '*', schema: 'public', table: 'inventario_ubicacion' },
      callback
    )
    .subscribe()
}
```

---

## 8. PWA - CONFIGURACIÓN Y ESTRATEGIA

### 8.1 Configuración de PWA

**manifest.json:**
```json
{
  "name": "Rutas de Solidaridad",
  "short_name": "RutasSolidaridad",
  "description": "Sistema de ayuda humanitaria para La Guaira",
  "start_url": "/",
  "display": "standalone",
  "background_color": "#FFFFFF",
  "theme_color": "#EF4444",
  "orientation": "portrait",
  "icons": [
    { "src": "/icon-192.png", "sizes": "192x192", "type": "image/png" },
    { "src": "/icon-512.png", "sizes": "512x512", "type": "image/png" }
  ]
}
```

**service-worker.js:**
```javascript
const CACHE_NAME = 'rutas-solidaridad-v1'
const urlsToCache = ['/', '/index.html', '/manifest.json']

self.addEventListener('install', (event) => {
  event.waitUntil(
    caches.open(CACHE_NAME)
      .then(cache => cache.addAll(urlsToCache))
  )
})

self.addEventListener('fetch', (event) => {
  event.respondWith(
    caches.match(event.request)
      .then(response => response || fetch(event.request))
  )
})
```

### 8.2 Estrategia Offline

**Cache Strategy:**
- HTML/JS/CSS: Cache First
- API Data: Stale While Revalidate
- Images: Cache First
- Dynamic: Network First con fallback a cache

**Sincronización Offline:**
```javascript
const pendingOperations = []

const syncOffline = async () => {
  if (navigator.onLine) {
    for (const op of pendingOperations) {
      await supabase.from(op.table).insert(op.data)
    }
    pendingOperations = []
    localStorage.setItem('pendingOps', JSON.stringify(pendingOperations))
  }
}

const registerOffline = (table, data) => {
  if (!navigator.onLine) {
    pendingOperations.push({ table, data })
    localStorage.setItem('pendingOps', JSON.stringify(pendingOperations))
  }
}
```

---

## 9. SEGURIDAD - IMPLEMENTACIÓN

### 9.1 Estrategia de Seguridad
- **Autenticación:** Supabase Auth con JWT
- **Autorización:** RLS (Row Level Security)
- **Validación:** Zod en frontend y backend
- **Sanitización:** Escape de datos
- **HTTPS:** Forzado en producción
- **CORS:** Configurado en Supabase

### 9.2 Políticas de RLS Detalladas

```sql
CREATE POLICY "Publico puede registrar" ON afectados
  FOR INSERT WITH CHECK (true);

CREATE POLICY "Voluntarios pueden ver" ON afectados
  FOR SELECT USING (auth.role() IN ('authenticated', 'voluntario', 'admin'));

CREATE POLICY "Voluntarios gestionan inventario" ON inventario_ubicacion
  FOR ALL USING (auth.role() IN ('voluntario', 'admin'));

CREATE POLICY "Voluntarios ven sus datos" ON voluntarios
  FOR SELECT USING (auth.uid() = auth_id);
```

### 9.3 Validaciones con Zod

```javascript
import { z } from 'zod'

const afectadoSchema = z.object({
  cedula: z.string().min(6, 'Cédula inválida'),
  nombre: z.string().min(2, 'Nombre requerido'),
  telefono: z.string().optional(),
  adultos: z.number().min(0).default(0),
  ninos: z.number().min(0).default(0),
  necesidades: z.array(z.string()).default([])
})

const validarAfectado = (data) => {
  try {
    return afectadoSchema.parse(data)
  } catch (error) {
    return { error: error.errors }
  }
}
```

---

## 10. DESPLIEGUE - ESTRATEGIA

### 10.1 Entornos

| Entorno | URL | Propósito |
|---------|-----|-----------|
| Desarrollo | localhost:5173 | Desarrollo local |
| Staging | voluntariado.foresve.com/staging | Pruebas |
| Producción | voluntariado.foresve.com | Producción |

### 10.2 Proceso de Despliegue

```bash
# 1. Build
npm run build

# 2. Verificar build
npm run preview

# 3. Subir por FTP (usar FTP-Simple para subir carpeta dist/)

# 4. Verificar
# Abrir https://voluntariado.foresve.com
```

### 10.3 Configuración de cPanel

**Variables de Entorno:**
```
VITE_SUPABASE_URL = https://nvxgygnrgjnddrtboskr.supabase.co
VITE_SUPABASE_PUBLISHABLE_KEY = sb_publishable_key
```

**Directivas .htaccess:**
```apache
<IfModule mod_rewrite.c>
  RewriteEngine On
  RewriteBase /
  RewriteRule ^index\.html$ - [L]
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteRule . /index.html [L]
</IfModule>

<FilesMatch "\.(js|css|png|jpg|jpeg|gif|svg|ico)$">
  Header set Cache-Control "max-age=31536000, public"
</FilesMatch>
```

---

## 11. RENDIMIENTO - OPTIMIZACIONES

### 11.1 Estrategias de Optimización

| Área | Técnica | Impacto |
|------|---------|---------|
| Carga | Lazy loading de rutas | -40% carga inicial |
| Imágenes | Optimización con Vite | -50% tamaño |
| Código | Code splitting automático | -30% bundle |
| Caché | Service Worker | Carga instantánea |
| Data | React Query con caché | -70% llamadas API |
| Mapas | Carga bajo demanda | -60% tiempo |

### 11.2 Métricas de Rendimiento

**Objetivos:**
- First Contentful Paint (FCP): < 1.5s
- Largest Contentful Paint (LCP): < 2.5s
- Time to Interactive (TTI): < 3s
- Lighthouse Score: > 90

### 11.3 Monitoreo

```javascript
import { onCLS, onFID, onFCP, onLCP, onTTFB } from 'web-vitals'

onCLS(console.log)
onFID(console.log)
onFCP(console.log)
onLCP(console.log)
onTTFB(console.log)
```

---

## 12. TESTING - ESTRATEGIA

### 12.1 Niveles de Testing
1. **Unit Testing**: Componentes y funciones
2. **Integration Testing**: Conexiones con Supabase
3. **E2E Testing**: Flujos completos (opcional)

### 12.2 Configuración de Testing

```javascript
// jest.config.js
export default {
  testEnvironment: 'jsdom',
  setupFilesAfterEnv: ['<rootDir>/src/setupTests.js'],
  moduleNameMapper: {
    '^@/(.*)$': '<rootDir>/src/$1'
  }
}
```

### 12.3 Ejemplo de Test

```javascript
import { render, screen } from '@testing-library/react'
import { RegistroAfectado } from './RegistroAfectado'

test('renderiza formulario de afectado', () => {
  render(<RegistroAfectado />)
  expect(screen.getByText('Registrar Afectado')).toBeInTheDocument()
})
```

---

## 13. MONITOREO - HERRAMIENTAS

### 13.1 Herramientas

| Herramienta | Propósito | Costo |
|-------------|-----------|-------|
| Supabase Dashboard | Base de datos y rendimiento | Incluido |
| React DevTools | Debugging frontend | Gratuito |
| Browser DevTools | Rendimiento y red | Gratuito |
| Sentry | Errores en producción | Gratuito (plan básico) |

### 13.2 Logging

```javascript
const logError = (error, context) => {
  console.error('Error:', error)
  console.error('Context:', context)
}

const logActivity = (action, data) => {
  console.log(`[${new Date().toISOString()}] ${action}:`, data)
}
```

---

## 14. DOCUMENTACIÓN - PLAN

### 14.1 Documentos Técnicos

| Documento | Propósito | Estado |
|-----------|-----------|--------|
| PRD.md | Requerimientos funcionales | ✅ Creado |
| TRD.md | Requerimientos técnicos | ✅ En creación |
| API.md | Documentación de API | ⏳ Pendiente |
| SETUP.md | Guía de instalación | ⏳ Pendiente |
| DEPLOY.md | Guía de despliegue | ⏳ Pendiente |

### 14.2 Estándares de Código
- **Variables:** camelCase
- **Componentes:** PascalCase
- **Archivos:** kebab-case para archivos, PascalCase para componentes
- **Comentarios:** JSDoc para funciones
- **Commits:** Conventional Commits

---

## 15. ROADMAP TÉCNICO

### Semana 1 - Fundación (Días 1-3)
- [ ] Configurar proyecto Vite
- [ ] Conectar con Supabase
- [ ] Crear estructura de carpetas
- [ ] Implementar autenticación básica
- [ ] Crear layout base

### Semana 1 - Funcionalidad (Días 4-7)
- [ ] Registro de afectados
- [ ] Dashboard básico
- [ ] Inventario simple
- [ ] CRUD de productos
- [ ] Movimientos de inventario

### Semana 2 - Operaciones (Días 8-14)
- [ ] Gestión de donaciones
- [ ] Asignación de ayudas
- [ ] Mapa de necesidades
- [ ] Seguimiento de entregas
- [ ] Perfil de voluntarios

### Semana 3 - PWA y Optimización
- [ ] Configuración PWA
- [ ] Modo offline
- [ ] Sincronización
- [ ] Notificaciones push
- [ ] Reportes y exportación

### Semana 4 - Pruebas y Producción
- [ ] Testing completo
- [ ] Optimización de rendimiento
- [ ] Documentación final
- [ ] Despliegue a producción
- [ ] Capacitación de voluntarios

---

## 📋 CHECKLIST TÉCNICO FINAL

- [ ] Repositorio con estructura definida
- [ ] Conexión a Supabase funcionando
- [ ] Variables de entorno configuradas
- [ ] Autenticación implementada
- [ ] RLS configurado y probado
- [ ] PWA configurada
- [ ] Modo offline funcionando
- [ ] Mapa integrado
- [ ] Inventario en tiempo real
- [ ] Registro de afectados funcionando
- [ ] Sistema de donaciones completo
- [ ] Asignaciones operativas
- [ ] Reportes exportables
- [ ] Documentación completa
- [ ] Despliegue en producción

---

**Fin del Documento de Requerimientos Técnicos**

**Próximos Pasos:**
1. Crear el proyecto con Vite
2. Instalar dependencias
3. Configurar Supabase en el frontend
4. Crear el primer componente