feat(WP-67): merge behandelportal into this repo as a monorepo
Restructures into apps/ssp + apps/behandelportal (two Angular projects) plus libs/shared + libs/beheer (cross-app libraries), replacing WP-61's separate sibling repo. That split had already produced real drift: a hand-vendored copy of the backend's OpenAPI doc, a shared/ui+layout tree forked and silently diverging (7 files), and beheer + the styles.scss token bridge duplicated byte-for-byte across both repos. - git mv the SSP's src/app/* into apps/ssp/; fold shared/, beheer/, environments/, the Storybook docs/*.mdx, and styles.scss into libs/shared + libs/beheer (all confirmed identical between the two repos before merging). auth stays deliberately duplicated per ADR-0002 (actor-specific, expected to diverge) - amended there. - One generated API client (libs/shared), no more vendored swagger.json. - .dependency-cruiser split into a base factory + one config per app, and Storybook into .storybook-ssp/.storybook-behandelportal - both forced by the @auth/* alias resolving to different directories per app. - SiteHeaderComponent/ShellComponent gained HEADER_NAV_ITEMS/ HEADER_ADMIN_LINKS/DEBUG_PANEL injection tokens so each app supplies its own nav/admin-links/dev-panel instead of one being hardcoded. - CLAUDE.md, ARCHITECTURE.md, dependencies.md, and ADR-0002 updated; WP-67 backlog entry documents the full decision trail. npm run ci green (lint, dep:check x2, 360 tests across ssp/ behandelportal/shared/beheer, both localized builds, backend tests, snippet + api-client drift); both dev servers, both Storybook instances, and docker compose verified working. The old sibling repo (/home/eho/repos/behandelportal) is left untouched, not deleted. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
import { Component, computed, input, output } from '@angular/core';
|
||||
import { formatDatumNl } from '@shared/kernel/datum';
|
||||
import { ButtonComponent } from '@shared/ui/button/button.component';
|
||||
import { AlertComponent } from '@shared/ui/alert/alert.component';
|
||||
import { Aanvraag } from '@registratie/domain/aanvraag';
|
||||
import { TYPE_LABELS } from '@registratie/domain/aanvraag-view';
|
||||
import { blockActions } from '@registratie/domain/block-actions';
|
||||
|
||||
/** Organism: a resumable Concept ("lopende aanvraag") on the dashboard, rendered as
|
||||
a CIBG "melding" (warning) with its actions — verwijderen as a link, aanvraag
|
||||
openen as a button. Which actions show is driven by the pure `blockActions(status)`;
|
||||
the block only renders. Submitted/resolved aanvragen are NOT rendered here — they
|
||||
render as CIBG "aanvragen" rows (see application-link + aanvraag-view). */
|
||||
@Component({
|
||||
selector: 'app-aanvraag-block',
|
||||
imports: [ButtonComponent, AlertComponent],
|
||||
styles: [
|
||||
`
|
||||
.actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--rhc-space-max-md);
|
||||
margin-block-start: var(--rhc-space-max-sm);
|
||||
}
|
||||
`,
|
||||
],
|
||||
template: `
|
||||
@if (aanvraag().status.tag === 'Concept') {
|
||||
<app-alert type="warning">
|
||||
<h3 class="h5">{{ typeLabel() }}</h3>
|
||||
<p>{{ conceptText() }}</p>
|
||||
<div class="actions">
|
||||
@if (actions().includes('cancel')) {
|
||||
<app-button variant="subtle" (click)="cancel.emit()" i18n="@@aanvraagBlock.verwijderen"
|
||||
>Verwijderen</app-button
|
||||
>
|
||||
}
|
||||
@if (actions().includes('resume')) {
|
||||
<app-button (click)="resume.emit()" i18n="@@aanvraagBlock.openen"
|
||||
>Aanvraag openen</app-button
|
||||
>
|
||||
}
|
||||
</div>
|
||||
</app-alert>
|
||||
}
|
||||
`,
|
||||
})
|
||||
export class AanvraagBlockComponent {
|
||||
aanvraag = input.required<Aanvraag>();
|
||||
|
||||
resume = output<void>();
|
||||
cancel = output<void>();
|
||||
|
||||
protected typeLabel = computed(() => TYPE_LABELS[this.aanvraag().type]);
|
||||
protected actions = computed(() => blockActions(this.aanvraag().status));
|
||||
|
||||
// ponytail: display-only deadline derived as createdAt + 30 dagen; move to a
|
||||
// server-sent `completeBefore` on the DTO when the expiry rule becomes real.
|
||||
private deadline = computed(() => {
|
||||
const d = new Date(this.aanvraag().createdAt);
|
||||
d.setDate(d.getDate() + 30);
|
||||
return d.toISOString();
|
||||
});
|
||||
|
||||
/** The melding body for a Concept: wizard not finished + complete-before date. */
|
||||
protected conceptText = computed(() => {
|
||||
const s = this.aanvraag().status;
|
||||
if (s.tag !== 'Concept') return '';
|
||||
return $localize`:@@aanvraagBlock.conceptMelding:Deze aanvraag is nog niet volledig afgerond — u bent gebleven bij stap ${s.stepIndex + 1}:stap: van ${s.stepCount}:totaal:. Rond de aanvraag af vóór ${formatDatumNl(this.deadline())}:datum:.`;
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user