@imj_media/tareas 1.5.53 → 1.5.55

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Barra masiva con el **`Toolbar`** del design system (sin tocar `packages/ui`):
3
+ *
4
+ * 1. Primera vista: acciones “Mover a …”.
5
+ * 2. Segunda vista (addons): bloque `(n) Seleccionados` + Cancelar / Confirmar.
6
+ *
7
+ * Modo controlado (`activeButtonId`). Tras confirmar con éxito: invalidación vía `invalidateAfterBulkSuccess`.
8
+ */
9
+ export declare function KanbanBulkToolbar(): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,21 @@
1
+ import { ToolbarButton } from '@imj_media/ui';
2
+ import { KanbanColumnTitle } from '../../context/kanbanBulkSelection.context';
3
+ import { BulkUpdateTaskStatusEstatus } from '../../core/types/bulk-update-task-status.types';
4
+ export declare const KANBAN_BULK_TOOLBAR_IDS: {
5
+ readonly MOVE_TO_TRABAJANDO: "kanban-bulk-move-trabajando";
6
+ readonly MOVE_TO_POR_HACER: "kanban-bulk-move-por-hacer";
7
+ readonly MOVE_TO_COMPLETADAS: "kanban-bulk-move-completadas";
8
+ };
9
+ type BuildParams = {
10
+ baseColumn: KanbanColumnTitle | null;
11
+ setPendingTargetStatus: (status: BulkUpdateTaskStatusEstatus | null) => void;
12
+ setActiveButtonId: (id: string | null) => void;
13
+ onConfirmBulkMove: () => void;
14
+ isBulkLoading: boolean;
15
+ };
16
+ /**
17
+ * Botones de la primera vista del `Toolbar`: cada “mover” abre la segunda vista (addons) donde el DS
18
+ * muestra `count` + `text` junto a Cancelar / Confirmar.
19
+ */
20
+ export declare function buildKanbanBulkToolbarButtons(p: BuildParams): ToolbarButton[];
21
+ export {};
@@ -7,6 +7,8 @@ interface IBoard {
7
7
  isFetching?: boolean;
8
8
  isLoadingData?: boolean;
9
9
  total?: number;
10
+ /** Tableros con modo masivo: devuelve los ids de la columna (paginado en listado, en memoria en campaña). */
11
+ bulkSelectAllIds?: () => Promise<number[]>;
10
12
  }
11
- declare const Board: ({ title, tasks, loadNextPage, isFetching, total }: IBoard) => import("react/jsx-runtime").JSX.Element;
13
+ declare const Board: ({ title, tasks, loadNextPage, isFetching, total, bulkSelectAllIds }: IBoard) => import("react/jsx-runtime").JSX.Element;
12
14
  export default Board;
@@ -8,6 +8,11 @@ type ButtonMoveTaskProps = {
8
8
  projectID: number;
9
9
  atrasoId?: number;
10
10
  categoria?: ICategory | null;
11
+ /**
12
+ * Kanban general: desactiva el menú «mover» mientras hay multiselección masiva activa en la columna,
13
+ * para no combinar PUT/POST individuales con el flujo del toolbar (regresión / UX).
14
+ */
15
+ disabled?: boolean;
11
16
  };
12
- declare const ButtonMoveTask: ({ status, nameRequiredTask, statusRequiredTask, id, statusLateTask, projectID, atrasoId, categoria }: ButtonMoveTaskProps) => import("react/jsx-runtime").JSX.Element;
17
+ declare const ButtonMoveTask: ({ status, nameRequiredTask, statusRequiredTask, id, statusLateTask, projectID, atrasoId, categoria, disabled, }: ButtonMoveTaskProps) => import("react/jsx-runtime").JSX.Element;
13
18
  export default ButtonMoveTask;
