[HIMA-591] working on customer creation refinement

This commit is contained in:
Eraldo Hasanaj
2019-08-09 17:33:02 +02:00
parent 7697d2921b
commit 33e6f623de
8 changed files with 124 additions and 79 deletions

View File

@@ -6,5 +6,6 @@
"prettier.trailingComma": "es5", "prettier.trailingComma": "es5",
"prettier.tabWidth": 4, "prettier.tabWidth": 4,
"prettier.printWidth": 140, "prettier.printWidth": 140,
"workbench.colorCustomizations": {} "workbench.colorCustomizations": {},
"typescriptHero.imports.insertSemicolons": false
} }

View File

@@ -1,6 +1,6 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { CustomerService as CustomerApiService, QueryTokenDTO, PayerService } from 'swagger'; import { CustomerService as CustomerApiService, QueryTokenDTO, PayerService } from 'swagger';
import { map, switchMap, tap, catchError } from 'rxjs/operators'; import { map, switchMap, tap, catchError, share } from 'rxjs/operators';
import { Observable, of, combineLatest } from 'rxjs'; import { Observable, of, combineLatest } from 'rxjs';
import { CustomerMapping } from '../mappings/customer.mapping'; import { CustomerMapping } from '../mappings/customer.mapping';
import { CustomerSearchResponse } from '../models/customer-search-response.model'; import { CustomerSearchResponse } from '../models/customer-search-response.model';
@@ -427,4 +427,19 @@ export class CustomerService {
}) })
); );
} }
emailExists(email: string) {
return this.customerService.CustomerEmailExists(email).pipe(
map(response => {
if (response && response.error) {
throw new Error(response.message);
}
return response && response.result;
}),
catchError(error => {
console.log(error);
return of(undefined);
})
);
}
} }

View File

@@ -7,7 +7,8 @@ declare global {
} }
interface Boolean { interface Boolean {
ifTrue(callback); ifTrue(callback): boolean;
ifFalse(callback): boolean;
} }
} }
@@ -22,5 +23,13 @@ Array.prototype.hasItems = function() {
Boolean.prototype.ifTrue = function(callback) { Boolean.prototype.ifTrue = function(callback) {
if (this && this.valueOf() === true) { if (this && this.valueOf() === true) {
callback(); callback();
return false;
}
};
Boolean.prototype.ifFalse = function(callback) {
if (this && this.valueOf() === false) {
callback();
return true;
} }
}; };

View File

@@ -6,6 +6,7 @@ const errorWhiteList: { url: string; codes: number[] }[] = [
{ url: '/customer/', codes: [409] }, { url: '/customer/', codes: [409] },
{ url: '/bonuscard', codes: [404] }, { url: '/bonuscard', codes: [404] },
{ url: '/order/', codes: [400, 409, 500] }, { url: '/order/', codes: [400, 409, 500] },
{ url: '/store/customer/emailexists', codes: [400, 409, 500] },
{ url: '/receipt/order/', codes: [401, 403, 404, 406, 407, 410, 412, 416, 418, 451, 500, 501, 502, 503, 504, 0, -1] }, { url: '/receipt/order/', codes: [401, 403, 404, 406, 407, 410, 412, 416, 418, 451, 500, 501, 502, 503, 504, 0, -1] },
{ url: '/5d1e00a230000080a4d72461', codes: [503] }, // test call { url: '/5d1e00a230000080a4d72461', codes: [503] }, // test call
]; ];

View File

