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"]
}
},