feat(avvikelserapport): implementerat report layout för avvikelserapport. TV-667

Squashed commit of the following:

commit 4ef5359297295bce54df281081c3f44f690cadab
Author: fueno <nicolas.fuentes-maturana@arbetsformedlingen.se>
Date:   Thu Sep 23 09:11:15 2021 +0200

    TV-667 changed names, cleanup

commit 4e2354ee25a11543b22ac74783989110cbc3c788
Author: fueno <nicolas.fuentes-maturana@arbetsformedlingen.se>
Date:   Thu Sep 23 08:50:52 2021 +0200

    TV-667 removed unused enum

commit fb393aa61617892f9ebe8af67963aa9ed21d391e
Author: fueno <nicolas.fuentes-maturana@arbetsformedlingen.se>
Date:   Thu Sep 23 08:20:09 2021 +0200

    TV-667 removed test api url

commit aadf97ef0d05915a72bdc1c95df10f8d8d932e2c
Author: fueno <nicolas.fuentes-maturana@arbetsformedlingen.se>
Date:   Thu Sep 23 08:09:13 2021 +0200

    TV-667 show dynamic name for notification alert

commit e5453f0f5ee3fb9706817cd208f797688fb453f7
Author: fueno <nicolas.fuentes-maturana@arbetsformedlingen.se>
Date:   Thu Sep 23 00:25:10 2021 +0200

    TV-667 restructoring report layout

commit f68e5bf2675dee5e8ae7c0d06f24389d8efddf25
Author: fueno <nicolas.fuentes-maturana@arbetsformedlingen.se>
Date:   Wed Sep 22 17:40:49 2021 +0200

    TV-667 updated path for report layout module

commit d2273a38304a457b3015dd086e93fc7d8d0d07ea
Merge: c9da568 3f7663a
Author: fueno <nicolas.fuentes-maturana@arbetsformedlingen.se>
Date:   Wed Sep 22 17:38:14 2021 +0200

    Merge branch 'feature/TV-633' into feature/TV-667

commit c9da568ecc950718f7d1f9d28e80ae18ebbf0994
Author: fueno <nicolas.fuentes-maturana@arbetsformedlingen.se>
Date:   Wed Sep 22 17:30:43 2021 +0200

    TV-667 implementerat report layout i avvikelserapporten

commit 3f7663a48b2f556c36752ab443754070136f2d6e
Author: fueno <nicolas.fuentes-maturana@arbetsformedlingen.se>
Date:   Wed Sep 22 16:46:44 2021 +0200

    TV-633 confirm dialog for reports

commit 32c1d194e9266100e70f5440b6bc62e40ed05d9d
Author: fueno <nicolas.fuentes-maturana@arbetsformedlingen.se>
Date:   Tue Sep 21 18:02:01 2021 +0200

    TV-633 delete previous version

commit b8fde47a4cc3c8e7e372eaa600f8ddd92a39b7a0
Author: fueno <nicolas.fuentes-maturana@arbetsformedlingen.se>
Date:   Tue Sep 21 17:57:22 2021 +0200

    TV-633 generic confirm dialog component

commit f0d34d639c8c91833cdfb82a42775ec0744573dc
Merge: df27008 5846c2c
Author: fueno <nicolas.fuentes-maturana@arbetsformedlingen.se>
Date:   Tue Sep 21 17:22:48 2021 +0200

    Merge branch 'develop' into feature/TV-633

commit df270080a361a052a186bbfc1f7e9a36804d4e9d
Merge: 7ff69bf fc6551a
Author: fueno <nicolas.fuentes-maturana@arbetsformedlingen.se>
Date:   Tue Sep 21 15:06:08 2021 +0200

    Merge remote-tracking branch 'origin/feature/TV-634-reports-layout' into feature/TV-633

commit fc6551a1101f448544bccb62c6272d105dd1e0a4
Merge: e3f7204 2dd9d3d
Author: Aden Hassan <aden.hassan@arbetsformedlingen.se>
Date:   Tue Sep 21 13:32:01 2021 +0200

    Merge branch 'develop' into feature/TV-634-reports-layout

commit e3f72043c68c326b7f1adc8bd85f993a4b2aafff
Author: Aden Hassan <aden.hassan@arbetsformedlingen.se>
Date:   Tue Sep 21 12:46:00 2021 +0200

    minor adjustments according to feedback

commit 7ff69bf5534ad4d96c838ac4969dddd222ccbd5c
Author: fueno <nicolas.fuentes-maturana@arbetsformedlingen.se>
Date:   Tue Sep 21 10:13:17 2021 +0200

    TV-633 Confirm Report Modal created

commit 6ef20a3b5074bcf06a84a7de4fded08cbe1e0026
Author: Aden Hassan <aden.hassan@arbetsformedlingen.se>
Date:   Mon Sep 20 21:55:38 2021 +0200

    added minor changes to default steps (TV-634)

commit 4835e8f48da04432505cc5225cc57a1763fcdd60
Author: Aden Hassan <aden.hassan@arbetsformedlingen.se>
Date:   Mon Sep 20 21:47:23 2021 +0200

    added output-event to send event from skicka in button (TV-634)

commit f01a87dfe099514529ed641c85007986f98b9ea8
Merge: 1a4bdfc e120e50
Author: Aden Hassan <aden.hassan@arbetsformedlingen.se>
Date:   Mon Sep 20 19:49:26 2021 +0200

    Merge branch 'develop' into feature/TV-634-reports-layout