@@ -0,0 +1,13 @@
1
+ import { ReactNode, RefObject } from 'react';
2
+ type PauseTaskFloatingMenuProps = {
3
+ idTask: number;
4
+ paused: boolean;
5
+ popupId: string;
6
+ children: (triggerRef: RefObject<HTMLButtonElement>) => ReactNode;
7
+ };
8
+ /**
9
+ * Encapsula el patrón del menú flotante de pausa/reanudar para reutilizarlo
10
+ * en `Task` y `ChildTask` sin duplicar la lógica de apertura/cierre.
11
+ */
12
+ declare const PauseTaskFloatingMenu: ({ idTask, paused, popupId, children }: PauseTaskFloatingMenuProps) => import("react/jsx-runtime").JSX.Element;
13
+ export default PauseTaskFloatingMenu;
@@ -1,3 +1,13 @@
1
+ import { KanbanColumnTitle } from '../../context/kanbanBulkSelection.context';
1
2
  import { TasksKanbanGeneral } from '../../infraestructure/interfaces/tasks-kanban-general';
2
- declare const Task: ({ id, task, endDate, users, willBePaused, nameProject, comments, priority, difficulty, responsible, nameRequiredTask, nameRequiredTaskResponsible, statusRequiredTask, status, repeatsToDo, repeats, medioName, paused, idProject, atraso, categoria, cambio_arte, name_father_required_task, name_father_required_task_responsible, }: TasksKanbanGeneral) => import("react/jsx-runtime").JSX.Element;
3
+ type TaskProps = TasksKanbanGeneral & {
4
+ /**
5
+ * Kanban general: columna de la tarjeta; `Board` lo envía cuando existe el provider de multiselección.
6
+ * Sin esto no hay lógica de selección masiva (p. ej. campaña).
7
+ */
8
+ boardColumnTitle?: KanbanColumnTitle;
9
+ /** Columna no base durante una sesión masiva: sin interacción con las cards. */
10
+ isBulkColumnLocked?: boolean;
11
+ };
12
+ declare const Task: ({ id, task, endDate, users, willBePaused, nameProject, comments, priority, difficulty, responsible, nameRequiredTask, nameRequiredTaskResponsible, statusRequiredTask, status, repeatsToDo, repeats, medioName, paused, idProject, atraso, categoria, cambio_arte, name_father_required_task, name_father_required_task_responsible, boardColumnTitle, isBulkColumnLocked, }: TaskProps) => import("react/jsx-runtime").JSX.Element;
3
13
  export default Task;
