diff --git a/apps/isa-app/src/app/app-routing.module.ts b/apps/isa-app/src/app/app-routing.module.ts
index 06ecd1004..3e524d7b0 100644
--- a/apps/isa-app/src/app/app-routing.module.ts
+++ b/apps/isa-app/src/app/app-routing.module.ts
@@ -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 },
},
diff --git a/apps/isa-app/src/environments/environment.prod.ts b/apps/isa-app/src/environments/environment.prod.ts
index c9669790b..b0a41d616 100644
--- a/apps/isa-app/src/environments/environment.prod.ts
+++ b/apps/isa-app/src/environments/environment.prod.ts
@@ -1,3 +1,4 @@
export const environment = {
production: true,
+ debug: false,
};
diff --git a/apps/isa-app/src/environments/environment.ts b/apps/isa-app/src/environments/environment.ts
index 66998ae9a..6c9336a03 100644
--- a/apps/isa-app/src/environments/environment.ts
+++ b/apps/isa-app/src/environments/environment.ts
@@ -4,6 +4,7 @@
export const environment = {
production: false,
+ debug: false,
};
/*
diff --git a/apps/isa-app/src/main.ts b/apps/isa-app/src/main.ts
index 23e538082..8538ec5e0 100644
--- a/apps/isa-app/src/main.ts
+++ b/apps/isa-app/src/main.ts
@@ -14,26 +14,28 @@ if (environment.production) {
const debugService = new DebugService();
-const consoleLog = console.log;
+if (environment.debug) {
+ const consoleLog = console.log;
-console.log = (...args) => {
- debugService.add({ type: 'log', args });
- consoleLog(...args);
-};
+ console.log = (...args) => {
+ debugService.add({ type: 'log', args });
+ consoleLog(...args);
+ };
-const consoleWarn = console.warn;
+ const consoleWarn = console.warn;
-console.warn = (...args) => {
- debugService.add({ type: 'warn', args });
- consoleWarn(...args);
-};
+ console.warn = (...args) => {
+ debugService.add({ type: 'warn', args });
+ consoleWarn(...args);
+ };
-const consoleError = console.error;
+ const consoleError = console.error;
-console.error = (...args) => {
- debugService.add({ type: 'error', args });
- consoleError(...args);
-};
+ console.error = (...args) => {
+ debugService.add({ type: 'error', args });
+ consoleError(...args);
+ };
+}
platformBrowserDynamic([{ provide: DebugService, useValue: debugService }])
.bootstrapModule(AppModule)
diff --git a/apps/page/customer-rd/ng-package.json b/apps/page/customer-rd/ng-package.json
new file mode 100644
index 000000000..847998831
--- /dev/null
+++ b/apps/page/customer-rd/ng-package.json
@@ -0,0 +1,7 @@
+{
+ "$schema": "../../../node_modules/ng-packagr/ng-package.schema.json",
+ "dest": "../../../dist/page/customer",
+ "lib": {
+ "entryFile": "src/public-api.ts"
+ }
+}
\ No newline at end of file
diff --git a/apps/page/customer-rd/src/lib/components/customer-result-list/customer-result-list-item-full/customer-result-list-item-full.component.css b/apps/page/customer-rd/src/lib/components/customer-result-list/customer-result-list-item-full/customer-result-list-item-full.component.css
new file mode 100644
index 000000000..06cf25fe8
--- /dev/null
+++ b/apps/page/customer-rd/src/lib/components/customer-result-list/customer-result-list-item-full/customer-result-list-item-full.component.css
@@ -0,0 +1,3 @@
+:host {
+ @apply grid grid-flow-row gap-[5px] h-[6.125rem] bg-surface text-surface-content overflow-hidden mb-px-2 px-4 py-3;
+}
diff --git a/apps/page/customer-rd/src/lib/components/customer-result-list/customer-result-list-item-full/customer-result-list-item-full.component.html b/apps/page/customer-rd/src/lib/components/customer-result-list/customer-result-list-item-full/customer-result-list-item-full.component.html
new file mode 100644
index 000000000..ff3bedc04
--- /dev/null
+++ b/apps/page/customer-rd/src/lib/components/customer-result-list/customer-result-list-item-full/customer-result-list-item-full.component.html
@@ -0,0 +1,24 @@
+
+
+ {{ label?.description }}
+
+
+ {{ customer?.created | date: 'dd.MM.yy' }}
+
+
+
+
+
{{ customer?.lastName }} {{ customer?.firstName }}
+
+
+
+ PLZ und Ort
+ {{ customer?.address?.zipCode }} {{ customer?.address?.city }}
+
+
+ E-Mail
+ {{ customer?.communicationDetails?.email }}
+
+
+
+
diff --git a/apps/page/customer-rd/src/lib/components/customer-result-list/customer-result-list-item-full/customer-result-list-item-full.component.ts b/apps/page/customer-rd/src/lib/components/customer-result-list/customer-result-list-item-full/customer-result-list-item-full.component.ts
new file mode 100644
index 000000000..f9df6adb0
--- /dev/null
+++ b/apps/page/customer-rd/src/lib/components/customer-result-list/customer-result-list-item-full/customer-result-list-item-full.component.ts
@@ -0,0 +1,19 @@
+import { Component, ChangeDetectionStrategy, Input } from '@angular/core';
+import { CustomerInfoDTO } from '@swagger/crm';
+
+@Component({
+ selector: 'page-customer-result-list-item-full',
+ templateUrl: 'customer-result-list-item-full.component.html',
+ styleUrls: ['customer-result-list-item-full.component.css'],
+ changeDetection: ChangeDetectionStrategy.OnPush,
+})
+export class CustomerResultListItemFullComponent {
+ get label() {
+ return this.customer?.features?.find((f) => f.enabled);
+ }
+
+ @Input()
+ customer: CustomerInfoDTO;
+
+ constructor() {}
+}
diff --git a/apps/page/customer-rd/src/lib/components/customer-result-list/customer-result-list-item/customer-result-list-item.component.css b/apps/page/customer-rd/src/lib/components/customer-result-list/customer-result-list-item/customer-result-list-item.component.css
new file mode 100644
index 000000000..779a058f8
--- /dev/null
+++ b/apps/page/customer-rd/src/lib/components/customer-result-list/customer-result-list-item/customer-result-list-item.component.css
@@ -0,0 +1,3 @@
+:host {
+ @apply flex flex-col bg-surface text-surface-content h-[11.313rem] mb-[0.625rem] p-4;
+}
diff --git a/apps/page/customer-rd/src/lib/components/customer-result-list/customer-result-list-item/customer-result-list-item.component.html b/apps/page/customer-rd/src/lib/components/customer-result-list/customer-result-list-item/customer-result-list-item.component.html
new file mode 100644
index 000000000..69f0104ff
--- /dev/null
+++ b/apps/page/customer-rd/src/lib/components/customer-result-list/customer-result-list-item/customer-result-list-item.component.html
@@ -0,0 +1,24 @@
+
+
+ {{ label?.description }}
+
+
+ {{ customer?.created | date: 'dd.MM.yy' }}
+
+
+
+
+
{{ customer?.lastName }} {{ customer?.firstName }}
+
+
+
+ PLZ und Ort
+ {{ customer?.address?.zipCode }} {{ customer?.address?.city }}
+
+
+ E-Mail
+ {{ customer?.communicationDetails?.email }}
+
+
+
+
diff --git a/apps/page/customer-rd/src/lib/components/customer-result-list/customer-result-list-item/customer-result-list-item.component.ts b/apps/page/customer-rd/src/lib/components/customer-result-list/customer-result-list-item/customer-result-list-item.component.ts
new file mode 100644
index 000000000..c6177e7f2
--- /dev/null
+++ b/apps/page/customer-rd/src/lib/components/customer-result-list/customer-result-list-item/customer-result-list-item.component.ts
@@ -0,0 +1,19 @@
+import { Component, ChangeDetectionStrategy, Input } from '@angular/core';
+import { CustomerInfoDTO } from '@swagger/crm';
+
+@Component({
+ selector: 'page-customer-result-list-item',
+ templateUrl: 'customer-result-list-item.component.html',
+ styleUrls: ['customer-result-list-item.component.css'],
+ changeDetection: ChangeDetectionStrategy.OnPush,
+})
+export class CustomerResultListItemComponent {
+ get label() {
+ return this.customer?.features?.find((f) => f.enabled);
+ }
+
+ @Input()
+ customer: CustomerInfoDTO;
+
+ constructor() {}
+}
diff --git a/apps/page/customer-rd/src/lib/components/customer-result-list/customer-result-list.component.css b/apps/page/customer-rd/src/lib/components/customer-result-list/customer-result-list.component.css
new file mode 100644
index 000000000..820553929
--- /dev/null
+++ b/apps/page/customer-rd/src/lib/components/customer-result-list/customer-result-list.component.css
@@ -0,0 +1,17 @@
+:host {
+ --shadow: 0px 0px 10px rgba(220, 226, 233, 0.5);
+ --border-radius: 0.313rem;
+ @apply grid grid-flow-row;
+ border-radius: var(--border-radius);
+}
+
+.customer-result-list-header {
+ box-shadow: var(--shadow);
+ border-radius: var(--border-radius) var(--border-radius) 0 0;
+}
+
+page-customer-result-list-item-full,
+page-customer-result-list-item {
+ cursor: pointer;
+ border-radius: var(--border-radius);
+}
diff --git a/apps/page/customer-rd/src/lib/components/customer-result-list/customer-result-list.component.html b/apps/page/customer-rd/src/lib/components/customer-result-list/customer-result-list.component.html
new file mode 100644
index 000000000..137b3eb8b
--- /dev/null
+++ b/apps/page/customer-rd/src/lib/components/customer-result-list/customer-result-list.component.html
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/apps/page/customer-rd/src/lib/components/customer-result-list/customer-result-list.component.ts b/apps/page/customer-rd/src/lib/components/customer-result-list/customer-result-list.component.ts
new file mode 100644
index 000000000..0c1e67cf7
--- /dev/null
+++ b/apps/page/customer-rd/src/lib/components/customer-result-list/customer-result-list.component.ts
@@ -0,0 +1,49 @@
+import { Component, ChangeDetectionStrategy, Input, EventEmitter, Output } from '@angular/core';
+import { CustomerInfoDTO } from '@swagger/crm';
+import { CrmCustomerService } from '@domain/crm';
+import { map } from 'rxjs/operators';
+import { BooleanInput, NumberInput, coerceBooleanProperty, coerceNumberProperty } from '@angular/cdk/coercion';
+import { CustomerSearchNavigation } from '../../navigations';
+
+@Component({
+ selector: 'page-customer-result-list',
+ templateUrl: 'customer-result-list.component.html',
+ styleUrls: ['customer-result-list.component.css'],
+ changeDetection: ChangeDetectionStrategy.OnPush,
+})
+export class CustomerResultListComponent {
+ private _compact: boolean;
+ @Input()
+ get compact() {
+ return this._compact;
+ }
+ set compact(value: BooleanInput) {
+ this._compact = coerceBooleanProperty(value);
+ }
+
+ customers$ = this._customerService.getCustomers('Lorenz Hilpert').pipe(map((res) => res.result));
+
+ @Input()
+ selected: CustomerInfoDTO;
+
+ @Output()
+ selectedChange = new EventEmitter();
+
+ private _processId: NumberInput;
+ @Input()
+ get processId() {
+ return this._processId;
+ }
+ set processId(value: NumberInput) {
+ this._processId = coerceNumberProperty(value);
+ }
+
+ trackByFn = (_: number, item: CustomerInfoDTO) => item?.id;
+
+ constructor(private _customerService: CrmCustomerService, public customerSearchNavigation: CustomerSearchNavigation) {}
+
+ select(customer: CustomerInfoDTO) {
+ this.selected = customer;
+ this.selectedChange.emit(customer);
+ }
+}
diff --git a/apps/page/customer-rd/src/lib/components/customer-result-list/customer-result-list.module.ts b/apps/page/customer-rd/src/lib/components/customer-result-list/customer-result-list.module.ts
new file mode 100644
index 000000000..6215422ed
--- /dev/null
+++ b/apps/page/customer-rd/src/lib/components/customer-result-list/customer-result-list.module.ts
@@ -0,0 +1,22 @@
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { ScrollingModule } from '@angular/cdk/scrolling';
+
+import { SearchboxModule } from '@shared/components/searchbox';
+
+import { CustomerResultListComponent } from './customer-result-list.component';
+import { CustomerResultListItemFullComponent } from './customer-result-list-item-full/customer-result-list-item-full.component';
+import { CustomerResultListItemComponent } from './customer-result-list-item/customer-result-list-item.component';
+import { RouterModule } from '@angular/router';
+
+@NgModule({
+ imports: [CommonModule, SearchboxModule, ScrollingModule, RouterModule],
+ exports: [CustomerResultListComponent, CustomerResultListComponent, CustomerResultListItemFullComponent, CustomerResultListItemComponent],
+ declarations: [
+ CustomerResultListComponent,
+ CustomerResultListComponent,
+ CustomerResultListItemFullComponent,
+ CustomerResultListItemComponent,
+ ],
+})
+export class CustomerResultListModule {}
diff --git a/apps/page/customer-rd/src/lib/customer-page.component.css b/apps/page/customer-rd/src/lib/customer-page.component.css
new file mode 100644
index 000000000..e69de29bb
diff --git a/apps/page/customer-rd/src/lib/customer-page.component.html b/apps/page/customer-rd/src/lib/customer-page.component.html
new file mode 100644
index 000000000..bcd6c94f7
--- /dev/null
+++ b/apps/page/customer-rd/src/lib/customer-page.component.html
@@ -0,0 +1,3 @@
+
+
+
diff --git a/apps/page/customer-rd/src/lib/customer-page.component.ts b/apps/page/customer-rd/src/lib/customer-page.component.ts
new file mode 100644
index 000000000..c6896e578
--- /dev/null
+++ b/apps/page/customer-rd/src/lib/customer-page.component.ts
@@ -0,0 +1,15 @@
+import { Component, ChangeDetectionStrategy } from '@angular/core';
+import { ActivatedRoute } from '@angular/router';
+import { map } from 'rxjs/operators';
+
+@Component({
+ selector: 'page-customer',
+ templateUrl: 'customer-page.component.html',
+ styleUrls: ['customer-page.component.css'],
+ changeDetection: ChangeDetectionStrategy.OnPush,
+})
+export class CustomerComponent {
+ processId$ = this._activatedRoute.data.pipe(map((data) => data.processId));
+
+ constructor(private _activatedRoute: ActivatedRoute) {}
+}
diff --git a/apps/page/customer-rd/src/lib/customer-page.module.ts b/apps/page/customer-rd/src/lib/customer-page.module.ts
new file mode 100644
index 000000000..2f28557b1
--- /dev/null
+++ b/apps/page/customer-rd/src/lib/customer-page.module.ts
@@ -0,0 +1,16 @@
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+
+import { CustomerComponent } from './customer-page.component';
+import { RouterModule } from '@angular/router';
+import { routes } from './routes';
+
+import { BreadcrumbModule } from '@shared/components/breadcrumb';
+import { CustomerSearchModule } from './customer-search/customer-search.module';
+
+@NgModule({
+ imports: [CommonModule, RouterModule.forChild(routes), BreadcrumbModule, CustomerSearchModule],
+ exports: [CustomerComponent],
+ declarations: [CustomerComponent],
+})
+export class CustomerModule {}
diff --git a/apps/page/customer-rd/src/lib/customer-search/customer-search.component.css b/apps/page/customer-rd/src/lib/customer-search/customer-search.component.css
new file mode 100644
index 000000000..e69de29bb
diff --git a/apps/page/customer-rd/src/lib/customer-search/customer-search.component.html b/apps/page/customer-rd/src/lib/customer-search/customer-search.component.html
new file mode 100644
index 000000000..f92b32e70
--- /dev/null
+++ b/apps/page/customer-rd/src/lib/customer-search/customer-search.component.html
@@ -0,0 +1,8 @@
+
diff --git a/apps/page/customer-rd/src/lib/customer-search/customer-search.component.ts b/apps/page/customer-rd/src/lib/customer-search/customer-search.component.ts
new file mode 100644
index 000000000..ac08d69b6
--- /dev/null
+++ b/apps/page/customer-rd/src/lib/customer-search/customer-search.component.ts
@@ -0,0 +1,108 @@
+import { Component, ChangeDetectionStrategy, OnInit, OnDestroy } from '@angular/core';
+import { ActivatedRoute, NavigationEnd, Router } from '@angular/router';
+import { combineLatest, BehaviorSubject, Subscription } from 'rxjs';
+import { map } from 'rxjs/operators';
+import { BreakpointObserver } from '@angular/cdk/layout';
+import { CustomerSearchStore } from './store/customer-search.store';
+
+@Component({
+ selector: 'page-customer-search',
+ templateUrl: 'customer-search.component.html',
+ styleUrls: ['customer-search.component.css'],
+ changeDetection: ChangeDetectionStrategy.OnPush,
+ providers: [CustomerSearchStore],
+})
+export class CustomerSearchComponent implements OnInit, OnDestroy {
+ isTablet$ = this._breakpointObserver.observe('(max-width: 1024px)').pipe(map((result) => result.matches));
+
+ side$ = new BehaviorSubject(undefined);
+
+ get side() {
+ return this.side$.value;
+ }
+
+ showSide$ = combineLatest([this.isTablet$, this.side$]).pipe(map(([isTablet, side]) => !isTablet && side));
+
+ hideSide$ = this.showSide$.pipe(map((showSide) => !showSide));
+
+ get snapshot() {
+ return this._activatedRoute.snapshot;
+ }
+
+ get parentSnapshot() {
+ return this._activatedRoute.parent?.snapshot;
+ }
+
+ get firstChildSnapshot() {
+ return this._activatedRoute.firstChild?.snapshot;
+ }
+
+ private _eventsSubscription: Subscription;
+
+ constructor(
+ private _store: CustomerSearchStore,
+ private _activatedRoute: ActivatedRoute,
+ private _breakpointObserver: BreakpointObserver,
+ private _router: Router
+ ) {}
+
+ ngOnInit(): void {
+ this.checkAndUpdateProcessId();
+ this.checkAndUpdateSide();
+ this.checkAndUpdateCustomerId();
+
+ this._eventsSubscription = this._router.events.subscribe((event) => {
+ if (event instanceof NavigationEnd) {
+ this.checkAndUpdateProcessId();
+ this.checkAndUpdateSide();
+ this.checkAndUpdateCustomerId();
+ }
+ });
+ }
+
+ ngOnDestroy(): void {
+ this._eventsSubscription.unsubscribe();
+ }
+
+ checkAndUpdateProcessId() {
+ let processId: number;
+
+ processId = this.snapshot.data?.processId;
+
+ if (!processId) {
+ processId = this.parentSnapshot?.data?.processId;
+ }
+
+ if (processId !== this._store.processId) {
+ this._store.setProcessId(processId);
+ }
+ }
+
+ checkAndUpdateSide() {
+ let side: string;
+
+ side = this.snapshot.data?.side;
+
+ if (!side) {
+ side = this.firstChildSnapshot.data?.side;
+ }
+
+ if (side !== this.side) {
+ this.side$.next(side);
+ }
+ }
+
+ checkAndUpdateCustomerId() {
+ let customerId: number;
+
+ customerId = this.snapshot.params.customerId;
+
+ if (!customerId) {
+ customerId = this.firstChildSnapshot?.params.customerId;
+ }
+
+ if (customerId !== this._store.customer?.id) {
+ this._store.selectCustomer(customerId);
+ }
+ }
+}
diff --git a/apps/page/customer-rd/src/lib/customer-search/customer-search.module.ts b/apps/page/customer-rd/src/lib/customer-search/customer-search.module.ts
new file mode 100644
index 000000000..01100453d
--- /dev/null
+++ b/apps/page/customer-rd/src/lib/customer-search/customer-search.module.ts
@@ -0,0 +1,23 @@
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+
+import { CustomerSearchComponent } from './customer-search.component';
+import { CustomerResultsSideViewModule } from './results-side-view/results-side-view.module';
+import { RouterModule } from '@angular/router';
+import { CustomerResultsMainViewModule } from './results-main-view/results-main-view.module';
+import { CustomerDetailsViewMainModule } from './details-main-view/details-main-view.module';
+import { CustomerHistoryMainViewModule } from './history-main-view/history-main-view.module';
+
+@NgModule({
+ imports: [
+ CommonModule,
+ RouterModule,
+ CustomerResultsSideViewModule,
+ CustomerResultsMainViewModule,
+ CustomerDetailsViewMainModule,
+ CustomerHistoryMainViewModule,
+ ],
+ exports: [CustomerSearchComponent],
+ declarations: [CustomerSearchComponent],
+})
+export class CustomerSearchModule {}
diff --git a/apps/page/customer-rd/src/lib/customer-search/details-main-view/details-main-view.component.css b/apps/page/customer-rd/src/lib/customer-search/details-main-view/details-main-view.component.css
new file mode 100644
index 000000000..50099add9
--- /dev/null
+++ b/apps/page/customer-rd/src/lib/customer-search/details-main-view/details-main-view.component.css
@@ -0,0 +1,19 @@
+:host {
+ @apply block bg-surface text-surface-content rounded-[0.313rem] mb-3;
+}
+
+.data-label {
+ @apply w-[10.75rem];
+}
+
+.data-value {
+ @apply grow font-bold;
+}
+
+.customer-details-customer-main-row {
+ @apply px-5 py-3 bg-surface text-surface-content border-t-2 border-solid border-surface-2 flex flex-row items-center;
+}
+
+.customer-details-customer-main-row .data-label {
+ @apply w-[6.875rem];
+}
diff --git a/apps/page/customer-rd/src/lib/customer-search/details-main-view/details-main-view.component.html b/apps/page/customer-rd/src/lib/customer-search/details-main-view/details-main-view.component.html
new file mode 100644
index 000000000..fa3bea865
--- /dev/null
+++ b/apps/page/customer-rd/src/lib/customer-search/details-main-view/details-main-view.component.html
@@ -0,0 +1,92 @@
+
+
+
+
+
+
{{ customerType$ | async }}
+
+
+
+
+
+
Erstellungsdatum
+
{{ created$ | async | date: 'dd.MM.yyyy' }} | {{ created$ | async | date: 'hh:mm' }} Uhr
+
+
+
Kundennummer
+
{{ customerNumber$ | async }}
+
+
+
Kundennummer-DIG
+
{{ customerNumberDig }}
+
+
+
+
Anrede
+
{{ gender$ | async }}
+
+
+
Titel
+
{{ title$ | async }}
+
+
+
Nachname
+
{{ lastName$ | async }}
+
+
+
Vorname
+
{{ firstName$ | async }}
+
+
+
E-Mail
+
{{ email$ | async }}
+
+
+
Straße
+
{{ street$ | async }}
+
+
+
Hausnr.
+
{{ streetNumber$ | async }}
+
+
+
PLZ
+
{{ zipCode$ | async }}
+
+
+
Ort
+
{{ city$ | async }}
+
+
+
Adresszusatz
+
{{ info$ | async }}
+
+
+
Land
+
{{ country$ | async | country }}
+
+
+
Festnetznr.
+
{{ landline$ | async }}
+
+
+
Mobilnr.
+
{{ mobile$ | async }}
+
+
+
Abteilung
+
{{ department$ | async }}
+
+
+
USt-ID
+
{{ vatId$ | async }}
+
+
diff --git a/apps/page/customer-rd/src/lib/customer-search/details-main-view/details-main-view.component.ts b/apps/page/customer-rd/src/lib/customer-search/details-main-view/details-main-view.component.ts
new file mode 100644
index 000000000..b0dc83ad8
--- /dev/null
+++ b/apps/page/customer-rd/src/lib/customer-search/details-main-view/details-main-view.component.ts
@@ -0,0 +1,68 @@
+import { Component, ChangeDetectionStrategy } from '@angular/core';
+import { combineLatest } from 'rxjs';
+import { map } from 'rxjs/operators';
+import { CustomerSearchNavigation } from '../../navigations';
+import { CustomerSearchStore } from '../store';
+
+const GENDER_MAP = {
+ 2: 'Herr',
+ 4: 'Frau',
+};
+
+@Component({
+ selector: 'page-customer-details-main-view',
+ templateUrl: 'details-main-view.component.html',
+ styleUrls: ['details-main-view.component.css'],
+ changeDetection: ChangeDetectionStrategy.OnPush,
+})
+export class CustomerDetailsViewMainComponent {
+ fetching$ = this._store.fetchingCustomer$;
+
+ processId$ = this._store.processId$;
+
+ customerId$ = this._store.customerId$;
+
+ historyRoute$ = combineLatest([this.processId$, this.customerId$]).pipe(
+ map(([processId, customerId]) => this._navigation.historyRoute({ processId, customerId }))
+ );
+
+ customerType$ = this._store.select((s) => s.customer?.features?.find((f) => f.enabled)?.description);
+
+ created$ = this._store.select((s) => s.customer?.created);
+
+ customerNumber$ = this._store.select((s) => s.customer?.customerNumber);
+
+ customerNumberDig$ = this._store.select((s) => s.customer?.linkedRecords?.find((r) => r.repository === 'dig')?.number);
+
+ gender$ = this._store.select((s) => GENDER_MAP[s.customer?.gender]);
+
+ title$ = this._store.select((s) => s.customer?.title);
+
+ lastName$ = this._store.select((s) => s.customer?.lastName);
+
+ firstName$ = this._store.select((s) => s.customer?.firstName);
+
+ email$ = this._store.select((s) => s.customer?.communicationDetails?.email);
+
+ street$ = this._store.select((s) => s.customer?.address?.street);
+
+ streetNumber$ = this._store.select((s) => s.customer?.address?.streetNumber);
+
+ zipCode$ = this._store.select((s) => s.customer?.address?.zipCode);
+
+ city$ = this._store.select((s) => s.customer?.address?.city);
+
+ country$ = this._store.select((s) => s.customer?.address?.country);
+
+ info$ = this._store.select((s) => s.customer?.address?.info);
+
+ landline$ = this._store.select((s) => s.customer?.communicationDetails?.phone);
+
+ mobile$ = this._store.select((s) => s.customer?.communicationDetails?.mobile);
+
+ department$ = this._store.select((s) => s.customer?.organisation?.department);
+
+ vatId$ = this._store.select((s) => s.customer?.organisation?.vatId);
+
+ constructor(private _store: CustomerSearchStore, private _navigation: CustomerSearchNavigation) {}
+}
diff --git a/apps/page/customer-rd/src/lib/customer-search/details-main-view/details-main-view.module.ts b/apps/page/customer-rd/src/lib/customer-search/details-main-view/details-main-view.module.ts
new file mode 100644
index 000000000..580afb4aa
--- /dev/null
+++ b/apps/page/customer-rd/src/lib/customer-search/details-main-view/details-main-view.module.ts
@@ -0,0 +1,13 @@
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+
+import { CustomerDetailsViewMainComponent } from './details-main-view.component';
+import { CountryPipe } from '@shared/pipes/country';
+import { RouterModule } from '@angular/router';
+
+@NgModule({
+ imports: [CommonModule, CountryPipe, RouterModule],
+ exports: [CustomerDetailsViewMainComponent],
+ declarations: [CustomerDetailsViewMainComponent],
+})
+export class CustomerDetailsViewMainModule {}
diff --git a/apps/page/customer-rd/src/lib/customer-search/edit-main-view/edit-main-view.component.css b/apps/page/customer-rd/src/lib/customer-search/edit-main-view/edit-main-view.component.css
new file mode 100644
index 000000000..e69de29bb
diff --git a/apps/page/customer-rd/src/lib/customer-search/edit-main-view/edit-main-view.component.html b/apps/page/customer-rd/src/lib/customer-search/edit-main-view/edit-main-view.component.html
new file mode 100644
index 000000000..e69de29bb
diff --git a/apps/page/customer-rd/src/lib/customer-search/edit-main-view/edit-main-view.component.ts b/apps/page/customer-rd/src/lib/customer-search/edit-main-view/edit-main-view.component.ts
new file mode 100644
index 000000000..e69de29bb
diff --git a/apps/page/customer-rd/src/lib/customer-search/edit-main-view/edit-main-view.module.ts b/apps/page/customer-rd/src/lib/customer-search/edit-main-view/edit-main-view.module.ts
new file mode 100644
index 000000000..e69de29bb
diff --git a/apps/page/customer-rd/src/lib/customer-search/history-main-view/history-main-view.component.css b/apps/page/customer-rd/src/lib/customer-search/history-main-view/history-main-view.component.css
new file mode 100644
index 000000000..40fca449b
--- /dev/null
+++ b/apps/page/customer-rd/src/lib/customer-search/history-main-view/history-main-view.component.css
@@ -0,0 +1,7 @@
+:host {
+ @apply block bg-surface text-surface-content rounded-[0.313rem] mb-3;
+}
+
+::ng-deep page-customer-history-main-view shared-history-list .scroll-container {
+ @apply h-[calc(100vh-24rem)];
+}
diff --git a/apps/page/customer-rd/src/lib/customer-search/history-main-view/history-main-view.component.html b/apps/page/customer-rd/src/lib/customer-search/history-main-view/history-main-view.component.html
new file mode 100644
index 000000000..c6d91affb
--- /dev/null
+++ b/apps/page/customer-rd/src/lib/customer-search/history-main-view/history-main-view.component.html
@@ -0,0 +1,29 @@
+
+
+
+
+
diff --git a/apps/page/customer-rd/src/lib/customer-search/history-main-view/history-main-view.component.ts b/apps/page/customer-rd/src/lib/customer-search/history-main-view/history-main-view.component.ts
new file mode 100644
index 000000000..8c9ef4eb0
--- /dev/null
+++ b/apps/page/customer-rd/src/lib/customer-search/history-main-view/history-main-view.component.ts
@@ -0,0 +1,76 @@
+import { coerceNumberProperty } from '@angular/cdk/coercion';
+import { Component, ChangeDetectionStrategy, AfterViewInit } from '@angular/core';
+import { ActivatedRoute } from '@angular/router';
+import { CrmCustomerService } from '@domain/crm';
+import { ComponentStore, tapResponse } from '@ngrx/component-store';
+import { HistoryDTO } from '@swagger/crm';
+import { Observable, combineLatest } from 'rxjs';
+import { map, switchMap, tap } from 'rxjs/operators';
+import { CustomerSearchStore } from '../store';
+import { CustomerSearchNavigation } from '../../navigations';
+
+export interface CustomerHistoryViewMainState {
+ history?: HistoryDTO[];
+ fetching?: boolean;
+}
+
+@Component({
+ selector: 'page-customer-history-main-view',
+ templateUrl: 'history-main-view.component.html',
+ styleUrls: ['history-main-view.component.css'],
+ changeDetection: ChangeDetectionStrategy.OnPush,
+})
+export class CustomerHistoryMainViewComponent extends ComponentStore implements AfterViewInit {
+ fetching$ = this.select((s) => s.fetching);
+
+ history$ = this.select((s) => s.history);
+
+ processId$ = this._store.processId$;
+
+ customerId$ = this._store.customerId$;
+
+ customer$ = this._store.customer$;
+
+ detailsRoute$ = combineLatest([this.processId$, this.customerId$]).pipe(
+ map(([processId, customerId]) => this._navigation.detailsRoute({ processId, customerId }))
+ );
+
+ customerName$ = this.customer$.pipe(map((customer) => `${customer?.lastName}, ${customer?.firstName}`));
+
+ customerNumber$ = this.customer$.pipe(map((customer) => customer?.customerNumber));
+
+ constructor(
+ private _store: CustomerSearchStore,
+ private _customerService: CrmCustomerService,
+ private _navigation: CustomerSearchNavigation
+ ) {
+ super({});
+ }
+
+ ngAfterViewInit(): void {
+ this.fetchHistory(this.customerId$);
+ }
+
+ fetchHistory = this.effect((customerId$: Observable) =>
+ customerId$.pipe(
+ tap(() => this.patchState({ fetching: true })),
+ switchMap((customerId) =>
+ this._customerService
+ .getCustomerHistory(customerId)
+ .pipe(tapResponse(this.handleFetchHistoryResponse, this.handleFetchHistoryError, this.handleFetchHistoryComplete))
+ )
+ )
+ );
+
+ handleFetchHistoryResponse = (history: HistoryDTO[]) => {
+ this.patchState({ history });
+ };
+
+ handleFetchHistoryError = (err: any) => {
+ console.error(err);
+ };
+
+ handleFetchHistoryComplete = () => {
+ this.patchState({ fetching: false });
+ };
+}
diff --git a/apps/page/customer-rd/src/lib/customer-search/history-main-view/history-main-view.module.ts b/apps/page/customer-rd/src/lib/customer-search/history-main-view/history-main-view.module.ts
new file mode 100644
index 000000000..3b742c0c8
--- /dev/null
+++ b/apps/page/customer-rd/src/lib/customer-search/history-main-view/history-main-view.module.ts
@@ -0,0 +1,14 @@
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { SharedHistoryListModule } from '@shared/components/history';
+
+import { CustomerHistoryMainViewComponent } from './history-main-view.component';
+import { UiIconModule } from '@ui/icon';
+import { RouterModule } from '@angular/router';
+
+@NgModule({
+ imports: [CommonModule, RouterModule, SharedHistoryListModule, UiIconModule],
+ exports: [CustomerHistoryMainViewComponent],
+ declarations: [CustomerHistoryMainViewComponent],
+})
+export class CustomerHistoryMainViewModule {}
diff --git a/apps/page/customer-rd/src/lib/customer-search/orders-main-view/orders-main-view.component.css b/apps/page/customer-rd/src/lib/customer-search/orders-main-view/orders-main-view.component.css
new file mode 100644
index 000000000..e69de29bb
diff --git a/apps/page/customer-rd/src/lib/customer-search/orders-main-view/orders-main-view.component.html b/apps/page/customer-rd/src/lib/customer-search/orders-main-view/orders-main-view.component.html
new file mode 100644
index 000000000..e69de29bb
diff --git a/apps/page/customer-rd/src/lib/customer-search/orders-main-view/orders-main-view.component.ts b/apps/page/customer-rd/src/lib/customer-search/orders-main-view/orders-main-view.component.ts
new file mode 100644
index 000000000..e69de29bb
diff --git a/apps/page/customer-rd/src/lib/customer-search/orders-main-view/orders-main-view.module.ts b/apps/page/customer-rd/src/lib/customer-search/orders-main-view/orders-main-view.module.ts
new file mode 100644
index 000000000..e69de29bb
diff --git a/apps/page/customer-rd/src/lib/customer-search/results-main-view/results-main-view.component.css b/apps/page/customer-rd/src/lib/customer-search/results-main-view/results-main-view.component.css
new file mode 100644
index 000000000..e69de29bb
diff --git a/apps/page/customer-rd/src/lib/customer-search/results-main-view/results-main-view.component.html b/apps/page/customer-rd/src/lib/customer-search/results-main-view/results-main-view.component.html
new file mode 100644
index 000000000..cd5a62cd2
--- /dev/null
+++ b/apps/page/customer-rd/src/lib/customer-search/results-main-view/results-main-view.component.html
@@ -0,0 +1 @@
+
diff --git a/apps/page/customer-rd/src/lib/customer-search/results-main-view/results-main-view.component.ts b/apps/page/customer-rd/src/lib/customer-search/results-main-view/results-main-view.component.ts
new file mode 100644
index 000000000..7ef4c4389
--- /dev/null
+++ b/apps/page/customer-rd/src/lib/customer-search/results-main-view/results-main-view.component.ts
@@ -0,0 +1,17 @@
+import { NumberInput } from '@angular/cdk/coercion';
+import { Component, ChangeDetectionStrategy, Input } from '@angular/core';
+import { Router } from '@angular/router';
+import { CustomerInfoDTO } from '@swagger/crm';
+import { CustomerSearchStore } from '../store/customer-search.store';
+
+@Component({
+ selector: 'page-customer-results-main-view',
+ templateUrl: 'results-main-view.component.html',
+ styleUrls: ['results-main-view.component.css'],
+ changeDetection: ChangeDetectionStrategy.OnPush,
+})
+export class CustomerResultsMainViewComponent {
+ processId$ = this._store.processId$;
+
+ constructor(private _store: CustomerSearchStore) {}
+}
diff --git a/apps/page/customer-rd/src/lib/customer-search/results-main-view/results-main-view.module.ts b/apps/page/customer-rd/src/lib/customer-search/results-main-view/results-main-view.module.ts
new file mode 100644
index 000000000..a2865bd19
--- /dev/null
+++ b/apps/page/customer-rd/src/lib/customer-search/results-main-view/results-main-view.module.ts
@@ -0,0 +1,12 @@
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+
+import { CustomerResultsMainViewComponent } from './results-main-view.component';
+import { CustomerResultListModule } from '../../components/customer-result-list/customer-result-list.module';
+
+@NgModule({
+ imports: [CommonModule, CustomerResultListModule],
+ exports: [CustomerResultsMainViewComponent],
+ declarations: [CustomerResultsMainViewComponent],
+})
+export class CustomerResultsMainViewModule {}
diff --git a/apps/page/customer-rd/src/lib/customer-search/results-side-view/results-side-view.component.css b/apps/page/customer-rd/src/lib/customer-search/results-side-view/results-side-view.component.css
new file mode 100644
index 000000000..e69de29bb
diff --git a/apps/page/customer-rd/src/lib/customer-search/results-side-view/results-side-view.component.html b/apps/page/customer-rd/src/lib/customer-search/results-side-view/results-side-view.component.html
new file mode 100644
index 000000000..7730cfdea
--- /dev/null
+++ b/apps/page/customer-rd/src/lib/customer-search/results-side-view/results-side-view.component.html
@@ -0,0 +1 @@
+
diff --git a/apps/page/customer-rd/src/lib/customer-search/results-side-view/results-side-view.component.ts b/apps/page/customer-rd/src/lib/customer-search/results-side-view/results-side-view.component.ts
new file mode 100644
index 000000000..e75608295
--- /dev/null
+++ b/apps/page/customer-rd/src/lib/customer-search/results-side-view/results-side-view.component.ts
@@ -0,0 +1,17 @@
+import { NumberInput } from '@angular/cdk/coercion';
+import { Component, ChangeDetectionStrategy, Input } from '@angular/core';
+import { Router } from '@angular/router';
+import { CustomerInfoDTO } from '@swagger/crm';
+import { CustomerSearchStore } from '../store/customer-search.store';
+
+@Component({
+ selector: 'page-customer-results-side-view',
+ templateUrl: 'results-side-view.component.html',
+ styleUrls: ['results-side-view.component.css'],
+ changeDetection: ChangeDetectionStrategy.OnPush,
+})
+export class CustomerResultsSideViewComponent {
+ processId$ = this._store.processId$;
+
+ constructor(private _store: CustomerSearchStore) {}
+}
diff --git a/apps/page/customer-rd/src/lib/customer-search/results-side-view/results-side-view.module.ts b/apps/page/customer-rd/src/lib/customer-search/results-side-view/results-side-view.module.ts
new file mode 100644
index 000000000..f30b52ab9
--- /dev/null
+++ b/apps/page/customer-rd/src/lib/customer-search/results-side-view/results-side-view.module.ts
@@ -0,0 +1,12 @@
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+
+import { CustomerResultsSideViewComponent } from './results-side-view.component';
+import { CustomerResultListModule } from '../../components/customer-result-list/customer-result-list.module';
+
+@NgModule({
+ imports: [CommonModule, CustomerResultListModule],
+ exports: [CustomerResultsSideViewComponent],
+ declarations: [CustomerResultsSideViewComponent],
+})
+export class CustomerResultsSideViewModule {}
diff --git a/apps/page/customer-rd/src/lib/customer-search/store/customer-search.state.ts b/apps/page/customer-rd/src/lib/customer-search/store/customer-search.state.ts
new file mode 100644
index 000000000..4e4beac35
--- /dev/null
+++ b/apps/page/customer-rd/src/lib/customer-search/store/customer-search.state.ts
@@ -0,0 +1,7 @@
+import { CustomerDTO } from '@swagger/crm';
+
+export interface CustomerSearchState {
+ processId?: number;
+ customer?: CustomerDTO;
+ fetchingCustomer?: boolean;
+}
diff --git a/apps/page/customer-rd/src/lib/customer-search/store/customer-search.store.ts b/apps/page/customer-rd/src/lib/customer-search/store/customer-search.store.ts
new file mode 100644
index 000000000..2190edb92
--- /dev/null
+++ b/apps/page/customer-rd/src/lib/customer-search/store/customer-search.store.ts
@@ -0,0 +1,66 @@
+import { ComponentStore, tapResponse } from '@ngrx/component-store';
+import { CustomerSearchState } from './customer-search.state';
+import * as S from './selectors';
+import { Injectable } from '@angular/core';
+import { Observable } from 'rxjs';
+import { distinctUntilChanged, switchMap, tap } from 'rxjs/operators';
+import { CrmCustomerService } from '@domain/crm';
+import { Result } from '@domain/defs';
+import { CustomerDTO } from '@swagger/crm';
+
+@Injectable()
+export class CustomerSearchStore extends ComponentStore {
+ get processId() {
+ return this.get(S.selectProcessId);
+ }
+
+ processId$ = this.select(S.selectProcessId);
+
+ get fetchingCustomer() {
+ return this.get(S.selectFetchingCustomer);
+ }
+
+ fetchingCustomer$ = this.select(S.selectFetchingCustomer);
+
+ get customerId() {
+ return this.get(S.selectCustomerId);
+ }
+
+ customerId$ = this.select(S.selectCustomerId);
+
+ get customer() {
+ return this.get(S.selectCustomer);
+ }
+
+ customer$ = this.select(S.selectCustomer);
+
+ constructor(private _customerService: CrmCustomerService) {
+ super({});
+ }
+
+ setProcessId = this.updater((state, processId: number) => ({ ...state, processId }));
+
+ selectCustomer = this.effect((customerId$: Observable) =>
+ customerId$.pipe(
+ distinctUntilChanged(),
+ tap((custoemrId) => this.patchState({ fetchingCustomer: true, customer: { id: custoemrId } })),
+ switchMap((customerId) =>
+ this._customerService
+ .getCustomer(customerId)
+ .pipe(tapResponse(this.handleSelectCustomerResponse, this.handleSelectCustomerError, this.handleSelectCustomerComplete))
+ )
+ )
+ );
+
+ handleSelectCustomerResponse = (result: Result) => {
+ this.patchState({ customer: result.result });
+ };
+
+ handleSelectCustomerError = (err: any) => {
+ console.error(err);
+ };
+
+ handleSelectCustomerComplete = () => {
+ this.patchState({ fetchingCustomer: false });
+ };
+}
diff --git a/apps/page/customer-rd/src/lib/customer-search/store/index.ts b/apps/page/customer-rd/src/lib/customer-search/store/index.ts
new file mode 100644
index 000000000..322a84ecf
--- /dev/null
+++ b/apps/page/customer-rd/src/lib/customer-search/store/index.ts
@@ -0,0 +1,3 @@
+export * from './customer-search.state';
+export * from './customer-search.store';
+export * from './selectors';
diff --git a/apps/page/customer-rd/src/lib/customer-search/store/selectors.ts b/apps/page/customer-rd/src/lib/customer-search/store/selectors.ts
new file mode 100644
index 000000000..b9a48347a
--- /dev/null
+++ b/apps/page/customer-rd/src/lib/customer-search/store/selectors.ts
@@ -0,0 +1,18 @@
+import { coerceNumberProperty } from '@angular/cdk/coercion';
+import { CustomerSearchState } from './customer-search.state';
+
+export function selectProcessId(s: CustomerSearchState): number {
+ return coerceNumberProperty(s.processId);
+}
+
+export function selectFetchingCustomer(s: CustomerSearchState) {
+ return s.fetchingCustomer;
+}
+
+export function selectCustomer(s: CustomerSearchState) {
+ return s.customer;
+}
+
+export function selectCustomerId(s: CustomerSearchState) {
+ return selectCustomer(s)?.id;
+}
diff --git a/apps/page/customer-rd/src/lib/navigations/customer-search.navigation.ts b/apps/page/customer-rd/src/lib/navigations/customer-search.navigation.ts
new file mode 100644
index 000000000..bf8b86bc9
--- /dev/null
+++ b/apps/page/customer-rd/src/lib/navigations/customer-search.navigation.ts
@@ -0,0 +1,24 @@
+import { NumberInput, coerceNumberProperty } from '@angular/cdk/coercion';
+import { Injectable } from '@angular/core';
+import { Router } from '@angular/router';
+
+@Injectable({ providedIn: 'root' })
+export class CustomerSearchNavigation {
+ constructor(private _router: Router) {}
+
+ detailsRoute(params: { processId: NumberInput; customerId: NumberInput }): any[] {
+ return ['/kunde', coerceNumberProperty(params.processId), 'customer', coerceNumberProperty(params.customerId)];
+ }
+
+ navigateToDetails(params: { processId: NumberInput; customerId: NumberInput }): Promise {
+ return this._router.navigate(this.detailsRoute(params));
+ }
+
+ historyRoute(params: { processId: NumberInput; customerId: NumberInput }): any[] {
+ return ['/kunde', coerceNumberProperty(params.processId), 'customer', coerceNumberProperty(params.customerId), 'history'];
+ }
+
+ navigateToHistory(params: { processId: NumberInput; customerId: NumberInput }): Promise {
+ return this._router.navigate(this.historyRoute(params));
+ }
+}
diff --git a/apps/page/customer-rd/src/lib/navigations/index.ts b/apps/page/customer-rd/src/lib/navigations/index.ts
new file mode 100644
index 000000000..e882f74a0
--- /dev/null
+++ b/apps/page/customer-rd/src/lib/navigations/index.ts
@@ -0,0 +1 @@
+export * from './customer-search.navigation';
diff --git a/apps/page/customer-rd/src/lib/routes.ts b/apps/page/customer-rd/src/lib/routes.ts
new file mode 100644
index 000000000..44f8f1952
--- /dev/null
+++ b/apps/page/customer-rd/src/lib/routes.ts
@@ -0,0 +1,26 @@
+import { Routes } from '@angular/router';
+import { CustomerComponent } from './customer-page.component';
+import { CustomerSearchComponent } from './customer-search/customer-search.component';
+import { CustomerResultsMainViewComponent } from './customer-search/results-main-view/results-main-view.component';
+import { CustomerDetailsViewMainComponent } from './customer-search/details-main-view/details-main-view.component';
+import { CustomerHistoryMainViewComponent } from './customer-search/history-main-view/history-main-view.component';
+
+export const routes: Routes = [
+ {
+ path: '',
+ component: CustomerComponent,
+ children: [
+ {
+ path: '',
+ component: CustomerSearchComponent,
+ children: [
+ { path: '', component: CustomerResultsMainViewComponent },
+ { path: ':customerId', component: CustomerDetailsViewMainComponent, data: { side: 'results' } },
+ { path: ':customerId/history', component: CustomerHistoryMainViewComponent, data: { side: 'results' } },
+ // { path: ':customerId/edit', component: CustomerSearchComponent, data: { side: 'results' } },
+ // { path: ':customerId/orders', component: CustomerSearchComponent, data: { side: 'orderItems' } },
+ ],
+ },
+ ],
+ },
+];
diff --git a/apps/page/customer-rd/src/public-api.ts b/apps/page/customer-rd/src/public-api.ts
new file mode 100644
index 000000000..713192e63
--- /dev/null
+++ b/apps/page/customer-rd/src/public-api.ts
@@ -0,0 +1,2 @@
+export * from './lib/customer-page.module';
+export * from './lib/customer-page.component';
diff --git a/apps/shared/components/searchbox/ng-package.json b/apps/shared/components/searchbox/ng-package.json
new file mode 100644
index 000000000..baed78b32
--- /dev/null
+++ b/apps/shared/components/searchbox/ng-package.json
@@ -0,0 +1,6 @@
+{
+ "$schema": "../../../../node_modules/ng-packagr/ng-package.schema.json",
+ "lib": {
+ "entryFile": "src/public-api.ts"
+ }
+ }
\ No newline at end of file
diff --git a/apps/shared/components/searchbox/src/lib/autocomplete-source.ts b/apps/shared/components/searchbox/src/lib/autocomplete-source.ts
new file mode 100644
index 000000000..a14f361ae
--- /dev/null
+++ b/apps/shared/components/searchbox/src/lib/autocomplete-source.ts
@@ -0,0 +1,5 @@
+import { Observable } from 'rxjs';
+
+export interface AutocompleteSource {
+ complete(searchText: string): T[] | Promise | Observable;
+}
diff --git a/apps/shared/components/searchbox/src/lib/searchbox-input.directive.ts b/apps/shared/components/searchbox/src/lib/searchbox-input.directive.ts
new file mode 100644
index 000000000..972531474
--- /dev/null
+++ b/apps/shared/components/searchbox/src/lib/searchbox-input.directive.ts
@@ -0,0 +1,75 @@
+import { Directive, EventEmitter, HostBinding, HostListener, Input, Output } from '@angular/core';
+import { ControlValueAccessor } from '@angular/forms';
+import { BehaviorSubject } from 'rxjs';
+
+@Directive({ selector: 'input[type=text][sharedSearchboxInput]' })
+export class SearchboxInputDirective implements ControlValueAccessor {
+ value$ = new BehaviorSubject('');
+
+ @Input()
+ @HostBinding('value')
+ value: string = '';
+
+ @Output()
+ valueChange = new EventEmitter();
+
+ @Input()
+ @HostBinding('disabled')
+ disabled: boolean;
+
+ onChange = (_: string) => {};
+
+ onTouched = () => {};
+
+ onSearch = () => {};
+
+ constructor() {}
+
+ writeValue(obj: any): void {
+ this.value = obj ?? '';
+ this.value$.next(this.value);
+ }
+
+ registerOnChange(fn: any): void {
+ this.onChange = fn;
+ }
+
+ registerOnTouched(fn: any): void {
+ this.onChange = fn;
+ }
+
+ regsiterOnSearch(fn: any): void {
+ this.onSearch = fn;
+ }
+
+ setDisabledState?(isDisabled: boolean): void {
+ this.disabled = isDisabled;
+ }
+
+ @HostListener('input', ['$event.target.value'])
+ onInput(value: string) {
+ this.value = value;
+ this.value$.next(value);
+ this.valueChange.emit(value);
+ this.onChange(value);
+ this.onTouched();
+ }
+
+ @HostListener('blur')
+ onBlur() {
+ this.onTouched();
+ }
+
+ clear() {
+ this.value = '';
+ this.value$.next('');
+ this.valueChange.emit('');
+ this.onChange('');
+ this.onTouched();
+ }
+
+ @HostListener('keydown.enter')
+ onEnter() {
+ this.onSearch();
+ }
+}
diff --git a/apps/shared/components/searchbox/src/lib/searchbox.component.css b/apps/shared/components/searchbox/src/lib/searchbox.component.css
new file mode 100644
index 000000000..0e1692dc0
--- /dev/null
+++ b/apps/shared/components/searchbox/src/lib/searchbox.component.css
@@ -0,0 +1,19 @@
+.shared-searchbox {
+ @apply inline-block;
+}
+
+.shared-searchbox-input-wrapper {
+ @apply bg-surface text-surface-content flex flex-row items-center rounded-button;
+}
+
+input[sharedSearchboxInput] {
+ @apply bg-transparent text-surface-content text-lg font-bold h-12 px-4 outline-transparent grow;
+}
+
+.shared-searchbox-input-clear {
+ @apply text-surface-content h-12 w-12 outline-transparent inline-grid justify-center items-center grow-0;
+}
+
+.shared-searchbox-input-search {
+ @apply text-white h-12 w-12 outline-transparent inline-grid justify-center items-center bg-brand rounded-button grow-0;
+}
diff --git a/apps/shared/components/searchbox/src/lib/searchbox.component.html b/apps/shared/components/searchbox/src/lib/searchbox.component.html
new file mode 100644
index 000000000..acdff98b7
--- /dev/null
+++ b/apps/shared/components/searchbox/src/lib/searchbox.component.html
@@ -0,0 +1,15 @@
+
+
+
+
+
+
diff --git a/apps/shared/components/searchbox/src/lib/searchbox.component.ts b/apps/shared/components/searchbox/src/lib/searchbox.component.ts
new file mode 100644
index 000000000..0b0898933
--- /dev/null
+++ b/apps/shared/components/searchbox/src/lib/searchbox.component.ts
@@ -0,0 +1,39 @@
+import {
+ Component,
+ ChangeDetectionStrategy,
+ Output,
+ EventEmitter,
+ ViewEncapsulation,
+ ContentChild,
+ AfterContentInit,
+ Input,
+} from '@angular/core';
+import { SearchboxInputDirective } from './searchbox-input.directive';
+import { AutocompleteSource } from './autocomplete-source';
+
+@Component({
+ selector: 'shared-searchbox',
+ templateUrl: 'searchbox.component.html',
+ styleUrls: ['searchbox.component.css'],
+ changeDetection: ChangeDetectionStrategy.OnPush,
+ encapsulation: ViewEncapsulation.None,
+ host: {
+ class: 'shared-searchbox',
+ },
+})
+export class SearchboxComponent implements AfterContentInit {
+ @Output()
+ search = new EventEmitter();
+
+ @ContentChild(SearchboxInputDirective, { static: true })
+ input: SearchboxInputDirective;
+
+ @Input()
+ autocompleteSource: AutocompleteSource;
+
+ constructor() {}
+
+ ngAfterContentInit(): void {
+ this.input.regsiterOnSearch((value) => this.search.emit(value));
+ }
+}
diff --git a/apps/shared/components/searchbox/src/lib/searchbox.module.ts b/apps/shared/components/searchbox/src/lib/searchbox.module.ts
new file mode 100644
index 000000000..faca3e8f4
--- /dev/null
+++ b/apps/shared/components/searchbox/src/lib/searchbox.module.ts
@@ -0,0 +1,13 @@
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+
+import { SearchboxComponent } from './searchbox.component';
+import { SearchboxInputDirective } from './searchbox-input.directive';
+import { UiIconModule } from '@ui/icon';
+
+@NgModule({
+ imports: [CommonModule, UiIconModule],
+ exports: [SearchboxComponent, SearchboxInputDirective],
+ declarations: [SearchboxComponent, SearchboxInputDirective],
+})
+export class SearchboxModule {}
diff --git a/apps/shared/components/searchbox/src/public-api.ts b/apps/shared/components/searchbox/src/public-api.ts
new file mode 100644
index 000000000..458f01dd7
--- /dev/null
+++ b/apps/shared/components/searchbox/src/public-api.ts
@@ -0,0 +1,2 @@
+export * from './lib/searchbox.component';
+export * from './lib/searchbox.module';
diff --git a/apps/shared/pipes/country/ng-package.json b/apps/shared/pipes/country/ng-package.json
new file mode 100644
index 000000000..5b6ba62cc
--- /dev/null
+++ b/apps/shared/pipes/country/ng-package.json
@@ -0,0 +1,6 @@
+{
+ "$schema": "../../../../node_modules/ng-packagr/ng-package.schema.json",
+ "lib": {
+ "entryFile": "src/public-api.ts"
+ }
+}
\ No newline at end of file
diff --git a/apps/shared/pipes/country/src/lib/country.pipe.ts b/apps/shared/pipes/country/src/lib/country.pipe.ts
new file mode 100644
index 000000000..e92f27850
--- /dev/null
+++ b/apps/shared/pipes/country/src/lib/country.pipe.ts
@@ -0,0 +1,40 @@
+import { ChangeDetectorRef, OnDestroy, Pipe, PipeTransform } from '@angular/core';
+import { CrmCustomerService } from '@domain/crm';
+import { BehaviorSubject, combineLatest } from 'rxjs';
+import { map } from 'rxjs/operators';
+
+@Pipe({
+ name: 'country',
+ standalone: true,
+ pure: false,
+})
+export class CountryPipe implements PipeTransform, OnDestroy {
+ private result: string;
+ private value$ = new BehaviorSubject(undefined);
+
+ countries$ = this.customerService.getCountries().pipe(map((res) => res.result));
+
+ subscriptions = combineLatest([this.value$, this.countries$]).subscribe(([value, countries]) => {
+ if (!!value && countries?.length > 0) {
+ const country = countries.find((c) => c.isO3166_A_3 === value);
+
+ if (country && this.result !== country.name) {
+ this.result = String(country.name);
+ this.cdr.markForCheck();
+ }
+ }
+ });
+
+ constructor(private customerService: CrmCustomerService, private cdr: ChangeDetectorRef) {}
+
+ ngOnDestroy() {
+ this.subscriptions.unsubscribe();
+ }
+
+ transform(value: string): any {
+ if (this.value$.value !== value) {
+ this.value$.next(value);
+ }
+ return this.result;
+ }
+}
diff --git a/apps/shared/pipes/country/src/public-api.ts b/apps/shared/pipes/country/src/public-api.ts
new file mode 100644
index 000000000..d9a830d37
--- /dev/null
+++ b/apps/shared/pipes/country/src/public-api.ts
@@ -0,0 +1 @@
+export * from './lib/country.pipe';
diff --git a/apps/shared/shell/src/lib/shell.component.html b/apps/shared/shell/src/lib/shell.component.html
index dc7ac21f0..7c2239e50 100644
--- a/apps/shared/shell/src/lib/shell.component.html
+++ b/apps/shared/shell/src/lib/shell.component.html
@@ -4,6 +4,6 @@
[class.translate-x-0]="sideMenuOpen$ | async"
>
-
+
diff --git a/tailwind-plugins/button.plugin.js b/tailwind-plugins/button.plugin.js
index ca9a671a3..b2dbeca9b 100644
--- a/tailwind-plugins/button.plugin.js
+++ b/tailwind-plugins/button.plugin.js
@@ -23,6 +23,11 @@ module.exports = plugin(function ({ addComponents, theme, addBase, addUtilities
'--btn-background-color': theme('colors.button.light.DEFAULT'),
'--btn-color': theme('colors.button.light.content'),
},
+ '.btn-label': {
+ '--btn-background-color': 'transparent',
+ '--btn-hover-background-color': 'transparent',
+ '--btn-hover-color': 'inherit',
+ },
});
for (const key in theme('colors.accent')) {
diff --git a/tailwind.config.js b/tailwind.config.js
index de237f5c1..2ff852b58 100644
--- a/tailwind.config.js
+++ b/tailwind.config.js
@@ -97,12 +97,16 @@ module.exports = {
'accent-darkblue': '#557596',
background: {
- DEFAULT: '#F5F5F5',
+ DEFAULT: '#EDEFF0',
content: '#000000',
},
surface: {
DEFAULT: '#ffffff',
content: '#000000',
+ 2: {
+ DEFAULT: '#F5F7FA',
+ content: '#000000',
+ },
},
components: {
menu: {
@@ -170,6 +174,7 @@ module.exports = {
card: '0px -2px 24px 0px rgba(220, 226, 233, 0.8)',
cta: '0px 0px 15px 0px rgba(0, 0, 0, 0.5)',
action: '0 0 20px 0 #596470',
+ s: '0px 6px 24px rgba(206, 212, 219, 0.8)',
},
borderRadius: {
button: '5px',