Merge pull request #184 in TEA/mina-sidor-fa-web from feature/TV-731-refaktorisera-avvikelserapport to develop

Squashed commit of the following:

commit 62ea9988b66107457da553bf2cd0e423a6f44606
Author: Daniel Appelgren <daniel.appelgren@arbetsformedlingen.se>
Date:   Thu Oct 7 08:26:52 2021 +0200

    simplify post requests

commit bf35fa3f4972536c52c15d0ef942678e565fff74
Author: Daniel Appelgren <daniel.appelgren@arbetsformedlingen.se>
Date:   Thu Oct 7 07:44:15 2021 +0200

    Update deltagare-avvikelse.component.html

commit 22e55d0e51eb83f2d8bbc6c9e3a65d2bd479fa92
Author: Daniel Appelgren <daniel.appelgren@arbetsformedlingen.se>
Date:   Wed Oct 6 17:06:27 2021 +0200

    wip

commit 2836a0c7687755dbf7b7e20d98f24d9bf3bc3f40
Author: Daniel Appelgren <daniel.appelgren@arbetsformedlingen.se>
Date:   Wed Oct 6 16:55:14 2021 +0200

    merge with develop

commit 77f16e8a1961b623bb741056882a1df3480f9d13
Merge: a4e3b940 890573b1
Author: Daniel Appelgren <daniel.appelgren@arbetsformedlingen.se>
Date:   Wed Oct 6 16:51:50 2021 +0200

    Merge branch 'develop' into feature/TV-731-refaktorisera-avvikelserapport

    # Conflicts:
    #	apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-details/pages/deltagare-reports/deltagare-avvikelse/deltagare-avvikelse.component.html
    #	apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-details/pages/deltagare-reports/deltagare-avvikelse/deltagare-avvikelse.component.ts

commit a4e3b940ca9e2e484f92dd5d05e14a65e714b897
Author: Daniel Appelgren <daniel.appelgren@arbetsformedlingen.se>
Date:   Wed Oct 6 16:38:35 2021 +0200

    Refactor avvikelse

commit 5e1923324801baba29bcf2273908075ccc5e29e1
Author: Daniel Appelgren <daniel.appelgren@arbetsformedlingen.se>
Date:   Wed Oct 6 15:13:34 2021 +0200

    Update deltagare-avvikelse.component.html

commit e57b42761b07899f3922f65995bc905abed44c83
Merge: 14a776bc 19a3b05e
Author: Erik Tiekstra <erik.tiekstra@arbetsformedlingen.se>
Date:   Wed Oct 6 12:54:23 2021 +0200

    Merged develop

commit 14a776bc2e72dd7145dfe27e5e5745cc0d5b43a1
Author: Daniel Appelgren <daniel.appelgren@arbetsformedlingen.se>
Date:   Wed Oct 6 12:33:57 2021 +0200

    correct API

commit 9c155b578454865aaa6a4557348d3fd460459434
Author: Daniel Appelgren <daniel.appelgren@arbetsformedlingen.se>
Date:   Wed Oct 6 11:36:38 2021 +0200

    match utv API

commit 6625524adab2e04269ad14a3c581505e83c8483a
Merge: 2a9cbee7 3d941fdd
Author: Daniel Appelgren <daniel.appelgren@arbetsformedlingen.se>
Date:   Wed Oct 6 10:45:46 2021 +0200

    Merge branch 'develop' into feature/TV-731-refaktorisera-avvikelserapport

commit 2a9cbee7e544decb0a897063bcbbe6b0ac883608
Author: Daniel Appelgren <daniel.appelgren@arbetsformedlingen.se>
Date:   Tue Oct 5 15:06:42 2021 +0200

    Update deltagare-avvikelse.component.ts
This commit is contained in:
Daniel Appelgren
2021-10-07 09:28:58 +02:00
parent 890573b1fe
commit 28f94c7a29
9 changed files with 267 additions and 218 deletions

View File

