feature(Slutredovisning): Formulär för att skapa och skicka in slutredovisning (TV-533)

Squashed commit of the following:

commit 5b427cdd62b881cc32d408beaf92f8e3c22a9bd4
Author: Daniel Appelgren <daniel.appelgren@arbetsformedlingen.se>
Date:   Fri Nov 12 09:24:18 2021 +0100

    refactor

commit b51af1b25b573a3203f3dd7e8e1c3e1401f0d228
Author: Daniel Appelgren <daniel.appelgren@arbetsformedlingen.se>
Date:   Fri Nov 12 09:20:58 2021 +0100

    add yrke names

commit 1ed3a33fb997669bf1af0be52347b371af0177ba
Merge: 4d9d2522 0235f1f9
Author: Daniel Appelgren <daniel.appelgren@arbetsformedlingen.se>
Date:   Fri Nov 12 07:40:48 2021 +0100

    Merge branch 'develop' into feature/tv-533-Skapa-slutredovisning-2

    # Conflicts:
    #	apps/mina-sidor-fa/src/app/shared/enums/feature.enum.ts

commit 4d9d25226fc3b91386832b1367edcf016d336c03
Author: Erik Tiekstra <erik.tiekstra@arbetsformedlingen.se>
Date:   Thu Nov 11 16:34:24 2021 +0100

    Fixed switch functionality inside slutredovisning model

commit cce93c169e39bba681e4e25f511fa42686134f97
Merge: b56ce52f 51ed2e84
Author: Erik Tiekstra <erik.tiekstra@arbetsformedlingen.se>
Date:   Thu Nov 11 16:15:46 2021 +0100

    Fixed conflicts and added deltid percent

commit 51ed2e841e00e8d7cea9225bd9cfeab8b783efbd
Author: Daniel Appelgren <daniel.appelgren@arbetsformedlingen.se>
Date:   Thu Nov 11 14:49:40 2021 +0100

    hide description on step 1 and 2

commit 269708be2f7fec84815b3e7f91e33d4c305b0846
Author: Daniel Appelgren <daniel.appelgren@arbetsformedlingen.se>
Date:   Thu Nov 11 14:04:59 2021 +0100

    cleanup

commit 05df3acf97f6115ec15cd295c1ed12721592f867
Merge: 3c803f38 c6adc71f
Author: Daniel Appelgren <daniel.appelgren@arbetsformedlingen.se>
Date:   Thu Nov 11 13:47:22 2021 +0100

    Merge branch 'develop' into feature/tv-533-Skapa-slutredovisning-2

commit 3c803f3883b23065c2e0c15f6946213e5972576b
Merge: c2724aa6 f332dd41
Author: Daniel Appelgren <daniel.appelgren@arbetsformedlingen.se>
Date:   Thu Nov 11 12:38:53 2021 +0100

    Merge branch 'develop' into feature/tv-533-Skapa-slutredovisning-2

    # Conflicts:
    #	apps/mina-sidor-fa/src/app/pages/deltagare/pages/deltagare-details/pages/deltagare-card/components/deltagare-tab-reports/components/reports-list/reports-list.component.ts
    #	apps/mina-sidor-fa/src/app/shared/enums/report-type.enum.ts

commit c2724aa654483001d48ca1c2d0a5bfc1b2552c89
Author: Daniel Appelgren <daniel.appelgren@arbetsformedlingen.se>
Date:   Thu Nov 11 12:22:05 2021 +0100

    add loader

commit b97b45fb22260dbdc9f9792e027b7bda68150ead
Author: Daniel Appelgren <daniel.appelgren@arbetsformedlingen.se>
Date:   Thu Nov 11 12:09:09 2021 +0100

    move formgroups to parent to persist stat

commit 37feaab19309777ef96fb70be62ede9e26498b89
Author: Daniel Appelgren <daniel.appelgren@arbetsformedlingen.se>
Date:   Thu Nov 11 10:43:53 2021 +0100

    fix radiobuttons