commit 1a4bdfc1684a36a168371d74d90ea2d41060af0e
Author: Aden Hassan <aden.hassan@arbetsformedlingen.se>
Date:   Mon Sep 20 19:48:21 2021 +0200

    created basic layout modul for all reports (TV-634 and TV-624)
This commit is contained in:
Nicolas Fuentes Maturana
2021-09-23 09:20:11 +02:00
parent caf235a2b4
commit 454699b785
22 changed files with 514 additions and 217 deletions

View File

@@ -0,0 +1,56 @@
<section class="deltagare-confirm">
<h3 class="deltagare-confirm__header">Vad är det du vill rapportera?</h3>
<p>{{ formGroup?.get('alternative').value === 'franvaro' ? 'Frånvaro' : 'Avvikelse'}}</p>
<ng-container *ngIf="formGroup?.get('alternative').value === 'franvaro'">
<h3 class="deltagare-confirm__header">Frånvaroorsak</h3>
<ng-container *ngFor="let orsak of orsakskoderfranvaro">
<p *ngIf="orsak.value == formGroup?.get('orsakerFormGroup').get('orsaker').value">{{orsak.name}}</p>
</ng-container>
<ng-container *ngIf="formGroup?.get('orsakerFormGroup').get('andraKandaOrsaker').value">
<h3 class="deltagare-confirm__header">Annan känd orsak</h3>
<ng-container *ngFor="let annanKandOrsak of andraKandaOrsaker">
<p *ngIf="annanKandOrsak.value == formGroup?.get('orsakerFormGroup').get('andraKandaOrsaker').value">
{{annanKandOrsak.name}}
</p>
</ng-container>
</ng-container>
<ng-container *ngIf="formGroup?.get('orsakerFormGroup').get('andraKandaOrsaker').value == 5">
<h3 class="deltagare-confirm__header">Beskrivning</h3>
<p>{{formGroup?.get('description').value}}</p>
</ng-container>
<h3 class="deltagare-confirm__header">Datum</h3>
<p>{{formGroup?.get('date').value}}</p>
<h3 class="deltagare-confirm__header">Hel- eller del av dag</h3>
<p>{{formGroup.get('dayOrPartOfDay').value === 'HELDAG' ? 'Heldag' : 'Del av dag'}}</p>
<ng-container *ngIf="formGroup.get('dayOrPartOfDay').value === 'DEL_AV_DAG'">
<h3 class="deltagare-confirm-header">Startid</h3>
<p>{{formGroup?.get('timepickerFormGroup').get('startTime').value}}</p>
<h3 class="deltagare-confirm-header">Sluttid</h3>
<p>{{formGroup?.get('timepickerFormGroup').get('endTime').value}}</p>
</ng-container>
</ng-container>
<ng-container *ngIf="formGroup?.get('alternative').value === 'avvikelse'">
<h3 class="deltagare-confirm-header">Avvikelseoorsak</h3>
<ng-container *ngFor="let orsak of avvikelseOrsaker">
<p *ngIf="orsak.value == formGroup?.get('orsakerFormGroup').get('orsaker').value">{{orsak.name}}</p>
</ng-container>
<h3 class="deltagare-confirm-header">Fråga 1</h3>
<p>{{formGroup?.get('fragorFormGroup').get('fraga1').value}}</p>
<ng-container *ngIf="formGroup?.get('fragorFormGroup').get('fraga2').value">
<h3 class="deltagare-confirm-header">Fråga 2</h3>
<p>{{formGroup?.get('fragorFormGroup').get('fraga2').value}}</p>
</ng-container>
<h3 class="deltagare-confirm-header">Datum</h3>
<p>{{formGroup?.get('date').value}}</p>
</ng-container>
</section>

View File

@@ -0,0 +1,10 @@
@import 'variables/gutters';
.deltagare-confirm {
margin-bottom: $digi--layout--gutter--xl;
&__header {
font-size: var(--digi--typography--font-size--l);
margin: 0;
}
}

View File