@@ -1,89 +1,104 @@
<msfa-layout *ngIf="avrop$ | async as avrop"> <msfa-layout *ngIf="avrop$ | async as avrop; else skeletonRef">
<msfa-report-layout <msfa-report-layout
reportTitle="Avvikelserapport" [currentStep]="currentStep"
[totalAmountOfSteps]="totalAmountOfSteps"
description="Här rapporterar du deltagarens frånvaro och eventuella misskötsel i tjänsten. Rapportering via avvikelserapport ska också ske om tjänsten inte fungerar för deltagaren." description="Här rapporterar du deltagarens frånvaro och eventuella misskötsel i tjänsten. Rapportering via avvikelserapport ska också ske om tjänsten inte fungerar för deltagaren."
reportSubTitle="Skapa rapport" reportSubTitle="Skapa rapport"
[totalAmountOfSteps]="totalAmountOfSteps" reportTitle="Avvikelserapport"
[currentStep]="currentStep"
[form]="avvikelseFormGroup"
[avrop]="avrop"
[reportName]="(alternativeFormControl.value === 'franvaro') ? 'frånvarorapport' : 'avvikelsereapport'"
[showSuccessNotification]="showSuccessNotification$ | async"
[showDangerNotification]="showDangerNotification$ | async"
> >
<div *ngIf="submittedDate$ | async as submittedDate; " class="deltagare-avvikelse__confirmation">
<digi-notification-alert
af-heading="Allt gick bra"
af-heading-level="h3"
af-variation="success"
class="deltagare-avvikelse__alert"
>
<p>
Avvikelserapport för deltagare {{avrop.fullName}} är nu inskickad till
Arbetsförmedlingen och inväntar
godkännande.
</p>
<dl>
<dt>Datum</dt>
<dd>{{submittedDate | date:'longDate'}} kl {{submittedDate | date:'shortTime'}}</dd>
</dl>
</digi-notification-alert>
<msfa-back-link [route]="['../']">Tillbaka till deltagaren</msfa-back-link>
</div>
<ng-container *ngIf="currentStep === 1"> <ng-container *ngIf="currentStep === 1">
<h3 class="deltagare-avvikelse__alternative-heading">Vad är det du vill rapportera?</h3> <h3 class="deltagare-avvikelse__alternative-heading">Vad är det du vill rapportera?</h3>
<form [formGroup]="avvikelseFormGroup"> <form [formGroup]="avvikelseFormGroup">
<div class="deltagare-avvikelse__alternative"> <div class="deltagare-avvikelse__alternative">
<digi-ng-form-radiobutton-group <digi-ng-form-radiobutton-group
(change)="setAlternative()"
[afRadiobuttons]="avvikelseAlternatives" [afRadiobuttons]="avvikelseAlternatives"
[formControlName]="alternativeFormControlName" [formControlName]="alternativeFormControlName"
(change)="setAlternative()"
></digi-ng-form-radiobutton-group> ></digi-ng-form-radiobutton-group>
<digi-form-validation-message <digi-form-validation-message
af-variation="error"
*ngIf="alternativeFormControl.invalid && alternativeFormControl.touched" *ngIf="alternativeFormControl.invalid && alternativeFormControl.touched"
af-variation="error"
> >
Alternativ är obligatoriskt Alternativ är obligatoriskt
</digi-form-validation-message> </digi-form-validation-message>
</div> </div>
<msfa-deltagare-orsaks-form <msfa-deltagare-orsaks-form
[franvaroOrsaker]="franvaroOrsaker$ | async"
[avvikelseOrsaker]="avvikelseOrsaker$ | async "
[andraKandaOrsaker]="andraKandaOrsaker$ | async"
[orsakerFormGroup]="avvikelseFormGroup.get('orsakerFormGroup')"
[avvikelseFormGroup]="avvikelseFormGroup"
[selectedAlternative]="alternativeFormControl.value"
(change)="setOrsakerChanged()" (change)="setOrsakerChanged()"
[andraKandaOrsaker]="andraKandaOrsaker$ | async"
[avvikelseFormGroup]="avvikelseFormGroup"
[avvikelseOrsaker]="avvikelseOrsaker$ | async "
[franvaroOrsaker]="franvaroOrsaker$ | async"
[orsakerFormGroup]="avvikelseFormGroup.get('orsakerFormGroup')"
[selectedAlternative]="alternativeFormControl.value"
></msfa-deltagare-orsaks-form> ></msfa-deltagare-orsaks-form>
<div *ngIf="showDescription" class="deltagare-avvikelse__description"> <div *ngIf="showDescription" class="deltagare-avvikelse__description">
<digi-ng-form-textarea <digi-ng-form-textarea
[formControlName]="descriptionFormControlName"
afLabel="Beskriv frånvaro"
[afSize]="sizeTextArea"
[afDisableValidStyle]="true" [afDisableValidStyle]="true"
[afMaxLength]="2000"
[afRequired]="true"
[afInvalidMessage]="descriptionFormControl.errors?.message" [afInvalidMessage]="descriptionFormControl.errors?.message"
[afInvalid]="descriptionFormControl?.invalid && descriptionFormControl.touched" [afInvalid]="descriptionFormControl?.invalid && descriptionFormControl.touched"
[afMaxLength]="2000"
[afRequired]="true"
[afSize]="sizeTextArea"
[formControlName]="descriptionFormControlName"
afLabel="Beskriv frånvaro"
></digi-ng-form-textarea> ></digi-ng-form-textarea>
</div> </div>
<msfa-deltagare-fragor-form <msfa-deltagare-fragor-form
*ngIf="showFragor" *ngIf="showFragor"
[avvikelseFormGroup]="avvikelseFormGroup"
[fragor1]="fragor1$ | async" [fragor1]="fragor1$ | async"
[fragor2]="fragor2$ | async" [fragor2]="fragor2$ | async"
[fragorFormGroup]="avvikelseFormGroup.get('fragorFormGroup')" [fragorFormGroup]="avvikelseFormGroup.get('fragorFormGroup')"
[avvikelseFormGroup]="avvikelseFormGroup"
[selectedOrsaksKod]="selectedOrsaksKod" [selectedOrsaksKod]="selectedOrsaksKod"
></msfa-deltagare-fragor-form> ></msfa-deltagare-fragor-form>
<div *ngIf="showDatePicker" class="deltagare-avvikelse__datepicker"> <div *ngIf="showDatePicker" class="deltagare-avvikelse__datepicker">
<digi-ng-form-datepicker <digi-ng-form-datepicker
[formControlName]="dateFormControlName"
[afLabel]="'Välj dag för ' + (alternativeFormControl.value === 'franvaro' ? 'frånvaro' : 'avvikelse')"
[afDisableValidStyle]="true" [afDisableValidStyle]="true"
[afMinDate]="setMinDate(avrop.startDate)" [afMinDate]="setMinDate(avrop.startDate)"
[afMaxDate]="setMaxDate" [afMaxDate]="setMaxDate"
[afInvalid]="avvikelseFormGroup.errors?.dateIsRequired" [afInvalid]="avvikelseFormGroup.errors?.dateIsRequired"
[afLabel]="'Välj dag för ' + (alternativeFormControl.value === 'franvaro' ? 'frånvaro' : 'avvikelse')"
[formControlName]="dateFormControlName"
></digi-ng-form-datepicker> ></digi-ng-form-datepicker>
<digi-form-validation-message af-variation="error" *ngIf="avvikelseFormGroup.errors?.dateIsRequired"> <digi-form-validation-message *ngIf="avvikelseFormGroup.errors?.dateIsRequired" af-variation="error">
{{avvikelseFormGroup.errors?.dateIsRequired}} {{avvikelseFormGroup.errors?.dateIsRequired}}
</digi-form-validation-message> </digi-form-validation-message>
</div> </div>
<div *ngIf="showDayOrPartOfDayPicker" class="deltagare-avvikelse__dayOrPartOfDay"> <div *ngIf="showDayOrPartOfDayPicker" class="deltagare-avvikelse__dayOrPartOfDay">
<digi-ng-form-radiobutton-group <digi-ng-form-radiobutton-group
[afRadiobuttons]="dayOrPartOfDay"
[formControlName]="dayOrPartOfDayFormControlName"
[afRequired]="dayOrPartOfDayFormControl.invalid && dayOrPartOfDayFormControl.touched"
(change)="setDayOrPartOfDayChanged()" (change)="setDayOrPartOfDayChanged()"
[afRadiobuttons]="dayOrPartOfDay"
[afRequired]="dayOrPartOfDayFormControl.invalid && dayOrPartOfDayFormControl.touched"
[formControlName]="dayOrPartOfDayFormControlName"
></digi-ng-form-radiobutton-group> ></digi-ng-form-radiobutton-group>
<digi-form-validation-message <digi-form-validation-message
af-variation="error"
*ngIf="dayOrPartOfDayFormControl.invalid && dayOrPartOfDayFormControl.touched" *ngIf="dayOrPartOfDayFormControl.invalid && dayOrPartOfDayFormControl.touched"
af-variation="error"
> >
{{dayOrPartOfDayFormControl.errors?.message}} {{dayOrPartOfDayFormControl.errors?.message}}
</digi-form-validation-message> </digi-form-validation-message>
@@ -91,51 +106,61 @@
<msfa-deltagare-time-picker <msfa-deltagare-time-picker
*ngIf="showTimePicker" *ngIf="showTimePicker"
[timepickerFormGroup]="avvikelseFormGroup.get('timepickerFormGroup')"
[avvikelseFormGroup]="avvikelseFormGroup" [avvikelseFormGroup]="avvikelseFormGroup"
[timepickerFormGroup]="avvikelseFormGroup.get('timepickerFormGroup')"
></msfa-deltagare-time-picker> ></msfa-deltagare-time-picker>
</form> </form>
</ng-container> </ng-container>
<msfa-deltagare-confirm-form <msfa-deltagare-confirm-form
*ngIf="currentStep === totalAmountOfSteps" *ngIf="currentStep === totalAmountOfSteps"
[formGroup]="avvikelseFormGroup"
[orsakskoderfranvaro]="franvaroOrsaker$ | async"
[andraKandaOrsaker]="andraKandaOrsaker$ | async" [andraKandaOrsaker]="andraKandaOrsaker$ | async"
[avvikelseOrsaker]="avvikelseOrsaker$ | async" [avvikelseOrsaker]="avvikelseOrsaker$ | async"
[formGroup]="avvikelseFormGroup"
[fragor1]="fragor1$ | async" [fragor1]="fragor1$ | async"
[fragor2]="fragor2$ | async" [fragor2]="fragor2$ | async"
[orsakskoderfranvaro]="franvaroOrsaker$ | async"
[selectedOrsak]="selectedOrsaksKod" [selectedOrsak]="selectedOrsaksKod"
></msfa-deltagare-confirm-form> ></msfa-deltagare-confirm-form>
<digi-notification-alert
*ngIf="error$ | async as error"
af-heading="Någonting gick fel"
af-variation="danger"
class="deltagare-avvikelse__alert"
>
<p>Kunde inte spara avvikelserapporten. Ladda om sidan och försök igen.</p>
<p *ngIf="error.message" class="msfa__small-text">{{error.message}}</p>
</digi-notification-alert>
<div class="deltagare-avvikelse__step-buttons-wrapper"> <div class="deltagare-avvikelse__step-buttons-wrapper">
<ng-container *ngIf="(showSuccessNotification$ | async) !== true"> <ng-container *ngIf="(submittedDate$ | async) === null">
<digi-button <digi-button
*ngIf="currentStep > 1"
class="deltagare-avvikelse__step-buttons-wrapper--space-right"
af-variation="secondary"
af-size="m"
(afOnClick)="previousStep()" (afOnClick)="previousStep()"
*ngIf="currentStep > 1"
af-size="m"
af-variation="secondary"
class="deltagare-avvikelse__step-buttons-wrapper--space-right"
> >
Tillbaka Tillbaka
</digi-button> </digi-button>
<digi-button *ngIf="currentStep === totalAmountOfSteps" af-size="m" (afOnClick)="openConfirmDialog = true"> <digi-button (afOnClick)="openConfirmDialog = true" *ngIf="currentStep === totalAmountOfSteps" af-size="m">
Skicka in Skicka in
</digi-button> </digi-button>
</ng-container> </ng-container>
<digi-button *ngIf="currentStep === (totalAmountOfSteps -1)" af-size="m" (afOnClick)="nextStep"> <digi-button (afOnClick)="nextStep" *ngIf="currentStep === (totalAmountOfSteps -1)" af-size="m">
Förhandsgranska Förhandsgranska
</digi-button> </digi-button>
<digi-button *ngIf="showSuccessNotification$ | async" af-size="m" (afOnClick)="backToDeltagare()">
Tillbaka till deltagaren
</digi-button>
</div> </div>
</msfa-report-layout> </msfa-report-layout>
<msfa-confirm-dialog <msfa-confirm-dialog
(confirmDialogChanged)="setConfirmDialogChanged($event)"
[openConfirmDialog]="openConfirmDialog" [openConfirmDialog]="openConfirmDialog"
reportToConfirm="avvikelserapport" reportToConfirm="avvikelserapport"
(confirmDialogChanged)="setConfirmDialogChanged($event)"
> >
</msfa-confirm-dialog> </msfa-confirm-dialog>
</msfa-layout> </msfa-layout>
<ng-template #skeletonRef>
<digi-ng-skeleton-base [afCount]="3" afText="Laddar data för avvikelserapport"></digi-ng-skeleton-base>
</ng-template>