@@ -0,0 +1,58 @@
1
+ import { QueryClient } from '@tanstack/react-query';
2
+ import { ReactNode } from 'react';
3
+ import { BulkUpdateTaskStatusEstatus } from '../core/types/bulk-update-task-status.types';
4
+ /**
5
+ * Tras un bulk-update exitoso, el tablero que montó el provider decide qué queries invalidar
6
+ * (listado infinito vs campaña `tasksProject`, etc.). Misma firma para ambos Kanban.
7
+ */
8
+ export type KanbanBulkInvalidateAfterSuccess = (queryClient: QueryClient) => Promise<void>;
9
+ /** Títulos de columna compartidos por Kanban listado y Kanban campaña (`Board`). */
10
+ export type KanbanColumnTitle = 'Por hacer' | 'Trabajando' | 'Completadas';
11
+ export type KanbanBulkSelectionContextValue = {
12
+ selectedTaskIds: number[];
13
+ baseColumn: KanbanColumnTitle | null;
14
+ /** Hay al menos un id seleccionado (útil para contadores en toolbar). */
15
+ isMultiSelectActive: boolean;
16
+ /** Hay “sesión” de selección masiva: columna base fijada; otras columnas bloqueadas hasta la X del toolbar. */
17
+ isBulkSessionActive: boolean;
18
+ isFullColumnSelected: boolean;
19
+ /**
20
+ * Destino del POST masivo (`BulkUpdateTaskStatusParams.estatus`: 0 por hacer, 1 trabajando, 2 completadas).
21
+ * Se asigna al elegir “Mover a …”; `null` si no hay confirmación pendiente.
22
+ */
23
+ pendingTargetStatus: BulkUpdateTaskStatusEstatus | null;
24
+ isBulkLoading: boolean;
25
+ /** Lo inyecta el provider padre; la toolbar lo usa tras un bulk exitoso. */
26
+ invalidateAfterBulkSuccess: KanbanBulkInvalidateAfterSuccess;
27
+ toggleTaskSelection: (taskId: number, columnTitle: KanbanColumnTitle) => void;
28
+ /**
29
+ * Quita todos los ids y el flag «toda la columna seleccionada».
30
+ * Si al quedar 0 ids sigue había sesión masiva (`baseColumn` no nulo), el efecto de sincronización
31
+ * del provider llama a `exitBulkSelectionMode()` y cierra el modo por completo (igual que la X de la toolbar).
32
+ */
33
+ deselectAllSelectedTasks: () => void;
34
+ /**
35
+ * Cierra el modo por completo (toolbar X): ids, columna base, fases y loading.
36
+ */
37
+ exitBulkSelectionMode: () => void;
38
+ /**
39
+ * “Seleccionar todas” en la columna indicada: obtiene ids (paginado en listado, o en memoria en campaña) y los asigna.
40
+ * Si aún no hay baseColumn, la fija en `columnTitle`.
41
+ */
42
+ selectEntireColumn: (columnTitle: KanbanColumnTitle, fetchAllIds: () => Promise<number[]>) => Promise<void>;
43
+ setPendingTargetStatus: (status: BulkUpdateTaskStatusEstatus | null) => void;
44
+ setIsBulkLoading: (loading: boolean) => void;
45
+ };
46
+ type KanbanBulkSelectionProviderProps = {
47
+ children: ReactNode;
48
+ invalidateAfterBulkSuccess: KanbanBulkInvalidateAfterSuccess;
49
+ };
50
+ /**
51
+ * Estado de multiselección masiva para cualquier tablero que use `Board`/`Task` con las tres columnas estándar.
52
+ * Cada vista (Kanban listado, Kanban campaña) monta su propio provider y pasa la invalidación de queries que corresponda.
53
+ */
54
+ export declare function KanbanBulkSelectionProvider({ children, invalidateAfterBulkSuccess, }: KanbanBulkSelectionProviderProps): import("react/jsx-runtime").JSX.Element;
55
+ export declare function useKanbanBulkSelection(): KanbanBulkSelectionContextValue;
56
+ /** Sin provider: `undefined` (p. ej. Kanban de campaña sin modo masivo o vistas sin tablero). */
57
+ export declare function useKanbanBulkSelectionOptional(): KanbanBulkSelectionContextValue;
58
+ export {};
@@ -0,0 +1,16 @@
1
+ import { AxiosInstance } from 'axios';
2
+ import { BulkUpdateTaskStatusParams, BulkUpdateTaskStatusResponse } from '../types/bulk-update-task-status.types';
3
+ /**
4
+ * POST masivo sobre `tasks_api` (misma baseURL que el resto de tareas). Debe coincidir con backend/doc desplegados;
5
+ * evitar rutas duplicadas tipo `…/tareas/tareas/…`.
6
+ */
7
+ export declare const BULK_UPDATE_TASK_STATUS_PATH = "/api/tareas/bulk-update-status";
8
+ /**
9
+ * Envía el POST masivo usando la instancia `tasks_api` del contexto (Bearer y baseURL ya configurados).
10
+ * No lanza si el 200 incluye `notFoundIds`: es parte del contrato exitoso; el consumidor decide cómo reconciliar.
11
+ */
12
+ export declare function bulkUpdateTaskStatus(tasks_api: AxiosInstance, params: BulkUpdateTaskStatusParams): Promise<BulkUpdateTaskStatusResponse>;
13
+ /**
14
+ * Mensaje legible para errores de red o HTTP al llamar al bulk-update (p. ej. para `mutation.error.message` o toasts en pasos posteriores).
15
+ */
16
+ export declare function getBulkUpdateTaskStatusErrorMessage(error: unknown): string;
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Contrato del endpoint de actualización masiva de estatus (Kanban general).
3
+ * Campos del JSON: `tasks_ids`, `estatus`, `user_id`; `ended_at` opcional cuando el destino es completadas.
4
+ */
5
+ export type BulkUpdateTaskStatusEstatus = 0 | 1 | 2;
6
+ export interface BulkUpdateTaskStatusParams {
7
+ tasks_ids: number[];
8
+ estatus: BulkUpdateTaskStatusEstatus;
9
+ user_id: number;
10
+ /** ISO 8601; aplica cuando `estatus === 2`; si se omite, el backend puede usar la fecha actual. */
11
+ ended_at?: string;
12
+ }
13
+ /** Cuerpo de respuesta HTTP 200 del bulk-update (persistencia aplicada o ids no encontrados sin fallar la petición). */
14
+ export interface BulkUpdateTaskStatusResponse {
15
+ updatedCount: number;
16
+ updatedIds: number[];
17
+ notFoundIds: number[];
18
+ }
@@ -0,0 +1,18 @@
1
+ import { UseMutationResult } from '@tanstack/react-query';
2
+ import { BulkUpdateTaskStatusParams, BulkUpdateTaskStatusResponse } from '../core/types/bulk-update-task-status.types';
3
+ /**
4
+ * Variables que puede pasar la UI al mutar: mismos campos que el API excepto `user_id`,
5
+ * que el hook rellena con el usuario de sesión si no viene en el objeto.
6
+ */
7
+ export type BulkUpdateTaskStatusMutationPayload = Omit<BulkUpdateTaskStatusParams, 'user_id'> & {
8
+ user_id?: number;
9
+ };
10
+ /**
11
+ * Mutación TanStack Query para el bulk-update de estatus (tablero listado y tablero campaña).
12
+ *
13
+ * - HTTP: `tasks_api` + `bulkUpdateTaskStatus` (POST a `BULK_UPDATE_TASK_STATUS_PATH`).
14
+ * - Sin toasts ni logs: el consumidor (p. ej. paso 4) usa `onSuccess` / `onError` o el estado de la mutación.
15
+ * - Errores axios se convierten en `Error` con texto útil vía `getBulkUpdateTaskStatusErrorMessage`.
16
+ */
17
+ export declare function useBulkUpdateTaskStatus(): UseMutationResult<BulkUpdateTaskStatusResponse, Error, BulkUpdateTaskStatusMutationPayload>;
18
+ export type { BulkUpdateTaskStatusParams, BulkUpdateTaskStatusResponse };
@@ -1,5 +1,13 @@
1
1
  declare const useDoneTasks: () => {
2
2
  doneTasks: import('@tanstack/react-query').UseInfiniteQueryResult<import('@tanstack/query-core').InfiniteData<any, unknown>, Error>;
3
3
  total: number;
4
+ filtersToSend: {
5
+ owner: {
6
+ user: number;
7
+ config: any;
8
+ role: string;
9
+ };
10
+ status: string;
11
+ };
4
12
  };