@@ -98,6 +98,7 @@
[label]="'Straße'" [label]="'Straße'"
[error]="submitted && f.address.errors" [error]="submitted && f.address.errors"
[errorMessage]="'Straße wird benötigt'" [errorMessage]="'Straße wird benötigt'"
[displayErrorUnder]="true"
[value]="f.address.value" [value]="f.address.value"
(valueChanges)="valueChanges(f.address, $event)" (valueChanges)="valueChanges(f.address, $event)"
></app-input> ></app-input>
@@ -111,6 +112,7 @@
[label]="'Hausnummer'" [label]="'Hausnummer'"
[error]="submitted && f.streetNo.errors" [error]="submitted && f.streetNo.errors"
[errorMessage]="'Hausnummer wird benötigt'" [errorMessage]="'Hausnummer wird benötigt'"
[displayErrorUnder]="true"
[value]="f.streetNo.value" [value]="f.streetNo.value"
(valueChanges)="valueChanges(f.streetNo, $event)" (valueChanges)="valueChanges(f.streetNo, $event)"
></app-input> ></app-input>
@@ -169,7 +171,7 @@
[id]="'email'" [id]="'email'"
[label]="'E-Mail-Adresse'" [label]="'E-Mail-Adresse'"
[error]="submitted && f.email.errors" [error]="submitted && f.email.errors"
[errorMessage]="'E-Mail-Adresse ungültig'" [errorMessage]="f.email.errors && f.email.errors.emailExists ? 'E-Mail-Adresse existiert' : 'E-Mail-Adresse ungültig'"
(valueChanges)="valueChanges(f.email, $event)" (valueChanges)="valueChanges(f.email, $event)"
[value]="f.email.value" [value]="f.email.value"
></app-input> ></app-input>

View File

