import { ChangeDetectionStrategy, Component, computed, input, linkedSignal, output } from '@angular/core'; import type { DetailColumn } from './grid.types'; import { RowsTable } from './rows-table'; type Row = Record; /** * Ventana con las filas de un detalle de línea (lotes, números de serie): tabla editable con «Añadir fila» * y «Quitar». Solo emite `saved` al aceptar; cancelar descarta los cambios. */ @Component({ selector: 'sbo-line-detail-dialog', changeDetection: ChangeDetectionStrategy.OnPush, imports: [RowsTable], template: `
`, styles: ` .overlay { position: fixed; inset: 0; z-index: 50; display: flex; align-items: center; justify-content: center; padding: 16px; background: var(--overlay); } .dlg { display: flex; flex-direction: column; width: min(720px, 100%); max-height: 80vh; background: var(--win); border: 1px solid var(--line); border-radius: var(--radius-panel); overflow: hidden; box-shadow: var(--shadow-pop); } header { display: flex; align-items: baseline; gap: 10px; padding: 8px 12px; background: var(--panel); border-bottom: 1px solid var(--line); } h2 { margin: 0; font-size: 14px; font-weight: 600; } .sub { font-size: 12px; color: var(--quiet); } .body { overflow: auto; padding: 8px 12px; } .hint { margin: 0; padding: 6px 12px; font-size: 12px; color: var(--quiet); border-top: 1px solid var(--line-soft); } .hint.bad { color: var(--err); } footer { display: flex; align-items: center; gap: 8px; padding: 8px 12px; border-top: 1px solid var(--line); background: var(--panel); } .sp { flex: 1; } `, }) export class LineDetailDialog { readonly title = input.required(); readonly subtitle = input(''); readonly columns = input.required(); readonly initial = input([]); readonly readonly = input(false); /** Texto bajo la tabla, calculado por quien abre la ventana con las filas en edición. */ readonly hintFor = input<((rows: readonly Row[]) => { text: string; bad: boolean }) | undefined>(undefined); readonly saved = output(); readonly closed = output(); protected readonly rows = linkedSignal(() => this.initial().map((r) => ({ ...r }))); protected readonly hintState = computed(() => this.hintFor()?.(this.rows()) ?? { text: '', bad: false }); protected readonly hint = computed(() => this.hintState().text); protected readonly bad = computed(() => this.hintState().bad); protected add(): void { this.rows.update((rs) => [...rs, {}]); } /** Las filas sin ningún dato no se guardan. */ protected clean(): Row[] { return this.rows().filter((r) => this.columns().some((c) => r[c.key] !== null && r[c.key] !== undefined && r[c.key] !== '')); } }