# Goals Módulo de objetivos / OKR: gestión de goals personales y de equipo, creación y edición de goals, vista de detalle con progreso, asignación de pesos por ciclo y vista de leader sobre los goals de su equipo. --- ## Pantallas y flujos | Pantalla / flujo | Descripción | Entrada | Ruta | |---|---|---|---| | Goals (home) | Shell con 3 tabs (`MyGoals` / `General` / `MyTeam`) según rol y feature flags. Selector de ciclo compartido | `Goals.tsx` → `GoalsContent.tsx` | `/goals` | | My Goals (tab) | Goals propios del usuario para el ciclo seleccionado, listado paginado con search | `MyGoals/index.tsx` | `/goals` (tab) | | General (tab) | Listado consolidado de goals del ciclo (vista organización) | `General/index.tsx` | `/goals` (tab) | | My Team (tab) | Tabla de subordinados con resumen de goals por colaborador | `MyTeam/index.tsx` | `/goals` (tab) | | Team Goals | Goals individuales de un colaborador del equipo + edición de pesos | `TeamGoals/index.tsx` | `/goals/team/:id` | | Goal Detail | Detalle de un goal: progreso, historial, AddProgress, responsables | `GoalDetail/index.tsx` | `/goals/:id` | | New Goal | Crear o editar un goal: form con detalles, fórmulas, valores y responsables | `NewGoal/NewGoalPage.tsx` | `/goals/new`, `/goals/:id/edit` | --- ## Forms clave | Form | Descripción | Path | |---|---|---| | `NewGoalForm` | Form principal de creación/edición de un goal: título, descripción, ciclo, criticality, fórmula, valores límite, responsable | `NewGoal/components/NewGoalForm.tsx` | | `EditDetails` | Bloque del form que orquesta los campos de detalle (criticality + value inputs + responsable picker). Usado por `NewGoalFormFields` | `NewGoal/components/EditDetails.tsx` | | `ValueInputsAndFormula` | Inputs de valores boundary (initial / min / target / max) con selección de fórmula y validación reactiva por trend | `NewGoal/components/ValueInputsAndFormula.tsx` | | `ResponsiblePicker` | Drawer + autocomplete para elegir responsable(s) del goal | `NewGoal/components/ResponsiblePicker/` | | `AddProgress` | Form embebido en `GoalDetail` para registrar un nuevo progreso (incremento o total, según tipo de goal) | `GoalDetail/components/AddProgress.tsx` | | `GoalWeightsDrawer` | Drawer para asignar pesos relativos a los goals de un usuario en un ciclo. Usado por `MyGoals` y `TeamGoals` | `components/GoalWeightsDrawer/` | --- ## Componentes y hooks clave | Nombre | Descripción | Ubicación | |---|---|---| | `GoalsContext` | Estado de tabs de la home (`selectedTab`, `goalsTabs`, `handleTabChange`, last-visited-tab). Scope: **home only** | `GoalsContext.tsx` | | `CycleContext` | Estado del ciclo seleccionado (`selectedCycleId`, `setSelectedCycleId`). Scope: **módulo** — lo montan la home y cualquier ruta que use `CycleSelector` (ej. `TeamGoals`) | `CycleContext.tsx` | | `GoalFeaturesConfigContext` | Provider con flags por ciclo (`isApprovalFlowEnabled`, `isBossCanEditPublishedObjectives`, …) | `components/GoalFeaturesConfigContext.tsx` | | `useGoalFeaturesConfig` | Consume `GoalFeaturesConfigContext`. Usado por todas las pantallas con goals | `hooks/useGoalFeaturesConfig.ts` | | `useDefaultCycleId` | Resuelve el ciclo por defecto a mostrar (último activo del usuario) | `hooks/useDefaultCycleId.ts` | | `useSubordinates` | Carga los subordinados del usuario actual (consumido por `GoalsContext`) | `hooks/useSubordinates.ts` | | `useTeamGoalsPageQuery` | Pesos de goals + configuración del ciclo para `TeamGoals` | `TeamGoals/hooks/useTeamGoalsPageQuery.ts` | | `useUpdateGoalProgress` | Mutación para registrar progreso en un goal (invalida list + detail) | `GoalDetail/hooks/useUpdateGoalProgress.ts` | | `useValueInputRules` | Reglas reactivas de validación de los inputs boundary con detección de trend INCREASING/DECREASING | `NewGoal/hooks/useValueInputRules.ts` | | `GoalCard` | Card del listado de un goal con menú de acciones, weight, progress | `components/GoalCard.tsx` | | `GoalCardMenu` / `GoalCardMenuItem` | Menú contextual del `GoalCard` (editar, eliminar, ver detalle, …) | `components/GoalCardMenu*.tsx` | | `GoalStatusPill` | Pill con estado del goal (in progress / finished / archived) | `components/GoalStatusPill.tsx` | | `CycleSelector` | Selector de ciclo compartido por todas las pantallas | `components/CycleSelector.tsx` | | `GoalsEmptyState` | Empty state reutilizado por General, MyGoals y la tabla de MyTeam | `components/GoalsEmptyState.tsx` | | `SkeletonCardsSummary` | Skeleton de las cards de summary, compartido entre MyGoals/MyTeam/TeamGoals | `components/SkeletonCardsSummary.tsx` | | `SegmentedToggle` / `SegmentedToggleItem` | Toggle de chips compartido por `CriticalityButtonGroup` (NewGoal) y `AddProgress` (GoalDetail) | `components/SegmentedToggle*.tsx` | | `DeleteGoalModal` | Modal de confirmación de eliminación usado por `GoalCard` | `components/DeleteGoalModal.tsx` | --- ## Archivos compartidos del módulo | Archivo | Contenido | |---|---| | `routes.ts` | URL builders del módulo (`goals`, `detail`, `individual`, `create`, `edit`) | | `services.ts` | Llamados a la API de goals (cycles, weights, formulas, responsibles, progress, …) | | `queries.ts` | Query keys y helpers de invalidación de React Query | | `constants.ts` | Constantes globales del módulo (sort order, layout sx compartido, sizes) | | `utils.ts` | Utilidades de dominio: `goalVisualProgress`, `isGoalCycle*Status`, `transformIndividualGoalsToGoals`, etc. | | `GoalsContext.tsx` | Context de tabs de la home (scope home) | | `CycleContext.tsx` | Context del ciclo seleccionado (scope módulo) — desacoplado de los tabs para que `CycleSelector` no arrastre la maquinaria de la home | | `Goals.tsx` / `GoalsContent.tsx` | Shell wrapper que provee `HuGoTheme` + `CycleProvider` + `GoalsProvider` + tabs | | `hooks/` | Hooks de scope módulo (`useDefaultCycleId`, `useGoalFeaturesConfig`, `useSubordinates`) | | `components/` | Componentes compartidos por 2+ rutas (ver tabla anterior) | > Tipos de dominio: `src/types/goals.ts` (cross-module — consumido por backoffice, performance, profile, etc.; **no** se mueve al módulo). Convención del workspace: tipos compartidos viven en `src/types/{domain}.ts`. --- ## Estructura de directorios ``` goals/ ├── Goals.tsx # Shell: HuGoTheme + CycleProvider + GoalsProvider + GoalsContent ├── GoalsContent.tsx # Tabs router (MyGoals / General / MyTeam) ├── GoalsContext.tsx # Context de tabs (scope home) ├── CycleContext.tsx # Context del ciclo seleccionado (scope módulo) ├── MyGoals/ # Tab "Mis objetivos" │ ├── components/ # MyGoalsSummary │ └── hooks/ ├── General/ # Tab "General" │ ├── components/ │ └── hooks/ ├── MyTeam/ # Tab "Mi equipo" (vista leader) │ ├── components/ # MyTeamGoalsSummary, TeamTable │ └── hooks/ ├── TeamGoals/ # Detalle de goals de un colaborador │ ├── index.tsx │ ├── components/ # TeamGoalsHeader, TeamGoalsSummaryCards │ └── hooks/ # useTeamGoalsPageQuery ├── GoalDetail/ # Detalle de un goal (/goals/:id) │ ├── index.tsx │ ├── components/ # AddProgress, DetailRow, FormulaDisplay, ProgressBar, ProgressHistoryTable, Responsible, ValueMarkers │ ├── hooks/ # useUpdateGoalProgress │ ├── constants.ts │ └── utils.ts ├── NewGoal/ # Crear / editar goal │ ├── NewGoalPage.tsx │ ├── index.tsx │ ├── components/ # NewGoalForm, NewGoalFormFields, EditDetails, CriticalityButtonGroup, ValueInputsAndFormula, FormulasAutocomplete, ResponsiblePicker/, ResponsibleAutocomplete/ │ ├── hooks/ # useNewGoalQueries, useValueInputRules │ ├── constants.ts │ └── utils/ ├── components/ # Compartidos por 2+ rutas │ ├── CycleSelector │ ├── GoalCard, GoalCardMenu, GoalCardMenuItem, GoalStatusPill, DeleteGoalModal │ ├── GoalFeaturesConfigContext │ ├── GoalsEmptyState │ ├── GoalWeightsDrawer/ │ ├── SegmentedToggle, SegmentedToggleItem │ └── SkeletonCardsSummary ├── hooks/ # Hooks de scope módulo │ ├── useDefaultCycleId │ ├── useGoalFeaturesConfig │ └── useSubordinates ├── routes.ts ├── services.ts ├── queries.ts ├── constants.ts └── utils.ts ``` --- ## Known issues / deuda técnica - **`src/types/goals.ts` vive afuera del módulo**. Es intencional: 35+ consumers cross-module (backoffice, performance, profile, …) — sigue la convención del workspace. No mover. --- > Actualizar este README cuando se agreguen pantallas, flujos principales o se reorganicen carpetas.