# Sprint 2 — Etapa 4: Edición inline de nombre de proceso y cliente > **Tipo:** UI — un solo componente. Sin cambios en dominio, persistencia ni reporte. > **Objetivo:** hacer editable el nombre del proceso y el cliente directamente desde el header del workspace. Hoy son campos estáticos (`

`); deben convertirse en inputs inline que guardan en IndexedDB al confirmar. > **Resultado esperado:** click sobre nombre o cliente → input inline → Enter o blur guarda → checkmark naranja breve confirma. Validación visual del director requerida antes del OK formal. --- ## Archivo a modificar **Un único archivo:** `src/features/workspace/WorkspacePage.tsx` Si durante la implementación identificás que otro archivo necesita cambio, **detenete y reportá el conflicto antes de tocarlo**. No procedas sin confirmación. --- ## Contexto: estado actual del header El header del workspace (líneas ~139–144) tiene hoy: ```tsx

{currentProcess.name}

{currentProcess.clientName && (

{currentProcess.clientName}

)}
``` Ambos son texto estático. La función `updateProcess` ya existe en el store (`useProcessStore`) y persiste en IndexedDB — no requiere ningún cambio fuera de este archivo. --- ## Cambios requeridos ### 1. Agregar `updateProcess` al destructuring del store ```tsx // ANTES (línea ~26) const { currentProcess, activities, isLoading, error, loadProcess, gateways } = useProcessStore() // DESPUÉS const { currentProcess, activities, isLoading, error, loadProcess, gateways, updateProcess } = useProcessStore() ``` ### 2. Agregar iconos al import de lucide-react Agregar `Check` y `Pencil` al import existente: ```tsx import { Loader2, BarChart3, Play, AlertTriangle, PanelRightClose, PanelRightOpen, Home, GitMerge, MousePointer2, Check, Pencil } from 'lucide-react' ``` ### 3. Agregar estado local para edición inline Insertar antes del `return`, junto a los otros estados del componente: ```tsx // Estado para edición inline del header const [editingField, setEditingField] = useState<'name' | 'client' | null>(null) const [editValue, setEditValue] = useState('') const [savedField, setSavedField] = useState<'name' | 'client' | null>(null) const savedTimerRef = useRef | null>(null) ``` `useRef` ya está importado desde React — no requiere cambio en imports de React. ### 4. Agregar función `saveField` Insertar junto a las otras funciones del componente (cerca de `handleSimulate`): ```tsx async function saveField(field: 'name' | 'client') { if (field === 'name') { const trimmed = editValue.trim() if (trimmed && trimmed !== currentProcess?.name) { await updateProcess({ name: trimmed }) } } else { const trimmed = editValue.trim() if (trimmed !== (currentProcess?.clientName ?? '')) { await updateProcess({ clientName: trimmed }) } } setEditingField(null) // Wow: checkmark naranja breve setSavedField(field) if (savedTimerRef.current) clearTimeout(savedTimerRef.current) savedTimerRef.current = setTimeout(() => setSavedField(null), 1500) } ``` ### 5. Reemplazar el bloque estático del header Reemplazar las líneas ~139–144 (el `
` completo) con: ```tsx
{/* Nombre del proceso — editable inline */} {editingField === 'name' ? ( setEditValue(e.target.value)} onBlur={() => saveField('name')} onKeyDown={(e) => { if (e.key === 'Enter') { e.preventDefault(); saveField('name') } if (e.key === 'Escape') setEditingField(null) }} /> ) : (
{ setEditValue(currentProcess.name); setEditingField('name') }} >

{currentProcess.name}

{savedField === 'name' ? : }
)} {/* Cliente — editable inline */} {editingField === 'client' ? ( setEditValue(e.target.value)} onBlur={() => saveField('client')} onKeyDown={(e) => { if (e.key === 'Enter') { e.preventDefault(); saveField('client') } if (e.key === 'Escape') setEditingField(null) }} placeholder="Agregar cliente…" /> ) : (
{ setEditValue(currentProcess.clientName ?? ''); setEditingField('client') }} > {currentProcess.clientName ?

{currentProcess.clientName}

:

Agregar cliente…

} {savedField === 'client' ? : }
)}
``` --- ## Comportamientos esperados - **Click sobre el nombre** → input inline con el valor actual, borde inferior naranja - **Enter o blur** → guarda, vuelve a modo lectura, aparece ✓ naranja 1.5 segundos - **Escape** → cancela sin guardar, vuelve al valor anterior - **Nombre vacío al guardar** → no guarda (el `if (trimmed && ...)` lo previene), vuelve al valor anterior - **Cliente vacío al guardar** → guarda string vacío (limpiar el cliente es una acción válida) - **Sin cliente asignado** → muestra "Agregar cliente…" en gris itálico; al hacer click se abre el input vacío - El ícono ✏️ es invisible hasta hacer hover sobre la fila — indica que es editable sin ocupar espacio visualmente --- ## Verificaciones obligatorias antes de reportar ### 1. Verificación de scope con git diff — OBLIGATORIO ```bash git diff --name-only HEAD ``` El resultado debe contener únicamente: ``` src/features/workspace/WorkspacePage.tsx ``` Si aparece cualquier archivo no listado: 1. Revertilo: `git checkout HEAD -- ` 2. Listarlo bajo "Conflictos de scope" en el reporte 3. No incluirlo en el entregable ### 2. Build limpio ```bash npm run build ``` Sin errores TypeScript. ### 3. Tests ```bash npm run test ``` Todos los tests existentes deben seguir verdes. Esta etapa no agrega tests nuevos (UI pura, sin lógica de dominio nueva). ### 4. Smoke test manual - [ ] Click sobre el nombre del proceso → se abre input con valor actual - [ ] Tipear un nombre nuevo → Enter → se cierra, aparece ✓ naranja breve, el nombre cambió - [ ] Recargar la página → el nombre nuevo persiste (IndexedDB) - [ ] Click sobre el cliente → input editable - [ ] Borrar el cliente completamente → guardar → el campo queda vacío mostrando "Agregar cliente…" - [ ] Escape cancela sin guardar --- ## Alcance estricto — lo que NO entra en esta etapa - ❌ `GlobalSettingsPanel.tsx` — no tocar (edición desde settings sigue funcionando igual) - ❌ Ningún archivo de reporte (`src/features/report/`) — Etapa 3 ya cerrada - ❌ Ningún archivo de dominio (`src/domain/`) — Etapas 1–3 ya cerraron dominio - ❌ Ningún archivo de persistencia (`src/persistence/`) — `updateProcess` del store es suficiente - ❌ PDFs — Etapa 5 - ❌ Edición de campos adicionales del proceso (frecuencia anual, overhead) — BACKLOG --- ## Reporte esperado al terminar ``` ## Etapa 4 completada ### Archivos modificados - src/features/workspace/WorkspacePage.tsx ### Cambios realizados - Edición inline de nombre de proceso: click → input → Enter/blur guarda - Edición inline de cliente: click → input → Enter/blur guarda - Checkmark naranja (#F59845) confirmatorio con timeout 1.5s - Ícono ✏️ visible al hover, oculto en reposo - Escape cancela sin guardar en ambos campos ### Verificaciones - git diff --name-only HEAD: solo WorkspacePage.tsx ✅ - npm run build: ✅ - npm run test: X/X tests verdes ✅ - Smoke test: [descripción breve] ### Conflictos de scope [ninguno / lista de archivos revertidos y razón] ### Notas para Etapas siguientes [hallazgos relevantes para Etapas 5+] ```