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 @@ +
+
+ + + + +
+ + + xxx Treffer + +
+ + + + + + + + + + + + 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 @@ + + + +
+
+ Historie +
+
+

Kundendetails

+

Sind Ihre Kundendaten korrekt?

+
+
+
+
{{ 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 @@ + + + +
+
+
+ + + +
+
+

Historie

+
+
+
+
Kundenname
+
{{ customerName$ | async }}
+
+
+
Kundennummer
+
{{ customerNumber$ | async }}
+
+
+
+
+ +
+
+
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',