# Tarea: construir el catálogo tipado de FSPM Eres el agente de datos del proyecto. Tu única entrega es **un archivo**: `src/data/catalogo.ts` en este repo (`H:\MegaSync\Proyectos\fspm\fspm-web`). No toques ningún otro archivo. No instales dependencias. No corras `npm`. ## Fuente de verdad (solo lectura) Base de conocimiento del sitio real, escrapeada: `H:\MegaSync\Proyectos\Web Clonner Scrapper toolkit\proyectos\fspm.com.mx\conocimiento\` Lee **estos archivos en español** (ignora los `en-*` y los que llevan sufijo hash como `-8e5a3550`): - `index.md` — las 8 categorías y cómo se presentan - `extintores-portatiles.md` - `extintores-fijos.md` - `productos-moviles.md` - `rociadores.md` - `agentes-extinguidores.md` - `firemiks.md` - `robots.md` - `proteccion-civil.md` - `normas-y-certificaciones.md` - `preguntas-frecuentes.md` ## Imágenes disponibles Ya están copiadas en `public/media/producto/` y `public/media/iconos/`. Lista real de archivos — usa **exactamente** estos nombres, con ruta `/media/producto/`: ``` firemiks.png FSPM_espumas_contra_incendios_flameAde.png fspm_extintores_facil_uso_en_mexico.png fspm_extintores_fijos_enforcer_10.png fspm_extintores_fijos_esfera_sin_detector_de_humo.png fspm_extintores_garantia_en_mexico.png fspm_extintores_largo_alcance_en_mexico.png fspm_extintores_moviles_carretilla_100litros.png fspm_extintores_moviles_carretilla_30litros_acero_inoxidable.png fspm_extintores_moviles_carretilla_50litros_acero_inoxidable.png fspm_extintores_moviles_carretilla_70litros_acero_inoxidable.png fspm_extintores_moviles_enforcer_60.png fspm_extintores_no_caducan_en_mexico.png fspm_extintores_portatiles_en_mexico_enforcer_12litros.png fspm_extintores_portatiles_en_mexico_enforcer_1litro.png fspm_extintores_portatiles_en_mexico_enforcer_2litros.png fspm_extintores_portatiles_en_mexico_enforcer_4litros.png fspm_extintores_portatiles_en_mexico_enforcer_6litros.png fspm_extintores_portatiles_en_mexico_enforcer_9litros.png fspm_extintores_rociadores_enforcer_esfera.png fspm_extintores_rociadores_enforcer_robot.png fspm_extintores_rociadores_enforcer_robot_componente_de_agua.png fspm_extintores_rociadores_enforcer_robot_panel_de_control.png fspm_extintores_sin_recarga_en_mexico.png FSPM-trakAde-supresion-de-polvos.png FSPM-vaporAde.png receptor-de-alertamiento.jpg ``` Iconos de aplicación en `/media/iconos/`: `icono-agricultura.png`, `icono-auditorios.png`, `icono-bosques.png`, `icono-central-bomberos.png`, `icono-exterior.png`, `icono-gasolineras.png`, `icono-hogar.png`, `icono-industria.png`, `icono-museos.png`, `icono-no-toxico.png`, `icono-oficina.png`, `iconos-aeropuertos.png`, `iconos-minas.png`. Si un producto no tiene imagen propia, reutiliza la más cercana de su categoría. Nunca inventes un nombre de archivo que no esté en la lista. ## Contrato de tipos — respétalo al carácter ```ts export type ClaseFuego = "A" | "B" | "C" | "D" | "K"; export type Categoria = { slug: string; // kebab-case, ej. "extintores-portatiles" nombre: string; // ej. "Extintores portátiles" tagline: string; // 1 línea: qué problema resuelve, orientado a comprador descripcion: string; // 2-3 frases imagen: string; // "/media/producto/..." aplicaciones: string[]; orden: number; }; export type Producto = { slug: string; categoria: string; // debe existir en CATEGORIAS nombre: string; modelo: string | null; // ej. "Enforcer 12" capacidad: string | null; // ej. "12 L" agente: string | null; // ej. "FireAde 2000" clases: ClaseFuego[]; // SOLO las clases que la fuente sostiene alcance: string | null; descarga: string | null; imagen: string; resumen: string; // 1-2 frases, orientado a venta, SIN claims sin sustento caracteristicas: string[]; // bullets tomados de la fuente aplicaciones: string[]; claimsPorVerificar: string[]; // ver regla crítica abajo orden: number; }; export const CATEGORIAS: Categoria[] = [ ... ]; export const PRODUCTOS: Producto[] = [ ... ]; // helpers que debes exportar también: export function getCategoria(slug: string): Categoria | undefined export function getProducto(slug: string): Producto | undefined export function productosDeCategoria(slug: string): Producto[] ``` ## REGLA CRÍTICA — honestidad de los datos El sitio original hace afirmaciones de alto riesgo comercial: *"no caduca"*, *"20 años de garantía"*, *"no requiere recarga"*, *"extingue clases A, B, C, D y K"*. Una auditoría concluyó que **no deben presentarse como universales sin condiciones y evidencia por modelo**. Por lo tanto: 1. **Nunca** pongas uno de esos claims en `resumen` ni en `caracteristicas` como hecho. 2. Cada claim así va en `claimsPorVerificar`, redactado como lo que hay que documentar. Ejemplo: `"Vida útil sin caducidad: requiere carta técnica del fabricante por número de modelo"`. 3. `clases` solo lleva las clases que la fuente realmente atribuye a **ese** modelo. Si la fuente es ambigua, pon las que sí sostiene y anota la duda en `claimsPorVerificar`. 4. No inventes capacidades, alcances, tiempos de descarga, precios ni certificados. Si el dato no está en la fuente, es `null` o se omite del arreglo. Es mejor `null` que un número inventado. ## Cobertura esperada - Las **8 categorías** del sitio. - Todos los modelos concretos que la fuente identifique. Del scrape se ven al menos: portátiles Enforcer de 1, 2, 4, 6, 9 y 12 litros; móviles Enforcer 60 y carretillas de 30, 50, 70 y 100 L; fijos Enforcer 10 y esfera; rociadores esfera y robot; agentes FireAde 2000, flameAde, vaporAde, trakAde; FIREMIKS; robot cañón; y receptor de alertamiento en protección civil. Confirma cada uno contra la fuente antes de escribirlo. ## Salida - TypeScript válido y formateado, sin `any`, sin imports. - Español de México en todo el contenido, con acentuación correcta. - Al terminar, escribe al final del archivo un comentario de bloque con: las categorías y el número de productos por categoría, y la lista de datos que no pudiste confirmar en la fuente. Cuando acabes, di exactamente `CATALOGO LISTO` y un resumen de 3 líneas.