5
13
  export default useDoneTasks;
@@ -1,5 +1,13 @@
1
1
  declare const useWorkingTasks: () => {
2
2
  workingTasks: import('@tanstack/react-query').UseInfiniteQueryResult<import('@tanstack/query-core').InfiniteData<any, unknown>, Error>;
3
3
  total: number;
4
+ filtersToSend: {
5
+ owner: {
6
+ user: number;
7
+ config: any;
8
+ role: string;
9
+ };
10
+ status: string;
11
+ };
4
12
  };
5
13
  export default useWorkingTasks;
@@ -0,0 +1,15 @@
1
+ import { AxiosInstance } from 'axios';
2
+ type KanbanListadoListStatus = 'por_hacer' | 'trabajando' | 'completadas';
3
+ /**
4
+ * Ids de una columna del tablero **listado** (infinite query + `getTasksResponse`), paginando en cliente.
5
+ * No aplica al Kanban campaña (ahí los datos vienen en una sola query y los ids se derivan en memoria).
6
+ *
7
+ * Solo incluye tareas elegibles para el flujo masivo (misma regla que el menú «mover» en la card),
8
+ * para que «Seleccionar todas» no marque dependencias aún bloqueadas.
9
+ */
10
+ export declare function fetchAllKanbanListadoTaskIds(params: {
11
+ tasks_api: AxiosInstance;
12
+ filters: Record<string, unknown>;
13
+ status: KanbanListadoListStatus;
14
+ }): Promise<number[]>;
15
+ export {};
@@ -0,0 +1,29 @@
1
+ import { QueryClient } from '@tanstack/react-query';
2
+ /**
3
+ * Invalidación centralizada de queries de tareas en tableros Kanban (`@tanstack/react-query`).
4
+ *
5
+ * **Listado (tres columnas infinitas):** claves `['to_do_tasks', filters]`, etc. Se invalida por **prefijo**
6
+ * `[root]` para cubrir todas las variantes de filtros (bulk, refresco layout).
7
+ *
8
+ * **Campaña:** una sola familia `['tasksProject', filtersToSend, project]`; el prefijo `['tasksProject']`
9
+ * invalida todas las instancias tras un bulk en el tablero campaña.
10
+ *
11
+ * En otros flujos (p. ej. pausa o mover una sola tarea) puede convenir invalidar con la `queryKey` completa
12
+ * en la mutación concreta; aquí solo agrupamos los casos «invalidar todo el tablero» por familia de clave.
13
+ */
14
+ /** Raíces alineadas con `useToDoTasks`, `useWorkingTasks` y `useDoneTasks` (tablero listado). */
15
+ export declare const KANBAN_LISTADO_COLUMN_QUERY_ROOTS: readonly ["to_do_tasks", "working_tasks", "done_tasks"];
16
+ /** Raíz de `useQuery` en `InfoCampaniaProvider` (`tasksProject`). */
17
+ export declare const KANBAN_CAMPAIGN_TASKS_QUERY_ROOT: "tasksProject";
18
+ /**
19
+ * Tras un bulk-update en el tablero **listado**: obsoletas todas las variantes de filtros por columna.
20
+ */
21
+ export declare function invalidateKanbanListadoTasksQueries(queryClient: QueryClient): Promise<void>;
22
+ /**
23
+ * Botón “refrescar” del layout en tablero listado: invalida y refetch explícito de las tres columnas.
24
+ */
25
+ export declare function invalidateAndRefetchKanbanListadoTasks(queryClient: QueryClient): Promise<void>;
26
+ /**
27
+ * Tras un bulk-update en el tablero **campaña**: obsoleta la query de proyecto (cualquier filtro/proyecto activo).
28
+ */
29
+ export declare function invalidateKanbanCampaignTasksQueries(queryClient: QueryClient): Promise<void>;
@@ -1,3 +1,8 @@
1
+ /**
2
+ * Tamaño de página del infinite query de las columnas del Kanban **listado** (`useToDoTasks`, etc.).
3
+ * `fetchAllKanbanListadoTaskIds` y `fetchNextPage` deben usar el mismo valor para no cortar mal el bucle.
4
+ */
5
+ export declare const KANBAN_LISTADO_INFINITE_PAGE_SIZE = 30;
1
6
  export declare const fetchNextPage: (key: any) => void;
