Feat: Cambios Varios
This commit is contained in:
92
frontend/counter-panel/src/utils/categoryTreeUtils.ts
Normal file
92
frontend/counter-panel/src/utils/categoryTreeUtils.ts
Normal file
@@ -0,0 +1,92 @@
|
||||
import { type Category } from '../types/Category';
|
||||
|
||||
// Interfaz para la categoría "Aplanada" y enriquecida para UI
|
||||
export interface FlatCategory {
|
||||
id: number;
|
||||
name: string;
|
||||
level: number;
|
||||
parentId: number | null;
|
||||
path: string; // "Vehículos > Autos"
|
||||
isSelectable: boolean; // True si no tiene hijos (es hoja)
|
||||
hasChildren: boolean;
|
||||
}
|
||||
|
||||
// Interfaz auxiliar para el árbol
|
||||
interface CategoryNode extends Category {
|
||||
children: CategoryNode[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Convierte una lista plana de BD en un árbol recursivo
|
||||
*/
|
||||
export const buildTree = (categories: Category[]): CategoryNode[] => {
|
||||
const map = new Map<number, CategoryNode>();
|
||||
const roots: CategoryNode[] = [];
|
||||
|
||||
// 1. Inicializar nodos
|
||||
categories.forEach(cat => {
|
||||
map.set(cat.id, { ...cat, children: [] });
|
||||
});
|
||||
|
||||
// 2. Construir relaciones
|
||||
categories.forEach(cat => {
|
||||
const node = map.get(cat.id);
|
||||
if (node) {
|
||||
if (cat.parentId && map.has(cat.parentId)) {
|
||||
map.get(cat.parentId)!.children.push(node);
|
||||
} else {
|
||||
roots.push(node);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return roots;
|
||||
};
|
||||
|
||||
/**
|
||||
* Aplana el árbol para usarlo en Selects/Autocompletes
|
||||
* Calcula breadcrumbs y deshabilita padres
|
||||
*/
|
||||
export const flattenCategoriesForSelect = (
|
||||
nodes: CategoryNode[],
|
||||
level = 0,
|
||||
parentPath = ""
|
||||
): FlatCategory[] => {
|
||||
let result: FlatCategory[] = [];
|
||||
|
||||
// Ordenar alfabéticamente para facilitar búsqueda visual
|
||||
const sortedNodes = [...nodes].sort((a, b) => a.name.localeCompare(b.name));
|
||||
|
||||
for (const node of sortedNodes) {
|
||||
const currentPath = parentPath ? `${parentPath} > ${node.name}` : node.name;
|
||||
const hasChildren = node.children && node.children.length > 0;
|
||||
|
||||
// Agregamos el nodo actual
|
||||
result.push({
|
||||
id: node.id,
|
||||
name: node.name,
|
||||
level: level,
|
||||
parentId: node.parentId || null,
|
||||
path: currentPath,
|
||||
hasChildren: hasChildren,
|
||||
// REGLA DE ORO: Solo seleccionable si NO tiene hijos
|
||||
isSelectable: !hasChildren
|
||||
});
|
||||
|
||||
// Recursión para los hijos
|
||||
if (hasChildren) {
|
||||
const childrenFlat = flattenCategoriesForSelect(node.children, level + 1, currentPath);
|
||||
result = [...result, ...childrenFlat];
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
/**
|
||||
* Función Helper que hace todo el proceso desde la respuesta de la API
|
||||
*/
|
||||
export const processCategories = (rawCategories: Category[]): FlatCategory[] => {
|
||||
const tree = buildTree(rawCategories);
|
||||
return flattenCategoriesForSelect(tree);
|
||||
};
|
||||
Reference in New Issue
Block a user