mirror of
https://dev.azure.com/hugendubel/ISA/_git/ISA-Frontend
synced 2025-12-31 09:37:15 +01:00
#665 Customize Searchbar for Desktop
This commit is contained in:
@@ -28,7 +28,7 @@
|
||||
<button
|
||||
*ngSwitchDefault
|
||||
class="isa-input-submit"
|
||||
[class.scan]="!errorMessage && !(searchQuery$ | async)"
|
||||
[class.scan]="!errorMessage && !(searchQuery$ | async) && isIPad"
|
||||
type="submit"
|
||||
(click)="triggerSearch()"
|
||||
></button>
|
||||
|
||||
@@ -7,16 +7,12 @@ import {
|
||||
EventEmitter,
|
||||
ChangeDetectionStrategy,
|
||||
} from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
import { Store } from '@ngxs/store';
|
||||
import { Process } from 'apps/sales/src/app/core/models/process.model';
|
||||
import { AddProcess } from 'apps/sales/src/app/core/store/actions/process.actions';
|
||||
import { AddBreadcrumb } from 'apps/sales/src/app/core/store/actions/breadcrumb.actions';
|
||||
import { Breadcrumb } from 'apps/sales/src/app/core/models/breadcrumb.model';
|
||||
import { CollectingShelfService } from 'apps/sales/src/app/core/services/collecting-shelf.service';
|
||||
import { Subject, Observable } from 'rxjs';
|
||||
import { map, first, takeUntil, tap, withLatestFrom } from 'rxjs/operators';
|
||||
|
||||
import { isNullOrUndefined } from 'util';
|
||||
import { FormControl } from '@angular/forms';
|
||||
|
||||
@@ -31,11 +27,12 @@ export class ShelfSearchbarComponent implements OnInit, OnDestroy {
|
||||
searchQuery$: Observable<string>;
|
||||
autocompleteResults$: Observable<any[]>;
|
||||
|
||||
@Input() isIPad: boolean;
|
||||
@Input() isIPad = false;
|
||||
@Input() isFetchingData = false;
|
||||
@Input() errorMessage = '';
|
||||
@Input() placeholder =
|
||||
'Kundenname, Abholfach, Abholschein, Kundenkartennummer';
|
||||
@Output() reset = new EventEmitter<void>();
|
||||
@Output() search = new EventEmitter<{
|
||||
type: 'scan' | 'search';
|
||||
value: string;
|
||||
@@ -60,7 +57,7 @@ export class ShelfSearchbarComponent implements OnInit, OnDestroy {
|
||||
|
||||
resetForm() {
|
||||
this.searchForm.reset();
|
||||
this.resetError();
|
||||
this.reset.emit();
|
||||
}
|
||||
|
||||
setError(message: string) {
|
||||
@@ -90,10 +87,6 @@ export class ShelfSearchbarComponent implements OnInit, OnDestroy {
|
||||
return this.searchForm.value && this.searchForm.value.length;
|
||||
}
|
||||
|
||||
private resetError() {
|
||||
this.errorMessage = '';
|
||||
}
|
||||
|
||||
/* search2(searchParams: string) {
|
||||
const branchNumber = this.store.selectSnapshot(
|
||||
BranchSelectors.getUserBranch
|
||||
|
||||
4
apps/sales/src/app/modules/shelf/defs/index.ts
Normal file
4
apps/sales/src/app/modules/shelf/defs/index.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
// start:ng42.barrel
|
||||
export * from './shell-search-device.model';
|
||||
// end:ng42.barrel
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
import { BehaviorSubject } from 'rxjs';
|
||||
|
||||
export abstract class ShelfSearchDeviceComponent {
|
||||
isFetchingData$: BehaviorSubject<boolean>;
|
||||
errorMessage$: BehaviorSubject<string>;
|
||||
triggerSearch({ type, value }: { type: 'search' | 'scan'; value: string }) {}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
// start:ng42.barrel
|
||||
export * from './shelf-search-desktop.component';
|
||||
export * from './shelf-search-desktop.module';
|
||||
// end:ng42.barrel
|
||||
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
<div class="container">
|
||||
<app-shelf-searchbar
|
||||
[isFetchingData]="isFetchingData$ | async"
|
||||
[errorMessage]="errorMessage$ | async"
|
||||
(search)="triggerSearch($event)"
|
||||
(reset)="reset()"
|
||||
></app-shelf-searchbar>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
.container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
user-select: none;
|
||||
margin-bottom: 90px;
|
||||
height: calc(100% - 55px);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,14 @@
|
||||
import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core';
|
||||
import { Component, ChangeDetectionStrategy, OnDestroy } from '@angular/core';
|
||||
import { Subject, BehaviorSubject } from 'rxjs';
|
||||
import {
|
||||
ShelfSearchFacadeService,
|
||||
ShelfStoreFacadeService,
|
||||
ShelfNavigationService,
|
||||
} from '../../../shared/services';
|
||||
import { ShelfSearchDeviceComponent } from '../../../defs';
|
||||
import { takeUntil, first } from 'rxjs/operators';
|
||||
import { SHELF_SCROLL_INDEX } from 'apps/sales/src/app/core/utils/app.constants';
|
||||
import { ListResponseArgsOfOrderItemListItemDTO } from '@swagger/oms/lib';
|
||||
|
||||
@Component({
|
||||
selector: 'app-shelf-search-desktop',
|
||||
@@ -6,8 +16,92 @@ import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core';
|
||||
styleUrls: ['./shelf-search-desktop.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class ShelfSearchDesktopComponent implements OnInit {
|
||||
constructor() {}
|
||||
export class ShelfSearchDesktopComponent
|
||||
implements OnDestroy, ShelfSearchDeviceComponent {
|
||||
destroy$ = new Subject();
|
||||
isFetchingData$ = new BehaviorSubject<boolean>(false);
|
||||
errorMessage$ = new BehaviorSubject<string>('');
|
||||
|
||||
ngOnInit() {}
|
||||
constructor(
|
||||
private shelfSearchService: ShelfSearchFacadeService,
|
||||
private shelfStoreFacade: ShelfStoreFacadeService,
|
||||
private shelfNavigationService: ShelfNavigationService
|
||||
) {}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.destroy$.next();
|
||||
this.destroy$.complete();
|
||||
}
|
||||
|
||||
reset() {
|
||||
this.setIsFetchingData(false);
|
||||
this.resetError();
|
||||
}
|
||||
|
||||
triggerSearch({ value }: { value: string }) {
|
||||
this.setIsFetchingData(true);
|
||||
this.resetError();
|
||||
|
||||
this.shelfSearchService
|
||||
.search(value)
|
||||
.pipe(takeUntil(this.destroy$), first())
|
||||
.subscribe(
|
||||
(result) => this.handleSearchResult(result, value),
|
||||
this.handleSearchResultError
|
||||
);
|
||||
}
|
||||
|
||||
private handleSearchResult(
|
||||
result: ListResponseArgsOfOrderItemListItemDTO,
|
||||
value: string
|
||||
) {
|
||||
this.setIsFetchingData(false);
|
||||
if (this.hasNoResult(result)) {
|
||||
this.setErrorMessage('Ergibt keine Suchergebnisse');
|
||||
} else if (this.hasMultipleSearchResults(result)) {
|
||||
this.shelfStoreFacade.setShelfSearch(value);
|
||||
this.shelfNavigationService.navigateToResultList({
|
||||
searchQuery: value,
|
||||
numberOfHits: result.hits,
|
||||
});
|
||||
this.resetSessionStorage();
|
||||
} else {
|
||||
this.shelfNavigationService.navigateToDetails(this.getDetails(result));
|
||||
}
|
||||
}
|
||||
|
||||
private hasNoResult(result: ListResponseArgsOfOrderItemListItemDTO): boolean {
|
||||
return !!result.result && !result.result.length;
|
||||
}
|
||||
|
||||
private hasMultipleSearchResults(
|
||||
result: ListResponseArgsOfOrderItemListItemDTO
|
||||
): boolean {
|
||||
return !!result.result && result.result.length > 1;
|
||||
}
|
||||
|
||||
private getDetails(result: ListResponseArgsOfOrderItemListItemDTO) {
|
||||
return result.result && result.result[0];
|
||||
}
|
||||
|
||||
private handleSearchResultError() {
|
||||
this.setErrorMessage('Ein Fehler ist aufgetreten');
|
||||
this.setIsFetchingData(false);
|
||||
}
|
||||
|
||||
private resetSessionStorage(key: string = SHELF_SCROLL_INDEX) {
|
||||
sessionStorage.removeItem(key);
|
||||
}
|
||||
|
||||
private setIsFetchingData(isFetching: boolean) {
|
||||
this.isFetchingData$.next(isFetching);
|
||||
}
|
||||
|
||||
private resetError() {
|
||||
this.setErrorMessage('');
|
||||
}
|
||||
|
||||
private setErrorMessage(message: string) {
|
||||
this.errorMessage$.next(message);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { ShelfSearchDesktopComponent } from './shelf-search-desktop.component';
|
||||
import { ShelfSearchBarModule } from '../../../components';
|
||||
|
||||
@NgModule({
|
||||
imports: [CommonModule, ShelfSearchBarModule],
|
||||
exports: [ShelfSearchDesktopComponent],
|
||||
declarations: [ShelfSearchDesktopComponent],
|
||||
providers: [],
|
||||
})
|
||||
export class ShelfSearchDesktopModule {}
|
||||
@@ -2,7 +2,9 @@
|
||||
<app-shelf-searchbar
|
||||
[isFetchingData]="isFetchingData$ | async"
|
||||
[errorMessage]="errorMessage$ | async"
|
||||
[isIPad]="true"
|
||||
(search)="triggerSearch($event)"
|
||||
(reset)="reset()"
|
||||
></app-shelf-searchbar>
|
||||
|
||||
<lib-collecting-shelf-scanner
|
||||
|
||||
@@ -8,12 +8,13 @@ import { BarcodeScannerScanditComponent } from 'shared/lib/barcode-scanner';
|
||||
import { ShelfSearchFacadeService } from '../../../shared/services/shelf-search.facade.service';
|
||||
import { ListResponseArgsOfOrderItemListItemDTO } from 'apps/swagger/oms/src/lib';
|
||||
import { Observable, Subject, BehaviorSubject } from 'rxjs';
|
||||
import { map, first, takeUntil } from 'rxjs/operators';
|
||||
import { first, takeUntil } from 'rxjs/operators';
|
||||
import {
|
||||
ShelfStoreFacadeService,
|
||||
ShelfNavigationService,
|
||||
} from '../../../shared/services';
|
||||
import { SHELF_SCROLL_INDEX } from 'apps/sales/src/app/core/utils/app.constants';
|
||||
import { ShelfSearchDeviceComponent } from '../../../defs';
|
||||
|
||||
@Component({
|
||||
selector: 'app-shelf-search-ipad',
|
||||
@@ -21,7 +22,8 @@ import { SHELF_SCROLL_INDEX } from 'apps/sales/src/app/core/utils/app.constants'
|
||||
styleUrls: ['./shelf-search-ipad.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class ShelfSearchIpadComponent implements OnDestroy {
|
||||
export class ShelfSearchIpadComponent
|
||||
implements OnDestroy, ShelfSearchDeviceComponent {
|
||||
@ViewChild('scanner', { static: false })
|
||||
scanner: BarcodeScannerScanditComponent;
|
||||
destroy$ = new Subject();
|
||||
@@ -39,6 +41,11 @@ export class ShelfSearchIpadComponent implements OnDestroy {
|
||||
this.destroy$.complete();
|
||||
}
|
||||
|
||||
reset() {
|
||||
this.setIsFetchingData(false);
|
||||
this.resetError();
|
||||
}
|
||||
|
||||
triggerBarcodeSearch(barcode: string) {
|
||||
this.triggerSearch({ type: 'scan', value: barcode });
|
||||
}
|
||||
@@ -46,6 +53,8 @@ export class ShelfSearchIpadComponent implements OnDestroy {
|
||||
triggerSearch({ type, value }: { type: 'search' | 'scan'; value: string }) {
|
||||
let result$: Observable<ListResponseArgsOfOrderItemListItemDTO>;
|
||||
this.setIsFetchingData(true);
|
||||
this.resetError();
|
||||
|
||||
if (type === 'search') {
|
||||
result$ = this.shelfSearchService.search(value);
|
||||
} else if (type === 'scan') {
|
||||
@@ -91,7 +100,7 @@ export class ShelfSearchIpadComponent implements OnDestroy {
|
||||
private hasMultipleSearchResults(
|
||||
result: ListResponseArgsOfOrderItemListItemDTO
|
||||
): boolean {
|
||||
return !!result.result && !!result.result.length;
|
||||
return !!result.result && result.result.length > 1;
|
||||
}
|
||||
|
||||
private getDetails(result: ListResponseArgsOfOrderItemListItemDTO) {
|
||||
@@ -106,6 +115,10 @@ export class ShelfSearchIpadComponent implements OnDestroy {
|
||||
this.isFetchingData$.next(isFetching);
|
||||
}
|
||||
|
||||
private resetError() {
|
||||
this.setErrorMessage('');
|
||||
}
|
||||
|
||||
private setErrorMessage(message: string) {
|
||||
this.errorMessage$.next(message);
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { ShelfSearchComponent } from './shelf-search.component';
|
||||
import { ShelfSearchIpadModule } from './shelf-search-ipad';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { ShelfSearchDesktopComponent } from './shelf-search-desktop';
|
||||
import { ShelfSearchDesktopModule } from './shelf-search-desktop';
|
||||
|
||||
@NgModule({
|
||||
imports: [CommonModule, ShelfSearchIpadModule],
|
||||
exports: [ShelfSearchComponent, ShelfSearchDesktopComponent],
|
||||
declarations: [ShelfSearchComponent, ShelfSearchDesktopComponent],
|
||||
imports: [CommonModule, ShelfSearchIpadModule, ShelfSearchDesktopModule],
|
||||
exports: [ShelfSearchComponent],
|
||||
declarations: [ShelfSearchComponent],
|
||||
providers: [],
|
||||
})
|
||||
export class ShelfSearchModule {}
|
||||
|
||||
@@ -5,7 +5,6 @@ import { Pipe, PipeTransform } from '@angular/core';
|
||||
})
|
||||
export class ShowSearchResetPipe implements PipeTransform {
|
||||
transform(queryString: string, minimumNumberOfChars?: number): boolean {
|
||||
console.log({ queryString });
|
||||
return (
|
||||
!!queryString && !!(queryString.length > (minimumNumberOfChars || 0))
|
||||
);
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
width: 27px;
|
||||
background-size: cover;
|
||||
top: 17px;
|
||||
cursor: pointer;
|
||||
|
||||
&.scan {
|
||||
top: 0;
|
||||
@@ -59,10 +60,30 @@
|
||||
top: 19px;
|
||||
outline: none;
|
||||
position: absolute;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.isa-input-error {
|
||||
color: $isa-red;
|
||||
font-size: 14px;
|
||||
font-weight: 700;
|
||||
animation: errorShake 0.3s cubic-bezier(0.7, 0.07, 0.19, 0.97) both;
|
||||
}
|
||||
|
||||
@keyframes errorShake {
|
||||
10% {
|
||||
transform: translate3d(-1px, 0, 0);
|
||||
}
|
||||
|
||||
50% {
|
||||
transform: translate3d(2px, 0, 0);
|
||||
}
|
||||
|
||||
70% {
|
||||
transform: translate3d(-3px, 0, 0);
|
||||
}
|
||||
|
||||
90% {
|
||||
transform: translate3d(3px, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user