commit 644b9fd6288589cc3a66ceb8beefb623345e4308
Author: Daniel Appelgren <daniel.appelgren@arbetsformedlingen.se>
Date:   Thu Nov 11 09:30:31 2021 +0100

    .

commit 28875f21a381a966054523ff7ccb7df126b30120
Author: Daniel Appelgren <daniel.appelgren@arbetsformedlingen.se>
Date:   Thu Nov 11 08:20:07 2021 +0100

    move submit logic to step3

commit eef52c39dd970abbedc413b4c348098e07abe036
Author: Daniel Appelgren <daniel.appelgren@arbetsformedlingen.se>
Date:   Thu Nov 11 07:40:56 2021 +0100

    submit button

commit 4d732240e0ff6196d827572ff865392d6aaa0a9c
Author: Daniel Appelgren <daniel.appelgren@arbetsformedlingen.se>
Date:   Wed Nov 10 12:47:43 2021 +0100

    fix some bugs

commit 642cc2b24fd3a5def8abb9ae45595d101ccdcfb7
Merge: c4d53407 2dc56685
Author: Daniel Appelgren <daniel.appelgren@arbetsformedlingen.se>
Date:   Wed Nov 10 12:24:18 2021 +0100

    Merge branch 'develop' into feature/tv-533-Skapa-slutredovisning-2

commit c4d53407399d695f58e5a0be074d81bbc1b1cb21
Author: Daniel Appelgren <daniel.appelgren@arbetsformedlingen.se>
Date:   Wed Nov 10 12:24:09 2021 +0100

    wip

commit 808810699850e611ead2ee7ed1b728acc3d93dd5
Author: Daniel Appelgren <daniel.appelgren@arbetsformedlingen.se>
Date:   Wed Nov 10 12:02:01 2021 +0100

    slutredovisning

commit fa446717acc66e779ecdb87ba7a5b2224eeca9fe
Author: Daniel Appelgren <daniel.appelgren@arbetsformedlingen.se>
Date:   Wed Nov 10 11:00:44 2021 +0100

    view for utbildning done

... and 64 more commits
This commit is contained in:
Daniel Appelgren
2021-11-12 09:28:42 +01:00
parent 0235f1f912
commit e947ab4b39
105 changed files with 5624 additions and 44 deletions

View File

@@ -1,34 +1,14 @@
<div class="error-list-wrapper" [hidden]="!validationErrorLinks || validationErrorLinks.length === 0">
<digi-notification-alert
class="error-list"
af-variation="danger"
[attr.af-heading]="headingText"
[af-heading-level]="headingLevel"
[afCloseable]="false"
<digi-form-error-list
*ngIf="validationErrorLinks && validationErrorLinks.length"
[afHeading]="headingText"
[afOverrideLink]="true"
(afOnClickLink)="setFocusOnFormElement($event.detail.detail.target)"
>
<a
msfaAnchorLink
*ngFor="let validationErrorLink of validationErrorLinks"
[attr.href]="'#' + validationErrorLink.elementId"
>
<ul class="error-list__validation-error-links">
<li *ngFor="let validationErrorLink of validationErrorLinks;">
<digi-ng-link-internal
msfaAnchorLink
class="error-list__validation-error-link"
[afHref]="'#' + validationErrorLink.elementId"
[afText]="validationErrorLink.text"
></digi-ng-link-internal>
</li>
</ul>
</digi-notification-alert>
</div>
<!-- <digi-form-error-list
class="edit-employee-form__validation-error-summary"
af-heading="Åtgärda följande fel för att spara dina ändringar:"
*ngIf="validationErrorLinks && validationErrorLinks.length !== 0"
>
Behöver hantera ankarlänkar kopplat till den här komponenten om det ska fungera att använda den...
<a
[attr.href]="'#' + validationErrorLink.elementId"
[attr.id]="first ? firstValidationErrorLinkId : 'validation-error-link-' + index"
*ngFor="let validationErrorLink of validationErrorLinks; let first = first; let index = index"
>
{{ validationErrorLink.text }}
</a>
</digi-form-error-list> -->
{{ validationErrorLink.text }}
</a>
</digi-form-error-list>