@@ -6,10 +6,10 @@ import { User, Address } from '../../../../core/models/user.model';
import { Router } from '@angular/router'; import { Router } from '@angular/router';
import { Process, CustomerFormState } from '../../../../core/models/process.model'; import { Process, CustomerFormState } from '../../../../core/models/process.model';
import { Breadcrumb } from '../../../../core/models/breadcrumb.model'; import { Breadcrumb } from '../../../../core/models/breadcrumb.model';
import { Observable, Subject } from 'rxjs'; import { Observable, Subject, of } from 'rxjs';
import { AddBreadcrumb } from '../../../../core/store/actions/breadcrumb.actions'; import { AddBreadcrumb } from '../../../../core/store/actions/breadcrumb.actions';
import { AddUser, SetUserDetails } from '../../../../core/store/actions/customer.actions'; import { AddUser, SetUserDetails } from '../../../../core/store/actions/customer.actions';
import { takeUntil, distinctUntilChanged, switchMap, map, filter, tap } from 'rxjs/operators'; import { takeUntil, distinctUntilChanged, switchMap, map, filter, tap, share, debounceTime } from 'rxjs/operators';
import { CustomValidators } from '../../../../shared/validation/custom-validation'; import { CustomValidators } from '../../../../shared/validation/custom-validation';
import { GENDERS, TIITLES } from '../../dropdown-values'; import { GENDERS, TIITLES } from '../../dropdown-values';
import { ProcessSelectors } from '../../../../core/store/selectors/process.selectors'; import { ProcessSelectors } from '../../../../core/store/selectors/process.selectors';
@@ -20,6 +20,7 @@ import { Country } from '../../../../core/models/country.model';
import { isoDateFromString } from '../../../../core/utils/app.utils'; import { isoDateFromString } from '../../../../core/utils/app.utils';
import { isNullOrUndefined } from 'util'; import { isNullOrUndefined } from 'util';
import { DeliveryOption } from 'apps/sales/src/app/core/models/delivery-option.model'; import { DeliveryOption } from 'apps/sales/src/app/core/models/delivery-option.model';
import { CustomerService } from 'apps/sales/src/app/core/services/customer.service';
@Component({ @Component({
selector: 'app-create-customer-card', selector: 'app-create-customer-card',
@@ -54,6 +55,7 @@ export class CreateCustomerCardComponent implements OnInit, OnDestroy {
guestChecked = false; guestChecked = false;
onlineChecked = false; onlineChecked = false;
customerCardChecked = false; customerCardChecked = false;
timer: any;
get countries() { get countries() {
return this.countries$.pipe( return this.countries$.pipe(
@@ -64,7 +66,13 @@ export class CreateCustomerCardComponent implements OnInit, OnDestroy {
); );
} }
constructor(private fb: FormBuilder, private store: Store, private router: Router, private renderer: Renderer) {} constructor(
private fb: FormBuilder,
private store: Store,
private router: Router,
private renderer: Renderer,
private customerService: CustomerService
) {}
ngOnInit() { ngOnInit() {
this.initialize(); this.initialize();
@@ -98,7 +106,6 @@ export class CreateCustomerCardComponent implements OnInit, OnDestroy {
this.cartHasItemsForDelivery.ifTrue(() => { this.cartHasItemsForDelivery.ifTrue(() => {
this.guestChecked = true; this.guestChecked = true;
}); });
// tslint:disable-next-line: semicolon
}; };
initializationSubscriptionHandler = (process: Process) => { initializationSubscriptionHandler = (process: Process) => {
@@ -115,19 +122,66 @@ export class CreateCustomerCardComponent implements OnInit, OnDestroy {
this.userForm = this.buildCreateForm(this.fb); this.userForm = this.buildCreateForm(this.fb);
} }
this.setValidations();
this.setCompanyValidators(); this.setCompanyValidators();
this.loaded = true; this.loaded = true;
} }
// tslint:disable-next-line: semicolon
}; };
@HostListener('window:scroll', ['$event']) setValidations() {
scrollHandler(event) { const deliveryAndGuestOrOnline = this.cartHasItemsForDelivery && (this.guestChecked || this.onlineChecked);
if (event.target.id === 'customer-form') { deliveryAndGuestOrOnline.ifTrue(this.deliveryAndGuestValidations);
this.renderer.invokeElementMethod(document.activeElement, 'blur');
}
} }
deliveryAndGuestValidations = () => {
this.userForm.get('title').setValidators([Validators.required]);
this.userForm.get('title').updateValueAndValidity();
this.userForm.get('email').setValidators([Validators.required, CustomValidators.validateEmail]);
this.userForm.get('email').updateValueAndValidity();
this.userForm.get('address').setValidators([Validators.required]);
this.userForm.get('address').updateValueAndValidity();
this.userForm.get('streetNo').setValidators([Validators.required]);
this.userForm.get('streetNo').updateValueAndValidity();
this.userForm.get('zipCode').setValidators([Validators.required]);
this.userForm.get('zipCode').updateValueAndValidity();
this.userForm.get('city').setValidators([Validators.required]);
this.userForm.get('city').updateValueAndValidity();
this.userForm.get('country').setValidators([Validators.required]);
this.userForm.get('country').updateValueAndValidity();
};
resetValidations = () => {
this.userForm.get('title').clearValidators();
this.userForm.get('title').updateValueAndValidity();
this.userForm.get('email').setValidators([CustomValidators.validateEmail]);
this.userForm.get('email').updateValueAndValidity();
this.userForm.get('address').clearValidators();
this.userForm.get('address').updateValueAndValidity();
this.userForm.get('streetNo').clearValidators();
this.userForm.get('streetNo').updateValueAndValidity();
this.userForm.get('zipCode').clearValidators();
this.userForm.get('zipCode').updateValueAndValidity();
this.userForm.get('city').clearValidators();
this.userForm.get('city').updateValueAndValidity();
this.userForm.get('country').clearValidators();
this.userForm.get('country').updateValueAndValidity();
};
validateIfEmailExists(control: AbstractControl) {
return control.value ? this.emailValidation$(control.value) : of(null);
}
emailValidation$ = (value: string) =>
this.customerService.emailExists(value).pipe(
map((exists: Boolean) => {
if (isNullOrUndefined(exists)) {
return { invalidEmail: true };
}
return exists ? { emailExists: true } : null;
}),
share()
);
createUser() { createUser() {
if (this.userForm.valid) { if (this.userForm.valid) {
this.createProcessIfDosntExists(); this.createProcessIfDosntExists();
@@ -322,7 +376,7 @@ export class CreateCustomerCardComponent implements OnInit, OnDestroy {
return fb.group({ return fb.group({
firstName: ['', Validators.required], firstName: ['', Validators.required],
lastName: ['', Validators.required], lastName: ['', Validators.required],
email: ['', CustomValidators.validateEmail], email: ['', CustomValidators.validateEmail, this.validateIfEmailExists.bind(this)],
address: [''], address: [''],
streetNo: [''], streetNo: [''],
zipCode: [''], zipCode: [''],
@@ -356,5 +410,18 @@ export class CreateCustomerCardComponent implements OnInit, OnDestroy {
toggle(checkbox: string) { toggle(checkbox: string) {
this[checkbox] = !this[checkbox]; this[checkbox] = !this[checkbox];
const type = this[checkbox] as boolean;
if (type) {
this.setValidations();
} else {
this.resetValidations();
}
}
@HostListener('window:scroll', ['$event'])
scrollHandler(event) {
if (event.target.id === 'customer-form') {
this.renderer.invokeElementMethod(document.activeElement, 'blur');
}
} }
} }

View File

@@ -33,6 +33,7 @@ export class CustomValidators extends Validators {
static validateEmail(control: FormControl) { static validateEmail(control: FormControl) {
if (control.value && control.value.length > 0) { if (control.value && control.value.length > 0) {
if (emaiValidation.test(control.value)) { if (emaiValidation.test(control.value)) {
console.log('passed email validation');
return null; return null;
} }

View File

@@ -1,68 +1,39 @@
{ {
"rulesDirectory": [ "rulesDirectory": ["codelyzer"],
"codelyzer"
],
"rules": { "rules": {
"arrow-return-shorthand": true, "arrow-return-shorthand": true,
"callable-types": true, "callable-types": true,
"class-name": true, "class-name": true,
"comment-format": [ "comment-format": [true, "check-space"],
true,
"check-space"
],
"curly": true, "curly": true,
"deprecation": { "deprecation": {
"severity": "warn" "severity": "warn"
}, },
"eofline": true, "eofline": true,
"forin": true, "forin": true,
"import-blacklist": [ "import-blacklist": [true, "rxjs/Rx"],
true,
"rxjs/Rx"
],
"import-spacing": true, "import-spacing": true,
"indent": [ "indent": [true, "spaces"],
true,
"spaces"
],
"interface-over-type-literal": true, "interface-over-type-literal": true,
"label-position": true, "label-position": true,
"max-line-length": [ "max-line-length": [true, 140],
true,
140
],
"member-access": false, "member-access": false,
"member-ordering": [ "member-ordering": [
true, true,
{ {
"order": [ "order": ["static-field", "instance-field", "static-method", "instance-method"]
"static-field",
"instance-field",
"static-method",
"instance-method"
]
} }
], ],
"no-arg": true, "no-arg": true,
"no-bitwise": true, "no-bitwise": true,
"no-console": [ "no-console": [true, "debug", "info", "time", "timeEnd", "trace"],
true,
"debug",
"info",
"time",
"timeEnd",
"trace"
],
"no-construct": true, "no-construct": true,
"no-debugger": true, "no-debugger": true,
"no-duplicate-super": true, "no-duplicate-super": true,
"no-empty": false, "no-empty": false,
"no-empty-interface": true, "no-empty-interface": true,
"no-eval": true, "no-eval": true,
"no-inferrable-types": [ "no-inferrable-types": [true, "ignore-params"],
true,
"ignore-params"
],
"no-misused-new": true, "no-misused-new": true,
"no-non-null-assertion": true, "no-non-null-assertion": true,
"no-redundant-jsdoc": true, "no-redundant-jsdoc": true,
@@ -76,27 +47,12 @@
"no-use-before-declare": true, "no-use-before-declare": true,
"no-var-keyword": true, "no-var-keyword": true,
"object-literal-sort-keys": false, "object-literal-sort-keys": false,
"one-line": [ "one-line": [true, "check-open-brace", "check-catch", "check-else", "check-whitespace"],
true,
"check-open-brace",
"check-catch",
"check-else",
"check-whitespace"
],
"prefer-const": true, "prefer-const": true,
"quotemark": [ "quotemark": [true, "single"],
true,
"single"
],
"radix": true, "radix": true,
"semicolon": [ "semicolon": [false, "always"],
true, "triple-equals": [true, "allow-null-check"],
"always"
],
"triple-equals": [
true,
"allow-null-check"
],
"typedef-whitespace": [ "typedef-whitespace": [
true, true,
{ {
@@ -109,14 +65,7 @@
], ],
"unified-signatures": true, "unified-signatures": true,
"variable-name": false, "variable-name": false,
"whitespace": [ "whitespace": [true, "check-branch", "check-decl", "check-operator", "check-separator", "check-type"],
true,
"check-branch",
"check-decl",
"check-operator",
"check-separator",
"check-type"
],
"no-output-on-prefix": true, "no-output-on-prefix": true,
"use-input-property-decorator": true, "use-input-property-decorator": true,
"use-output-property-decorator": true, "use-output-property-decorator": true,