diff --git a/apps/mina-sidor-fa/src/app/pages/avrop/avrop.component.html b/apps/mina-sidor-fa/src/app/pages/avrop/avrop.component.html index 3acae70..5daae00 100644 --- a/apps/mina-sidor-fa/src/app/pages/avrop/avrop.component.html +++ b/apps/mina-sidor-fa/src/app/pages/avrop/avrop.component.html @@ -42,12 +42,12 @@ -
- Steg {{ currentStep }} av {{ totalAmountOfSteps }}: - +
+
diff --git a/apps/mina-sidor-fa/src/app/pages/avrop/avrop.component.scss b/apps/mina-sidor-fa/src/app/pages/avrop/avrop.component.scss index cc16cab..d84d03b 100644 --- a/apps/mina-sidor-fa/src/app/pages/avrop/avrop.component.scss +++ b/apps/mina-sidor-fa/src/app/pages/avrop/avrop.component.scss @@ -19,6 +19,7 @@ &__progress-bar { z-index: $msfa__z-index-default; + min-width: 12rem; } &__select-handledare { diff --git a/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-details/pages/deltagare-reports/components/report-layout/report-layout.component.html b/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-details/pages/deltagare-reports/components/report-layout/report-layout.component.html index cd3cd34..5ca0ea2 100644 --- a/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-details/pages/deltagare-reports/components/report-layout/report-layout.component.html +++ b/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-details/pages/deltagare-reports/components/report-layout/report-layout.component.html @@ -1,55 +1,47 @@ -
+
+

{{ reportTitle }}

-

{{description}}

-
-

{{reportSubTitle}}

-
{{contactInformation.firstName + ' ' + contactInformation.lastName}}
-
- Personnummer: - -
- Tjänst: KROM - - Startdatum: {{startDate}} - Slutdatum: {{endDate}} - - Avser period: {{startDate}} - {{endDate}} +

{{description}}

+
+

{{reportSubTitle}}

+
+
Namn
+
{{avrop.fullName}}
+
+
+
Personnummer
+
+ +
+
Tjänst
+
{{avrop.tjanst}}
+ +
Startdatum
+
{{avrop.startDate | date:'longDate'}}
+
Slutdatum
+
{{avrop.endDate | date:'longDate'}}
+
+ +
Avser period
+
{{avrop.startDate | date:'longDate'}} - {{avrop.endDate | date:'longDate'}}
+
+
-
- -

Din {{reportTitle.toLocaleLowerCase()}} är nu inskickad till Arbetsförmedlingen.

-
- - -

Vi kunde inte skicka in din {{reportTitle.toLocaleLowerCase()}}.

-
+
+
- -
+
- - - - diff --git a/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-details/pages/deltagare-reports/components/report-layout/report-layout.component.scss b/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-details/pages/deltagare-reports/components/report-layout/report-layout.component.scss index 21e1fbc..58a0aa7 100644 --- a/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-details/pages/deltagare-reports/components/report-layout/report-layout.component.scss +++ b/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-details/pages/deltagare-reports/components/report-layout/report-layout.component.scss @@ -1,32 +1,11 @@ @import 'apps/mina-sidor-fa/src/styles/variables/gutters'; .report-layout { - &__name { - margin-top: 0; - font-weight: var(--digi--typography--font-weight--semibold); - } - - &__deltagare-info { - display: flex; - flex-direction: column; - margin-bottom: $digi--layout--gutter--xl; - font-size: var(--digi--typography--font-size--m); - font-weight: var(--digi--typography--font-weight--semibold); - } - - &__personnummer { - display: flex; - } - - &__personnummer msfa-hide-text { - margin-left: var(--digi--layout--gutter--s); - } - &__notification-alert { margin-bottom: $digi--layout--gutter--xl; } - &__main-content { + &__progress-bar { margin: $digi--layout--gutter--xl 0; } } diff --git a/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-details/pages/deltagare-reports/components/report-layout/report-layout.component.ts b/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-details/pages/deltagare-reports/components/report-layout/report-layout.component.ts index 124634d..10c06ca 100644 --- a/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-details/pages/deltagare-reports/components/report-layout/report-layout.component.ts +++ b/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-details/pages/deltagare-reports/components/report-layout/report-layout.component.ts @@ -1,9 +1,5 @@ import { ChangeDetectionStrategy, Component, Input } from '@angular/core'; -import { ActivatedRoute } from '@angular/router'; -import { ContactInformation } from '@msfa-models/contact-information.model'; -import { DeltagareApiService } from '@msfa-services/api/deltagare.api.service'; -import { Observable } from 'rxjs'; -import { switchMap } from 'rxjs/operators'; +import { Avrop } from '@msfa-models/avrop.model'; @Component({ selector: 'msfa-report-layout', @@ -12,23 +8,17 @@ import { switchMap } from 'rxjs/operators'; changeDetection: ChangeDetectionStrategy.OnPush, }) export class ReportLayoutComponent { - @Input() reportTitle = 'Report Title'; - @Input() reportSubTitle = 'Report Sub Title'; - @Input() description = 'Report description ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem'; + @Input() reportTitle: string; + @Input() reportSubTitle: string; + @Input() description: string; @Input() startDate: string; @Input() endDate: string; @Input() service: string; @Input() isPeriodDate = false; + @Input() avrop: Avrop; @Input() totalAmountOfSteps = 3; @Input() currentStep = 1; @Input() showSuccessNotification = false; @Input() showDangerNotification = false; - - contactInformation$: Observable = this.activatedRoute.params.pipe( - switchMap(({ genomforandeReferens }) => - this.deltagareApiService.fetchContactInformation$(genomforandeReferens) - ) - ); - - constructor(private deltagareApiService: DeltagareApiService, private activatedRoute: ActivatedRoute) { } + @Input() submitted = false; } diff --git a/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-details/pages/deltagare-reports/components/report-layout/report-layout.module.ts b/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-details/pages/deltagare-reports/components/report-layout/report-layout.module.ts index 7f77b11..6623ece 100644 --- a/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-details/pages/deltagare-reports/components/report-layout/report-layout.module.ts +++ b/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-details/pages/deltagare-reports/components/report-layout/report-layout.module.ts @@ -1,22 +1,15 @@ +import { DigiNgProgressProgressbarModule } from '@af/digi-ng/_progress/progressbar'; import { CommonModule } from '@angular/common'; -import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; +import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; +import { RouterModule } from '@angular/router'; +import { HideTextModule } from '@msfa-shared/components/hide-text/hide-text.module'; import { LayoutModule } from '@msfa-shared/components/layout/layout.module'; import { ReportLayoutComponent } from './report-layout.component'; -import { DigiNgProgressProgressbarModule } from '@af/digi-ng/_progress/progressbar'; -import { HideTextModule } from '@msfa-shared/components/hide-text/hide-text.module'; -import { RouterModule } from '@angular/router'; -import { DigiNgSkeletonBaseModule } from '@af/digi-ng/_skeleton/skeleton-base'; @NgModule({ schemas: [CUSTOM_ELEMENTS_SCHEMA], declarations: [ReportLayoutComponent], - imports: [ - CommonModule, - RouterModule, - LayoutModule, - DigiNgProgressProgressbarModule, - DigiNgSkeletonBaseModule, - HideTextModule], + imports: [CommonModule, RouterModule, LayoutModule, DigiNgProgressProgressbarModule, HideTextModule], exports: [ReportLayoutComponent], }) export class ReportLayoutModule {} diff --git a/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-details/pages/deltagare-reports/deltagare-avvikelse/deltagare-avvikelse.component.spec.ts b/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-details/pages/deltagare-reports/deltagare-avvikelse/deltagare-avvikelse.component.spec.ts index a136d81..f062a51 100644 --- a/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-details/pages/deltagare-reports/deltagare-avvikelse/deltagare-avvikelse.component.spec.ts +++ b/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-details/pages/deltagare-reports/deltagare-avvikelse/deltagare-avvikelse.component.spec.ts @@ -7,7 +7,7 @@ import { ReactiveFormsModule } from '@angular/forms'; import { RouterTestingModule } from '@angular/router/testing'; import { LayoutComponent } from '@msfa-shared/components/layout/layout.component'; import { DeltagareAvvikelseComponent } from './deltagare-avvikelse.component'; - +import { DeltagareAvvikelseService } from './deltagare-avvikelse.service'; describe('DeltagareAvvikelseComponent', () => { let component: DeltagareAvvikelseComponent; @@ -22,8 +22,9 @@ describe('DeltagareAvvikelseComponent', () => { HttpClientTestingModule, ReactiveFormsModule, DigiNgFormRadiobuttonGroupModule, - DigiNgFormDatepickerModule - ] + DigiNgFormDatepickerModule, + ], + providers: [DeltagareAvvikelseService], }).compileComponents(); }); diff --git a/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-details/pages/deltagare-reports/deltagare-gemensam-planering/deltagare-gemensam-planering.component.html b/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-details/pages/deltagare-reports/deltagare-gemensam-planering/deltagare-gemensam-planering.component.html index 46c06e4..ed5faeb 100644 --- a/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-details/pages/deltagare-reports/deltagare-gemensam-planering/deltagare-gemensam-planering.component.html +++ b/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-details/pages/deltagare-reports/deltagare-gemensam-planering/deltagare-gemensam-planering.component.html @@ -1,43 +1,126 @@ -
- -
-

