From 9fe6e0f91f2c189bbd404fdbde7994c07d44b3cd Mon Sep 17 00:00:00 2001 From: Erik Tiekstra Date: Thu, 15 Apr 2021 11:32:19 +0200 Subject: [PATCH] Added some form elements and validation --- apps/dafa-web/src/app/data/models/.gitkeep | 0 .../app/data/models/validation-error.model.ts | 4 ++ .../create-account.component.html | 63 +++++++++++++++++ .../create-account.component.scss | 15 ++++ .../create-account.component.ts | 44 +++++++++++- .../create-account/create-account.module.ts | 11 ++- apps/dafa-web/src/app/utils/.gitkeep | 0 .../utils/validators/required.validator.ts | 12 ++++ .../social-security-number.validator.ts | 68 +++++++++++++++++++ tsconfig.base.json | 1 + 10 files changed, 216 insertions(+), 2 deletions(-) delete mode 100644 apps/dafa-web/src/app/data/models/.gitkeep create mode 100644 apps/dafa-web/src/app/data/models/validation-error.model.ts delete mode 100644 apps/dafa-web/src/app/utils/.gitkeep create mode 100644 apps/dafa-web/src/app/utils/validators/required.validator.ts create mode 100644 apps/dafa-web/src/app/utils/validators/social-security-number.validator.ts diff --git a/apps/dafa-web/src/app/data/models/.gitkeep b/apps/dafa-web/src/app/data/models/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/apps/dafa-web/src/app/data/models/validation-error.model.ts b/apps/dafa-web/src/app/data/models/validation-error.model.ts new file mode 100644 index 0000000..9253548 --- /dev/null +++ b/apps/dafa-web/src/app/data/models/validation-error.model.ts @@ -0,0 +1,4 @@ +export interface ValidationError { + type: string; + message: string; +} diff --git a/apps/dafa-web/src/app/pages/administration/pages/create-account/create-account.component.html b/apps/dafa-web/src/app/pages/administration/pages/create-account/create-account.component.html index 94ec4e4..e8fb56b 100644 --- a/apps/dafa-web/src/app/pages/administration/pages/create-account/create-account.component.html +++ b/apps/dafa-web/src/app/pages/administration/pages/create-account/create-account.component.html @@ -6,5 +6,68 @@ rutrum velit. Sed vitae ullamcorper sem. Aliquam malesuada nunc sed purus mollis scelerisque. Curabitur bibendum leo quis ante porttitor tincidunt. Nam tincidunt imperdiet tortor eu suscipit. Maecenas ut dui est.