View File

@@ -1,5 +1,5 @@
import { TypographyDynamicHeadingLevel } from '@af/digi-ng/_typography/typography-dynamic-heading';
import { Component, ChangeDetectionStrategy, Input } from '@angular/core';
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
export interface ValidationErrorLink {
elementId: string;
@@ -16,4 +16,22 @@ export class ErrorListComponent {
@Input() validationErrorLinks: ValidationErrorLink[] = [];
@Input() headingText: string;
@Input() headingLevel: TypographyDynamicHeadingLevel = TypographyDynamicHeadingLevel.H3;
setFocusOnFormElement(element: HTMLElement): void {
const id = element.getAttribute('href').replace('#', '');
const target = document.getElementById(id);
if (target) {
const targetPosition: DOMRect = target.getBoundingClientRect();
const absoluteElementPosition = targetPosition.top + window.scrollY;
const newPosition = absoluteElementPosition - window.innerHeight / 2;
if (target.focus) {
target.tabIndex = -1;
target.focus();
window.scrollTo(0, newPosition);
target.tabIndex = 0;
}
}
}
}

View File

@@ -5,6 +5,7 @@ export const DELTAGARE_REPORTING_ROUTES = {
avvikelserapport: 'Avvikelserapport (avvikelse)',
signal: 'Signal om arbete eller studier',
'informativ-rapport': 'Informativ rapport',
slutredovisning: 'Slutredovisning',
};
export const NAVIGATION = {

File diff suppressed because it is too large Load Diff

View File

@@ -12,13 +12,17 @@ export class AnchorLinkDirective {
const elementId = href?.trim().replace('#', '');
const element = document.getElementById(elementId);
if (element && element.focus) {
element.tabIndex = -1;
element.focus();
}
if (element) {
const elementPosition: DOMRect = element.getBoundingClientRect();
const absoluteElementPosition = elementPosition.top + window.scrollY;
const newPosition = absoluteElementPosition - window.innerHeight / 2;
if (element.tabIndex < 0) {
element.scrollIntoView();
if (element.focus) {
element.tabIndex = -1;
element.focus();
window.scrollTo(0, newPosition);
element.tabIndex = 0;
}
}
event.stopPropagation();

View File

@@ -16,5 +16,6 @@ export enum Feature {
REPORTING_PERIODISK_REDOVISNING,
REPORTING_INFORMATIV_RAPPORT,
EXPORTS,
SLUTREDOVISNING,
NEWS,
}

View File

@@ -5,6 +5,7 @@ export enum ReportType {
Avvikelse = 'Avvikelserapport (avvikelse)',
Franvaro = 'Avvikelserapport (frånvaro)',
PeriodiskRedovisning = 'Periodisk redovisning',
Slutredovisning = 'Slutredovisning',
InformativRapport = 'Informativ rapport',
InformativRedovisning = 'Informativ rapport',
}

View File

@@ -0,0 +1,68 @@
import {
Anstallningsform,
EducationLength,
EducationLevel,
MainOccupation,
Omfattning,
StillUnemployedReason,
} from '@msfa-models/slutredovisning.model';
export interface SlutredovisningRequestMainOccupationWorkDetails {
yrkesomrade: string;
yrkesgrupp: string;
anstallningsform: Anstallningsform;
otherExplanation: string;
omfattning: Omfattning;
omfattningPercent: number;
}
export interface SlutredovisningRequestMainOccupationWork {
type: MainOccupation.Work;
work: SlutredovisningRequestMainOccupationWorkDetails[];
}
export interface SlutredovisningRequestMainOccupationEducationDetails {
educationLevel: EducationLevel;
otherExplanation: string;
educationLength: EducationLength;
educationSpecification: string;
}
export interface SlutredovisningRequestMainOccupationEducation {
type: MainOccupation.Education;
education: SlutredovisningRequestMainOccupationEducationDetails;
}
export interface SlutredovisningRequestMainOccupationOtherDetails {
otherExplanation: string;
}
export interface SlutredovisningRequestMainOccupationOther {
type: MainOccupation.Other;
other: SlutredovisningRequestMainOccupationOtherDetails;
}
export interface SlutredovisningRequestMainOccupationStillUnemployedDetails {
reasonsGoalNotReached: StillUnemployedReason[];
otherExplanation: string;
}
export interface SlutredovisningRequestMainOccupationStillUnemployed {
type: MainOccupation.StillUnemployed;
stillUnemployed: SlutredovisningRequestMainOccupationStillUnemployedDetails;
}
export type SlutredovisningRequestMainOccupationDetails =
| SlutredovisningRequestMainOccupationWork
| SlutredovisningRequestMainOccupationEducation
| SlutredovisningRequestMainOccupationOther
| SlutredovisningRequestMainOccupationStillUnemployed;
export interface SlutredovisningRequest {
genomforandereferens: number;
mainOccupation: SlutredovisningRequestMainOccupationDetails;
activities: { id: string; whatHasBeenDone: string }[];
progressDescription: string;
nextStepDescription: string;
otherInformation: string;
}

View File

@@ -0,0 +1,70 @@
import {
Anstallningsform,
EducationLength,
EducationLevel,
MainOccupation,
Omfattning,
StillUnemployedReason,
} from '@msfa-models/slutredovisning.model';
export interface SlutredovisningResponseMainOccupationWorkDetails {
yrkesomrade: string;
yrkesgrupp: string;
yrkesomradeName: string;
yrkesgruppName: string;
anstallningsform: Anstallningsform;
otherExplanation: string;
omfattning: Omfattning;
omfattningPercent: number;
}
export interface SlutredovisningResponseMainOccupationWork {
type: MainOccupation.Work;
work: SlutredovisningResponseMainOccupationWorkDetails[];
}
export interface SlutredovisningResponseMainOccupationEducationDetails {
educationLevel: EducationLevel;
otherExplanation: string;
educationLength: EducationLength;
educationSpecification: string;
}
export interface SlutredovisningResponseMainOccupationEducation {
type: MainOccupation.Education;
education: SlutredovisningResponseMainOccupationEducationDetails;
}
export interface SlutredovisningResponseMainOccupationOtherDetails {
otherExplanation: string;
}
export interface SlutredovisningResponseMainOccupationOther {
type: MainOccupation.Other;
other: SlutredovisningResponseMainOccupationOtherDetails;
}
export interface SlutredovisningResponseMainOccupationStillUnemployedDetails {
reasonsGoalNotReached: StillUnemployedReason[];
otherExplanation: string;
}
export interface SlutredovisningResponseMainOccupationStillUnemployed {
type: MainOccupation.StillUnemployed;
stillUnemployed: SlutredovisningResponseMainOccupationStillUnemployedDetails;
}
export type SlutredovisningResponseMainOccupationDetails =
| SlutredovisningResponseMainOccupationWork
| SlutredovisningResponseMainOccupationEducation
| SlutredovisningResponseMainOccupationOther
| SlutredovisningResponseMainOccupationStillUnemployed;
export interface SlutredovisningResponse {
genomforandereferens: number;
mainOccupation: SlutredovisningResponseMainOccupationDetails;
activities: { id: string; whatHasBeenDone: string; name: string }[];
progressDescription: string;
nextStepDescription: string;
otherInformation: string;
}

View File

@@ -0,0 +1,5 @@
export interface YrkesgruppResponse {
id: string;
name: string;
parentId: string;
}

View File

@@ -0,0 +1,7 @@
import { YrkesgruppResponse } from './yrkesgrupp.response.model';
export interface YrkesomradeResponse {
id: string;
name: string;
items: YrkesgruppResponse[];
}

View File

@@ -0,0 +1,108 @@
import { SlutredovisningResponse } from '@msfa-models/api/slutredovisning.response.model';
export enum MainOccupation {
Work = 'work',
Education = 'education',
StillUnemployed = 'stillUnemployed',
ByteTillNyLeverantorIRustaOchMatcha = 'byte till ny leverantör i rusta och matcha',
Other = 'other',
}
export enum EducationLevel {
HogskolaEllerUniversitet = 'högskola eller universitet',
Yrkeshogskola = 'yrkeshögskola',
KomvuxGymnasiumFolkhogskola = 'komvux, gymnasium eller folkhögskola',
VetEj = 'vet ej',
Annat = 'annat',
}
export function educationLevelToString(educationLevel: EducationLevel): string | null {
switch (educationLevel) {
case EducationLevel.HogskolaEllerUniversitet:
return 'Högskola eller universitet';
case EducationLevel.Yrkeshogskola:
return 'Yrkeshögskola';
case EducationLevel.KomvuxGymnasiumFolkhogskola:
return 'Komvux, gymnasium eller folkhögskola';
case EducationLevel.VetEj:
return 'Vet ej';
case EducationLevel.Annat:
return 'Annat';
default:
return null;
}
}
export enum StillUnemployedReason {
SaknarRelevantUtbildning = 'saknar relevant utbildning',
SaknarArbetslivserfarenhet = 'saknar arbetslivserfarenhet',
SaknarNatverkOchKontakter = 'saknar nätverk och kontakter',
BristandeSprakkunskaperISvenska = 'bristande språkkunskaper i svenska',
KonjukturLaget = 'konjunkturläget',
Annat = 'annat',
}
export enum EducationLength {
UpToOneYear = 'upp till ett år',
OneToTwoYears = 'ett år till två år',
OverTwoYears = 'två år eller längre',
}
export function educationLengthToString(educationLength: EducationLength): string | null {
switch (educationLength) {
case EducationLength.UpToOneYear:
return 'Upp till ett år';
case EducationLength.OneToTwoYears:
return 'Ett år till två år';
case EducationLength.OverTwoYears:
return 'Två år eller längre';
default:
return null;
}
}
export enum Anstallningsform {
Tillsvidare = 'tillsvidareanställning',
Prov = 'provanstallning',
Visstid = 'visstidsanställning',
VetEj = 'vet ej',
Annat = 'annat',
}
export enum Omfattning {
Heltid = 'heltid',
Deltid = 'deltid',
VetEj = 'vet ej',
}
export function omfattningToString(omfattning: Omfattning): string | null {
switch (omfattning) {
case Omfattning.Heltid:
return 'Heltid';
case Omfattning.Deltid:
return 'Deltid';
case Omfattning.VetEj:
return 'Vet ej';
default:
return null;
}
}
export type Slutredovisning = SlutredovisningResponse;
export function mainOccupationToString(mainOccupation: MainOccupation): string | null {
switch (mainOccupation) {
case MainOccupation.Education:
return 'Utbildning';
case MainOccupation.StillUnemployed:
return 'Fortsatt arbetssökande';
case MainOccupation.ByteTillNyLeverantorIRustaOchMatcha:
return 'Byte till ny leverantör i Rusta och matcha';
case MainOccupation.Other:
return 'Annat';
case MainOccupation.Work:
return 'Arbete';
default:
return null;
}
}

View File

@@ -0,0 +1,13 @@
import { YrkesgruppResponse } from './api/yrkesgrupp.response.model';
export interface Yrkesgrupp {
value: string;
name: string;
parentId: string;
}
export function mapResponseToYrkesgrupp(data: YrkesgruppResponse): Yrkesgrupp {
const { id, name, parentId } = data;
return { value: id, name, parentId };
}

View File

@@ -0,0 +1,26 @@
import { YrkesomradeResponse } from './api/yrkesomrade.response.model';
import { mapResponseToYrkesgrupp, Yrkesgrupp } from './yrkesgrupp.model';
export interface Yrkesomrade {
value: string;
name: string;
items: Yrkesgrupp[];
}
export function mapResponseToYrkesomrade(data: YrkesomradeResponse): Yrkesomrade {
const { id, name, items } = data;
return { value: id, name, items: items.map(item => mapResponseToYrkesgrupp(item)) };
}
export function yrkeToTextMap(yrkesomraden: Yrkesomrade[]): { [key: string]: string } {
const translateMap: { [key: string]: string } = {};
yrkesomraden.forEach(yrkesomrade => {
translateMap[yrkesomrade.value] = yrkesomrade.name;
yrkesomrade.items.forEach(yrkesgrupp => {
translateMap[yrkesgrupp.value] = yrkesgrupp.name;
});
});
return translateMap;
}

View File

@@ -6,6 +6,7 @@ import { FranvaroReportResponse } from '@msfa-models/api/franvaro-response.model
import { GemensamPlaneringResponse } from '@msfa-models/api/gemensam-planering.response.model';
import { InformativRapportResponse } from '@msfa-models/api/informativ-rapport.response.model';
import { Observable } from 'rxjs';
import { SlutredovisningResponse } from '@msfa-models/api/slutredovisning.response.model';
@Injectable({
providedIn: 'root',
@@ -34,4 +35,8 @@ export class HandlingarApiService {
public fetchAvvikelseReport$(handlingId: string): Observable<{ data: AvvikelseReportResponse }> {
return this.httpClient.get<{ data: AvvikelseReportResponse }>(`${this._apiBaseUrl}/avvikelse/${handlingId}`);
}
public fetchSlutredovisning$(handlingId: string) {
return this.httpClient.get<{ data: SlutredovisningResponse }>(`${this._apiBaseUrl}/slutredovisning/${handlingId}`);
}
}

View File

@@ -0,0 +1,43 @@
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { YRKEN } from '@msfa-constants/yrken';
import { ErrorType } from '@msfa-enums/error-type.enum';
import { environment } from '@msfa-environment';
import { SlutredovisningRequest } from '@msfa-models/api/slutredovisning.request.model';
import { SlutredovisningResponse } from '@msfa-models/api/slutredovisning.response.model';
import { YrkesomradeResponse } from '@msfa-models/api/yrkesomrade.response.model';
import { CustomError } from '@msfa-models/error/custom-error';
import { Observable, of } from 'rxjs';
import { catchError } from 'rxjs/operators';
@Injectable({
providedIn: 'root',
})
export class SlutredovisningApiService {
private _apiBaseUrl = `${environment.api.url}/rapporter/slutredovisning`;
private _handlingarBaseUrl = `${environment.api.url}/handlingar`;
constructor(private httpClient: HttpClient) {}
public fetchYrken$(): Observable<{ data: YrkesomradeResponse[] }> {
return of({ data: YRKEN });
}
public fetchSlutredovisning$(handlingId: string): Observable<{ data: SlutredovisningResponse }> {
return this.httpClient.get<{ data: SlutredovisningResponse }>(
`${this._handlingarBaseUrl}/slutredovisning/${handlingId}`
);
}
public submitSlutredovisning$(requestData: SlutredovisningRequest): Observable<void> {
return this.httpClient.post<void>(`${this._apiBaseUrl}`, requestData).pipe(
catchError((error: Error) => {
throw new CustomError({
error,
message: `Kunde inte spara Periodisk redovisning.\n\n${error.message}`,
type: ErrorType.API,
});
})
);
}
}

View File

@@ -0,0 +1,3 @@
export function capitalizeSentence(sentence: string): string {
return sentence.charAt(0).toUpperCase() + sentence.slice(1);
}