Updated Breadcrumb for Kundensuche

This commit is contained in:
Lorenz Hilpert
2023-05-12 13:10:00 +02:00
parent a8bfedcd5d
commit d2c307b08a
29 changed files with 570 additions and 55 deletions

View File

@@ -11,6 +11,47 @@
@import './scss/customer';
@import './scss/branch';
.par-select-list {
@apply z-dropdown;
}
:root {
--par-base: #ffffff;
--par-base-content: #000000;
--par-primary-300: #324bc9;
--par-primary-200: #324bc9;
--par-primary-100: #d3d8f4; /*NEU*/
--par-subtle-300: #596470;
--par-subtle-200: #aeb7c1;
--par-subtle-100: #edeff0;
--par-subtle-50: #f5f7fa;
--par-disabled-content: #aeb7c1;
--par-disabled: #ebeaef; /*??*/
--par-error-content: #f70400;
--par-error: #ffc5c4; /*NEU*/
--par-success-content: #26830c;
--par-success: #d2fac7; /*NEU*/
--par-warning-content: #be8100;
--par-warning: #ffcc01; /*heller: #ffeb9a*/
--par-secondary-300: #1f466c; /*für tooltips*/
--par-secondary-200: #0556b4; /*für links */
/* --par-secondary-100: #0556B4; */
--par-tertiary-300: #d52a5d;
--par-tertiary-200: #f70400;
/*--par-tertiary-100: #f7d4df; /*selbst generiert*/
--par-random-1: #f66131;
--par-random-2: #008079;
--par-border-radius-input: 0.3125rem; /*5px*/
--par-border-radius-button: 0.3125rem; /*5px*/
--par-border-radius-checkbox: 0.3125rem; /*5px*/
--par-shadow-input: 0px 0px 4px 2.5px;
--par-shadow-button: 0px 0px 4px 2.5px;
--par-font-family: 'Open Sans';
}
* {
@apply font-sans;
}

View File

