Customer Create Forms

This commit is contained in:
Lorenz Hilpert
2023-06-14 15:04:15 +02:00
parent c134f645ef
commit ca21931d93
46 changed files with 444 additions and 175 deletions

View File

@@ -69,12 +69,12 @@ const routes: Routes = [
},
{
path: 'customer',
loadChildren: () => import('@page/customer').then((m) => m.PageCustomerModule),
loadChildren: () => import('@page/customer-rd').then((m) => m.CustomerModule),
canActivate: [CanActivateCustomerGuard],
},
{
path: ':processId/customer',
loadChildren: () => import('@page/customer').then((m) => m.PageCustomerModule),
loadChildren: () => import('@page/customer-rd').then((m) => m.CustomerModule),
canActivate: [CanActivateCustomerWithProcessIdGuard],
resolve: { processId: ProcessIdResolver },
},

View File

@@ -67,3 +67,14 @@
@apply block bg-gray-300 h-6;
animation: load 1s ease-in-out infinite;
}
@layer components {
.input-control {
@apply bg-[#e5e7eb] rounded border border-solid border-[#AEB7C1] px-4 py-[1.125rem] outline-none;
}
.input-control:focus,
.input-control:not(:placeholder-shown) {
@apply bg-white;
}
}

View File

@@ -1,4 +1,4 @@
<ui-checkbox [formControl]="control" [tabindex]="tabIndexStart" [autofocus]="focusAfterInit" [readonly]="readonly">
<shared-checkbox [formControl]="control" [tabindex]="tabIndexStart" [autofocus]="focusAfterInit" [readonly]="readonly">
Bitte unterschreiben Sie die Teilnahmebedingungen im Kundenkartenformular, um die Prämiennutzung zu ermöglichen.
{{ requiredMark ? '*' : '' }}
</ui-checkbox>
</shared-checkbox>

View File

@@ -2,12 +2,11 @@ import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { AcceptAGBFormBlockComponent } from './accept-agb-form-block.component';
import { UiCheckboxModule } from '@ui/checkbox';
import { ReactiveFormsModule } from '@angular/forms';
import { UiCommonModule } from '@ui/common';
import { CheckboxComponent } from '@shared/components/checkbox';
@NgModule({
imports: [CommonModule, UiCommonModule, UiCheckboxModule, ReactiveFormsModule],
imports: [CommonModule, CheckboxComponent, ReactiveFormsModule],
exports: [AcceptAGBFormBlockComponent],
declarations: [AcceptAGBFormBlockComponent],
})

View File

@@ -1,25 +1,62 @@
<ng-container [formGroup]="control">
<ui-form-control label="Straße" [requiredMark]="requiredMarks.includes('street') ? '*' : ''">
<input uiInput type="text" formControlName="street" [tabindex]="tabIndexStart" [autofocus]="focusAfterInit" [readonly]="readonly" />
</ui-form-control>
<ui-form-control label="Hausnummer" [requiredMark]="requiredMarks.includes('streetNumber') ? '*' : ''">
<input uiInput type="text" formControlName="streetNumber" [tabindex]="tabIndexStart + 1" [readonly]="readonly" />
</ui-form-control>
<ui-form-control label="PLZ" [requiredMark]="requiredMarks.includes('zipCode') ? '*' : ''">
<input uiInput type="text" formControlName="zipCode" [tabindex]="tabIndexStart + 2" [readonly]="readonly" />
</ui-form-control>
<ui-form-control label="Ort" [requiredMark]="requiredMarks.includes('city') ? '*' : ''">
<input uiInput type="text" formControlName="city" [tabindex]="tabIndexStart + 3" [readonly]="readonly" />
</ui-form-control>
<shared-form-control label="Straße">
<input
placeholder="Straße"
class="input-control"
type="text"
formControlName="street"
[tabindex]="tabIndexStart"
[autofocus]="focusAfterInit"
[readonly]="readonly"
/>
</shared-form-control>
<shared-form-control label="Hausnummer">
<input
placeholder="Hausnummer"
class="input-control"
type="text"
formControlName="streetNumber"
[tabindex]="tabIndexStart + 1"
[readonly]="readonly"
/>
</shared-form-control>
<shared-form-control label="PLZ">
<input
placeholder="PLZ"
class="input-control"
type="text"
formControlName="zipCode"
[tabindex]="tabIndexStart + 2"
[readonly]="readonly"
/>
</shared-form-control>
<shared-form-control label="Ort">
<input
placeholder="Ort"
class="input-control"
type="text"
formControlName="city"
[tabindex]="tabIndexStart + 3"
[readonly]="readonly"
/>
</shared-form-control>
<ui-form-control class="col-span-2" label="Adresszusatz" [clearable]="false" [requiredMark]="requiredMarks.includes('info') ? '*' : ''">
<input uiInput type="text" formControlName="info" [tabindex]="tabIndexStart + 4" [readonly]="readonly" />
</ui-form-control>
<shared-form-control class="col-span-2" label="Adresszusatz">
<input
placeholder="Adresszusatz"
class="input-control"
type="text"
formControlName="info"
[tabindex]="tabIndexStart + 4"
[readonly]="readonly"
/>
</shared-form-control>
<ui-form-control class="col-span-2" label="Land" [clearable]="true" [requiredMark]="requiredMarks.includes('country') ? '*' : ''">
<ui-select formControlName="country" [tabindex]="tabIndexStart + 5" [readonly]="readonly">
<ui-select-option *ngFor="let country of countries || (countries$ | async)" [label]="country.name" [value]="country.isO3166_A_3">
</ui-select-option>
</ui-select>
</ui-form-control>
<shared-form-control class="col-span-2" label="Land">
<shared-select placeholder="Land" formControlName="country" [tabindex]="tabIndexStart + 5" [readonly]="readonly">
<shared-select-option *ngFor="let country of countries || (countries$ | async)" [value]="country.isO3166_A_3">
{{ country.name }}
</shared-select-option>
</shared-select>
</shared-form-control>
</ng-container>

View File

@@ -2,14 +2,12 @@ import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { AddressFormBlockComponent } from './address-form-block.component';
import { UiFormControlModule } from '@ui/form-control';
import { UiInputModule } from '@ui/input';
import { UiSelectModule } from '@ui/select';
import { ReactiveFormsModule } from '@angular/forms';
import { UiCommonModule } from '@ui/common';
import { FormControlComponent } from '@shared/components/form-control';
import { SelectModule } from '@shared/components/select';
@NgModule({
imports: [CommonModule, UiCommonModule, UiFormControlModule, UiInputModule, UiSelectModule, ReactiveFormsModule],
imports: [CommonModule, ReactiveFormsModule, FormControlComponent, SelectModule],
exports: [AddressFormBlockComponent],
declarations: [AddressFormBlockComponent],
})

View File

@@ -1,3 +1,12 @@
<ui-form-control label="Geburtsdatum (TT.MM.JJJJ)" [requiredMark]="requiredMark ? '*' : ''">
<input uiDateInput type="text" [formControl]="control" [tabindex]="tabIndexStart" [autofocus]="focusAfterInit" [readonly]="readonly" />
</ui-form-control>
<shared-form-control label="Geburtsdatum (TT.MM.JJJJ)">
<input
placeholder="Geburtsdatum"
class="input-control"
uiDateInput
type="text"
[formControl]="control"
[tabindex]="tabIndexStart"
[autofocus]="focusAfterInit"
[readonly]="readonly"
/>
</shared-form-control>

View File

@@ -2,13 +2,11 @@ import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { BirthDateFormBlockComponent } from './birth-date-form-block.component';
import { UiFormControlModule } from '@ui/form-control';
import { UiInputModule } from '@ui/input';
import { ReactiveFormsModule } from '@angular/forms';
import { UiCommonModule } from '@ui/common';
import { FormControlComponent } from '@shared/components/form-control';
@NgModule({
imports: [CommonModule, ReactiveFormsModule, UiFormControlModule, UiInputModule, UiCommonModule],
imports: [CommonModule, ReactiveFormsModule, FormControlComponent],
exports: [BirthDateFormBlockComponent],
declarations: [BirthDateFormBlockComponent],
})

View File

@@ -1,6 +1,12 @@
<ui-checkbox [formControl]="deviatingAddress" [tabindex]="tabIndexStart" [autofocus]="focusAfterInit" [readonly]="readonly">
<shared-checkbox
class="mb-4"
[formControl]="deviatingAddress"
[tabindex]="tabIndexStart"
[autofocus]="focusAfterInit"
[readonly]="readonly"
>
<ng-content></ng-content>
</ui-checkbox>
</shared-checkbox>
<div class="address-block" *ngIf="control.value.deviatingAddress">
<div class="wrapper">
<app-organisation-form-block

View File

@@ -2,26 +2,24 @@ import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { DeviatingAddressFormBlockComponent } from './deviating-address-form-block.component';
import { UiCheckboxModule } from '@ui/checkbox';
import { AddressFormBlockModule } from '../address';
import { NameFormBlockModule } from '../name';
import { ReactiveFormsModule } from '@angular/forms';
import { OrganisationFormBlockModule } from '../organisation';
import { EmailFormBlockModule } from '../email';
import { PhoneNumbersFormBlockModule } from '../phone-numbers';
import { UiCommonModule } from '@ui/common';
import { CheckboxComponent } from '@shared/components/checkbox';
@NgModule({
imports: [
CommonModule,
ReactiveFormsModule,
UiCheckboxModule,
NameFormBlockModule,
AddressFormBlockModule,
OrganisationFormBlockModule,
EmailFormBlockModule,
PhoneNumbersFormBlockModule,
UiCommonModule,
CheckboxComponent,
],
exports: [DeviatingAddressFormBlockComponent],
declarations: [DeviatingAddressFormBlockComponent],

View File

@@ -1,3 +1,11 @@
<ui-form-control label="E-Mail" [requiredMark]="requiredMark ? '*' : ''">
<input uiInput type="mail" [formControl]="control" [tabindex]="tabIndexStart" [autofocus]="focusAfterInit" [readonly]="readonly" />
</ui-form-control>
<shared-form-control label="E-Mail">
<input
placeholder="E-Mail"
type="mail"
class="input-control"
[formControl]="control"
[tabindex]="tabIndexStart"
[autofocus]="focusAfterInit"
[readonly]="readonly"
/>
</shared-form-control>

View File

@@ -3,12 +3,10 @@ import { CommonModule } from '@angular/common';
import { EmailFormBlockComponent } from './email-form-block.component';
import { ReactiveFormsModule } from '@angular/forms';
import { UiFormControlModule } from '@ui/form-control';
import { UiInputModule } from '@ui/input';
import { UiCommonModule } from '@ui/common';
import { FormControlComponent } from '@shared/components/form-control';
@NgModule({
imports: [CommonModule, UiCommonModule, ReactiveFormsModule, UiFormControlModule, UiInputModule],
imports: [CommonModule, ReactiveFormsModule, FormControlComponent],
exports: [EmailFormBlockComponent],
declarations: [EmailFormBlockComponent],
})

View File

@@ -1,6 +1,6 @@
<div class="interests-description">Geben Sie Interessen an, um Ihre persönlichen Kontoangaben zu verfeinern.</div>
<div class="interests-wrapper" [formGroup]="control">
<ui-checkbox
<shared-checkbox
*ngFor="let pair of interests | keyvalue; let idx = index"
[formControlName]="pair.key"
[tabindex]="tabIndexStart + idx"
@@ -8,5 +8,5 @@
[readonly]="readonly"
>
{{ pair.value }}
</ui-checkbox>
</shared-checkbox>
</div>

View File

@@ -2,12 +2,11 @@ import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { InterestsFormBlockComponent } from './interests-form-block.component';
import { UiCheckboxModule } from '@ui/checkbox';
import { ReactiveFormsModule } from '@angular/forms';
import { UiCommonModule } from '@ui/common';
import { CheckboxComponent } from '@shared/components/checkbox';
@NgModule({
imports: [CommonModule, UiCommonModule, ReactiveFormsModule, UiCheckboxModule],
imports: [CommonModule, ReactiveFormsModule, CheckboxComponent],
exports: [InterestsFormBlockComponent],
declarations: [InterestsFormBlockComponent],
})

View File

@@ -1,16 +1,18 @@
<ng-container [formGroup]="control">
<label class="grid grid-flow-row gap-1">
<span>Anrede</span>
<shared-select formControlName="gender" placeholder="Anrede" [readonly]="readonly" [tabindex]="tabIndexStart">
<shared-form-control label="Anrede">
<shared-select
formControlName="gender"
placeholder="Anrede"
[readonly]="readonly"
[tabindex]="tabIndexStart"
[autofocus]="focusAfterInit"
>
<shared-select-option [value]="2">Herr</shared-select-option>
<shared-select-option [value]="4">Frau</shared-select-option>
</shared-select>
</label>
<label class="grid grid-flow-row gap-1">
<span>Titel</span>
</shared-form-control>
<shared-form-control label="Titel">
<shared-select formControlName="title" placeholder="Titel" [readonly]="readonly" [tabindex]="tabIndexStart + 1">
<shared-select-option value="Dipl.-Ing.">Dipl.-Ing.</shared-select-option>
<shared-select-option value="Dr.">Dr.</shared-select-option>
@@ -19,29 +21,27 @@
<shared-select-option value="Prof. Dr.">Prof. Dr.</shared-select-option>
<shared-select-option value="RA">RA</shared-select-option>
</shared-select>
</label>
</shared-form-control>
<!-- <ui-form-control [clearable]="!readonly" label="Anrede" [requiredMark]="requiredMarks.includes('gender') ? '*' : ''">
<ui-select formControlName="gender" [tabindex]="tabIndexStart" [autofocus]="focusAfterInit" [readonly]="readonly">
<ui-select-option [value]="2" label="Herr"></ui-select-option>
<ui-select-option [value]="4" label="Frau"></ui-select-option>
</ui-select>
</ui-form-control> -->
<!-- <ui-form-control [clearable]="!readonly" label="Titel" [requiredMark]="requiredMarks.includes('title') ? '*' : ''">
<ui-select formControlName="title" [tabindex]="tabIndexStart + 1" [readonly]="readonly">
<ui-select-option value="Dipl.-Ing." label="Dipl.-Ing."></ui-select-option>
<ui-select-option value="Dr." label="Dr."></ui-select-option>
<ui-select-option value="Dr. med." label="Dr. med."></ui-select-option>
<ui-select-option value="Prof." label="Prof."></ui-select-option>
<ui-select-option value="Prof. Dr." label="Prof. Dr."></ui-select-option>
<ui-select-option value="RA" label="RA"></ui-select-option>
</ui-select>
</ui-form-control> -->
<shared-form-control label="Nachname">
<input
class="input-control"
placeholder="Nachname"
type="text"
formControlName="lastName"
[tabindex]="tabIndexStart + 2"
[readonly]="readonly"
/>
</shared-form-control>
<ui-form-control label="Nachname" [requiredMark]="requiredMarks.includes('firstName') ? '*' : ''">
<input uiInput type="text" formControlName="lastName" [tabindex]="tabIndexStart + 2" [readonly]="readonly" />
</ui-form-control>
<ui-form-control label="Vorname" [requiredMark]="requiredMarks.includes('lastName') ? '*' : ''">
<input uiInput type="text" formControlName="firstName" [tabindex]="tabIndexStart + 3" [readonly]="readonly" />
</ui-form-control>
<shared-form-control label="Vorname">
<input
class="input-control"
placeholder="Vorname"
type="text"
formControlName="firstName"
[tabindex]="tabIndexStart + 3"
[readonly]="readonly"
/>
</shared-form-control>
</ng-container>

View File

@@ -2,14 +2,12 @@ import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { NameFormBlockComponent } from './name-form-block.component';
import { UiFormControlModule } from '@ui/form-control';
import { UiInputModule } from '@ui/input';
import { ReactiveFormsModule } from '@angular/forms';
import { UiCommonModule } from '@ui/common';
import { SelectModule } from '@shared/components/select';
import { FormControlComponent } from '@shared/components/form-control';
@NgModule({
imports: [CommonModule, UiCommonModule, ReactiveFormsModule, UiFormControlModule, UiInputModule, SelectModule],
imports: [CommonModule, ReactiveFormsModule, SelectModule, FormControlComponent],
exports: [NameFormBlockComponent],
declarations: [NameFormBlockComponent],
})

View File

@@ -1,3 +1,3 @@
<ui-checkbox [formControl]="control" [tabindex]="tabIndexStart" [autofocus]="focusAfterInit" [readonly]="readonly">
<shared-checkbox [formControl]="control" [tabindex]="tabIndexStart" [autofocus]="focusAfterInit" [readonly]="readonly">
Erhalten Sie 250 Lesepunkte mit der Anmeldung zum Newsletter und eine Geburtstagsüberraschung
</ui-checkbox>
</shared-checkbox>

View File

@@ -2,12 +2,11 @@ import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { NewsletterFormBlockComponent } from './newsletter-form-block.component';
import { UiCheckboxModule } from '@ui/checkbox';
import { ReactiveFormsModule } from '@angular/forms';
import { UiCommonModule } from '@ui/common';
import { CheckboxComponent } from '@shared/components/checkbox';
@NgModule({
imports: [CommonModule, UiCommonModule, ReactiveFormsModule, UiCheckboxModule],
imports: [CommonModule, ReactiveFormsModule, CheckboxComponent],
exports: [NewsletterFormBlockComponent],
declarations: [NewsletterFormBlockComponent],
})

View File

@@ -1,13 +1,35 @@
<ng-container [formGroup]="control">
<ui-form-control class="col-span-2" label="Firmenname" [requiredMark]="requiredMarks.includes('name') ? '*' : ''">
<input uiInput type="text" formControlName="name" [tabindex]="tabIndexStart" [autofocus]="focusAfterInit" [readonly]="readonly" />
</ui-form-control>
<shared-form-control class="col-span-2" label="Firmenname">
<input
placeholder="Firmenname"
class="input-control"
type="text"
formControlName="name"
[tabindex]="tabIndexStart"
[autofocus]="focusAfterInit"
[readonly]="readonly"
/>
</shared-form-control>
<ng-container *ngIf="appearence === 'default'">
<ui-form-control label="Abteilung" [requiredMark]="requiredMarks.includes('department') ? '*' : ''">
<input uiInput type="text" formControlName="department" [tabindex]="tabIndexStart + 1" [readonly]="readonly" />
</ui-form-control>
<ui-form-control label="USt-ID" [requiredMark]="requiredMarks.includes('vatId') ? '*' : ''">
<input uiInput type="text" formControlName="vatId" [tabindex]="tabIndexStart + 2" [readonly]="readonly" />
</ui-form-control>
<shared-form-control label="Abteilung">
<input
placeholder="Abteilung"
class="input-control"
type="text"
formControlName="department"
[tabindex]="tabIndexStart + 1"
[readonly]="readonly"
/>
</shared-form-control>
<shared-form-control label="USt-ID">
<input
placeholder="USt-ID"
class="input-control"
type="text"
formControlName="vatId"
[tabindex]="tabIndexStart + 2"
[readonly]="readonly"
/>
</shared-form-control>
</ng-container>
</ng-container>

View File

@@ -2,13 +2,11 @@ import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { OrganisationFormBlockComponent } from './organisation-form-block.component';
import { UiFormControlModule } from '@ui/form-control';
import { UiInputModule } from '@ui/input';
import { ReactiveFormsModule } from '@angular/forms';
import { UiCommonModule } from '@ui/common';
import { FormControlComponent } from '@shared/components/form-control';
@NgModule({
imports: [CommonModule, UiCommonModule, ReactiveFormsModule, UiFormControlModule, UiInputModule],
imports: [CommonModule, ReactiveFormsModule, FormControlComponent],
exports: [OrganisationFormBlockComponent],
declarations: [OrganisationFormBlockComponent],
})

View File

@@ -1,6 +1,14 @@
<ui-form-control label="Kundenkartencode" requiredMark="*" class="flex-grow">
<input uiInput type="text" [formControl]="control" [tabindex]="tabIndexStart" [readonly]="readonly" [autofocus]="focusAfterInit" />
</ui-form-control>
<shared-form-control label="Kundenkartencode" class="flex-grow">
<input
placeholder="Kundenkartencode"
class="input-control"
type="text"
[formControl]="control"
[tabindex]="tabIndexStart"
[readonly]="readonly"
[autofocus]="focusAfterInit"
/>
</shared-form-control>
<button type="button" *ngIf="!readonly && canScan()" (click)="scan()">
<shared-icon icon="barcode-scan" [size]="32"></shared-icon>
</button>

View File

@@ -3,13 +3,11 @@ import { CommonModule } from '@angular/common';
import { P4mNumberFormBlockComponent } from './p4m-number-form-block.component';
import { ReactiveFormsModule } from '@angular/forms';
import { UiFormControlModule } from '@ui/form-control';
import { UiInputModule } from '@ui/input';
import { UiCommonModule } from '@ui/common';
import { IconComponent } from '@shared/components/icon';
import { FormControlComponent } from '@shared/components/form-control';
@NgModule({
imports: [CommonModule, UiCommonModule, ReactiveFormsModule, UiFormControlModule, UiInputModule, IconComponent],
imports: [CommonModule, ReactiveFormsModule, FormControlComponent, IconComponent],
exports: [P4mNumberFormBlockComponent],
declarations: [P4mNumberFormBlockComponent],
})

View File

@@ -1,8 +1,23 @@
<ng-container [formGroup]="control">
<ui-form-control label="Festnetznummer" [requiredMark]="requiredMarks.includes('phone') ? '*' : ''">
<input uiInput type="tel" formControlName="phone" [tabindex]="tabIndexStart" [autofocus]="focusAfterInit" [readonly]="readonly" />
</ui-form-control>
<ui-form-control label="Mobilnummer" [clearable]="false" [requiredMark]="requiredMarks.includes('mobile') ? '*' : ''">
<input uiInput type="tel" formControlName="mobile" [tabindex]="tabIndexStart + 1" [readonly]="readonly" />
</ui-form-control>
<shared-form-control label="Festnetznummer">
<input
placeholder="Festnetznummer"
class="input-control"
type="tel"
formControlName="phone"
[tabindex]="tabIndexStart"
[autofocus]="focusAfterInit"
[readonly]="readonly"
/>
</shared-form-control>
<shared-form-control label="Mobilnummer">
<input
placeholder="Mobilnummer"
class="input-control"
type="tel"
formControlName="mobile"
[tabindex]="tabIndexStart + 1"
[readonly]="readonly"
/>
</shared-form-control>
</ng-container>

View File

@@ -1,14 +1,12 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { UiFormControlModule } from '@ui/form-control';
import { UiInputModule } from '@ui/input';
import { ReactiveFormsModule } from '@angular/forms';
import { PhoneNumbersFormBlockComponent } from './phone-numbers-form-block.component';
import { UiCommonModule } from '@ui/common';
import { FormControlComponent } from '@shared/components/form-control';
@NgModule({
imports: [CommonModule, UiCommonModule, ReactiveFormsModule, UiFormControlModule, UiInputModule],
imports: [CommonModule, ReactiveFormsModule, FormControlComponent],
exports: [PhoneNumbersFormBlockComponent],
declarations: [PhoneNumbersFormBlockComponent],
})

View File

@@ -30,7 +30,7 @@ app-newsletter-form-block,
app-accept-agb-form-block,
app-interests-form-block,
app-deviating-address-form-block {
@apply mt-8;
@apply mt-4;
}
.spacer {

View File

@@ -43,6 +43,7 @@
</app-accept-agb-form-block>
<app-newsletter-form-block
class="mb-4"
#newsletterBlock
[tabIndexStart]="p4mBlock.tabIndexEnd + 1"
(onInit)="addFormBlock('newsletter', $event)"

View File

@@ -35,6 +35,7 @@ export class CreateStoreCustomerComponent extends AbstractCreateCustomer {
nameRequiredMarks: (keyof NameFormBlockData)[] = ['gender', 'firstName', 'lastName'];
nameValidationFns: Record<string, ValidatorFn[]> = {
title: [],
gender: [Validators.required, Validators.min(1)],
firstName: [Validators.required],
lastName: [Validators.required],

View File

@@ -27,6 +27,7 @@
</app-accept-agb-form-block>
<app-newsletter-form-block
class="mb-4"
#newsletterBlock
[tabIndexStart]="p4mBlock.tabIndexEnd + 1"
(onInit)="addFormBlock('newsletter', $event)"

View File

@@ -43,6 +43,7 @@
</app-accept-agb-form-block>
<app-newsletter-form-block
class="mb-4"
#newsletterBlock
[tabIndexStart]="p4mBlock.tabIndexEnd + 1"
(onInit)="addFormBlock('newsletter', $event)"

View File

@@ -27,6 +27,7 @@
</app-accept-agb-form-block>
<app-newsletter-form-block
class="mb-4"
#newsletterBlock
[tabIndexStart]="p4mBlock.tabIndexEnd + 1"
(onInit)="addFormBlock('newsletter', $event)"

View File

@@ -1,3 +1,4 @@
import { BooleanInput, coerceBooleanProperty } from '@angular/cdk/coercion';
import { NgIf } from '@angular/common';
import {
ChangeDetectionStrategy,
@@ -43,11 +44,18 @@ export class CheckboxComponent implements ControlValueAccessor {
}
@Input()
@HostBinding('class.readonly')
readonly = false;
name: string;
private _readonly = false;
@Input()
name: string;
@HostBinding('attr.readonly')
get readonly(): BooleanInput {
return this._readonly;
}
set readonly(value: BooleanInput) {
this._readonly = coerceBooleanProperty(value);
}
private onChange = (v: any) => {};
private onChangeForParent = (checked: boolean, value: any) => {};

View File

@@ -1 +0,0 @@
<ng-content></ng-content>

View File

@@ -1,14 +0,0 @@
import { Component, ChangeDetectionStrategy } from '@angular/core';
@Component({
selector: 'shared-control-field',
templateUrl: 'control-field.component.html',
styleUrls: ['control-field.component.css'],
changeDetection: ChangeDetectionStrategy.OnPush,
host: { class: 'shared-control-field' },
standalone: true,
imports: [],
})
export class ControlFieldComponent {
constructor() {}
}

View File

@@ -1,8 +0,0 @@
import { NgModule } from '@angular/core';
import { ControlFieldComponent } from './control-field.component';
@NgModule({
imports: [ControlFieldComponent],
exports: [ControlFieldComponent],
})
export class ControlFieldModule {}

View File

@@ -0,0 +1,33 @@
import { BooleanInput, coerceBooleanProperty } from '@angular/cdk/coercion';
import { Directive, HostBinding, Input } from '@angular/core';
@Directive()
export class BaseFormControlDirective {
// @Input()
// @HostBinding('attr.name')
// name: string = (Date.now() + Math.random()).toString(32);
// @Input()
// @HostBinding('attr.id')
// id: string = (Date.now() + Math.random()).toString(32);
private _readonly = false;
@Input()
@HostBinding('readonly')
get readonly(): boolean {
return this._readonly;
}
set readonly(value: BooleanInput) {
this._readonly = coerceBooleanProperty(value);
}
private _disabled: boolean = false;
@Input()
get disabled(): BooleanInput {
return this._disabled;
}
set disabled(value: BooleanInput) {
this._disabled = coerceBooleanProperty(value);
}
}

View File

@@ -0,0 +1,11 @@
import { AbstractControl } from '@angular/forms';
export class EmptyControl extends AbstractControl {
constructor() {
super([], []);
}
setValue(value: any, options?: Object): void {}
patchValue(value: any, options?: Object): void {}
reset(value?: any, options?: Object): void {}
}

View File

@@ -0,0 +1,28 @@
import { Pipe, PipeTransform } from '@angular/core';
import { ValidationErrors } from '@angular/forms';
@Pipe({
name: 'firstError',
standalone: true,
})
export class FirstErrorPipe implements PipeTransform {
transform(errors: ValidationErrors, label: string): string {
if (errors) {
const error = Object.keys(errors)[0];
switch (error) {
case 'min':
return `${label} wird benötigt`; // gender validation for create (upgrade) online customer with gender min value of 2
case 'max':
return `${label} ist ungültig`;
case 'required':
return `${label} wird benötigt`;
case 'email':
return `${label} ist ungültig`;
case 'pattern':
return `${label} ist ungültig`;
default:
return errors[error];
}
}
return undefined;
}
}

View File

@@ -0,0 +1,15 @@
.shared-form-control {
@apply flex flex-col;
}
.shared-fomr-control-label {
@apply mb-1 text-base;
}
.shared-fomr-control-error {
@apply text-brand text-sm invisible text-right h-4;
}
.shared-form-control:has(.ng-touched) .shared-fomr-control-error {
@apply visible;
}

View File

@@ -0,0 +1,5 @@
<label class="shared-fomr-control-label">{{ displayLabel }}</label>
<ng-content select="shared-select, input"></ng-content>
<div class="shared-fomr-control-error">
{{ control?.errors | firstError: label }}
</div>

View File

@@ -0,0 +1,69 @@
import {
Component,
ChangeDetectionStrategy,
Input,
ContentChild,
ElementRef,
ViewEncapsulation,
ChangeDetectorRef,
OnDestroy,
AfterContentInit,
} from '@angular/core';
import { NgControl } from '@angular/forms';
import { EmptyControl } from './empty-control';
import { FirstErrorPipe } from './first-error.pipe';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
@Component({
selector: 'shared-form-control',
templateUrl: 'form-control.component.html',
styleUrls: ['form-control.component.css'],
changeDetection: ChangeDetectionStrategy.OnPush,
encapsulation: ViewEncapsulation.None,
host: { class: 'shared-form-control' },
standalone: true,
imports: [FirstErrorPipe],
})
export class FormControlComponent implements OnDestroy, AfterContentInit {
@Input()
label: string;
@ContentChild(NgControl, { static: true })
controlDirective: NgControl;
get control() {
return this.controlDirective.control;
}
required = false;
get displayLabel() {
return (this.label ?? this.control?.['name'] ?? '') + (this.required ? '*' : '');
}
private _onDestroy$ = new Subject<void>();
constructor(private _elementRef: ElementRef, private _cdr: ChangeDetectorRef) {}
ngAfterContentInit() {
this.checkValidator();
this.control.statusChanges.pipe(takeUntil(this._onDestroy$)).subscribe(() => {
this.checkValidator();
this._cdr.markForCheck();
});
}
ngOnDestroy() {
this._onDestroy$.next();
this._onDestroy$.complete();
}
checkValidator() {
const errors = this.control?.validator?.(new EmptyControl());
this.required = !!errors?.required;
}
clickLabel() {}
}

View File

@@ -0,0 +1,8 @@
import { NgModule } from '@angular/core';
import { FormControlComponent } from './form-control.component';
@NgModule({
imports: [FormControlComponent],
exports: [FormControlComponent],
})
export class FormControldModule {}

View File

@@ -0,0 +1,3 @@
export * from './lib/base-form-control.directive';
export * from './lib/form-control.component';
export * from './lib/form-control.module';

View File

@@ -12,10 +12,15 @@ import {
HostListener,
ElementRef,
HostBinding,
AfterContentInit,
OnDestroy,
} from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
import { SelectOptionComponent } from './select-option.component';
import { IconComponent } from '@shared/components/icon';
import { BaseFormControlDirective } from '@shared/components/form-control';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
@Component({
selector: 'shared-select',
@@ -28,25 +33,7 @@ import { IconComponent } from '@shared/components/icon';
imports: [IconComponent],
providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: SelectComponent, multi: true }],
})
export class SelectComponent<T = any> implements ControlValueAccessor {
private _readonly: boolean = false;
@Input()
get readonly(): BooleanInput {
return this._readonly;
}
set readonly(value: BooleanInput) {
this._readonly = coerceBooleanProperty(value);
}
private _disabled: boolean = false;
@Input()
get disabled(): BooleanInput {
return this._disabled;
}
set disabled(value: BooleanInput) {
this._disabled = coerceBooleanProperty(value);
}
export class SelectComponent<T = any> extends BaseFormControlDirective implements ControlValueAccessor, AfterContentInit, OnDestroy {
@ContentChildren(SelectOptionComponent)
options: QueryList<SelectOptionComponent>;
@@ -69,6 +56,9 @@ export class SelectComponent<T = any> implements ControlValueAccessor {
tabindex: NumberInput = 0;
get hasValue(): boolean {
if (typeof this.value === 'string') {
return this.value.trim().length > 0;
}
return this.value !== undefined && this.value !== null;
}
@@ -91,7 +81,22 @@ export class SelectComponent<T = any> implements ControlValueAccessor {
return this._forceClose;
}
constructor(private _cdr: ChangeDetectorRef, private _elementRef: ElementRef<HTMLElement>) {}
private _onDestroy$ = new Subject<void>();
constructor(private _cdr: ChangeDetectorRef, private _elementRef: ElementRef<HTMLElement>) {
super();
}
ngAfterContentInit() {
this.options.changes.pipe(takeUntil(this._onDestroy$)).subscribe(() => {
this._cdr.markForCheck();
});
}
ngOnDestroy() {
this._onDestroy$.next();
this._onDestroy$.complete();
}
writeValue(obj: any): void {
this.value = obj;
@@ -155,4 +160,9 @@ export class SelectComponent<T = any> implements ControlValueAccessor {
private contains(target: EventTarget): boolean {
return this._elementRef.nativeElement.contains(target as Element);
}
@HostListener('blur')
onBlur(): void {
this._onTouched();
}
}