Sprint 4 — Etapa 7 completada. Build limpio, 521/521 tests verdes. Resumen:
Some checks failed
/ Deploy to Cloudflare Pages (push) Has been cancelled

Tipos: Resource.processId? eliminado (vestigial); ResourceType ya tenía los 5 valores correctos, sin cambios.

resource-repo.ts: agregado getAllWithCreator() con JOIN a users!created_by (mismo patrón que Etapa 6) y tipo ResourceWithCreator. delete() ahora valida que no haya asignaciones activas en activity_resource_assignments antes de borrar — lanza error explicativo si las hay. Verifiqué ambos contra Supabase real: el JOIN funciona (FK reconocida por PostgREST) y el conteo de guarda también.

Nuevo — src/features/resources/:

resource-display.tsx — labels, colores/íconos por tipo (Lucide: User/Briefcase/Server/Wrench/Package) y ResourceTypeAvatar compartido
ResourceFormSheet.tsx — Sheet reutilizable para crear/editar, usado tanto en el catálogo como en el panel del workspace
ResourceCatalogPage.tsx — página /recursos: búsqueda, filtro por tipo, tabla con badge de tipo, costo, "creado por", editar/eliminar con confirmación
Nuevo — src/components/ui/sheet.tsx: componente shadcn Sheet (no existía), construido sobre @radix-ui/react-dialog que ya estaba instalado — no agregué dependencias nuevas.

ResourcesPanel.tsx rediseñado: ahora solo muestra recursos usados en el proceso actual (derivado de assignedResources), con conteo de actividades por recurso. CRUD completo se mudó a /recursos; el panel solo permite "Nuevo" (catálogo global) y tiene el link "Ver catálogo completo".

Router: ruta /recursos registrada.

ActivityPanel no se tocó, como indicaba el scope.
This commit is contained in:
2026-06-19 00:01:46 -03:00
parent 4f51c74717
commit 892b8b3bc7
14 changed files with 789 additions and 189 deletions

View File

@@ -15,7 +15,7 @@ const SINGLE_TASK_BPMN = `<?xml version="1.0" encoding="UTF-8"?>
</definitions>`
const makeResource = (id: string, costPerHour: number): Resource => ({
id, processId: 'proc1', name: `Recurso ${id}`, type: 'role', costPerHour,
id, name: `Recurso ${id}`, type: 'role', costPerHour,
})
const baseActivity = (overrides: Partial<Activity> = {}): Activity => ({

View File

@@ -68,7 +68,6 @@ describe('parseBpmnXml', () => {
describe('runSimulation', () => {
const makeResource = (id: string, name: string, costPerHour: number): Resource => ({
id,
processId: 'proc1',
name,
type: 'role',
costPerHour,
@@ -398,7 +397,7 @@ describe('runSimulation — scenario automated', () => {
describe('runSimulation — recursos con modelo utilizationMinutes + units', () => {
const makeRes = (id: string, costPerHour: number): Resource => ({
id, processId: 'proc1', name: `Recurso ${id}`, type: 'role', costPerHour,
id, name: `Recurso ${id}`, type: 'role', costPerHour,
})
const makeAct = (