+ +
+ + + +
diff --git a/apps/dafa-web/src/app/pages/administration/pages/create-account/create-account.component.scss b/apps/dafa-web/src/app/pages/administration/pages/create-account/create-account.component.scss index e69de29..a264b2c 100644 --- a/apps/dafa-web/src/app/pages/administration/pages/create-account/create-account.component.scss +++ b/apps/dafa-web/src/app/pages/administration/pages/create-account/create-account.component.scss @@ -0,0 +1,15 @@ +.create-account { + &__block { + max-width: var(--digi--typography--text--max-width); + } + + &__combined-inputs { + display: flex; + gap: var(--digi--layout--gutter); + } + + &__input { + width: 100%; + margin-bottom: var(--digi--layout--gutter); + } +} diff --git a/apps/dafa-web/src/app/pages/administration/pages/create-account/create-account.component.ts b/apps/dafa-web/src/app/pages/administration/pages/create-account/create-account.component.ts index 8d80f28..c219c0e 100644 --- a/apps/dafa-web/src/app/pages/administration/pages/create-account/create-account.component.ts +++ b/apps/dafa-web/src/app/pages/administration/pages/create-account/create-account.component.ts @@ -1,4 +1,8 @@ +import { RadiobuttonModel } from '@af/digi-ng/_form/form-radiobutton-group'; import { ChangeDetectionStrategy, Component } from '@angular/core'; +import { AbstractControl, FormBuilder, FormGroup } from '@angular/forms'; +import { RequiredValidator } from '@dafa-validators/required.validator'; +import { SocialSecurityNumberValidator } from '@dafa-validators/social-security-number.validator'; @Component({ selector: 'dafa-create-account', @@ -6,4 +10,42 @@ import { ChangeDetectionStrategy, Component } from '@angular/core'; styleUrls: ['./create-account.component.scss'], changeDetection: ChangeDetectionStrategy.OnPush, }) -export class CreateAccountComponent {} +export class CreateAccountComponent { + formGroup: FormGroup; + + constructor(private formBuilder: FormBuilder) { + this.formGroup = this.formBuilder.group({ + firstName: this.formBuilder.control('', [RequiredValidator('Förnamn')]), + lastName: this.formBuilder.control('', [RequiredValidator('Efternamn')]), + ssn: this.formBuilder.control('', [RequiredValidator('Personnummer'), SocialSecurityNumberValidator()]), + email: this.formBuilder.control('', [RequiredValidator('Arbetsmejl')]), + phone: this.formBuilder.control('', [RequiredValidator('Telefonnummer arbete')]), + active: this.formBuilder.control(true), + }); + + this.formGroup.valueChanges.subscribe(values => console.table(values)); + } + + get activeRadioButtons(): RadiobuttonModel[] { + return [ + { + label: 'Ja', + value: true, + }, + { + label: 'Nej', + value: false, + }, + ]; + } + + get firstNameControl(): AbstractControl { + return this.formGroup.get('firstName'); + } + get lastNameControl(): AbstractControl { + return this.formGroup.get('lastName'); + } + get ssnControl(): AbstractControl { + return this.formGroup.get('ssn'); + } +} diff --git a/apps/dafa-web/src/app/pages/administration/pages/create-account/create-account.module.ts b/apps/dafa-web/src/app/pages/administration/pages/create-account/create-account.module.ts index 51bc6ef..4926ea5 100644 --- a/apps/dafa-web/src/app/pages/administration/pages/create-account/create-account.module.ts +++ b/apps/dafa-web/src/app/pages/administration/pages/create-account/create-account.module.ts @@ -1,11 +1,20 @@ +import { DigiNgFormInputModule } from '@af/digi-ng/_form/form-input'; +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 { CreateAccountComponent } from './create-account.component'; @NgModule({ schemas: [CUSTOM_ELEMENTS_SCHEMA], declarations: [CreateAccountComponent], - imports: [CommonModule, RouterModule.forChild([{ path: '', component: CreateAccountComponent }])], + imports: [ + CommonModule, + RouterModule.forChild([{ path: '', component: CreateAccountComponent }]), + ReactiveFormsModule, + DigiNgFormInputModule, + DigiNgFormRadiobuttonGroupModule, + ], }) export class CreateAccountModule {} diff --git a/apps/dafa-web/src/app/utils/.gitkeep b/apps/dafa-web/src/app/utils/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/apps/dafa-web/src/app/utils/validators/required.validator.ts b/apps/dafa-web/src/app/utils/validators/required.validator.ts new file mode 100644 index 0000000..18954ca --- /dev/null +++ b/apps/dafa-web/src/app/utils/validators/required.validator.ts @@ -0,0 +1,12 @@ +import { AbstractControl, ValidatorFn } from '@angular/forms'; +import { ValidationError } from '@dafa-models/validation-error.model'; + +export function RequiredValidator(label = 'Fältet'): ValidatorFn { + return (control: AbstractControl): ValidationError => { + if (control && !control.value) { + return { type: 'required', message: `${label} är obligatoriskt` }; + } + + return null; + }; +} diff --git a/apps/dafa-web/src/app/utils/validators/social-security-number.validator.ts b/apps/dafa-web/src/app/utils/validators/social-security-number.validator.ts new file mode 100644 index 0000000..b7490b0 --- /dev/null +++ b/apps/dafa-web/src/app/utils/validators/social-security-number.validator.ts @@ -0,0 +1,68 @@ +import { AbstractControl, ValidatorFn } from '@angular/forms'; +import { ValidationError } from '@dafa-models/validation-error.model'; + +export function SocialSecurityNumberValidator(): ValidatorFn { + return (control: AbstractControl): ValidationError => { + if (!control || !control.value) { + return null; + } + + const ssn = control.value; + + if (/[^0-9-]/g.test(ssn)) { + return { type: 'ssnInvalid', message: 'Inkorrekt personnummer' }; + } + + let strippedSsn = control.value.replace(/[^0-9]/g, ''); + + // Year format 1991 -> 91 + if (strippedSsn.length === 12) { + strippedSsn = strippedSsn.substr(2); + } + + // Check length + if (strippedSsn.length !== 10) { + return { type: 'ssnNotComplete', message: 'Personnummret är inte fullständigt' }; + } + + // Check month + if (strippedSsn.substr(2, 2) > 12 || strippedSsn.substr(2, 2) === '00') { + return { type: 'ssnInvalid', message: 'Inkorrekt personnummer' }; + } + + // Check date (valid date + 60 is also apporved because of co-ordination number) + if ( + (strippedSsn.substr(4, 2) > 31 || strippedSsn.substr(4, 2) === '00') && + (strippedSsn.substr(4, 2) > 91 || strippedSsn.substr(4, 2) <= 60) + ) { + return { type: 'ssnInvalid', message: 'Inkorrekt personnummer' }; + } + + return isControlDigitLegit(strippedSsn) ? null : { type: 'ssnInvalid', message: 'Inkorrekt personnummer' }; + }; +} + +function isControlDigitLegit(ssn: string): boolean { + // Run the mod 10 algorithm to produce check digit + const enteredControlDigit = +ssn.substr(-1); + let inc = 0; + let multiplicator = 2; + let product: number; + + for (const char of ssn.slice(0, -1)) { + product = +char * multiplicator; + if (product > 9) { + inc += product - 9; + } else { + inc += product; + } + multiplicator = multiplicator === 1 ? 2 : 1; + } + + let calculatedControlDigit = 10 - (inc - Math.floor(inc / 10) * 10); + if (calculatedControlDigit === 10) { + calculatedControlDigit = 0; + } + + return calculatedControlDigit === enteredControlDigit; +} diff --git a/tsconfig.base.json b/tsconfig.base.json index 698fe87..38fecec 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -23,6 +23,7 @@ "@dafa-enums/*": ["apps/dafa-web/src/app/data/enums/*"], "@dafa-services/*": ["apps/dafa-web/src/app/services/*"], "@dafa-utils/*": ["apps/dafa-web/src/app/utils/*"], + "@dafa-validators/*": ["apps/dafa-web/src/app/utils/validators/*"], "@dafa-environment": ["apps/dafa-web/src/environments/environment"] } },