@@ -1,7 +1,8 @@
import { Component, ChangeDetectionStrategy } from '@angular/core';
import { UntypedFormControl, UntypedFormGroup, Validators } from '@angular/forms';
import { UntypedFormControl, UntypedFormGroup } from '@angular/forms';
import { FormBlockGroup } from '../form-block';
import { NameFormBlockData } from './name-form-block-data';
import { Gender } from '@swagger/crm';
@Component({
selector: 'app-name-form-block',
@@ -14,6 +15,17 @@ export class NameFormBlockComponent extends FormBlockGroup<NameFormBlockData> {
return this.tabIndexStart + 3;
}
displayGenderNameFn = (gender: Gender) => {
if (gender == 2) {
return 'Herr';
}
if (gender == 4) {
return 'Frau';
}
return undefined;
};
constructor() {
super();
}

View File

@@ -7,7 +7,6 @@ import { UiFormControlModule } from '@ui/form-control';
import { UiInputModule } from '@ui/input';
import { ReactiveFormsModule } from '@angular/forms';
import { UiCommonModule } from '@ui/common';
@NgModule({
imports: [CommonModule, UiCommonModule, ReactiveFormsModule, UiFormControlModule, UiSelectModule, UiInputModule],
exports: [NameFormBlockComponent],

View File

@@ -0,0 +1,3 @@
export * from './side-template.directive';
export * from './split-screen.component';
export * from './split-screen.module';

View File

@@ -0,0 +1,9 @@
import { Directive, Input, TemplateRef } from '@angular/core';
@Directive({ selector: '[sideTemplate]', standalone: true })
export class SideTemplateDirective {
@Input()
sideTemplate: string = 'default';
constructor(public readonly templateRef: TemplateRef<any>) {}
}

View File

@@ -0,0 +1,3 @@
:host {
@apply grid grid-cols-[27.5rem_auto] gap-6;
}

View File

@@ -0,0 +1,6 @@
<div *ngIf="hasSide">
<ng-container *ngTemplateOutlet="sideTemplate?.templateRef"></ng-container>
</div>
<div [class.col-span-2]="!hasSide" class="overflow-y-scroll">
<ng-content></ng-content>
</div>

View File

@@ -0,0 +1,99 @@
import { BreakpointObserver } from '@angular/cdk/layout';
import { CommonModule } from '@angular/common';
import {
Component,
ChangeDetectionStrategy,
Input,
ContentChildren,
QueryList,
AfterContentInit,
ChangeDetectorRef,
OnDestroy,
} from '@angular/core';
import { BehaviorSubject, Subject } from 'rxjs';
import { map, takeUntil } from 'rxjs/operators';
import { SideTemplateDirective } from './side-template.directive';
import { EnvironmentService } from '@core/environment';
@Component({
selector: 'page-split-screen',
templateUrl: 'split-screen.component.html',
styleUrls: ['split-screen.component.css'],
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: true,
imports: [CommonModule],
})
export class SplitScreenComponent implements AfterContentInit, OnDestroy {
static OBSERVED_BREAKPOINTS = ['(max-width: 1024px)'];
isTablet$ = this._breakpointObserver.observe(SplitScreenComponent.OBSERVED_BREAKPOINTS).pipe(map((result) => result.matches));
private _isTablet = false;
get isTablet() {
return this._isTablet;
}
set isTablet(value: boolean) {
this._isTablet = value;
}
side$ = new BehaviorSubject<string>('default');
@Input()
get side() {
return this.side$.value;
}
set side(value: string) {
this.side$.next(value ?? 'default');
}
get hasSide() {
return !!this.sideTemplate;
}
@ContentChildren(SideTemplateDirective)
sideTemplates: QueryList<SideTemplateDirective>;
sideTemplate: SideTemplateDirective | undefined;
private _onDestroy$ = new Subject<void>();
constructor(private _breakpointObserver: BreakpointObserver, private _cdr: ChangeDetectorRef, private _envService: EnvironmentService) {}
ngAfterContentInit(): void {
this.sideTemplates.changes.pipe(takeUntil(this._onDestroy$)).subscribe(() => {
this.checkAndUpdateSide();
});
this.side$.pipe(takeUntil(this._onDestroy$)).subscribe(() => {
this.checkAndUpdateSide();
});
this.isTablet$.pipe(takeUntil(this._onDestroy$)).subscribe((isTablet) => {
this.isTablet = isTablet;
this.checkAndUpdateSide();
});
}
ngOnDestroy(): void {
this._onDestroy$.next();
this._onDestroy$.complete();
}
private checkAndUpdateSide() {
if (this.isTablet) {
this.sideTemplate = undefined;
this._cdr.markForCheck();
return;
}
const sideTemplate = this.sideTemplates.find((sideTemplate) => sideTemplate.sideTemplate === this.side);
if (sideTemplate !== this.sideTemplate) {
this.sideTemplate = sideTemplate;
this._cdr.markForCheck();
} else if (!sideTemplate) {
this.sideTemplate = undefined;
this._cdr.markForCheck();
}
}
}

View File

@@ -0,0 +1,10 @@
import { NgModule } from '@angular/core';
import { SplitScreenComponent } from './split-screen.component';
import { SideTemplateDirective } from './side-template.directive';
@NgModule({
imports: [SplitScreenComponent, SideTemplateDirective],
exports: [SplitScreenComponent, SideTemplateDirective],
})
export class SplitScreenModule {}

View File

@@ -0,0 +1,4 @@
<page-split-screen class="max-h-[calc(100vh-13.875rem)] h-[calc(100vh-13.875rem)]">
<page-customer-create-side-view [processId]="processId$ | async" *sideTemplate></page-customer-create-side-view>
<router-outlet></router-outlet>
</page-split-screen>

View File

@@ -0,0 +1,20 @@
import { CommonModule } from '@angular/common';
import { Component, ChangeDetectionStrategy } from '@angular/core';
import { ActivatedRoute, RouterModule } from '@angular/router';
import { SplitScreenModule } from '../components/split-screen';
import { CustomerCreateSideViewModule } from './customer-create-side-view';
import { map } from 'rxjs/operators';
@Component({
selector: 'page-create-customer',
templateUrl: 'create-customer.component.html',
styleUrls: ['create-customer.component.css'],
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: true,
imports: [CommonModule, RouterModule, SplitScreenModule, CustomerCreateSideViewModule],
})
export class CreateCustomerComponent {
processId$ = this._activatedRoute.parent.data.pipe(map((data) => data.processId));
constructor(private _activatedRoute: ActivatedRoute) {}
}

View File

@@ -5,6 +5,7 @@ import { CreateP4MCustomerModule } from './create-p4m-customer';
import { CreateStoreCustomerModule } from './create-store-customer/create-store-customer.module';
import { CreateWebshopCustomerModule } from './create-webshop-customer/create-webshop-customer.module';
import { UpdateP4MWebshopCustomerModule } from './update-p4m-webshop-customer';
import { CreateCustomerComponent } from './create-customer.component';
@NgModule({
imports: [
@@ -14,6 +15,7 @@ import { UpdateP4MWebshopCustomerModule } from './update-p4m-webshop-customer';
CreateWebshopCustomerModule,
CreateP4MCustomerModule,
UpdateP4MWebshopCustomerModule,
CreateCustomerComponent,
],
exports: [
CreateB2BCustomerModule,
@@ -22,6 +24,7 @@ import { UpdateP4MWebshopCustomerModule } from './update-p4m-webshop-customer';
CreateWebshopCustomerModule,
CreateP4MCustomerModule,
UpdateP4MWebshopCustomerModule,
CreateCustomerComponent,
],
})
export class CreateCustomerModule {}

View File

@@ -19,7 +19,7 @@ form {
}
button.cta-submit {
@apply fixed left-1/2 bottom-28 text-center bg-brand text-cta-l text-white font-bold px-7 py-3 rounded-full transform -translate-x-1/2 transition-all duration-200 ease-in-out;
@apply sticky left-1/2 bottom-8 text-center bg-brand text-cta-l text-white font-bold px-7 py-3 rounded-full transform -translate-x-1/2 transition-all duration-200 ease-in-out;
&:disabled {
@apply bg-active-branch cursor-not-allowed;

View File

@@ -0,0 +1,7 @@
:host {
@apply bg-surface text-surface-content rounded-card flex flex-col h-full;
}
.side-view-shadow {
box-shadow: 0px -2px 24px rgba(220, 226, 233, 0.8);
}

View File

@@ -0,0 +1,12 @@
<a
[routerLink]="customerSearchNavigation.path"
[queryParams]="customerSearchNavigation.queryParams"
class="text-[1.375rem] font-bold text-[#596470] text-center py-4"
>Kundensuche</a
>
<div class="text-center pt-10 px-8 rounded-card side-view-shadow grow">
<h1 class="text-[1.625rem] font-bold">Kundendaten erfassen</h1>
<p class="text-lg mt-2">
Wir legen Ihnen gerne ein Onlinekonto an, dort können Sie Ihre Bestellungen einsehen.
</p>
</div>

View File

@@ -0,0 +1,23 @@
import { CommonModule } from '@angular/common';
import { Component, ChangeDetectionStrategy, Input } from '@angular/core';
import { RouterModule } from '@angular/router';
import { CustomerSearchNavigation } from '../../navigations';
@Component({
selector: 'page-customer-create-side-view',
templateUrl: 'customer-create-side-view.component.html',
styleUrls: ['customer-create-side-view.component.css'],
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: true,
imports: [CommonModule, RouterModule],
})
export class CustomerCreateSideViewComponent {
@Input()
processId: string | undefined;
get customerSearchNavigation() {
return this.searchNavigation.defaultRoute({ processId: this.processId });
}
constructor(public readonly searchNavigation: CustomerSearchNavigation) {}
}

View File

@@ -0,0 +1,8 @@
import { NgModule } from '@angular/core';
import { CustomerCreateSideViewComponent } from './customer-create-side-view.component';
@NgModule({
imports: [CustomerCreateSideViewComponent],
exports: [CustomerCreateSideViewComponent],
})
export class CustomerCreateSideViewModule {}

View File

@@ -0,0 +1,2 @@
export * from './customer-create-side-view.component';
export * from './customer-create-side-view.module';

View File

@@ -1,8 +1,4 @@
<div class="grid grid-cols-[27.5rem_auto] max-h-[calc(100vh-13.875rem)] h-[calc(100vh-13.875rem)] gap-6">
<div *ngIf="showSide$ | async" [ngSwitch]="side$ | async">
<page-customer-results-side-view *ngSwitchCase="'results'"></page-customer-results-side-view>
</div>
<div [class.col-span-2]="hideSide$ | async" class="overflow-y-scroll">
<router-outlet></router-outlet>
</div>
</div>
<page-split-screen class="max-h-[calc(100vh-13.875rem)] h-[calc(100vh-13.875rem)]" [side]="side$ | async">
<page-customer-results-side-view *sideTemplate="'results'"></page-customer-results-side-view>
<router-outlet></router-outlet>
</page-split-screen>

View File

@@ -1,10 +1,11 @@
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 { BehaviorSubject, Subscription } from 'rxjs';
import { CustomerSearchStore } from './store/customer-search.store';
import { provideComponentStore } from '@ngrx/component-store';
import { Breadcrumb, BreadcrumbService } from '@core/breadcrumb';
import { filter, first, switchMap } from 'rxjs/operators';
import { CustomerSearchNavigation } from '../navigations';
@Component({
selector: 'page-customer-search',
@@ -14,7 +15,11 @@ import { provideComponentStore } from '@ngrx/component-store';
providers: [provideComponentStore(CustomerSearchStore)],
})
export class CustomerSearchComponent implements OnInit, OnDestroy {
isTablet$ = this._breakpointObserver.observe('(max-width: 1024px)').pipe(map((result) => result.matches));
private _breadcrumb: string | undefined;
private _breadcrumbs$ = this._store.processId$.pipe(
filter((id) => !!id),
switchMap((id) => this._breadcrumbService.getBreadcrumbsByKeyAndTag$(id, 'customer'))
);
side$ = new BehaviorSubject<string | undefined>(undefined);
@@ -22,10 +27,6 @@ export class CustomerSearchComponent implements OnInit, OnDestroy {
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;
}
@@ -40,29 +41,40 @@ export class CustomerSearchComponent implements OnInit, OnDestroy {
private _eventsSubscription: Subscription;
private _customerChangedSubscription: Subscription;
constructor(
private _store: CustomerSearchStore,
private _activatedRoute: ActivatedRoute,
private _breakpointObserver: BreakpointObserver,
private _router: Router
private _router: Router,
private _breadcrumbService: BreadcrumbService,
private _navigation: CustomerSearchNavigation
) {}
ngOnInit(): void {
this.checkAndUpdateProcessId();
this.checkAndUpdateSide();
this.checkAndUpdateCustomerId();
this.checkBreadcrumbs();
this._customerChangedSubscription = this._store.customer$.subscribe((c) => {
this.checkDetailsBreadcrumb();
});
this._eventsSubscription = this._router.events.subscribe((event) => {
if (event instanceof NavigationEnd) {
this.checkAndUpdateProcessId();
this.checkAndUpdateSide();
this.checkAndUpdateCustomerId();
this.checkBreadcrumbs();
}
});
}
ngOnDestroy(): void {
this._eventsSubscription.unsubscribe();
this._customerChangedSubscription.unsubscribe();
this.side$.complete();
}
checkAndUpdateProcessId() {
@@ -106,4 +118,115 @@ export class CustomerSearchComponent implements OnInit, OnDestroy {
this._store.selectCustomer(customerId);
}
}
async checkBreadcrumbs() {
let breadcumb: string;
breadcumb = this.snapshot.data?.breadcumb;
if (!breadcumb) {
breadcumb = this.firstChildSnapshot.data?.breadcumb;
}
if (breadcumb !== this._breadcrumb) {
this._breadcrumb = breadcumb;
await this.checkMainBreadcrumb();
await this.checkDetailsBreadcrumb();
await this.checkHistoryBreadcrumb();
}
}
getBreadcrumbs(): Promise<Breadcrumb[]> {
return this._breadcrumbs$.pipe(first()).toPromise();
}
async getMainBreadcrumb(): Promise<Breadcrumb | undefined> {
const breadcrumbs = await this.getBreadcrumbs();
return breadcrumbs.find((b) => b.tags.includes('main'));
}
async checkMainBreadcrumb() {
const mainBreadcrumb = await this.getMainBreadcrumb();
if (!mainBreadcrumb) {
const navigation = this._navigation.defaultRoute({ processId: this._store.processId });
const breadcrumb: Breadcrumb = {
key: this._store.processId,
tags: ['customer', 'main'],
name: 'Kundensuche',
path: navigation.urlTree.toString(),
params: navigation.queryParams,
section: 'customer',
};
this._breadcrumbService.addBreadcrumb(breadcrumb);
}
}
async getDetailsBreadcrumb(): Promise<Breadcrumb | undefined> {
const breadcrumbs = await this.getBreadcrumbs();
return breadcrumbs.find((b) => b.tags.includes('details'));
}
async checkDetailsBreadcrumb() {
const detailsBreadcrumb = await this.getDetailsBreadcrumb();
if (['details', 'history'].includes(this._breadcrumb)) {
const customer = this._store.customer;
const fullName = `${customer?.firstName ?? ''} ${customer?.lastName ?? ''}`.trim();
if (!detailsBreadcrumb) {
const navigation = this._navigation.detailsRoute({ processId: this._store.processId, customerId: this._store.customerId });
const breadcrumb: Breadcrumb = {
key: this._store.processId,
tags: ['customer', 'details'],
name: fullName || 'Kunde',
path: navigation.urlTree.toString(),
params: navigation.queryParams,
section: 'customer',
};
this._breadcrumbService.addBreadcrumb(breadcrumb);
} else if (!!fullName) {
const navigation = this._navigation.detailsRoute({ processId: this._store.processId, customerId: this._store.customerId });
this._breadcrumbService.patchBreadcrumb(detailsBreadcrumb.id, {
name: fullName,
path: navigation.urlTree.toString(),
params: navigation.queryParams,
});
}
} else if (detailsBreadcrumb) {
this._breadcrumbService.removeBreadcrumb(detailsBreadcrumb.id);
}
}
async getHistoryBreadcrumb(): Promise<Breadcrumb | undefined> {
const breadcrumbs = await this.getBreadcrumbs();
return breadcrumbs.find((b) => b.tags.includes('history'));
}
async checkHistoryBreadcrumb() {
const historyBreadcrumb = await this.getHistoryBreadcrumb();
if (this._breadcrumb === 'history') {
if (!historyBreadcrumb) {
const navigation = this._navigation.historyRoute({ processId: this._store.processId, customerId: this._store.customerId });
const breadcrumb: Breadcrumb = {
key: this._store.processId,
tags: ['customer', 'history'],
name: 'Historie',
path: navigation.urlTree.toString(),
params: navigation.queryParams,
section: 'customer',
};
this._breadcrumbService.addBreadcrumb(breadcrumb);
}
} else if (historyBreadcrumb) {
this._breadcrumbService.removeBreadcrumb(historyBreadcrumb.id);
}
}
}

View File

@@ -8,11 +8,13 @@ import { CustomerResultsMainViewModule } from './results-main-view/results-main-
import { CustomerDetailsMainViewModule } from './details-main-view/details-main-view.module';
import { CustomerHistoryMainViewModule } from './history-main-view/history-main-view.module';
import { CustomerFilterMainViewModule } from './filter-main-view/filter-main-view.module';
import { SplitScreenModule } from '../components/split-screen/split-screen.module';
@NgModule({
imports: [
CommonModule,
RouterModule,
SplitScreenModule,
CustomerResultsSideViewModule,
CustomerResultsMainViewModule,
CustomerDetailsMainViewModule,

View File

@@ -71,8 +71,8 @@ export class CustomerSearchStore extends ComponentStore<CustomerSearchState> imp
)
);
handleSelectCustomerResponse = (result: Result<CustomerDTO>) => {
this.patchState({ customer: result.result });
handleSelectCustomerResponse = ({ result }: Result<CustomerDTO>) => {
this.patchState({ customer: result });
};
handleSelectCustomerError = (err: any) => {

View File

@@ -1,10 +1,11 @@
import { NumberInput, coerceNumberProperty } from '@angular/cdk/coercion';
import { Injectable } from '@angular/core';
import { NavigationExtras, Params, Router } from '@angular/router';
import { NavigationExtras, Params, Router, UrlTree } from '@angular/router';
export interface NavigationRoute {
path: any[];
queryParams?: Params;
urlTree: UrlTree;
}
@Injectable({ providedIn: 'root' })
@@ -12,8 +13,13 @@ export class CustomerSearchNavigation {
constructor(private _router: Router) {}
defaultRoute(params: { processId: NumberInput }): NavigationRoute {
const path = ['/kunde', coerceNumberProperty(params.processId), 'customer'];
const urlTree = this._router.createUrlTree(path, { queryParams: {} });
return {
path: ['/kunde', coerceNumberProperty(params.processId)],
path,
urlTree,
};
}
@@ -23,8 +29,13 @@ export class CustomerSearchNavigation {
}
detailsRoute(params: { processId: NumberInput; customerId: NumberInput }): NavigationRoute {
const path = ['/kunde', coerceNumberProperty(params.processId), 'customer', coerceNumberProperty(params.customerId)];
const urlTree = this._router.createUrlTree(path, { queryParams: {} });
return {
path: ['/kunde', coerceNumberProperty(params.processId), 'customer', coerceNumberProperty(params.customerId)],
path,
urlTree,
};
}
@@ -34,8 +45,13 @@ export class CustomerSearchNavigation {
}
historyRoute(params: { processId: NumberInput; customerId: NumberInput }): NavigationRoute {
const path = ['/kunde', coerceNumberProperty(params.processId), 'customer', coerceNumberProperty(params.customerId), 'history'];
const urlTree = this._router.createUrlTree(path, { queryParams: {} });
return {
path: ['/kunde', coerceNumberProperty(params.processId), 'customer', coerceNumberProperty(params.customerId), 'history'],
path,
urlTree,
};
}
@@ -45,11 +61,14 @@ export class CustomerSearchNavigation {
}
filterRoute(params: { processId: NumberInput; comingFrom?: string }): NavigationRoute {
const path = ['/kunde', coerceNumberProperty(params.processId), 'customer', 'filter'];
const urlTree = this._router.createUrlTree(path, { queryParams: { comingFrom: params.comingFrom } });
return {
path: ['/kunde', coerceNumberProperty(params.processId), 'customer', 'filter'],
queryParams: {
comingFrom: params.comingFrom,
},
path,
queryParams: urlTree.queryParams,
urlTree,
};
}

View File

@@ -14,34 +14,36 @@ import {
CreateWebshopCustomerComponent,
} from './create-customer';
import { UpdateP4MWebshopCustomerComponent } from './create-customer/update-p4m-webshop-customer';
import { CreateCustomerComponent } from './create-customer/create-customer.component';
export const routes: Routes = [
{
path: '',
component: CustomerComponent,
children: [
{
path: 'create',
component: CreateCustomerComponent,
canActivate: [CustomerCreateGuard],
canActivateChild: [CustomerCreateGuard],
children: [
{ path: 'store', component: CreateStoreCustomerComponent },
{ path: 'webshop', component: CreateWebshopCustomerComponent },
{ path: 'b2b', component: CreateB2BCustomerComponent },
{ path: 'guest', component: CreateGuestCustomerComponent },
{ path: 'webshop-p4m', component: CreateP4MCustomerComponent, data: { customerType: 'webshop' } },
{ path: 'store-p4m', component: CreateP4MCustomerComponent, data: { customerType: 'store' } },
{ path: 'webshop-p4m/update', component: UpdateP4MWebshopCustomerComponent, data: { customerType: 'webshop' } },
],
},
{
path: '',
component: CustomerSearchComponent,
children: [
{
path: 'create',
canActivate: [CustomerCreateGuard],
canActivateChild: [CustomerCreateGuard],
children: [
{ path: 'store', component: CreateStoreCustomerComponent },
{ path: 'webshop', component: CreateWebshopCustomerComponent },
{ path: 'b2b', component: CreateB2BCustomerComponent },
{ path: 'guest', component: CreateGuestCustomerComponent },
{ path: 'webshop-p4m', component: CreateP4MCustomerComponent, data: { customerType: 'webshop' } },
{ path: 'store-p4m', component: CreateP4MCustomerComponent, data: { customerType: 'store' } },
{ path: 'webshop-p4m/update', component: UpdateP4MWebshopCustomerComponent, data: { customerType: 'webshop' } },
],
},
{ path: '', component: CustomerResultsMainViewComponent },
{ path: 'filter', component: CustomerFilterMainViewComponent, data: { side: 'results' } },
{ path: ':customerId', component: CustomerDetailsViewMainComponent, data: { side: 'results' } },
{ path: ':customerId/history', component: CustomerHistoryMainViewComponent, data: { side: 'results' } },
{ path: '', component: CustomerResultsMainViewComponent, data: { breadcumb: 'main' } },
{ path: 'filter', component: CustomerFilterMainViewComponent, data: { side: 'results', breadcumb: 'main' } },
{ path: ':customerId', component: CustomerDetailsViewMainComponent, data: { side: 'results', breadcumb: 'details' } },
{ path: ':customerId/history', component: CustomerHistoryMainViewComponent, data: { side: 'results', breadcumb: 'history' } },
// { path: ':customerId/edit', component: CustomerSearchComponent, data: { side: 'results' } },
// { path: ':customerId/orders', component: CustomerSearchComponent, data: { side: 'orderItems' } },
],

34
package-lock.json generated
View File

@@ -26,7 +26,7 @@
"@ngrx/entity": "^15.0.0",
"@ngrx/store": "^15.0.0",
"@ngrx/store-devtools": "^15.0.0",
"@paragondata/ngx-ui": "^12.0.0-beta.23",
"@paragondata/ngx-ui": "^12.0.0-beta.91",
"angular-oauth2-oidc": "^15.0.1",
"angular-oauth2-oidc-jwks": "^15.0.1",
"core-js": "^2.6.5",
@@ -93,6 +93,19 @@
"npm": "8.x"
}
},
"../../@paragondata/ngx-ui/dist/paragondata/ngx-ui": {
"name": "@paragondata/ngx-ui",
"version": "0.0.0-watch+1683643023778",
"extraneous": true,
"dependencies": {
"tslib": "^2.3.0"
},
"peerDependencies": {
"@angular/cdk": ">= 13.0.0 < 16.0.0",
"@angular/common": ">= 13.0.0 < 16.0.0",
"@angular/core": ">= 13.0.0 < 16.0.0"
}
},
"node_modules/@ampproject/remapping": {
"version": "2.2.0",
"license": "Apache-2.0",
@@ -2710,7 +2723,17 @@
}
},
"node_modules/@paragondata/ngx-ui": {
"version": "12.0.0-beta.25"
"version": "12.0.0-beta.91",
"resolved": "https://npm.pkg.github.com/download/@paragondata/ngx-ui/12.0.0-beta.91/18864a278241d4874fc1ab1e41b8d43330721ffb",
"integrity": "sha512-Ran2ZOw7tNhSJwaBJPDUwGwxfC/bpaVrUum+Hn7Q/RfIuC3PUmFSJkBaZdAL4eyOASIWD6ZrmNxb2qcVCo7ctA==",
"dependencies": {
"tslib": "^2.3.0"
},
"peerDependencies": {
"@angular/cdk": ">= 13.0.0 < 16.0.0",
"@angular/common": ">= 13.0.0 < 16.0.0",
"@angular/core": ">= 13.0.0 < 16.0.0"
}
},
"node_modules/@rollup/plugin-json": {
"version": "5.0.2",
@@ -18023,7 +18046,12 @@
}
},
"@paragondata/ngx-ui": {
"version": "12.0.0-beta.25"
"version": "12.0.0-beta.91",
"resolved": "https://npm.pkg.github.com/download/@paragondata/ngx-ui/12.0.0-beta.91/18864a278241d4874fc1ab1e41b8d43330721ffb",
"integrity": "sha512-Ran2ZOw7tNhSJwaBJPDUwGwxfC/bpaVrUum+Hn7Q/RfIuC3PUmFSJkBaZdAL4eyOASIWD6ZrmNxb2qcVCo7ctA==",
"requires": {
"tslib": "^2.3.0"
}
},
"@rollup/plugin-json": {
"version": "5.0.2",

View File

@@ -80,7 +80,7 @@
"@ngrx/entity": "^15.0.0",
"@ngrx/store": "^15.0.0",
"@ngrx/store-devtools": "^15.0.0",
"@paragondata/ngx-ui": "^12.0.0-beta.23",
"@paragondata/ngx-ui": "^12.0.0-beta.91",
"angular-oauth2-oidc": "^15.0.1",
"angular-oauth2-oidc-jwks": "^15.0.1",
"core-js": "^2.6.5",
@@ -146,4 +146,4 @@
"node": "18.x",
"npm": "8.x"
}
}
}

81
paragon-preset.js Normal file
View File

@@ -0,0 +1,81 @@
//the preset extends the default tailwind config
const defaultTheme = require('tailwindcss/defaultTheme');
module.exports = {
theme: {
extend: {
colors: {
base: {
content: 'var(--par-base-content)',
DEFAULT: 'var(--par-base)',
},
primary: {
300: 'var(--par-primary-300)',
200: 'var(--par-primary-200)',
100: 'var(--par-primary-100)',
},
subtle: {
300: 'var(--par-subtle-300)',
200: 'var(--par-subtle-200)',
100: 'var(--par-subtle-100)',
50: 'var(--par-subtle-50)',
},
disabled: {
content: 'var(--par-disabled-content)',
DEFAULT: 'var(--par-disabled)',
},
error: {
content: 'var(--par-error-content)',
DEFAULT: 'var(--par-error)',
},
success: {
content: 'var(--par-success-content)',
DEFAULT: 'var(--par-success)',
},
warning: {
content: 'var(--par-warning-content)',
DEFAULT: 'var(--par-warning)',
},
secondary: {
300: 'var(--par-secondary-300)',
200: 'var(--par-secondary-200)',
100: 'var(--par-secondary-100)',
},
tertiary: {
300: 'var(--par-tertiary-300)',
200: 'var(--par-tertiary-200)',
100: 'var(--par-tertiary-100)',
},
random: {
1: 'var(--par-random-1)',
2: 'var(--par-random-2)',
},
},
boxShadow: {
input: 'var( --par-shadow-input)',
button: 'var( --par-shadow-button)',
},
spacing: {
'radio-check': '19px',
'radio-ring': '4px',
input: '3.25rem',
inputButton: '3rem',
inputPaddingButton: '64px',
},
borderWidth: {
medium: '1.5px',
},
borderRadius: {
checkbox: 'var(--par-border-radius-checkbox)',
input: 'var(--par-border-radius-input)',
button: 'var(--par-border-radius-button)',
},
scale: {
'98': '98%',
},
fontFamily: {
sans: ['var(--par-font-family)', ...defaultTheme.fontFamily.sans],
},
},
},
};

View File

@@ -1,6 +1,6 @@
/** @type {import('tailwindcss').Config} */
module.exports = {
content: ['./apps/**/*.{html,ts}'],
content: ['./apps/**/*.{html,ts,css,scss}'],
darkMode: 'media', // or 'media' or 'class'
theme: {
screens: {
@@ -194,5 +194,8 @@ module.exports = {
require('./tailwind-plugins/menu.plugin.js'),
require('./tailwind-plugins/select-bullet.plugin.js'),
require('./tailwind-plugins/section.plugin.js'),
require('@paragondata/ngx-ui/tailwind'),
],
safelist: [{ pattern: /par-.*/ }],
presets: [require('./paragon-preset.js')],
};