import { Component, computed, input, output, signal } from '@angular/core'; import { FormsModule } from '@angular/forms'; import { CheckboxComponent } from '@shared/ui/atoms/checkbox/checkbox.component'; import { ButtonComponent } from '@shared/ui/atoms/button/button.component'; import { TextInputComponent } from '@shared/ui/atoms/text-input/text-input.component'; import { textOf } from '@shared/kernel/rich-text'; import { LibraryPassage } from '@brief/domain/brief'; /** Molecule: multi-select list of the section's library passages. One "Voeg toe" inserts ALL checked passages at once (a single message upstream) — there is no single-insert path. Presentational: emits the chosen passages in list order. Superseded by `besluit-panel`'s guided drafting: no consumer left in `src/app` outside its own story. Kept for now rather than deleted in-flight of an unrelated WP; a future cleanup can remove it. */ @Component({ selector: 'app-passage-picker', imports: [FormsModule, CheckboxComponent, ButtonComponent, TextInputComponent], styles: [ ` :host { display: block; background: var(--rhc-color-wit); border: var(--rhc-border-width-sm) solid var(--rhc-color-border-default); border-radius: var(--rhc-border-radius-md); padding: var(--rhc-space-max-md); } .search { margin-block-end: var(--rhc-space-max-md); } ul { list-style: none; margin: 0 0 var(--rhc-space-max-md); padding: 0; display: grid; gap: var(--rhc-space-max-sm); } .scope { color: var(--rhc-color-foreground-subtle); } .empty { color: var(--rhc-color-foreground-subtle); font-style: italic; margin: 0 0 var(--rhc-space-max-md); } `, ], template: ` {{ addLabel() }} ({{ count() }}) `, }) export class PassagePickerComponent { passages = input.required(); insert = output(); addLabel = input($localize`:@@brief.picker.add:Voeg toe`); globalLabel = input($localize`:@@brief.picker.global:algemeen`); beroepLabel = input($localize`:@@brief.picker.beroep:beroepsspecifiek`); searchLabel = input($localize`:@@brief.picker.search:Zoek in standaardteksten…`); noMatchLabel = input($localize`:@@brief.picker.noMatch:Geen standaardteksten gevonden.`); protected checked = signal>({}); protected query = signal(''); /** Client-side filter on label + rendered content text — the library is small, so no server search. Placeholder keys are searchable too (see `textOf`). */ protected filtered = computed(() => { const q = this.query().trim().toLowerCase(); if (!q) return this.passages(); return this.passages().filter( (p) => p.label.toLowerCase().includes(q) || textOf(p.content).includes(q), ); }); protected count = () => Object.values(this.checked()).filter(Boolean).length; protected set(id: string, on: boolean) { this.checked.update((c) => ({ ...c, [id]: on })); } protected add() { const chosen = this.passages().filter((p) => this.checked()[p.passageId]); if (chosen.length) { this.insert.emit(chosen); this.checked.set({}); } } }