2
7
  export declare const getPaginationEstructure: (page: number) => {
3
8
  pagination: {
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Elegibilidad para multiselección masiva del Kanban (listado y campaña) y para mostrar el menú «mover»
3
+ * en la card (`Task` → `ButtonMoveTask`): una sola fuente de verdad.
4
+ *
5
+ * Incluye:
6
+ * - **Unidades / repeticiones (rutas):** si la tarea tiene cuota (`repeatsToDo > 0`), no se puede mover ni
7
+ * seleccionar en bloque hasta que el contador esté completo (`repeats === repeatsToDo`). Antes, el caso
8
+ * `repeatsToDo === 1` se trataba como «sin repeticiones» y permitía `0/1` con menú mover y bulk.
9
+ * - **Dependencia:** misma regla que el render de `ButtonMoveTask` (tarea previa obligatoria incompleta bloquea).
10
+ */
11
+ export type TaskKanbanBulkEligibilityInput = {
12
+ status: number;
13
+ nameRequiredTask: string | null | undefined;
14
+ statusRequiredTask: number | null | undefined;
15
+ repeatsToDo?: number | null | undefined;
16
+ repeats?: number | null | undefined;
17
+ };
18
+ export declare function isTaskEligibleForKanbanBulkSelection(t: TaskKanbanBulkEligibilityInput): boolean;