@@ -0,0 +1,25 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { DeltagareConfirmFormComponent } from './deltagare-confirm-form.component';
describe('DeltagareConfirmFormComponent', () => {
let component: DeltagareConfirmFormComponent;
let fixture: ComponentFixture<DeltagareConfirmFormComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ DeltagareConfirmFormComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(DeltagareConfirmFormComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -0,0 +1,17 @@
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
import { FormGroup } from '@angular/forms';
import { OrsaksKoderAvvikelse } from '@msfa-models/orsaks-koder-avvikelse.model';
import { KandaAvvikelseKoder, OrsaksKoderFranvaro } from '@msfa-models/orsaks-koder-franvaro.model';
@Component({
selector: 'msfa-deltagare-confirm-form',
templateUrl: './deltagare-confirm-form.component.html',
styleUrls: ['./deltagare-confirm-form.component.scss'],
changeDetection: ChangeDetectionStrategy.Default
})
export class DeltagareConfirmFormComponent {
@Input() formGroup: FormGroup | null = null;
@Input() orsakskoderfranvaro: OrsaksKoderFranvaro[];
@Input() andraKandaOrsaker: KandaAvvikelseKoder[];
@Input() avvikelseOrsaker: OrsaksKoderAvvikelse[];
}

View File

@@ -0,0 +1,15 @@
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { DeltagareConfirmFormComponent } from './deltagare-confirm-form.component';
@NgModule({
schemas: [CUSTOM_ELEMENTS_SCHEMA],
declarations: [DeltagareConfirmFormComponent],
imports: [
CommonModule
],
exports: [DeltagareConfirmFormComponent]
})
export class DeltagareConfirmFormModule { }

View File

@@ -18,7 +18,7 @@
</div>
</ng-container>
<ng-container *ngFor="let fraga of fragor2 | filterFragor: selectedOrsaksKod">
<div *ngIf="fragor1.length > 0" class="fragor-form__content">
<div *ngIf="fragor1?.length > 0" class="fragor-form__content">
<digi-ng-form-textarea
[formControlName]="'fraga2'"
[afLabel]="fraga.name"

View File

@@ -1,113 +1,138 @@
<msfa-layout>
<section class="deltagare-avvikelse">
<digi-typography>
<h1>Rapport</h1>
<p>
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.
</p>
<h2>Skapa rapport</h2>
<div *ngIf="contactInformation$ | async as contactInformation" class="deltagare-avvikelse__deltagare">
<p><span>Deltagare:</span> {{contactInformation.fornamn + ' ' + contactInformation.efternamn}}</p>
<p><span>Personnummer:</span> {{contactInformation.personnummer}}</p>
</div>
<div>
<h3 class="deltagare-avvikelse__alternative-heading">Vad är det du vill rapportera?</h3>
<form [formGroup]="avvikelseFormGroup" (ngSubmit)="onFormSubmitted()">
<div class="deltagare-avvikelse__alternative">
<digi-ng-form-radiobutton-group
[afRadiobuttons]="avvikelseAlternatives"
[formControlName]="alternativeFormControlName"
(change)="setAlternative()"
></digi-ng-form-radiobutton-group>
<msfa-report-layout
reportTitle="Avvikelserapport"
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"
[totalAmountOfSteps]="totalAmountOfSteps"
[currentStep]="currentStep"
[form]="avvikelseFormGroup"
[reportName]="(alternativeFormControl.value === 'franvaro') ? 'frånvarorapport' : 'avvikelsereapport'"
[showSuccessNotification]="showSuccessNotification$ | async"
[showDangerNotification]="showDangerNotification$ | async"
>
<ng-container *ngIf="currentStep === 1">
<h3 class="deltagare-avvikelse__alternative-heading">Vad är det du vill rapportera?</h3>
<form [formGroup]="avvikelseFormGroup">
<div class="deltagare-avvikelse__alternative">
<digi-ng-form-radiobutton-group
[afRadiobuttons]="avvikelseAlternatives"
[formControlName]="alternativeFormControlName"
(change)="setAlternative()"
></digi-ng-form-radiobutton-group>
<digi-form-validation-message
af-variation="error"
*ngIf="alternativeFormControl.invalid && avvikelseFormGroup.touched"
>
Alternativ är obligatoriskt
</digi-form-validation-message>
</div>
<msfa-deltagare-orsaks-form
[franvaroOrsaker]="franvaroOrsaker$ | async"
[avvikelseOrsaker]="avvikelseOrsaker$ | async "
[andraKandaOrsaker]="andraKandaOrsaker$ | async"
[orsakerFormGroup]="avvikelseFormGroup.get('orsakerFormGroup')"
[avvikelseFormGroup]="avvikelseFormGroup"
[selectedAlternative]="alternativeFormControl.value"
(change)="setOrsakerChanged()"
></msfa-deltagare-orsaks-form>
<ng-container *ngIf="showDescription">
<div class="deltagare-avvikelse__description">
<digi-ng-form-textarea
[formControlName]="descriptionFormControlName"
afLabel="Beskriv frånvaro"
[afSize]="sizeTextArea"
[afDisableValidStyle]="true"
[afMaxLength]="2000"
[afRequired]="true"
[afInvalid]="avvikelseFormGroup?.errors?.descriptionIsRequired && descriptionFormControl.touched"
></digi-ng-form-textarea>
<digi-form-validation-message
af-variation="error"
*ngIf="alternativeFormControl.invalid && avvikelseFormGroup.touched"
*ngIf="avvikelseFormGroup?.errors?.descriptionIsRequired && descriptionFormControl.touched"
>
Alternativ är obligatoriskt
Beskrivning är obligatoriskt
</digi-form-validation-message>
</div>
<msfa-deltagare-orsaks-form
[franvaroOrsaker]="franvaroOrsaker$ | async"
[avvikelseOrsaker]="avvikelseOrsaker$ | async "
[andraKandaOrsaker]="andraKandaOrsaker$ | async"
[orsakerFormGroup]="avvikelseFormGroup.get('orsakerFormGroup')"
</ng-container>
<ng-container *ngIf="showFragor">
<msfa-deltagare-fragor-form
[fragor1]="fragor1$ | async"
[fragor2]="fragor2$ | async"
[fragorFormGroup]="avvikelseFormGroup.get('fragorFormGroup')"
[avvikelseFormGroup]="avvikelseFormGroup"
[selectedAlternative]="alternativeFormControl.value"
(change)="setOrsakerChanged()"
></msfa-deltagare-orsaks-form>
[selectedOrsaksKod]="selectedOrsaksKod"
></msfa-deltagare-fragor-form>
</ng-container>
<ng-container *ngIf="showDescription">
<div class="deltagare-avvikelse__description">
<digi-ng-form-textarea
[formControlName]="descriptionFormControlName"
afLabel="Beskriv frånvaro"
[afSize]="sizeTextArea"
[afDisableValidStyle]="true"
[afMaxLength]="2000"
[afRequired]="true"
[afInvalid]="avvikelseFormGroup?.errors?.descriptionIsRequired && descriptionFormControl.touched"
></digi-ng-form-textarea>
<digi-form-validation-message
af-variation="error"
*ngIf="avvikelseFormGroup?.errors?.descriptionIsRequired && descriptionFormControl.touched"
>
Beskrivning är obligatoriskt
</digi-form-validation-message>
</div>
</ng-container>
<div *ngIf="showDatePicker" class="deltagare-avvikelse__datepicker">
<digi-ng-form-datepicker
[formControlName]="dateFormControlName"
[afLabel]="'Välj dag för ' + (alternativeFormControl.value === 'franvaro' ? 'frånvaro' : 'avvikelse')"
[afDisableValidStyle]="true"
[afInvalid]="avvikelseFormGroup.errors?.dateIsRequired"
></digi-ng-form-datepicker>
<digi-form-validation-message af-variation="error" *ngIf="avvikelseFormGroup.errors?.dateIsRequired">
{{avvikelseFormGroup.errors?.dateIsRequired}}
</digi-form-validation-message>
</div>
<ng-container *ngIf="showFragor">
<msfa-deltagare-fragor-form
[fragor1]="fragor1$ | async"
[fragor2]="fragor2$ | async"
[fragorFormGroup]="avvikelseFormGroup.get('fragorFormGroup')"
[avvikelseFormGroup]="avvikelseFormGroup"
[selectedOrsaksKod]="selectedOrsaksKod"
></msfa-deltagare-fragor-form>
</ng-container>
<div *ngIf="showDayOrPartOfDayPicker" class="deltagare-avvikelse__dayOrPartOfDay">
<digi-ng-form-radiobutton-group
[afRadiobuttons]="dayOrPartOfDay"
[formControlName]="dayOrPartOfDayFormControlName"
[afRequired]="avvikelseFormGroup.errors?.dayOrPartOfDayIsRequired"
></digi-ng-form-radiobutton-group>
</div>
<div *ngIf="showDatePicker" class="deltagare-avvikelse__datepicker">
<digi-ng-form-datepicker
[formControlName]="dateFormControlName"
[afLabel]="'Välj dag för ' + (alternativeFormControl.value === 'franvaro' ? 'frånvaro' : 'avvikelse')"
[afDisableValidStyle]="true"
[afInvalid]="avvikelseFormGroup.errors?.dateIsRequired"
></digi-ng-form-datepicker>
<digi-form-validation-message af-variation="error" *ngIf="avvikelseFormGroup.errors?.dateIsRequired">
{{avvikelseFormGroup.errors?.dateIsRequired}}
</digi-form-validation-message>
</div>
<ng-container *ngIf="showTimePicker">
<msfa-deltagare-time-picker
[timepickerFormGroup]="avvikelseFormGroup.get('timepickerFormGroup')"
[avvikelseFormGroup]="avvikelseFormGroup"
></msfa-deltagare-time-picker>
</ng-container>
</form>
</ng-container>
<div *ngIf="showDayOrPartOfDayPicker" class="deltagare-avvikelse__dayOrPartOfDay">
<digi-ng-form-radiobutton-group
[afRadiobuttons]="dayOrPartOfDay"
[formControlName]="dayOrPartOfDayFormControlName"
[afRequired]="avvikelseFormGroup.errors?.dayOrPartOfDayIsRequired"
></digi-ng-form-radiobutton-group>
</div>
<ng-container *ngIf="showTimePicker">
<msfa-deltagare-time-picker
[timepickerFormGroup]="avvikelseFormGroup.get('timepickerFormGroup')"
[avvikelseFormGroup]="avvikelseFormGroup"
></msfa-deltagare-time-picker>
</ng-container>
<msfa-deltagare-confirm-form
*ngIf="currentStep === totalAmountOfSteps"
[formGroup]="avvikelseFormGroup"
[orsakskoderfranvaro]="franvaroOrsaker$ | async"
[andraKandaOrsaker]="andraKandaOrsaker$ | async"
[avvikelseOrsaker]="avvikelseOrsaker$ | async"
></msfa-deltagare-confirm-form>
<div class="deltagare-avvikelse__step-buttons-wrapper">
<ng-container *ngIf="(showSuccessNotification$ | async) !== true">
<ng-container *ngIf="currentStep > 1">
<digi-button
[attr.af-aria-label]="'Tillbaka till deltagaren'"
class="deltagare-avvikelse__go-back"
af-size="m"
class="deltagare-avvikelse__step-buttons-wrapper--space-right"
af-variation="secondary"
(afOnClick)="goBack()"
>
Tillbaka</digi-button
af-size="m"
(afOnClick)="previousStep()"
>
Tillbaka
</digi-button>
</ng-container>
<ng-container *ngIf="currentStep === totalAmountOfSteps">
<digi-button af-size="m" (afOnClick)="openConfirmDialog = true;"> Skicka in </digi-button>
</ng-container>
</ng-container>
<ng-container *ngIf="currentStep === (totalAmountOfSteps -1)">
<digi-button af-size="m" (afOnClick)="nextStep"> Förhandsgranska </digi-button>
</ng-container>
<ng-container *ngIf="showSuccessNotification$ | async">
<digi-button af-size="m" (afOnClick)="backToDeltagare()"> Tillbaka till deltagaren </digi-button>
</ng-container>
</div>
</msfa-report-layout>
<digi-button [attr.af-aria-label]="'Skapa en avvikelserapport'" [attr.af-type]="'submit'" af-size="m"
>Nästa</digi-button
>
</form>
</div>
</digi-typography>
</section>
<msfa-confirm-dialog
[openConfirmDialog]="openConfirmDialog"
[itemToConfirm]="alternativeFormControl.value === 'avvikelse' ? 'avvikelse' : 'frånvaro' + 'rapport'"
(confirmDialogChanged)="setConfirmDialogChanged($event)"
>
</msfa-confirm-dialog>
</msfa-layout>

View File

@@ -22,7 +22,7 @@
font-size: var(--digi--typography--font-size--h3);
}
&__go-back {
margin-right: $digi--layout--gutter;
&__step-buttons-wrapper--space-right {
margin-right: var(--digi--layout--gutter--s);
}
}

View File

@@ -4,6 +4,7 @@ import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core';
import { AbstractControl, FormControl, FormGroup } from '@angular/forms';
import { ActivatedRoute, Router } from '@angular/router';
import { Alternative } from '@msfa-enums/alternative.enum';
import { ConfirmDialog } from '@msfa-enums/confirm-dialog.enum';
import { DayOrPartOfDay } from '@msfa-enums/day-or-part-of-day.enum';
import { FranvaroOrsaksKodEnum } from '@msfa-enums/franvaro-orsak-kod.enum';
import { KandaOrsakerEnum } from '@msfa-enums/kanda-orsaker-kod.enum';
@@ -15,17 +16,17 @@ import { FranvaroAlternativ } from '@msfa-models/franvaro-alternativ.model';
import { OrsaksKoderAvvikelse } from '@msfa-models/orsaks-koder-avvikelse.model';
import { KandaAvvikelseKoder, OrsaksKoderFranvaro } from '@msfa-models/orsaks-koder-franvaro.model';
import {
OrsakerIsRequiredCheck,
AnnanKandOrsakeIsRequiredCheck,
DescriptionIsRequiredCheck,
DateIsRequiredCheck,
DayOrPartOfDayIsRequiredCheck,
StartTimeIsRequiredCheck,
DescriptionIsRequiredCheck,
EndTimeIsRequiredCheck,
MotiveringIsRequiredCheck
MotiveringIsRequiredCheck,
OrsakerIsRequiredCheck,
StartTimeIsRequiredCheck
} from '@msfa-utils/validators/avvikelse-form-validator';
import { RequiredValidator } from '@msfa-utils/validators/required.validator';
import { Observable } from 'rxjs';
import { BehaviorSubject, Observable } from 'rxjs';
import { first, map, switchMap } from 'rxjs/operators';
import { DeltagareAvvikelseService } from '../../services/deltagare-avvikelse.service';
import { avvikelseAlternatives, dayOrPartOfDay } from './report-alternatives';
@@ -48,6 +49,9 @@ export class DeltagareAvvikelseComponent implements OnInit {
readonly startTimeFormControlName = 'startTime';
readonly endTimeFormControlName = 'endTime';
private _showSuccessNotification$ = new BehaviorSubject<boolean>(false);
private _showDangerNotification$ = new BehaviorSubject<boolean>(false);
contactInformation$: Observable<ContactInformationCompact> = this.activatedRoute.params
.pipe(
switchMap(({ deltagareId }) => this.deltagareAvvikelseService.getContactInformationCompact$(deltagareId))
@@ -64,12 +68,16 @@ export class DeltagareAvvikelseComponent implements OnInit {
dayOrPartOfDay: RadiobuttonModel[] = dayOrPartOfDay;
selectedOrsaksKod: string;
avvikelseFormGroup: FormGroup | null = null;
totalAmountOfSteps = 2;
currentStep = 1;
openConfirmDialog = false;
showSuccessNotification$ = this._showSuccessNotification$.asObservable();
showDangerNotification$ = this._showDangerNotification$.asObservable();
constructor(
private deltagareAvvikelseService: DeltagareAvvikelseService,
private activatedRoute: ActivatedRoute,
private router: Router) {
}
private router: Router,
private activatedRoute: ActivatedRoute) { }
ngOnInit(): void {
this.contactInformation$
@@ -152,34 +160,32 @@ export class DeltagareAvvikelseComponent implements OnInit {
return this.avvikelseFormGroup.get('timepickerFormGroup').get(this.endTimeFormControlName);
}
onFormSubmitted(): void {
if (this.avvikelseFormGroup.invalid) {
this.alternativeFormControl.markAsTouched();
return;
setConfirmDialogChanged(confirm: ConfirmDialog): void {
this.openConfirmDialog = false;
if (confirm === ConfirmDialog.ACCEPTED) {
const postAvvikelse: Avvikelse = {
datum_for_rapportering: this.todayDate,
arbetssokande: {
personnummer: this.contactInformation.personnummer.toString(),
fornamn: this.contactInformation.fornamn.toString(),
efternamn: this.contactInformation.efternamn.toString()
},
sokandeId: +this.activatedRoute.snapshot.params['deltagareId']
}
if (this.alternativeFormControl.value as string === Alternative.AVVIKELSE) {
postAvvikelse['avvikelsealternativ'] = this.avvikelse;
} else if (this.alternativeFormControl.value as string == Alternative.FRANVARO) {
postAvvikelse['franvaro'] = this.franvaro;
}
this.deltagareAvvikelseService.createAvvikelse$(postAvvikelse, this.alternativeFormControl.value as string)
.subscribe({
error: () => this._showDangerNotification$.next(true),
next: () => this._showSuccessNotification$.next(true),
complete: () => this.avvikelseFormGroup.reset()
});
}
this.avvikelseFormGroup.markAllAsTouched();
const postAvvikelse: Avvikelse = {
datum_for_rapportering: this.todayDate,
arbetssokande: {
personnummer: this.contactInformation.personnummer.toString(),
fornamn: this.contactInformation.fornamn.toString(),
efternamn: this.contactInformation.efternamn.toString()
},
sokandeId: +this.activatedRoute.snapshot.params['deltagareId']
}
if (this.alternativeFormControl.value as string === Alternative.AVVIKELSE) {
postAvvikelse['avvikelsealternativ'] = this.avvikelse;
} else if (this.alternativeFormControl.value as string == Alternative.FRANVARO) {
postAvvikelse['franvaro'] = this.franvaro;
}
this.deltagareAvvikelseService.createAvvikelse$(postAvvikelse, this.alternativeFormControl.value as string)
.subscribe({
next: () => this.avvikelseFormGroup.reset()
});
}
get franvaro(): FranvaroAlternativ {
@@ -218,7 +224,6 @@ export class DeltagareAvvikelseComponent implements OnInit {
}
}
setAlternative(): void {
if (this.alternativeFormControl.value as string == Alternative.FRANVARO) {
this.franvaroOrsaker$ = this.deltagareAvvikelseService.getOrsaksKoderFranvaro$();
@@ -293,6 +298,25 @@ export class DeltagareAvvikelseComponent implements OnInit {
this.dayOrPartOfDayFormControl.value as string === DayOrPartOfDay.DEL_AV_DAG
}
get nextStep(): number {
this.avvikelseFormGroup.markAllAsTouched();
if (this.avvikelseFormGroup.valid && this.currentStep < this.totalAmountOfSteps) {
return this.currentStep++;
}
}
previousStep(): void {
if (this.currentStep > 1) {
this.currentStep--;
this._showSuccessNotification$.next(false);
this._showDangerNotification$.next(false);
}
}
backToDeltagare(): void {
void this.router.navigate(['./deltagare', this.activatedRoute.snapshot.params['deltagareId']]);
}
private clearControlOnAlternativeChange(): void {
this.descriptionFormControl.setValue('');
this.fraga1FormControl.setValue('');
@@ -301,8 +325,4 @@ export class DeltagareAvvikelseComponent implements OnInit {
this.avvikelseFormGroup?.get('timepickerFormGroup').reset();
}
goBack(): void {
void this.router.navigate(['./deltagare', this.activatedRoute.snapshot.params['deltagareId']]);
}
}

View File

@@ -1,11 +1,15 @@
import { DigiNgFormDatepickerModule } from '@af/digi-ng/_form/form-datepicker';
import { DigiNgFormRadiobuttonGroupModule } from '@af/digi-ng/_form/form-radiobutton-group';
import { DigiNgFormTextareaModule } from '@af/digi-ng/_form/form-textarea';
import { DigiNgProgressProgressbarModule } from '@af/digi-ng/_progress/progressbar';
import { CommonModule } from '@angular/common';
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { ReactiveFormsModule } from '@angular/forms';
import { RouterModule } from '@angular/router';
import { LayoutModule } from '@msfa-shared/components/layout/layout.module';
import { ConfirmDialogModule } from '../../../../shared/confirm-dialog/confirm-dialog.module';
import { ReportLayoutModule } from '../../../../shared/report-layout/report-layout.module';
import { DeltagareConfirmFormModule } from './components/deltagare-confirm-form/deltagare-confirm-form.module';
import { DeltagareFragorFormModule } from './components/deltagare-fragor-form/deltagare-fragor-form.module';
import { DeltagareOrsaksFormModule } from './components/deltagare-orsaks-form/deltagare-orsaks-form.module';
import { DeltagareTimePickerModule } from './components/deltagare-time-picker/deltagare-time-picker.module';
@@ -23,9 +27,13 @@ import { DeltagareAvvikelseComponent } from './deltagare-avvikelse.component';
DigiNgFormRadiobuttonGroupModule,
DigiNgFormDatepickerModule,
DigiNgFormTextareaModule,
DigiNgProgressProgressbarModule,
DeltagareOrsaksFormModule,
DeltagareFragorFormModule,
DeltagareTimePickerModule
DeltagareTimePickerModule,
DeltagareConfirmFormModule,
ReportLayoutModule,
ConfirmDialogModule
],
exports: [DeltagareAvvikelseComponent]
})

View File

@@ -0,0 +1,14 @@
<digi-ng-dialog
*ngIf="openConfirmDialog"
[afActive]="openConfirmDialog"
(afOnPrimaryClick)="sendRequest()"
(afOnSecondaryClick)="closeConfirmDialog()"
(afOnInactive)="closeConfirmDialog()"
afHeading="Bekräfta"
afHeadingLevel="h2"
[afAriaLabel]="'Bekräfta skicka in ' + itemToConfirm"
afPrimaryButtonText="Skicka"
afSecondaryButtonText="Avbryt"
>
<p>Är du säker på att du vill skicka in en {{itemToConfirm}}?</p>
</digi-ng-dialog>

View File

@@ -0,0 +1,29 @@
import { DigiNgDialogModule } from '@af/digi-ng/_dialog/dialog';
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ConfirmDialogComponent } from './confirm-dialog.component';
describe('DeltagareCreateAvvikelseComponent', () => {
let component: ConfirmDialogComponent;
let fixture: ComponentFixture<ConfirmDialogComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
schemas: [CUSTOM_ELEMENTS_SCHEMA],
declarations: [ConfirmDialogComponent],
imports: [DigiNgDialogModule]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(ConfirmDialogComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -0,0 +1,25 @@
import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from '@angular/core';
import { ConfirmDialog } from '@msfa-enums/confirm-dialog.enum';
@Component({
selector: 'msfa-confirm-dialog',
templateUrl: './confirm-dialog.component.html',
styleUrls: ['./confirm-dialog.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class ConfirmDialogComponent {
@Input() openConfirmDialog: boolean;
@Input() itemToConfirm: string;
@Output() confirmDialogChanged = new EventEmitter<ConfirmDialog>();
sendRequest(): void {
this.openConfirmDialog = false;
this.confirmDialogChanged.emit(ConfirmDialog.ACCEPTED);
}
closeConfirmDialog(): void {
this.openConfirmDialog = false;
this.confirmDialogChanged.emit(ConfirmDialog.DISMISSED);
}
}

View File

@@ -0,0 +1,14 @@
import { DigiNgDialogModule } from '@af/digi-ng/_dialog/dialog';
import { CommonModule } from '@angular/common';
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { ConfirmDialogComponent } from './confirm-dialog.component';
@NgModule({
schemas: [CUSTOM_ELEMENTS_SCHEMA],
declarations: [ConfirmDialogComponent],
imports: [CommonModule, DigiNgDialogModule],
exports: [ConfirmDialogComponent]
})
export class ConfirmDialogModule { }

View File

@@ -1,58 +1,82 @@
<section class="report-layout" *ngIf="contactInformation$ | async as contactInformation">
<digi-typography>
<h1>{{ reportTitle }}</h1>
<p class="report-layout__description">{{description}}</p>
<div class="report-layout__deltagare-info">
<h2>{{reportSubTitle}}</h2>
<div class="report-layout__name">{{contactInformation.fornamn + ' ' + contactInformation.efternamn}}</div>
<div class="report-layout__personnummer">
<span>Personnummer:</span>
<msfa-hide-text
symbols="********-****"
[changingText]="contactInformation.personnummer"
ariaLabelType="Personnumer"
></msfa-hide-text>
</div>
<span *ngIf="service">Tjänst: KROM</span>
<ng-container *ngIf="startDate && endDate && !isPeriodDate">
<span>Startdatum: {{startDate}}</span>
<span>Slutdatum: {{endDate}}</span>
</ng-container>
<span *ngIf="startDate && endDate && isPeriodDate">Avser period: {{startDate}} - {{endDate}}</span>
</div>
<digi-typography>
<h1>{{ reportTitle }}</h1>
<p class="report-layout__description">{{description}}</p>
<div class="report-layout__deltagare-info">
<h2>{{reportSubTitle}}</h2>
<div class="report-layout__name">{{contactInformation.fornamn + ' ' + contactInformation.efternamn}}</div>
<div class="report-layout__personnummer">
<span>Personnummer:</span>
<msfa-hide-text
symbols="********-****"
[changingText]="contactInformation.personnummer"
ariaLabelType="Personnumer"
></msfa-hide-text>
</div>
<span *ngIf="service">Tjänst: KROM</span>
<ng-container *ngIf="startDate && endDate && !isPeriodDate">
<span>Startdatum: {{startDate}}</span>
<span>Slutdatum: {{endDate}}</span>
</ng-container>
<span *ngIf="startDate && endDate && isPeriodDate">Avser period: {{startDate}} - {{endDate}}</span>
</div>
<digi-ng-progress-progressbar
[afSteps]="totalAmountOfSteps"
[afActiveStep]="currentStep"
></digi-ng-progress-progressbar>
<div class="report-layout__notification-alert">
<digi-notification-alert
*ngIf="showSuccessNotification"
af-variation="success"
af-heading="Allt gick bra"
af-heading-level="h3"
>
<p>Din {{reportName}} är nu inskickad till Arbetsförmedlingen.</p>
</digi-notification-alert>
<div class="report-layout__main-content">
<ng-content></ng-content>
</div>
<digi-notification-alert
*ngIf="showDangerNotification"
af-variation="danger"
af-heading="Någonting gick fel"
af-heading-level="h3"
>
<p>Vi kunde inte skicka in din {{reportName}}.</p>
</digi-notification-alert>
</div>
<div class="report-layout__step-buttons-wrapper">
<ng-container *ngIf="currentStep > 1">
<digi-button class="report-layout__step-buttons-wrapper--space-right"
af-variation="secondary" af-size="m" (afOnClick)="previousStep()">
Tillbaka
</digi-button>
</ng-container>
<ng-container *ngIf="currentStep < (totalAmountOfSteps -1)">
<digi-button class="report-layout__step-buttons-wrapper"
af-size="m" (afOnClick)="nextStep()">
Nästa
</digi-button>
</ng-container>
<ng-container *ngIf="currentStep === (totalAmountOfSteps -1)">
<digi-button af-size="m" (afOnClick)="nextStep()">
Förhandsgranska
</digi-button>
</ng-container>
<ng-container *ngIf="currentStep === totalAmountOfSteps">
<digi-button af-size="m" (afOnClick)="sendRequest()">
Skicka in
</digi-button>
</ng-container>
</div>
</digi-typography>
</section>
<digi-ng-progress-progressbar
[afSteps]="totalAmountOfSteps"
[afActiveStep]="currentStep"
></digi-ng-progress-progressbar>
<div class="report-layout__main-content">
<ng-content></ng-content>
</div>
<!-- <div class="report-layout__step-buttons-wrapper">
<ng-container *ngIf="!showSuccessNotification">
<ng-container *ngIf="currentStep > 1">
<digi-button
class="report-layout__step-buttons-wrapper--space-right"
af-variation="secondary"
af-size="m"
(afOnClick)="previousStep()"
>
Tillbaka
</digi-button>
</ng-container>
<ng-container *ngIf="currentStep < (totalAmountOfSteps -1)">
<digi-button class="report-layout__step-buttons-wrapper" af-size="m" (afOnClick)="nextStep()">
Nästa
</digi-button>
</ng-container>
</ng-container>
<ng-container *ngIf="currentStep === (totalAmountOfSteps -1)">
<digi-button af-size="m" (afOnClick)="nextStep()"> Förhandsgranska </digi-button>
</ng-container>
<ng-container *ngIf="currentStep === totalAmountOfSteps">
<digi-button af-size="m" (afOnClick)="sendRequest()"> Skicka in </digi-button>
</ng-container>
<ng-container *ngIf="showSuccessNotification">
<digi-button af-size="m" (afOnClick)="backToDeltagare()"> Tillbaka till deltagaren </digi-button>
</ng-container>
</div> -->
</digi-typography>
</section>

View File

@@ -1,8 +1,5 @@
@import 'variables/gutters';
.report-layout {
&__description {
}
&____name {
margin-top: 0;
font-size: var(--digi--typography--font-size--s);
@@ -25,6 +22,10 @@
margin-left: var(--digi--layout--gutter--s);
}
&__notification-alert {
margin-bottom: $digi--layout--gutter--xl;
}
&__main-content {
margin: $digi--layout--gutter--xl 0;
}

View File

@@ -1,5 +1,6 @@
import { Component, ChangeDetectionStrategy, Input, EventEmitter, Output } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from '@angular/core';
import { FormGroup } from '@angular/forms';
import { ActivatedRoute, Router } from '@angular/router';
import { ContactInformationCompact } from '@msfa-models/api/contact-information.response.model';
import { Observable } from 'rxjs';
import { switchMap } from 'rxjs/operators';
@@ -22,36 +23,50 @@ export class ReportLayoutComponent {
@Input() isPeriodDate = false;
@Input() totalAmountOfSteps = 3;
@Input() currentStep = 1;
@Input() form: FormGroup | null = null;
@Input() reportName: string;
@Input() showSuccessNotification = false;
@Input() showDangerNotification = false;
@Output() currentStepEvent = new EventEmitter<number>();
@Output() sendRequestEvent = new EventEmitter<boolean>();
contactInformation$: Observable<ContactInformationCompact> = this.activatedRoute.params
.pipe(
switchMap(({ deltagareId }) => this.deltagareAvvikelseService.getContactInformationCompact$(deltagareId))
);
.pipe(
switchMap(({ deltagareId }) => this.deltagareAvvikelseService.getContactInformationCompact$(deltagareId))
);
constructor(
private deltagareAvvikelseService: DeltagareAvvikelseService,
private activatedRoute: ActivatedRoute,
private router: Router
) { }
nextStep():void {
if(this.currentStep < this.totalAmountOfSteps) {
nextStep(): void {
console.log(this.form);
if (this.form.valid && this.currentStep < this.totalAmountOfSteps) {
this.currentStep++;
this.currentStepEvent.emit(this.currentStep);
}
this.form.markAllAsTouched();
}
previousStep():void {
if(this.currentStep > 1) {
previousStep(): void {
if (this.currentStep > 1) {
this.currentStep--;
this.currentStepEvent.emit(this.currentStep);
this.showSuccessNotification = false;
this.showDangerNotification = false;
}
this.currentStep !== this.totalAmountOfSteps ? this.sendRequestEvent.emit(false): null;
this.currentStep !== this.totalAmountOfSteps ? this.sendRequestEvent.emit(false) : null;
}
sendRequest():void {
sendRequest(): void {
this.sendRequestEvent.emit(true);
}
backToDeltagare(): void {
void this.router.navigate(['./deltagare', this.activatedRoute.snapshot.params['deltagareId']]);
}
}

View File

@@ -0,0 +1,4 @@
export enum ConfirmDialog {
ACCEPTED = 'ACCEPTED',
DISMISSED = 'DISMISSED'
}

View File

@@ -3,6 +3,6 @@ export enum FranvaroOrsaksKodEnum {
Arbete = 16,
OkandOrsak = 17,
AnnanKandOrsak = 18,
VAB = 26,
Utbildning = 27,
VAB = 23,
Utbildning = 24,
}

View File

@@ -1,4 +0,0 @@
export enum ReportType {
AVVIKELSERAPPORT = 'Avvikelserapport',
OKAND = 'Okänd',
}

View File

@@ -1,11 +1,10 @@
import { AvvikelseOrsaksKodEnum } from '@msfa-enums/avvikelse-orsak-kod.enum';
import { KandaOrsakerEnum } from '@msfa-enums/kanda-orsaker-kod.enum';
import { FranvaroOrsaksKodEnum } from '@msfa-enums/franvaro-orsak-kod.enum';
import { KandaAvvikelseKoderResponse } from './api/kanda-avvikelse-koder.response.model';
import { OrsaksKoderFranvaroResponse } from './api/orsaks-koder-franvaro.response.model';
export interface OrsaksKoderFranvaro {
name: string;
value: AvvikelseOrsaksKodEnum | KandaOrsakerEnum;
value: FranvaroOrsaksKodEnum;
state: number;
index?: number;
}