View File

@@ -1,6 +1,13 @@
@import 'apps/mina-sidor-fa/src/styles/variables/gutters'; @import 'variables/gutters';
.deltagare-avvikelse { .deltagare-avvikelse {
&__confirmation,
&__form {
display: flex;
flex-direction: column;
gap: $digi--layout--gutter--l;
}
&__deltagare, &__deltagare,
&__alternative, &__alternative,
&__description, &__description,
@@ -25,4 +32,8 @@
&__step-buttons-wrapper--space-right { &__step-buttons-wrapper--space-right {
margin-right: var(--digi--layout--gutter--s); margin-right: var(--digi--layout--gutter--s);
} }
&__alert {
max-width: var(--digi--typography--text--max-width);
}
} }

View File

@@ -1,14 +1,13 @@
import { RadiobuttonModel } from '@af/digi-ng/_form/form-radiobutton-group'; import { RadiobuttonModel } from '@af/digi-ng/_form/form-radiobutton-group';
import { FormTextareaSize } from '@af/digi-ng/_form/form-textarea'; import { FormTextareaSize } from '@af/digi-ng/_form/form-textarea';
import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core'; import { ChangeDetectionStrategy, Component } from '@angular/core';
import { AbstractControl, FormControl, FormGroup } from '@angular/forms'; import { AbstractControl, FormControl, FormGroup } from '@angular/forms';
import { ActivatedRoute, Router } from '@angular/router'; import { ActivatedRoute } from '@angular/router';
import { ReportType } from '@msfa-enums/report-type.enum';
import { ConfirmDialog } from '@msfa-enums/confirm-dialog.enum'; import { ConfirmDialog } from '@msfa-enums/confirm-dialog.enum';
import { DayOrPartOfDay } from '@msfa-enums/day-or-part-of-day.enum'; import { DayOrPartOfDay } from '@msfa-enums/day-or-part-of-day.enum';
import { FranvaroOrsaksKodEnum } from '@msfa-enums/franvaro-orsak-kod.enum'; import { FranvaroOrsaksKodEnum } from '@msfa-enums/franvaro-orsak-kod.enum';
import { KandaOrsakerEnum } from '@msfa-enums/kanda-orsaker-kod.enum'; import { KandaOrsakerEnum } from '@msfa-enums/kanda-orsaker-kod.enum';
import { Avrop } from '@msfa-models/avrop.model'; import { ReportType } from '@msfa-enums/report-type.enum';
import { AvvikelseAlternativ } from '@msfa-models/avvikelse-alternativ.model'; import { AvvikelseAlternativ } from '@msfa-models/avvikelse-alternativ.model';
import { Avvikelse } from '@msfa-models/avvikelse.model'; import { Avvikelse } from '@msfa-models/avvikelse.model';
import { FragorForAvvikelser } from '@msfa-models/fragor-for-avvikelser.model'; import { FragorForAvvikelser } from '@msfa-models/fragor-for-avvikelser.model';
@@ -17,21 +16,28 @@ import { OrsaksKoderAvvikelse } from '@msfa-models/orsaks-koder-avvikelse.model'
import { KandaAvvikelseKoder, OrsaksKoderFranvaro } from '@msfa-models/orsaks-koder-franvaro.model'; import { KandaAvvikelseKoder, OrsaksKoderFranvaro } from '@msfa-models/orsaks-koder-franvaro.model';
import { DeltagareApiService } from '@msfa-services/api/deltagare.api.service'; import { DeltagareApiService } from '@msfa-services/api/deltagare.api.service';
import { import {
requiredOrsakerValidator,
requiredAnnanKandOrsakValidator, requiredAnnanKandOrsakValidator,
requiredDescriptionValidator,
RequiredDateValidator, RequiredDateValidator,
requiredDayOrPartOfDayValidator, requiredDayOrPartOfDayValidator,
requiredStartTimeValidator, requiredDescriptionValidator,
requiredEndTimeValidator, requiredEndTimeValidator,
requiredFraga1Validator, requiredFraga1Validator,
requiredfraga2Validator requiredfraga2Validator,
requiredOrsakerValidator,
requiredStartTimeValidator,
} from '@msfa-validators/avvikelse-form-validator'; } from '@msfa-validators/avvikelse-form-validator';
import { RequiredValidator } from '@msfa-validators/required.validator'; import { RequiredValidator } from '@msfa-validators/required.validator';
import { BehaviorSubject, Observable } from 'rxjs'; import { BehaviorSubject, Observable } from 'rxjs';
import { map, switchMap } from 'rxjs/operators'; import { map, shareReplay, switchMap } from 'rxjs/operators';
import { DeltagareAvvikelseService } from './deltagare-avvikelse.service'; import { DeltagareAvvikelseService } from './deltagare-avvikelse.service';
import { avvikelseAlternatives, dayOrPartOfDay } from './report-alternatives'; import { avvikelseAlternatives, dayOrPartOfDay } from './report-alternatives';
import { CustomError } from '@msfa-models/error/custom-error';
import { ErrorType } from '@msfa-enums/error-type.enum';
import { Avrop } from '@msfa-models/avrop.model';
interface Params {
genomforandeReferens: string;
}
@Component({ @Component({
selector: 'msfa-deltagare-avvikelse', selector: 'msfa-deltagare-avvikelse',
@@ -39,7 +45,7 @@ import { avvikelseAlternatives, dayOrPartOfDay } from './report-alternatives';
styleUrls: ['./deltagare-avvikelse.component.scss'], styleUrls: ['./deltagare-avvikelse.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush, changeDetection: ChangeDetectionStrategy.OnPush,
}) })
export class DeltagareAvvikelseComponent implements OnInit { export class DeltagareAvvikelseComponent {
readonly alternativeFormControlName = 'alternative'; readonly alternativeFormControlName = 'alternative';
readonly descriptionFormControlName = 'description'; readonly descriptionFormControlName = 'description';
readonly dateFormControlName = 'date'; readonly dateFormControlName = 'date';
@@ -50,11 +56,14 @@ export class DeltagareAvvikelseComponent implements OnInit {
readonly fraga2FormControlName = 'fraga2'; readonly fraga2FormControlName = 'fraga2';
readonly startTimeFormControlName = 'startTime'; readonly startTimeFormControlName = 'startTime';
readonly endTimeFormControlName = 'endTime'; readonly endTimeFormControlName = 'endTime';
genomforandeReferens$: Observable<number> = this.activatedRoute.params.pipe(
map((params: Params) => +params.genomforandeReferens)
);
avrop$: Observable<Avrop> = this.genomforandeReferens$.pipe(
switchMap(genomforandeReferens => this.deltagareAvvikelseService.fetchAvropInformation$(genomforandeReferens)),
shareReplay(1)
);
private _showSuccessNotification$ = new BehaviorSubject<boolean>(false);
private _showDangerNotification$ = new BehaviorSubject<boolean>(false);
avrop$: Observable<Avrop>;
franvaroOrsaker$: Observable<OrsaksKoderFranvaro[]>; franvaroOrsaker$: Observable<OrsaksKoderFranvaro[]>;
avvikelseOrsaker$: Observable<OrsaksKoderAvvikelse[]>; avvikelseOrsaker$: Observable<OrsaksKoderAvvikelse[]>;
andraKandaOrsaker$: Observable<KandaAvvikelseKoder[]>; andraKandaOrsaker$: Observable<KandaAvvikelseKoder[]>;
@@ -65,50 +74,43 @@ export class DeltagareAvvikelseComponent implements OnInit {
avvikelseAlternatives: RadiobuttonModel[] = avvikelseAlternatives; avvikelseAlternatives: RadiobuttonModel[] = avvikelseAlternatives;
dayOrPartOfDay: RadiobuttonModel[] = dayOrPartOfDay; dayOrPartOfDay: RadiobuttonModel[] = dayOrPartOfDay;
selectedOrsaksKod: string; selectedOrsaksKod: string;
avvikelseFormGroup: FormGroup | null = null; avvikelseFormGroup = new FormGroup(
{
alternative: new FormControl(null, [RequiredValidator()]),
description: new FormControl('', [requiredDescriptionValidator()]),
date: new FormControl(this.todayDate),
dayOrPartOfDay: new FormControl(null, [requiredDayOrPartOfDayValidator()]),
orsakerFormGroup: new FormGroup({
orsaker: new FormControl([], [requiredOrsakerValidator()]),
andraKandaOrsaker: new FormControl([], [requiredAnnanKandOrsakValidator()]),
}),
fragorFormGroup: new FormGroup({
fraga1: new FormControl('', [requiredFraga1Validator()]),
fraga2: new FormControl('', [requiredfraga2Validator()]),
}),
timepickerFormGroup: new FormGroup({
startTime: new FormControl('', [requiredStartTimeValidator()]),
endTime: new FormControl('', [requiredEndTimeValidator()]),
}),
},
{
validators: [RequiredDateValidator.CheckIfRequired()],
}
);
totalAmountOfSteps = 2; totalAmountOfSteps = 2;
currentStep = 1; currentStep = 1;
openConfirmDialog = false; openConfirmDialog = false;
showSuccessNotification$ = this._showSuccessNotification$.asObservable(); private _submittedDate$ = new BehaviorSubject<Date | null>(null);
showDangerNotification$ = this._showDangerNotification$.asObservable(); submittedDate$: Observable<Date | null> = this._submittedDate$.asObservable();
private _error$ = new BehaviorSubject<CustomError>(null);
error$: Observable<CustomError> = this._error$.asObservable();
private _showDangerNotification$ = new BehaviorSubject<boolean>(false);
constructor( constructor(
private deltagareAvvikelseService: DeltagareAvvikelseService, private deltagareAvvikelseService: DeltagareAvvikelseService,
private deltagareApiService: DeltagareApiService, private deltagareApiService: DeltagareApiService,
private router: Router,
private activatedRoute: ActivatedRoute private activatedRoute: ActivatedRoute
) { } ) {}
ngOnInit(): void {
this.avrop$ = this.activatedRoute.params
.pipe(
switchMap(({ genomforandeReferens }) => this.deltagareApiService.fetchAvropInformation$(genomforandeReferens))
)
this.avvikelseFormGroup = new FormGroup(
{
alternative: new FormControl(null, [RequiredValidator()]),
description: new FormControl('', [requiredDescriptionValidator()]),
date: new FormControl(this.todayDate),
dayOrPartOfDay: new FormControl(null, [requiredDayOrPartOfDayValidator()]),
orsakerFormGroup: new FormGroup({
orsaker: new FormControl([], [requiredOrsakerValidator()]),
andraKandaOrsaker: new FormControl([], [requiredAnnanKandOrsakValidator()]),
}),
fragorFormGroup: new FormGroup({
fraga1: new FormControl('', [requiredFraga1Validator()]),
fraga2: new FormControl('', [requiredfraga2Validator()]),
}),
timepickerFormGroup: new FormGroup({
startTime: new FormControl('', [requiredStartTimeValidator()]),
endTime: new FormControl('', [requiredEndTimeValidator()]),
}),
},
{
validators: [RequiredDateValidator.CheckIfRequired()],
}
);
}
get alternativeFormControl(): AbstractControl | undefined { get alternativeFormControl(): AbstractControl | undefined {
return this.avvikelseFormGroup?.get(this.alternativeFormControlName); return this.avvikelseFormGroup?.get(this.alternativeFormControlName);
@@ -152,16 +154,16 @@ export class DeltagareAvvikelseComponent implements OnInit {
get franvaro(): FranvaroAlternativ { get franvaro(): FranvaroAlternativ {
return { return {
avvikelseorsakskod: this.orsakerFormControl.value as string, avvikelseOrsaksKod: this.orsakerFormControl.value as string,
datum: this.dateFormControl.value as string, datum: this.dateFormControl.value as string,
heldag: this.dayOrPartOfDayFormControl.value === DayOrPartOfDay.HELDAG ? true : false, heldag: this.dayOrPartOfDayFormControl.value === DayOrPartOfDay.HELDAG,
starttid: (this.startTimeFormControl.value as string) || '9:00', startTid: (this.startTimeFormControl.value as string) || '9:00',
sluttid: (this.endTimeFormControl.value as string) || '16:00', slutTid: (this.endTimeFormControl.value as string) || '16:00',
forvantad_narvaro: { forvantadNarvaro: {
starttid: '', startTid: '',
sluttid: '', slutTid: '',
}, },
alternativ_for_kanda_orsaker: { alternativForKandaOrsaker: {
typ: (this.andraKandaOrsakerFormControl.value as string) || '', typ: (this.andraKandaOrsakerFormControl.value as string) || '',
motivering: this.descriptionFormControl.value as string, motivering: this.descriptionFormControl.value as string,
}, },
@@ -190,7 +192,7 @@ export class DeltagareAvvikelseComponent implements OnInit {
get showDescription(): boolean { get showDescription(): boolean {
return ( return (
(this.alternativeFormControl.value as string) == ReportType.FRANVARO && (this.alternativeFormControl.value as string) === ReportType.FRANVARO &&
+this.orsakerFormControl.value === FranvaroOrsaksKodEnum.AnnanKandOrsak && +this.orsakerFormControl.value === FranvaroOrsaksKodEnum.AnnanKandOrsak &&
+this.andraKandaOrsakerFormControl.value === KandaOrsakerEnum.AnnanOrsak +this.andraKandaOrsakerFormControl.value === KandaOrsakerEnum.AnnanOrsak
); );
@@ -222,8 +224,6 @@ export class DeltagareAvvikelseComponent implements OnInit {
} }
get nextStep(): number { get nextStep(): number {
console.log(this.avvikelseFormGroup);
this.avvikelseFormGroup.markAllAsTouched(); this.avvikelseFormGroup.markAllAsTouched();
if (this.avvikelseFormGroup.valid && this.currentStep < this.totalAmountOfSteps) { if (this.avvikelseFormGroup.valid && this.currentStep < this.totalAmountOfSteps) {
return this.currentStep++; return this.currentStep++;
@@ -234,41 +234,72 @@ export class DeltagareAvvikelseComponent implements OnInit {
this.openConfirmDialog = false; this.openConfirmDialog = false;
if (confirm === ConfirmDialog.ACCEPTED) { if (confirm === ConfirmDialog.ACCEPTED) {
const postAvvikelse: Avvikelse = { const postAvvikelse: Avvikelse = {
datum_for_rapportering: this.todayDate, genomforandeReferens: +this.activatedRoute.snapshot.params['genomforandeReferens'],
sokandeId: +this.activatedRoute.snapshot.params['genomforandeReferens'],
}; };
if ((this.alternativeFormControl.value as string) === ReportType.AVVIKELSE) { if ((this.alternativeFormControl.value as string) === ReportType.AVVIKELSE) {
postAvvikelse['avvikelsealternativ'] = this.avvikelse; this.postAvvikelse();
} else if ((this.alternativeFormControl.value as string) == ReportType.FRANVARO) { } else if ((this.alternativeFormControl.value as string) === ReportType.FRANVARO) {
postAvvikelse['franvaro'] = this.franvaro; this.postFranvaro();
} }
this.deltagareAvvikelseService
.createAvvikelse$(postAvvikelse, this.alternativeFormControl.value as string)
.subscribe({
error: () => this._showDangerNotification$.next(true),
next: () => this._showSuccessNotification$.next(true),
complete: () => this.avvikelseFormGroup.reset(),
});
} }
} }
get genomforandeReferensSnapshot() {
return +this.activatedRoute.snapshot.params['genomforandeReferens'];
}
postAvvikelse() {
const avvikelseData: Avvikelse = {
genomforandeReferens: this.genomforandeReferensSnapshot,
avvikelseAlternativ: this.avvikelse,
};
this.deltagareAvvikelseService
.createAvvikelse$(avvikelseData)
.then(() => {
this._submittedDate$.next(new Date());
this.avvikelseFormGroup.reset();
this.currentStep = 3;
})
.catch((error: Error) => {
this._error$.next(new CustomError({ error, message: error.message, type: ErrorType.API }));
});
}
postFranvaro() {
const avvikelseData: Avvikelse = {
genomforandeReferens: this.genomforandeReferensSnapshot,
franvaro: this.franvaro,
};
this.deltagareAvvikelseService
.createFranvaro$(avvikelseData)
.then(() => {
this._submittedDate$.next(new Date());
this.avvikelseFormGroup.reset();
this.currentStep = 3;
})
.catch((error: Error) => {
this._error$.next(new CustomError({ error, message: error.message, type: ErrorType.API }));
});
}
setAlternative(): void { setAlternative(): void {
if ((this.alternativeFormControl.value as string) == ReportType.FRANVARO) { if ((this.alternativeFormControl.value as string) == ReportType.FRANVARO) {
this.franvaroOrsaker$ = this.deltagareAvvikelseService.getOrsaksKoderFranvaro$(); this.franvaroOrsaker$ = this.deltagareAvvikelseService.getOrsaksKoderFranvaro$.pipe(shareReplay(1));
this.andraKandaOrsaker$ = this.deltagareAvvikelseService.getAndraKandaOrsaker$(); this.andraKandaOrsaker$ = this.deltagareAvvikelseService.getAndraKandaOrsaker$.pipe(shareReplay(1));
} }
if ((this.alternativeFormControl.value as string) == ReportType.AVVIKELSE) { if ((this.alternativeFormControl.value as string) == ReportType.AVVIKELSE) {
this.avvikelseOrsaker$ = this.deltagareAvvikelseService.getOrsaksKoderAvvikelse$(); this.avvikelseOrsaker$ = this.deltagareAvvikelseService.getOrsaksKoderAvvikelse$.pipe(shareReplay(1));
this.fragor1$ = this.deltagareAvvikelseService.getFragorForAvvikelser$().pipe( this.fragor1$ = this.deltagareAvvikelseService.fragorForAvvikelser$.pipe(
map((fragor: FragorForAvvikelser[]) => { map((fragor: FragorForAvvikelser[]) => {
return fragor.filter((fraga: FragorForAvvikelser) => fraga.id.includes('_1')); return fragor.filter((fraga: FragorForAvvikelser) => fraga.id.includes('_1'));
}) })
); );
this.fragor2$ = this.deltagareAvvikelseService.getFragorForAvvikelser$().pipe( this.fragor2$ = this.deltagareAvvikelseService.fragorForAvvikelser$.pipe(
map((fragor: FragorForAvvikelser[]) => { map((fragor: FragorForAvvikelser[]) => {
return fragor.filter((fraga: FragorForAvvikelser) => { return fragor.filter((fraga: FragorForAvvikelser) => {
return fraga.id.includes('_2'); return fraga.id.includes('_2');
@@ -314,17 +345,11 @@ export class DeltagareAvvikelseComponent implements OnInit {
previousStep(): void { previousStep(): void {
if (this.currentStep > 1) { if (this.currentStep > 1) {
this.currentStep--; this.currentStep--;
this._showSuccessNotification$.next(false); this._submittedDate$.next(null);
this._showDangerNotification$.next(false); this._showDangerNotification$.next(false);
} }
} }
backToDeltagare(): void {
this.router
.navigate(['./deltagare', this.activatedRoute.snapshot.params['genomforandeReferens']])
.catch(error => console.log(error, 'Failed to go back to deltagare'));
}
private clearControlOnAlternativeChange(): void { private clearControlOnAlternativeChange(): void {
this.descriptionFormControl.setValue(''); this.descriptionFormControl.setValue('');
this.fraga1FormControl.setValue(''); this.fraga1FormControl.setValue('');

View File

@@ -15,6 +15,8 @@ import { DeltagareOrsaksFormModule } from './components/deltagare-orsaks-form/de
import { DeltagareTimePickerModule } from './components/deltagare-time-picker/deltagare-time-picker.module'; import { DeltagareTimePickerModule } from './components/deltagare-time-picker/deltagare-time-picker.module';
import { DeltagareAvvikelseComponent } from './deltagare-avvikelse.component'; import { DeltagareAvvikelseComponent } from './deltagare-avvikelse.component';
import { DeltagareAvvikelseService } from './deltagare-avvikelse.service'; import { DeltagareAvvikelseService } from './deltagare-avvikelse.service';
import { BackLinkModule } from '@msfa-shared/components/back-link/back-link.module';
import { DigiNgSkeletonBaseModule } from '@af/digi-ng/_skeleton/skeleton-base';
@NgModule({ @NgModule({
schemas: [CUSTOM_ELEMENTS_SCHEMA], schemas: [CUSTOM_ELEMENTS_SCHEMA],
@@ -34,6 +36,8 @@ import { DeltagareAvvikelseService } from './deltagare-avvikelse.service';
DeltagareConfirmFormModule, DeltagareConfirmFormModule,
ReportLayoutModule, ReportLayoutModule,
ConfirmDialogModule, ConfirmDialogModule,
BackLinkModule,
DigiNgSkeletonBaseModule,
], ],
providers: [DeltagareAvvikelseService], providers: [DeltagareAvvikelseService],
exports: [DeltagareAvvikelseComponent], exports: [DeltagareAvvikelseComponent],

View File

@@ -6,39 +6,42 @@ import { OrsaksKoderAvvikelse } from '@msfa-models/orsaks-koder-avvikelse.model'
import { KandaAvvikelseKoder, OrsaksKoderFranvaro } from '@msfa-models/orsaks-koder-franvaro.model'; import { KandaAvvikelseKoder, OrsaksKoderFranvaro } from '@msfa-models/orsaks-koder-franvaro.model';
import { AvvikelseApiService } from '@msfa-services/api/avvikelse-api.service'; import { AvvikelseApiService } from '@msfa-services/api/avvikelse-api.service';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
import { map } from 'rxjs/operators'; import { map, shareReplay } from 'rxjs/operators';
import { DeltagareApiService } from '@msfa-services/api/deltagare.api.service';
@Injectable() @Injectable()
export class DeltagareAvvikelseService { export class DeltagareAvvikelseService {
constructor(private avvikelseApiService: AvvikelseApiService) {} public fragorForAvvikelser$: Observable<
FragorForAvvikelser[]
> = this.avvikelseApiService.getFragorForAvvikelser$().pipe(shareReplay(1));
public getOrsaksKoderFranvaro$: Observable<
OrsaksKoderFranvaro[]
> = this.avvikelseApiService.getOrsaksKoderFranvaro$().pipe(
map((orsaksKoder: OrsaksKoderFranvaro[]) => {
orsaksKoder.find(kod => {
if (kod.value === FranvaroOrsaksKodEnum.VAB) {
kod.name = 'Vård av barn';
}
});
return this.sortOrsaksKoder(orsaksKoder);
}),
shareReplay(1)
);
public getOrsaksKoderFranvaro$(): Observable<OrsaksKoderFranvaro[]> { constructor(private avvikelseApiService: AvvikelseApiService, private deltagareApiService: DeltagareApiService) {}
return this.avvikelseApiService.getOrsaksKoderFranvaro$().pipe(
map((orsaksKoder: OrsaksKoderFranvaro[]) => { public getOrsaksKoderAvvikelse$: Observable<
orsaksKoder.find(kod => { OrsaksKoderAvvikelse[]
if (kod.value === FranvaroOrsaksKodEnum.VAB) { > = this.avvikelseApiService.getOrsaksKoderAvvikelse$();
kod.name = 'Vård av barn';
} public getAndraKandaOrsaker$: Observable<KandaAvvikelseKoder[]> = this.avvikelseApiService.getAndraKandaOrsaker$();
});
return this.sortOrsaksKoder(orsaksKoder); public createAvvikelse$(avvikelse: Avvikelse): Promise<void> {
}) return this.avvikelseApiService.createAvvikelse$(avvikelse);
);
} }
public getOrsaksKoderAvvikelse$(): Observable<OrsaksKoderAvvikelse[]> { public createFranvaro$(avvikelse: Avvikelse): Promise<void> {
return this.avvikelseApiService.getOrsaksKoderAvvikelse$(); return this.avvikelseApiService.createFranvaro$(avvikelse);
}
public getAndraKandaOrsaker$(): Observable<KandaAvvikelseKoder[]> {
return this.avvikelseApiService.getAndraKandaOrsaker$();
}
public getFragorForAvvikelser$(): Observable<FragorForAvvikelser[]> {
return this.avvikelseApiService.getFragorForAvvikelser$();
}
public createAvvikelse$(avvikelse: Avvikelse, alternative: string): Observable<Avvikelse> {
return this.avvikelseApiService.createAvvikelse$(avvikelse, alternative);
} }
private sortOrsaksKoder(orsaksKoder: OrsaksKoderFranvaro[]): OrsaksKoderFranvaro[] { private sortOrsaksKoder(orsaksKoder: OrsaksKoderFranvaro[]): OrsaksKoderFranvaro[] {
@@ -66,4 +69,8 @@ export class DeltagareAvvikelseService {
const sortedOrsaksKoder = orsaksKoder.sort((kodA, kodB) => (kodA.index < kodB.index ? -1 : 1)); const sortedOrsaksKoder = orsaksKoder.sort((kodA, kodB) => (kodA.index < kodB.index ? -1 : 1));
return sortedOrsaksKoder; return sortedOrsaksKoder;
} }
fetchAvropInformation$(genomforandeReferens: number) {
return this.deltagareApiService.fetchAvropInformation$(genomforandeReferens);
}
} }

View File

@@ -2,30 +2,27 @@ import { AvvikelseAlternativ } from './avvikelse-alternativ.model';
import { FranvaroAlternativ } from './franvaro-alternativ.model'; import { FranvaroAlternativ } from './franvaro-alternativ.model';
export interface Avvikelse { export interface Avvikelse {
datum_for_rapportering: string, genomforandeReferens: number;
sokandeId: number; avvikelseAlternativ?: AvvikelseAlternativ;
avvikelsealternativ?: AvvikelseAlternativ, franvaro?: FranvaroAlternativ;
franvaro?: FranvaroAlternativ
} }
export interface AvvikelseRequestData { export interface AvvikelseRequestData {
datum_for_rapportering: string, genomforandeReferens: number;
sokandeId: number; avvikelseAlternativ: AvvikelseAlternativ;
avvikelsealternativ: AvvikelseAlternativ,
} }
export interface FranvaroRequestData { export interface FranvaroRequestData {
datum_for_rapportering: string, genomforandeReferens: number;
sokandeId: number; franvaro: FranvaroAlternativ;
franvaro: FranvaroAlternativ
} }
export function mapAvvikelseRequestDataToAvvikelse(data: AvvikelseRequestData): Avvikelse { export function mapAvvikelseRequestDataToAvvikelse(data: AvvikelseRequestData): Avvikelse {
const { datum_for_rapportering, sokandeId, avvikelsealternativ } = data; return data;
// const { genomforandeReferens, avvikelseAlternativ } = data;
return { //
datum_for_rapportering, // return {
sokandeId, // genomforandeReferens,
avvikelsealternativ // avvikelseAlternativ,
} // };
} }

View File

@@ -1,15 +1,15 @@
export interface FranvaroAlternativ { export interface FranvaroAlternativ {
avvikelseorsakskod: string; avvikelseOrsaksKod: string;
datum: string; datum: string;
heldag: boolean; heldag: boolean;
starttid: string; startTid: string;
sluttid: string; slutTid: string;
forvantad_narvaro: { forvantadNarvaro: {
starttid: string; startTid: string;
sluttid: string; slutTid: string;
}, };
alternativ_for_kanda_orsaker: { alternativForKandaOrsaker: {
typ: string, typ: string;
motivering: string; motivering: string;
} };
} }

View File

@@ -1,12 +1,10 @@
import { HttpClient } from '@angular/common/http'; import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { ReportType } from '@msfa-enums/report-type.enum';
import { ErrorType } from '@msfa-enums/error-type.enum';
import { environment } from '@msfa-environment'; import { environment } from '@msfa-environment';
import { FragorForAvvikelserResponse } from '@msfa-models/api/fragor-for-avvikelser.response'; import { FragorForAvvikelserResponse } from '@msfa-models/api/fragor-for-avvikelser.response';
import { KandaAvvikelseKoderResponse } from '@msfa-models/api/kanda-avvikelse-koder.response.model'; import { KandaAvvikelseKoderResponse } from '@msfa-models/api/kanda-avvikelse-koder.response.model';
import { OrsaksKoderAvvikelseResponse } from '@msfa-models/api/orsaks-koder-avvikelse.response.model'; import { OrsaksKoderAvvikelseResponse } from '@msfa-models/api/orsaks-koder-avvikelse.response.model';
import { Avvikelse, AvvikelseRequestData, mapAvvikelseRequestDataToAvvikelse } from '@msfa-models/avvikelse.model'; import { Avvikelse } from '@msfa-models/avvikelse.model';
import { FragorForAvvikelser, mapResponseToFragorForAvvikelser } from '@msfa-models/fragor-for-avvikelser.model'; import { FragorForAvvikelser, mapResponseToFragorForAvvikelser } from '@msfa-models/fragor-for-avvikelser.model';
import { mapResponseToOrsaksKoderAvvikelse, OrsaksKoderAvvikelse } from '@msfa-models/orsaks-koder-avvikelse.model'; import { mapResponseToOrsaksKoderAvvikelse, OrsaksKoderAvvikelse } from '@msfa-models/orsaks-koder-avvikelse.model';
import { import {
@@ -15,15 +13,16 @@ import {
mapResponseToOrsaksKoderFranvaro, mapResponseToOrsaksKoderFranvaro,
OrsaksKoderFranvaro, OrsaksKoderFranvaro,
} from '@msfa-models/orsaks-koder-franvaro.model'; } from '@msfa-models/orsaks-koder-franvaro.model';
import { ErrorService } from '@msfa-services/error.service'; import { Observable } from 'rxjs';
import { Observable, throwError } from 'rxjs'; import { filter, map } from 'rxjs/operators';
import { catchError, filter, map, take } from 'rxjs/operators';
@Injectable({ @Injectable({
providedIn: 'root', providedIn: 'root',
}) })
export class AvvikelseApiService { export class AvvikelseApiService {
private _apiBaseUrl = `${environment.api.url}/report`; private _apiBaseUrl = `${environment.api.url}/rapporter`;
constructor(private httpClient: HttpClient) {}
public getOrsaksKoderFranvaro$(): Observable<OrsaksKoderFranvaro[]> { public getOrsaksKoderFranvaro$(): Observable<OrsaksKoderFranvaro[]> {
return this.httpClient return this.httpClient
@@ -57,32 +56,11 @@ export class AvvikelseApiService {
); );
} }
public createAvvikelse$(avvikelse: Avvikelse, alternative: string): Observable<Avvikelse> { public createAvvikelse$(avvikelse: Avvikelse): Promise<void> {
return this.httpClient return this.httpClient.post<void>(`${this._apiBaseUrl}/avvikelse`, avvikelse).toPromise();
.post<{ data: AvvikelseRequestData }>(`${this._apiBaseUrl}/${this.setEndPoint(alternative)}`, avvikelse)
.pipe(
filter(response => !!response?.data),
take(1),
map(({ data }) => mapAvvikelseRequestDataToAvvikelse(data)),
catchError(error => throwError({ message: error as string, type: ErrorType.API }))
);
} }
private setEndPoint(alternative: string): string { public createFranvaro$(avvikelse: Avvikelse): Promise<void> {
let endpoint = ''; return this.httpClient.post<void>(`${this._apiBaseUrl}/franvaro`, avvikelse).toPromise();
switch (alternative) {
case ReportType.AVVIKELSE:
endpoint = 'avvikelse';
break;
case ReportType.FRANVARO:
endpoint = 'franvaro';
break;
default:
break;
}
return endpoint;
} }
constructor(private httpClient: HttpClient, private errorService: ErrorService) {}
} }

View File

@@ -8,6 +8,8 @@
"target": "https://298b3305d4834aa4869f8250a0d0b314.ece-test.arbetsformedlingen.se:9243", "target": "https://298b3305d4834aa4869f8250a0d0b314.ece-test.arbetsformedlingen.se:9243",
"secure": false, "secure": false,
"changeOrigin": true, "changeOrigin": true,
"pathRewrite": { "^/logging": "" } "pathRewrite": {
"^/logging": ""
}
} }
} }