Edifiko
Edifiko DocsDocumentación del proyecto
  • Overview
Proyecto
  • README
  • CONTRIBUTING
  • WORKFLOW
  • Workflows CI/CD
  • UI Components
  • Showcase: Works UI Components
  • Schemas
  • Servicios
  • Hooks
  • Utils
  • Types
  • Constants
  • Errors
  • API Materiales
Herramientas de IA
  • Agentes
  • Skills
  1. Documentación
  2. Utils

Utils

utils/README.md

Utils

Funciones utilitarias puras agrupadas por dominio. No tienen estado, no producen side-effects y no dependen de React. Pueden usarse tanto en hooks como en componentes.

Descripción General

text
utils/
├── categories/
│   ├── build-catalog.ts          # Transforma ICategoryCatalog[] → IGroupCatalogView[]
│   └── icon-map.ts               # Resuelve nombre de ícono → componente LucideIcon
├── materials/
│   ├── build-material-rows.ts    # Convierte IMaterial[] + catálogo → IMaterialRow[]
│   └── resolve-categorization.ts # Resuelve la jerarquía completa a partir de un subcategoryId
└── shared/
    ├── text-utils.ts             # normalizeText / matchesSearch
    └── utils.ts                  # cn() — classnames + tailwind-merge

🗂️ utils/categories

buildGroupCatalogViews(catalog)

Archivo: utils/categories/build-catalog.ts

Transforma el resultado de getCategoryCatalog() (forma de Firestore) en el modelo de vista que usan los componentes de UI.

ParámetroTipoDescripción
catalogICategoryCatalog[]Array de grupos con sus categorías y subcategorías

Retorna: IGroupCatalogView[]

ts
buildGroupCatalogViews(catalog);
// Input (Firestore shape)
// { group: IGroup, categories: ICategory[], subcategories: ISubcategory[] }

// Output (View shape)
// { id, title, description, iconName, categories: [{ id, name, subcategories: [{ id, name, materialsCount }] }] }

Nota: materialsCount se resuelve desde Firestore cuando el UI usa hooks/categories/use-material-counts.ts.


getGroupIcon(iconName)

Archivo: utils/categories/icon-map.ts

Resuelve un nombre de ícono (string key de CONSTRUCTION_ICON_OPTIONS) al componente LucideIcon correspondiente. Si no encuentra coincidencia, retorna el primer ícono disponible como fallback.

ParámetroTipoDescripción
iconNamestringClave del ícono (ej. 'brick-wall')

Retorna: LucideIcon

ts
import { getGroupIcon } from '@/utils/categories/icon-map';

const Icon = getGroupIcon('paint-bucket'); // → PaintBucket

� utils/materials

buildSubcategoryLookup(catalog)

Archivo: utils/materials/build-material-rows.ts

Construye un Map<subcategoryId, label> recorriendo el catálogo completo. El label tiene la forma "Rubro / Categoría / Subcategoría" y se usa para mostrar la categorización en tablas.


buildMaterialRows(materials, lookup)

Archivo: utils/materials/build-material-rows.ts

Transforma un array de IMaterial (forma de Firestore) en el modelo de vista IMaterialRow que consumen los componentes de tabla. Incorpora groupId, categoryId y subcategoryId para el filtrado en cliente.

ParámetroTipoDescripción
materialsIMaterial[]Array de materiales crudos de Firestore
lookupMap<string, string>Mapa generado por buildSubcategoryLookup

Retorna: IMaterialRow[]


resolveFullCategorization(subcategoryId, catalog)

Archivo: utils/materials/resolve-categorization.ts

Navega el catálogo completo buscando la subcategoría por ID y retorna todos los campos de la jerarquía necesarios para persistir un material. Se usa en los hooks de diálogo y en la importación masiva para enriquecer el payload antes de guardarlo.

ParámetroTipoDescripción
subcategoryIdstringID de la subcategoría
catalogICategoryCatalog[]Catálogo completo cargado

Retorna: IFullCategorization

ts
interface IFullCategorization {
  categoryId: string;
  groupId: string;
  groupName: string;
  categoryName: string;
  subcategoryName: string;
  label: string; // "Rubro > Categoría > Subcategoría"
  isValid: boolean; // false si el subcategoryId no existe en el catálogo
}

resolveCategorizationById(subcategoryId, catalog)

Archivo: utils/materials/resolve-categorization.ts

Atajo que retorna solo { label, isValid } a partir de resolveFullCategorization. Útil para resolver el texto de categorización cuando no se necesitan los IDs individuales.


resolveCategorizationFromRawLabel(rawLabel, catalog)

Archivo: utils/materials/resolve-categorization.ts

Extrae el subcategoryId de un texto con el formato "Cualquier texto [ID: <id>]" (generado por la plantilla de importación Excel) y luego llama a resolveCategorizationById. Se usa en el flujo de importación masiva de materiales.


🔧 utils/shared

normalizeText(text)

Archivo: utils/shared/text-utils.ts

Normaliza un string para búsquedas: elimina diacríticos (acentos), convierte a minúsculas y recorta espacios. Internamente usa String.normalize('NFD') + regex Unicode para remover las marcas diacríticas.

ts
normalizeText('Cémento Portland'); // → 'cemento portland'
normalizeText('MAÑERÍA'); // → 'mañeria'  (no elimina la ñ, solo los diacríticos de acento)

Usado en: búsqueda en useMaterialCatalogPage, useCategoriesPage, useCategoryCombobox, y en el Route Handler GET /api/materials.


matchesSearch(text, search)

Archivo: utils/shared/text-utils.ts

Devuelve true si text normalizado contiene search normalizado. Envuelve normalizeText para uso directo en filtros de array.

ts
matchesSearch('Cemento Portland 50kg', 'portland'); // → true
matchesSearch('Ladrillo común', 'ladrillos'); // → false

cn(...inputs)

Archivo: utils/shared/utils.ts

Wrapper sobre clsx + tailwind-merge. Combina clases condicionales y resuelve conflictos de Tailwind.

ts
import { cn } from '@/utils/shared/utils';

<div className={cn('base-class', isActive && 'active-class', className)} />

Cómo Agregar Utilidades

  1. Si es específica de un dominio, crear en utils/<dominio>/nombre.ts.
  2. Si es genérica, agregar en utils/shared/utils.ts o en un archivo nuevo dentro de utils/shared/.
  3. Las funciones deben ser puras: mismo input → mismo output, sin efectos secundarios.
  4. Documentar el tipo de input y output con TypeScript — no con comentarios.