[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.tabWidth": 4,
"prettier.printWidth": 140,
"workbench.colorCustomizations": {}
"workbench.colorCustomizations": {},
"typescriptHero.imports.insertSemicolons": false
}

View File

@@ -1,6 +1,6 @@
import { Injectable } from '@angular/core';
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 { CustomerMapping } from '../mappings/customer.mapping';
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 {
ifTrue(callback);
ifTrue(callback): boolean;
ifFalse(callback): boolean;
}
}
@@ -22,5 +23,13 @@ Array.prototype.hasItems = function() {
Boolean.prototype.ifTrue = function(callback) {
if (this && this.valueOf() === true) {
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: '/bonuscard', codes: [404] },
{ 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: '/5d1e00a230000080a4d72461', codes: [503] }, // test call
];

View File

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

View File

@@ -6,10 +6,10 @@ import { User, Address } from '../../../../core/models/user.model';
import { Router } from '@angular/router';
import { Process, CustomerFormState } from '../../../../core/models/process.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 { 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 { GENDERS, TIITLES } from '../../dropdown-values';
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 { isNullOrUndefined } from 'util';
import { DeliveryOption } from 'apps/sales/src/app/core/models/delivery-option.model';
import { CustomerService } from 'apps/sales/src/app/core/services/customer.service';
@Component({
selector: 'app-create-customer-card',
@@ -54,6 +55,7 @@ export class CreateCustomerCardComponent implements OnInit, OnDestroy {
guestChecked = false;
onlineChecked = false;
customerCardChecked = false;
timer: any;
get countries() {
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() {
this.initialize();
@@ -98,7 +106,6 @@ export class CreateCustomerCardComponent implements OnInit, OnDestroy {
this.cartHasItemsForDelivery.ifTrue(() => {
this.guestChecked = true;
});
// tslint:disable-next-line: semicolon
};
initializationSubscriptionHandler = (process: Process) => {
@@ -115,19 +122,66 @@ export class CreateCustomerCardComponent implements OnInit, OnDestroy {
this.userForm = this.buildCreateForm(this.fb);
}
this.setValidations();
this.setCompanyValidators();
this.loaded = true;
}
// tslint:disable-next-line: semicolon
};
@HostListener('window:scroll', ['$event'])
scrollHandler(event) {
if (event.target.id === 'customer-form') {
this.renderer.invokeElementMethod(document.activeElement, 'blur');
}
setValidations() {
const deliveryAndGuestOrOnline = this.cartHasItemsForDelivery && (this.guestChecked || this.onlineChecked);
deliveryAndGuestOrOnline.ifTrue(this.deliveryAndGuestValidations);
}
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() {
if (this.userForm.valid) {
this.createProcessIfDosntExists();
@@ -322,7 +376,7 @@ export class CreateCustomerCardComponent implements OnInit, OnDestroy {
return fb.group({
firstName: ['', Validators.required],
lastName: ['', Validators.required],
email: ['', CustomValidators.validateEmail],
email: ['', CustomValidators.validateEmail, this.validateIfEmailExists.bind(this)],
address: [''],
streetNo: [''],
zipCode: [''],
@@ -356,5 +410,18 @@ export class CreateCustomerCardComponent implements OnInit, OnDestroy {
toggle(checkbox: string) {
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) {
if (control.value && control.value.length > 0) {
if (emaiValidation.test(control.value)) {
console.log('passed email validation');
return null;
}

View File

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