panels-origin/web-panel/utils/workProgramGantt.ts
Alberto Martinez 17c40c66a6 feat: ver el programa de obra como Gantt (no la grilla de ceros)
<!-- CURSOR_AGENT_PR_BODY_BEGIN -->
## Qué pasaba

El Excel que importaste es **por partida** (erogaciones semanales). Eso llena **Partidas** y el **Gantt**, no las barras de concepto. La pestaña que se abría era **Conceptos**, con 0–0 en cada semana.

Además el Gantt que ya existía tenía el encabezado de semanas mal alineado.

## Cambio

- **Gantt es la primera pestaña** y se abre sola si el programa es solo por partida.
- Cada partida es una barra de la primera a la última semana con monto (tooltip con total).
- En Conceptos, si no hay barras, se explica que hay que mirar Gantt o Partidas.

## Cómo probar

1. Mergear y recargar (solo front; no hay Liquibase).
2. Abrir Programa de obra en la obra ya importada: debe entrar en **Gantt** con barras (A001, A002, …) sobre Sem 1–9.
3. Partidas: montos semanales (no ceros).
4. Conceptos: sigue en 0 y el aviso; es normal en este Excel.

<!-- CURSOR_AGENT_PR_BODY_END -->

<div><a href="https://cursor.com/agents/bc-d8a5d34a-ead9-4912-8296-322cff799783?cursor_ref=pr_footer&cursor_cta=open_in_web"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/open-in-web-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/open-in-web-light.png"><img alt="Open in Web" width="114" height="28" src="https://cursor.com/assets/images/open-in-web-dark.png"></picture></a>&nbsp;<a href="https://cursor.com/background-agent?bcId=bc-d8a5d34a-ead9-4912-8296-322cff799783&cursor_ref=pr_footer&cursor_cta=open_in_cursor"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/open-in-cursor-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/open-in-cursor-light.png"><img alt="Open in Cursor" width="131" height="28" src="https://cursor.com/assets/images/open-in-cursor-dark.png"></picture></a>&nbsp;</div>
2026-09-08 22:12:23 +00:00

37 lines
1.3 KiB
TypeScript

/** period_index is 1-based (Sem 1 … Sem N). */
export function ganttSpan(
activeIndexes: number[],
periodCount: number,
): { leftPct: number; widthPct: number; first: number; last: number } | null {
const n = Number(periodCount) || 0;
const idxs = activeIndexes.filter((i) => Number.isFinite(i) && i >= 1 && (n <= 0 || i <= n));
if (!idxs.length || n <= 0) return null;
const first = Math.min(...idxs);
const last = Math.max(...idxs);
return {
first,
last,
leftPct: ((first - 1) / n) * 100,
widthPct: ((last - first + 1) / n) * 100,
};
}
export function periodHasAmount(
periods: { period_id?: number; period_index?: number; amount?: number }[],
week: { id: number; period_index: number },
): number {
const slot = periods.find((x) => x.period_index === week.period_index || x.period_id === week.id);
return Number(slot?.amount || 0);
}
export function periodHasConceptBar(
periods: { period_index?: number; start_pct?: number; end_pct?: number }[],
week: { period_index: number },
): { start_pct: number; end_pct: number } | null {
const slot = periods.find((x) => x.period_index === week.period_index);
if (!slot) return null;
const start = Number(slot.start_pct || 0);
const end = Number(slot.end_pct || 0);
if (start === 0 && end === 0) return null;
return { start_pct: start, end_pct: Math.max(start, end) };
}