import {Component, forwardRef} from '@angular/core'; import { DataCard, PreviousAbortionsSectionAbortions, PreviousBirthsSectionBirths, PreviousBirthsSectionBirthsChild } from 'facade-api'; import {ControlContainer, ControlValueAccessor, NG_VALUE_ACCESSOR, NgForm} from '@angular/forms'; // @ts-ignore import deepEqual from 'deep-equal'; import {JsonTransformerUtil} from '../../../utils/json-transformer.util'; export const APP_PREVIOUS_PREGNANCIES_CONTROL_VALUE_ACCESSOR: any = { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => PreviousPregnanciesComponent), multi: true }; @Component({ selector: 'app-previous-pregnancies', templateUrl: './previous-pregnancies.component.html', styleUrls: ['./previous-pregnancies.component.scss'], providers: [APP_PREVIOUS_PREGNANCIES_CONTROL_VALUE_ACCESSOR], viewProviders: [ { provide: ControlContainer, useExisting: NgForm } ] }) export class PreviousPregnanciesComponent implements ControlValueAccessor { public disabled = false; public yes = true; public no = false; public abortions: AbortionBundle[] = []; public births: BirthBundle[] = []; private innerModel: DataCard | undefined; private dirtyAble = false; private onChangeCallback: (newValue: DataCard|undefined) => any = () => {}; private onTouchedCallback: () => any = () => {}; constructor() { } get value(): DataCard|undefined { return this.innerModel; } set value(value: DataCard|undefined) { if (!deepEqual(value, this.innerModel)) { this.innerModel = value; this.abortions = this.innerModel?.previousAbortionsSection?.abortions?.map( (abortion, index) => new AbortionBundle(abortion, index) ) || []; this.births = this.innerModel?.previousBirthsSection?.births?.map( (birth, index) => new BirthBundle(birth, index) ) || []; if (this.dirtyAble) { this.onChangeCallback(value); } if (!this.dirtyAble && this.innerModel) { // We don't want to mark the field as dirty while data gets initialized this.dirtyAble = true; } } } registerOnChange(fn: any): void { this.onChangeCallback = fn; } registerOnTouched(fn: any): void { this.onTouchedCallback = fn; } setDisabledState(isDisabled: boolean): void { this.disabled = isDisabled; } writeValue(newValue: DataCard): void { this.value = newValue; } public removeAbortion(item: AbortionBundle): void { const card = this.copyCard(); // tslint:disable-next-line:no-non-null-assertion if we call this we have an abortion to remove and hence things should not be null-ish card.previousAbortionsSection!.abortions!.splice(item.index, 1); this.value = card; } public removeBirth(item: BirthBundle): void { const card = this.copyCard(); // tslint:disable-next-line:no-non-null-assertion -- if we call this we have a birth to remove and hence things should not be null-ish card.previousBirthsSection!.births!.splice(item.index, 1); this.value = card; } public addFetus(item: BirthBundle): void { const fetus: PreviousBirthsSectionBirthsChild = { childsCurrentHealthStatus: '', sex: undefined, outcome: undefined, birthWeight: { value: undefined, unit: 'g' } }; item.birth.children.push(fetus); } public removeFetus(item: BirthBundle, fetusIndex: number): void { item.birth.children.splice(fetusIndex, 1); } public addAbortion(): void { const abortion: PreviousAbortionsSectionAbortions = { date: undefined, type: undefined, gestationLength: { value: undefined, unit: 'w' }, indication: '' }; const card = this.copyCard(); // tslint:disable-next-line:no-non-null-assertion -- if we call this we have a birth to remove and hence things should not be null-ish card.previousAbortionsSection!.abortions!.unshift(abortion); this.value = card; } public addBirth(): void { const birth = { date: undefined, gestationLength: { value: undefined, unit: 'd' }, birthPlace: '', pregnancySummary: '', birthSummary: '', subjectiveBirthExperience: undefined, puerperalSepsis: undefined, children: [ { childsCurrentHealthStatus: '', sex: undefined, outcome: undefined, birthWeight: { value: undefined, unit: 'g' } } ] } as unknown as PreviousBirthsSectionBirths; const card = this.copyCard(); // tslint:disable-next-line:no-non-null-assertion -- if we call this we have a birth to remove and hence things should not be null-ish card.previousBirthsSection!.births!.unshift(birth); this.value = card; } /** * Makes a deep copy of the data-card. * This is needed so we can mutate a copy of the card in order to hook into the natural change detection flow */ private copyCard(): DataCard { return JsonTransformerUtil.transformDates(JSON.parse(JSON.stringify(this.value))); } } export class AbortionBundle { constructor(public abortion: PreviousAbortionsSectionAbortions, public readonly index: number) {} get year(): number|undefined { if (!this.abortion.date) { return undefined; } return this.abortion.date.getUTCFullYear(); } set year(newValue: number|undefined) { if (newValue == null) { this.abortion.date = undefined; return; } const toEdit = this.abortion.date || new Date(); toEdit.setUTCFullYear(newValue); this.abortion.date = toEdit; } } export class BirthBundle { constructor(public birth: PreviousBirthsSectionBirths, public readonly index: number) {} get gestationAge(): string { const weeks = Math.floor((this.birth.gestationLength?.value || 0) / 7.0); const days = (this.birth.gestationLength?.value || 0) % 7.0; return `${weeks}+${days}`; } set gestationAge(newValue: string) { const parts = newValue.split('+'); const weeks = Number(parts?.[0]); const days = Number(parts?.[1] || 0); if (!this.birth.gestationLength) { this.birth.gestationLength = {unit: 'd', value: 0}; } if (weeks != null && !isNaN(weeks)) { this.birth.gestationLength.value = weeks * 7 + days; } else { this.birth.gestationLength.value = 0; } } get birthYear(): number|undefined { if (!this.birth.date) { return undefined; } return this.birth.date.getUTCFullYear(); } set birthYear(newValue: number|undefined) { if (newValue == null) { this.birth.date = undefined; return; } const toEdit = this.birth.date || new Date(); toEdit.setUTCFullYear(newValue); this.birth.date = toEdit; } }