Deltar arbetssökande på distans?

- + +
+
+ +

+ Gemensam planering för deltagare {{avrop.fullName}} är nu inskickad till Arbetsförmedlingen och inväntar + godkännande. +

+
+
Datum
+
{{lastSubmittedGP | date:'longDate'}} kl {{lastSubmittedGP | date:'shortTime'}}
+
+
+ Tillbaka till deltagaren
-
Förhandsgranska
-
- - - Tillbaka - - - - Förhandsgranska - - - Skicka in - -
- - + +
+ + + + + +

+ Varje gemensam planering måste innehålla de två obligatoriska aktiviteterna samt en frivillig aktivitet + som en del av det individuella stödet för varje deltagare. +

+ + +
    +
  • + +
  • +
+ {{gpFormGroup.errors.activityIds}} +
+
+
+ +
+
Deltar arbetssökande på distans?
+
{{gpFormGroup.value.distance ? 'Ja' : 'Nej'}}
+
Aktiviteter
+
+
    +
  • + + {{activity.name}} +
  • +
+
+
+
+
+ + Tillbaka + + + Förhandsgranska + + + Bekräfta och skicka in + +
+
+ +
+
+
+ + + + + + + + diff --git a/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-details/pages/deltagare-reports/deltagare-gemensam-planering/deltagare-gemensam-planering.component.scss b/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-details/pages/deltagare-reports/deltagare-gemensam-planering/deltagare-gemensam-planering.component.scss index dfc3b1d..90ced48 100644 --- a/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-details/pages/deltagare-reports/deltagare-gemensam-planering/deltagare-gemensam-planering.component.scss +++ b/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-details/pages/deltagare-reports/deltagare-gemensam-planering/deltagare-gemensam-planering.component.scss @@ -1,8 +1,43 @@ +@import 'mixins/list'; +@import 'variables/gutters'; + .gemensam-planering { - &__pages { - margin: 5rem 0rem; + &__confirmation, + &__form { + display: flex; + flex-direction: column; + gap: $digi--layout--gutter--l; } - &__step-buttons-wrapper--space-right { - margin-right: 1rem; + + &__activity-list { + @include msfa__reset-list; + margin-bottom: var(--digi--layout--gutter--s); + } + + &__activity-item { + display: flex; + align-items: center; + gap: var(--digi--layout--gutter--s); + margin-top: var(--digi--layout--gutter--s); + } + + &__activity-check { + color: var(--digi--ui--color--border--success); + } + + &__footer { + display: flex; + gap: var(--digi--layout--gutter); + } + + ::ng-deep { + .digi-form-fieldset { + margin: 0; + + &__legend { + margin-bottom: var(--digi--layout--gutter--s); + padding: 0; + } + } } } diff --git a/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-details/pages/deltagare-reports/deltagare-gemensam-planering/deltagare-gemensam-planering.component.ts b/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-details/pages/deltagare-reports/deltagare-gemensam-planering/deltagare-gemensam-planering.component.ts index 48fae84..cc70d2f 100644 --- a/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-details/pages/deltagare-reports/deltagare-gemensam-planering/deltagare-gemensam-planering.component.ts +++ b/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-details/pages/deltagare-reports/deltagare-gemensam-planering/deltagare-gemensam-planering.component.ts @@ -1,8 +1,18 @@ -import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core'; import { RadiobuttonGroupDirection, RadiobuttonModel } from '@af/digi-ng/_form/form-radiobutton-group'; -import { AbstractControl, FormControl, FormGroup } from '@angular/forms'; -import { RequiredValidator } from '@msfa-validators/required.validator'; -import { GemensamPlaneringApiService } from '@msfa-services/api/gemensam-planering-api.service'; +import { ChangeDetectionStrategy, Component } from '@angular/core'; +import { FormArray, FormControl, FormGroup } from '@angular/forms'; +import { ActivatedRoute } from '@angular/router'; +import { ConfirmDialog } from '@msfa-enums/confirm-dialog.enum'; +import { Activity } from '@msfa-models/activity.model'; +import { Avrop } from '@msfa-models/avrop.model'; +import { + GemensamPlanering, + mapGemensamPlaneringToGemensamPlaneringPostRequest, +} from '@msfa-models/gemensam-planering.model'; +import { BehaviorSubject, Observable } from 'rxjs'; +import { distinctUntilChanged, map, shareReplay, switchMap } from 'rxjs/operators'; +import { GemensamPlaneringService } from './gemensam-planering.service'; +import { GemensamPlaneringValidator } from './gemensam-planering.validator'; @Component({ selector: 'msfa-deltagare-gemensam-planering', @@ -10,54 +20,124 @@ import { GemensamPlaneringApiService } from '@msfa-services/api/gemensam-planeri styleUrls: ['./deltagare-gemensam-planering.component.scss'], changeDetection: ChangeDetectionStrategy.OnPush, }) -export class DeltagareGemensamPlaneringComponent implements OnInit { +export class DeltagareGemensamPlaneringComponent { totalAmountOfSteps = 2; currentStep = 1; - direction = RadiobuttonGroupDirection.HORIZONTAL; - planeringFormGroup: FormGroup | null = null; + obligatoryActivityIds = [165, 188]; + shouldValidate = false; + RadiobuttonGroupDirection = RadiobuttonGroupDirection; + confirmDialogOpen = false; + private _lastSubmittedGP$ = new BehaviorSubject(null); + lastSubmittedGP$: Observable = this._lastSubmittedGP$.asObservable(); - readonly participatedOnDistansFormControlName = 'participatedOnDistans'; - distanceChoice: RadiobuttonModel[] = [ + activities$: Observable = this.gemensamPlaneringService.activities$; + currentGenomforandeReferens$: Observable = this.activatedRoute.params.pipe( + map(params => params.genomforandeReferens as string), + distinctUntilChanged( + ([prevGenomforandeReferens], [currGenomforandeReferens]) => prevGenomforandeReferens === currGenomforandeReferens + ), + map(genomforandeReferens => +genomforandeReferens) + ); + avrop$: Observable = this.currentGenomforandeReferens$.pipe( + switchMap(genomforandeReferens => this.gemensamPlaneringService.fetchAvropInformation$(genomforandeReferens)), + shareReplay(1) + ); + + gpFormGroup = new FormGroup( { - label: 'Ja', - value: 'Ja', - }, - { - label: 'Nej', - value: 'Nej', + distance: new FormControl(false), + activityIds: new FormArray(this.obligatoryActivityIds.map(id => new FormControl(id))), }, + [GemensamPlaneringValidator.isGemensamPlaneringValid(this.obligatoryActivityIds)] + ); + + distanceRadiobuttons: RadiobuttonModel[] = [ + { label: 'Ja', value: true }, + { label: 'Nej', value: false }, ]; - constructor(private gemensamPlaneringService: GemensamPlaneringApiService) {} - - get participatedOnDistansFormControl(): AbstractControl | undefined { - return this.planeringFormGroup?.get(this.participatedOnDistansFormControlName); + get activityIdsFormArray(): FormArray { + return this.gpFormGroup.get('activityIds') as FormArray; } - ngOnInit(): void { - this.planeringFormGroup = new FormGroup({ - participatedOnDistans: new FormControl('', [RequiredValidator()]), - }); + get selectedActivityIds(): number[] { + return this.activityIdsFormArray.value as number[]; } - nextStep(): void { - if (this.planeringFormGroup?.valid && this.currentStep < this.totalAmountOfSteps) { - console.log(this.participatedOnDistansFormControl.value); - this.currentStep++; - console.log(this.currentStep); + get selectedActivityIdsExcludingObligatory(): number[] { + return this.selectedActivityIds.filter(id => this.obligatoryActivityIds.indexOf(id) === -1); + } + + isActivityChecked(id: number): boolean { + return this.selectedActivityIds.includes(id); + } + + isActivityObligatory(id: number): boolean { + return this.obligatoryActivityIds.includes(id); + } + + showActivityAsInvalid(id: number): boolean { + if (this.shouldValidate) { + if (this.isActivityObligatory(id) && !this.isActivityChecked(id)) { + return true; + } + if (!this.isActivityObligatory(id) && !this.selectedActivityIdsExcludingObligatory.length) { + return true; + } + } + + return false; + } + + constructor(private gemensamPlaneringService: GemensamPlaneringService, private activatedRoute: ActivatedRoute) {} + + updateActivityIds(activityId: string, checked: boolean): void { + if (checked) { + this.activityIdsFormArray.push(new FormControl(+activityId)); + } else { + const index: number = this.selectedActivityIds.findIndex(id => id === +activityId); + + if (index > -1) { + this.activityIdsFormArray.removeAt(index); + } } } - previousStep(): void { - if (this.currentStep > 1) { - this.currentStep--; - console.log(this.currentStep); + goToPreview(): void { + this.shouldValidate = true; + + if (this.gpFormGroup.invalid) { + return; + } + + this.currentStep = 2; + } + + goToStep1(): void { + this.shouldValidate = false; + this.currentStep = 1; + } + + openConfirmDialog(): void { + this.confirmDialogOpen = true; + } + + closeConfirmDialogAndProceed(confirmDialogAnswer: ConfirmDialog, genomforandeReferens: number): void { + if (confirmDialogAnswer === ConfirmDialog.ACCEPTED) { + const distance = this.gpFormGroup.get('distance').value as boolean; + const activityIds = this.gpFormGroup.get('activityIds').value as number[]; + + void this.postGemensamPlanering({ distance, activityIds, genomforandeReferens }); + } else { + this.confirmDialogOpen = false; } } - sendRequest(val: boolean): boolean { - return val; + async postGemensamPlanering(postRequest: GemensamPlanering): Promise { + return this.gemensamPlaneringService + .postGemensamPlanering(mapGemensamPlaneringToGemensamPlaneringPostRequest(postRequest)) + .then(() => { + this._lastSubmittedGP$.next(new Date()); + }); } - - onFormSubmitted(): void {} } diff --git a/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-details/pages/deltagare-reports/deltagare-gemensam-planering/deltagare-gemensam-planering.module.ts b/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-details/pages/deltagare-reports/deltagare-gemensam-planering/deltagare-gemensam-planering.module.ts index dff5b7e..2c43c72 100644 --- a/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-details/pages/deltagare-reports/deltagare-gemensam-planering/deltagare-gemensam-planering.module.ts +++ b/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-details/pages/deltagare-reports/deltagare-gemensam-planering/deltagare-gemensam-planering.module.ts @@ -1,13 +1,17 @@ +import { DigiNgFormCheckboxModule } from '@af/digi-ng/_form/form-checkbox'; +import { DigiNgFormRadiobuttonGroupModule } from '@af/digi-ng/_form/form-radiobutton-group'; +import { DigiNgProgressProgressbarModule } from '@af/digi-ng/_progress/progressbar'; +import { DigiNgSkeletonBaseModule } from '@af/digi-ng/_skeleton/skeleton-base'; import { CommonModule } from '@angular/common'; import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; -import { RouterModule } from '@angular/router'; -import { LayoutModule } from '@msfa-shared/components/layout/layout.module'; -import { DeltagareGemensamPlaneringComponent } from './deltagare-gemensam-planering.component'; -import { DigiNgProgressProgressbarModule } from '@af/digi-ng/_progress/progressbar'; -import { DigiNgFormRadiobuttonGroupModule } from '@af/digi-ng/_form/form-radiobutton-group'; import { ReactiveFormsModule } from '@angular/forms'; +import { RouterModule } from '@angular/router'; +import { BackLinkModule } from '@msfa-shared/components/back-link/back-link.module'; +import { ConfirmDialogModule } from '@msfa-shared/components/confirm-dialog/confirm-dialog.module'; +import { LayoutModule } from '@msfa-shared/components/layout/layout.module'; +import { LoaderModule } from '@msfa-shared/components/loader/loader.module'; import { ReportLayoutModule } from '../components/report-layout/report-layout.module'; -import { DigiNgFormCheckboxModule } from '@af/digi-ng/_form/form-checkbox'; +import { DeltagareGemensamPlaneringComponent } from './deltagare-gemensam-planering.component'; @NgModule({ schemas: [CUSTOM_ELEMENTS_SCHEMA], @@ -20,6 +24,10 @@ import { DigiNgFormCheckboxModule } from '@af/digi-ng/_form/form-checkbox'; DigiNgFormRadiobuttonGroupModule, ReactiveFormsModule, ReportLayoutModule, + ConfirmDialogModule, + BackLinkModule, + LoaderModule, + DigiNgSkeletonBaseModule, DigiNgFormCheckboxModule, ], exports: [DeltagareGemensamPlaneringComponent], diff --git a/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-details/pages/deltagare-reports/deltagare-gemensam-planering/gemensam-planering.service.ts b/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-details/pages/deltagare-reports/deltagare-gemensam-planering/gemensam-planering.service.ts new file mode 100644 index 0000000..acc100b --- /dev/null +++ b/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-details/pages/deltagare-reports/deltagare-gemensam-planering/gemensam-planering.service.ts @@ -0,0 +1,27 @@ +import { Injectable } from '@angular/core'; +import { Activity } from '@msfa-models/activity.model'; +import { GemensamPlaneringPostRequest } from '@msfa-models/api/gemensam-planering.request.model'; +import { Avrop } from '@msfa-models/avrop.model'; +import { GemensamPlaneringApiService } from '@msfa-services/api/gemensam-planering-api.service'; +import { BehaviorSubject, Observable, of } from 'rxjs'; + +@Injectable({ + providedIn: 'root', +}) +export class GemensamPlaneringService { + public activities$: Observable = this.gemensamPlaneringApiService.fetchActivities$(); + private _error$ = new BehaviorSubject(null); + public error$: Observable = this._error$.asObservable(); + + public fetchAvropInformation$(genomforandeReferens: number): Observable { + return this.gemensamPlaneringApiService.fetchAvropInformation$(genomforandeReferens); + } + + public async postGemensamPlanering(requestData: GemensamPlaneringPostRequest): Promise { + // TODO: When API has been updated we can activate the real post + return of(undefined as void).toPromise(); + return this.gemensamPlaneringApiService.postGemensamPlanering(requestData); + } + + constructor(private gemensamPlaneringApiService: GemensamPlaneringApiService) {} +} diff --git a/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-details/pages/deltagare-reports/deltagare-gemensam-planering/gemensam-planering.validator.ts b/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-details/pages/deltagare-reports/deltagare-gemensam-planering/gemensam-planering.validator.ts new file mode 100644 index 0000000..096e7f4 --- /dev/null +++ b/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-details/pages/deltagare-reports/deltagare-gemensam-planering/gemensam-planering.validator.ts @@ -0,0 +1,37 @@ +import { AbstractControl, ValidatorFn } from '@angular/forms'; + +export class GemensamPlaneringValidator { + static isGemensamPlaneringValid(obligatoryActivityIds: number[] = []): ValidatorFn { + return (c: AbstractControl): { [key: string]: string } => { + let errors: { [key: string]: string } = null; + const activityIds = (c.get('activityIds')?.value as number[]) || []; + const obligatoryActivityIdsMissing = !obligatoryActivityIds.every(id => activityIds.includes(id)); + const activityIdsWithoutObligatoryActivityIds = activityIds.filter( + id => obligatoryActivityIds.indexOf(id) === -1 + ); + + if (obligatoryActivityIdsMissing && !activityIdsWithoutObligatoryActivityIds.length) { + errors = { + ...errors, + activityIds: 'Obligatoriska aktiviteter och minst en frivillig aktivitet måste väljas', + }; + } else { + if (obligatoryActivityIdsMissing) { + errors = { + ...errors, + activityIds: 'Obligatoriska aktiviteter måste väljas', + }; + } + + if (!activityIdsWithoutObligatoryActivityIds.length) { + errors = { + ...errors, + activityIds: 'Minst en frivillig aktivitet måste väljas', + }; + } + } + + return errors; + }; + } +} diff --git a/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-details/pages/deltagare-reports/deltagare-periodisk-redovisning/deltagare-periodisk-redovisning.component.spec.ts b/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-details/pages/deltagare-reports/deltagare-periodisk-redovisning/deltagare-periodisk-redovisning.component.spec.ts index 46f7cc7..a28be43 100644 --- a/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-details/pages/deltagare-reports/deltagare-periodisk-redovisning/deltagare-periodisk-redovisning.component.spec.ts +++ b/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-details/pages/deltagare-reports/deltagare-periodisk-redovisning/deltagare-periodisk-redovisning.component.spec.ts @@ -1,8 +1,7 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; - import { DeltagarePeriodiskRedovisningComponent } from './deltagare-periodisk-redovisning.component'; -describe('PeriodiskRedovisningComponent', () => { +describe('DeltagarePeriodiskRedovisningComponent', () => { let component: DeltagarePeriodiskRedovisningComponent; let fixture: ComponentFixture; diff --git a/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-details/pages/deltagare-reports/deltagare-periodisk-redovisning/deltagare-periodisk-redovisning.component.ts b/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-details/pages/deltagare-reports/deltagare-periodisk-redovisning/deltagare-periodisk-redovisning.component.ts index fa72a68..75bed36 100644 --- a/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-details/pages/deltagare-reports/deltagare-periodisk-redovisning/deltagare-periodisk-redovisning.component.ts +++ b/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-details/pages/deltagare-reports/deltagare-periodisk-redovisning/deltagare-periodisk-redovisning.component.ts @@ -1,8 +1,7 @@ import { RadiobuttonGroupDirection } from '@af/digi-ng/_form/form-radiobutton-group'; -import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core'; +import { ChangeDetectionStrategy, Component } from '@angular/core'; import { AbstractControl, FormArray, FormControl, FormGroup, Validators } from '@angular/forms'; import { Activity, SubActivity } from '@msfa-models/activity.model'; -import { ActivitiesApiService } from '@msfa-services/api/activities-api.service'; @Component({ selector: 'msfa-deltagare-periodisk-redovisning', @@ -10,7 +9,7 @@ import { ActivitiesApiService } from '@msfa-services/api/activities-api.service' styleUrls: ['./deltagare-periodisk-redovisning.component.scss'], changeDetection: ChangeDetectionStrategy.OnPush, }) -export class DeltagarePeriodiskRedovisningComponent implements OnInit { +export class DeltagarePeriodiskRedovisningComponent { radiobuttonGroupDirection = RadiobuttonGroupDirection; totalAmountOfSteps = 3; currentStep = 1; @@ -25,8 +24,6 @@ export class DeltagarePeriodiskRedovisningComponent implements OnInit { readonly datesForActivitiesFormArrayName = 'datesForActivities'; readonly subActivitiesFormArrayName = 'subActivities'; - constructor(private activitiesApiService: ActivitiesApiService) {} - get lamnatJobbForslagFormControl(): AbstractControl { return this.periodiskRedovisningFormGroup.get(this.lamnatJobbForslagFormControlName); } @@ -39,12 +36,6 @@ export class DeltagarePeriodiskRedovisningComponent implements OnInit { return this.periodiskRedovisningFormGroup.get(this.activitiesFormArrayName) as FormArray; } - ngOnInit(): void { - this.activitiesApiService - .getActivities$() - .subscribe(activities => this.initializePeriodiskRedovisningFormGroup(activities)); - } - initializePeriodiskRedovisningFormGroup(activitiesList: Activity[]): void { this.periodiskRedovisningFormGroup = new FormGroup({ lamnatJobbForslag: new FormControl(null, [Validators.required]), @@ -70,9 +61,8 @@ export class DeltagarePeriodiskRedovisningComponent implements OnInit { getActivtiesFormField(formCtrlName: string, activity: Activity): FormArray | FormControl { if (formCtrlName === 'datesForActivities') { return new FormArray([]); - } else if (formCtrlName === 'subActivities') { - return this.addSubActivitesFormArray(activity?.subActivities, activity.id); } + return new FormControl(null, []); } diff --git a/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-details/pages/deltagare-reports/deltagare-periodisk-redovisning/deltagare-periodisk-redovisning.module.ts b/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-details/pages/deltagare-reports/deltagare-periodisk-redovisning/deltagare-periodisk-redovisning.module.ts index 5a42819..b132812 100644 --- a/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-details/pages/deltagare-reports/deltagare-periodisk-redovisning/deltagare-periodisk-redovisning.module.ts +++ b/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-details/pages/deltagare-reports/deltagare-periodisk-redovisning/deltagare-periodisk-redovisning.module.ts @@ -1,12 +1,12 @@ +import { DigiNgFormRadiobuttonGroupModule } from '@af/digi-ng/_form/form-radiobutton-group'; 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 { ReportLayoutModule } from '../components/report-layout/report-layout.module'; -import { DeltagarePeriodiskRedovisningComponent } from './deltagare-periodisk-redovisning.component'; import { PeriodiskRedovisningFormModule } from './components/periodisk-redovisning-form/periodisk-redovisning-form.module'; -import { DigiNgFormRadiobuttonGroupModule } from '@af/digi-ng/_form/form-radiobutton-group'; +import { DeltagarePeriodiskRedovisningComponent } from './deltagare-periodisk-redovisning.component'; @NgModule({ schemas: [CUSTOM_ELEMENTS_SCHEMA], diff --git a/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-list/deltagare-list.component.html b/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-list/deltagare-list.component.html index 2e0ffec..d6d3e12 100644 --- a/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-list/deltagare-list.component.html +++ b/apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-list/deltagare-list.component.html @@ -1,31 +1,33 @@ -
-
-

Deltagarlista

-

- Här ser du en lista på de deltagare som tillhör din organisation. Klicka på deltagarens namn för att öppna - och se mer information om deltagarna. -

-
-
- -
- -
+ +
+
+

Deltagarlista

+

+ Här ser du en lista på de deltagare som tillhör din organisation. Klicka på deltagarens namn för att öppna + och se mer information om deltagarna. +

+
+
+ +
+ +
+
diff --git a/apps/mina-sidor-fa/src/app/shared/components/confirm-dialog/confirm-dialog.component.ts b/apps/mina-sidor-fa/src/app/shared/components/confirm-dialog/confirm-dialog.component.ts index 882b5b4..1d71865 100644 --- a/apps/mina-sidor-fa/src/app/shared/components/confirm-dialog/confirm-dialog.component.ts +++ b/apps/mina-sidor-fa/src/app/shared/components/confirm-dialog/confirm-dialog.component.ts @@ -5,7 +5,7 @@ import { ConfirmDialog } from '@msfa-enums/confirm-dialog.enum'; selector: 'msfa-confirm-dialog', templateUrl: './confirm-dialog.component.html', styleUrls: ['./confirm-dialog.component.scss'], - changeDetection: ChangeDetectionStrategy.OnPush + changeDetection: ChangeDetectionStrategy.OnPush, }) export class ConfirmDialogComponent { @Input() openConfirmDialog: boolean; @@ -21,5 +21,4 @@ export class ConfirmDialogComponent { this.openConfirmDialog = false; this.confirmDialogChanged.emit(ConfirmDialog.DISMISSED); } - } diff --git a/apps/mina-sidor-fa/src/app/shared/models/activity.model.ts b/apps/mina-sidor-fa/src/app/shared/models/activity.model.ts index f6e3e55..6433cb7 100644 --- a/apps/mina-sidor-fa/src/app/shared/models/activity.model.ts +++ b/apps/mina-sidor-fa/src/app/shared/models/activity.model.ts @@ -1,8 +1,6 @@ export interface Activity { id: number; name: string; - description?: string; - subActivities: SubActivity[]; } export interface SubActivity { id: number; @@ -12,15 +10,12 @@ export interface SubActivity { export interface ActivityResponse { id: number; name: string; - description?: string; - subActivities: SubActivity[]; } + export function mapResponseToActivity(data: ActivityResponse): Activity { - const { id, name, description, subActivities } = data; + const { id, name } = data; return { id, name, - description, - subActivities, }; } diff --git a/apps/mina-sidor-fa/src/app/shared/models/api/gemensam-planering.request.model.ts b/apps/mina-sidor-fa/src/app/shared/models/api/gemensam-planering.request.model.ts new file mode 100644 index 0000000..266d841 --- /dev/null +++ b/apps/mina-sidor-fa/src/app/shared/models/api/gemensam-planering.request.model.ts @@ -0,0 +1,5 @@ +export interface GemensamPlaneringPostRequest { + genomforandeReferens: string; + distans: boolean; + aktivitetsIds: number[]; +} diff --git a/apps/mina-sidor-fa/src/app/shared/models/avrop.model.ts b/apps/mina-sidor-fa/src/app/shared/models/avrop.model.ts index 6e55df1..3410848 100644 --- a/apps/mina-sidor-fa/src/app/shared/models/avrop.model.ts +++ b/apps/mina-sidor-fa/src/app/shared/models/avrop.model.ts @@ -1,4 +1,5 @@ import { TrackName } from '@msfa-enums/track-name.enum'; +import { mapStringToSsn } from '@msfa-utils/map-string-to-ssn.util'; import { AvropResponse } from './api/avrop.response.model'; import { PaginationMeta } from './pagination-meta.model'; @@ -17,6 +18,7 @@ export interface AvropCompact { } export interface Avrop extends AvropCompact { + ssn: string; // personnummer genomforandeReferens: number; // genomforandeReferens participationFrequency: number; // deltagandeGrad utforandeVerksamhet: string; // utforandeverksamhet @@ -41,6 +43,7 @@ export function mapAvropResponseToAvrop(data: AvropResponse): Avrop { sprakstod, adress, sparkod, + personnummer, genomforandeReferens, deltagandeGrad, utforandeverksamhet, @@ -60,6 +63,7 @@ export function mapAvropResponseToAvrop(data: AvropResponse): Avrop { utforandeAdress: adress, trackCode: sparkod, trackName: (TrackName[sparkod] || TrackName.UNKNOWN) as TrackName, + ssn: mapStringToSsn(personnummer), genomforandeReferens, participationFrequency: deltagandeGrad, utforandeVerksamhet: utforandeverksamhet, diff --git a/apps/mina-sidor-fa/src/app/shared/models/gemensam-planering.model.ts b/apps/mina-sidor-fa/src/app/shared/models/gemensam-planering.model.ts index 2d460e6..895432e 100644 --- a/apps/mina-sidor-fa/src/app/shared/models/gemensam-planering.model.ts +++ b/apps/mina-sidor-fa/src/app/shared/models/gemensam-planering.model.ts @@ -1,3 +1,11 @@ +import { GemensamPlaneringPostRequest } from './api/gemensam-planering.request.model'; + +export interface GemensamPlanering { + genomforandeReferens: number; + distance: boolean; + activityIds: number[]; +} + export interface Activity { activityId: string; name: string; @@ -9,3 +17,15 @@ export interface SubActivity { name: string; description: string; } + +export function mapGemensamPlaneringToGemensamPlaneringPostRequest( + gemensamPlanering: GemensamPlanering +): GemensamPlaneringPostRequest { + const { genomforandeReferens, distance, activityIds } = gemensamPlanering; + + return { + genomforandeReferens: genomforandeReferens.toString(), + distans: distance, + aktivitetsIds: activityIds, + }; +} diff --git a/apps/mina-sidor-fa/src/app/shared/services/api/gemensam-planering-api.service.ts b/apps/mina-sidor-fa/src/app/shared/services/api/gemensam-planering-api.service.ts index 7b987cd..ff6d70c 100644 --- a/apps/mina-sidor-fa/src/app/shared/services/api/gemensam-planering-api.service.ts +++ b/apps/mina-sidor-fa/src/app/shared/services/api/gemensam-planering-api.service.ts @@ -2,21 +2,48 @@ import { HttpClient } from '@angular/common/http'; import { Injectable } from '@angular/core'; import { environment } from '@msfa-environment'; import { Activity, ActivityResponse, mapResponseToActivity } from '@msfa-models/activity.model'; +import { GemensamPlaneringPostRequest } from '@msfa-models/api/gemensam-planering.request.model'; +import { Avrop } from '@msfa-models/avrop.model'; +import { CustomError, errorToCustomError } from '@msfa-models/error/custom-error'; +import { DeltagareApiService } from '@msfa-services/api/deltagare.api.service'; import { Observable } from 'rxjs'; -import { filter, map } from 'rxjs/operators'; +import { catchError, filter, map, shareReplay } from 'rxjs/operators'; @Injectable({ providedIn: 'root', }) export class GemensamPlaneringApiService { - private _apiBaseUrl = `${environment.api.url}`; + private _apiBaseUrl = `${environment.api.url}/rapporter/gemensam-planering`; - constructor(private httpClient: HttpClient) {} - - public getActivities$(): Observable { - return this.httpClient.get<{ data: ActivityResponse[] }>(`${this._apiBaseUrl}/activities`).pipe( + public fetchActivities$(): Observable { + return this.httpClient.get<{ data: ActivityResponse[] }>(`${this._apiBaseUrl}/aktiviteter`).pipe( filter(response => !!response?.data), - map(({ data }) => data.map(aktivitet => mapResponseToActivity(aktivitet))) + map(({ data }) => data.map(activity => mapResponseToActivity(activity))), + catchError((error: Error & { status: number }) => { + throw new CustomError( + errorToCustomError({ ...error, message: `Kunde inte hämta aktiviteter.\n\n${error.message}` }) + ); + }), + shareReplay(1) ); } + + public fetchAvropInformation$(genomforandeReferens: number): Observable { + return this.deltagareApiService.fetchAvropInformation$(genomforandeReferens); + } + + public async postGemensamPlanering(requestData: GemensamPlaneringPostRequest): Promise { + return this.httpClient + .post(`${this._apiBaseUrl}`, requestData) + .pipe( + catchError((error: Error & { status: number }) => { + throw new CustomError( + errorToCustomError({ ...error, message: `Kunde inte spara gemensam planering.\n\n${error.message}` }) + ); + }) + ) + .toPromise(); + } + + constructor(private httpClient: HttpClient, private deltagareApiService: DeltagareApiService) {} } diff --git a/config/proxy.conf.json b/config/proxy.conf.json index a7d9746..2aee625 100644 --- a/config/proxy.conf.json +++ b/config/proxy.conf.json @@ -1,4 +1,9 @@ { + "/api/rapporter/gemensam-planering": { + "target": "https://mina-sidor-fa-utv.tocp.arbetsformedlingen.se", + "secure": false, + "changeOrigin": true + }, "/api": { "target": "https://mina-sidor-fa-test.tocp.arbetsformedlingen.se", "secure": false,