mirror of
https://dev.azure.com/hugendubel/ISA/_git/ISA-Frontend
synced 2025-12-31 09:37:15 +01:00
Merge branch 'feature/189-Warenausgabe/276-Startseite/664-Ipad-Suchfeld' into feature/189-Warenausgabe/276-Startseite/main
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
// start:ng42.barrel
|
||||
export * from './article-details.component';
|
||||
// end:ng42.barrel
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
<div class="container">
|
||||
<h1 class="no-padding">Abholschein oder</h1>
|
||||
<h1>Kundenkarte scannen</h1>
|
||||
<caption>
|
||||
Nutzen Sie die Scanfunktion des iPads.
|
||||
</caption>
|
||||
|
||||
<lib-collecting-shelf-scanner #scanner (scan)="triggerSearch($event)"></lib-collecting-shelf-scanner>
|
||||
</div>
|
||||
@@ -1,44 +0,0 @@
|
||||
.container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 36px 0;
|
||||
flex-direction: column;
|
||||
background-color: rgba(255, 255, 255, 1);
|
||||
border-radius: 5px;
|
||||
box-shadow: 0px -2px 24px 0px rgba(220, 226, 233, 0.8);
|
||||
user-select: none;
|
||||
margin-bottom: 90px;
|
||||
height: calc(100% - 55px);
|
||||
|
||||
h1 {
|
||||
font-family: 'Open Sans';
|
||||
font-size: 26px;
|
||||
font-weight: 600;
|
||||
color: rgba(0, 0, 0, 1);
|
||||
margin: 0;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.no-padding {
|
||||
margin-bottom: 1px;
|
||||
}
|
||||
|
||||
caption {
|
||||
width: 400px;
|
||||
font-family: 'Open Sans';
|
||||
font-size: 22px;
|
||||
color: rgba(0, 0, 0, 1);
|
||||
text-align: center;
|
||||
margin-bottom: 25px;
|
||||
}
|
||||
}
|
||||
|
||||
lib-barcode-scanner-scandit {
|
||||
width: 550px;
|
||||
height: 300px;
|
||||
border: #e1ebf5 2px solid;
|
||||
}
|
||||
|
||||
.btn {
|
||||
margin-top: 15px;
|
||||
}
|
||||
@@ -1,99 +0,0 @@
|
||||
import { Subject } from 'rxjs';
|
||||
import { BarcodeScannerScanditComponent } from 'shared/lib/barcode-scanner';
|
||||
|
||||
import { Component, OnDestroy, OnInit, ViewChild } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
import { Store } from '@ngxs/store';
|
||||
import { isNullOrUndefined } from 'util';
|
||||
import { CollectingShelfService } from 'apps/sales/src/app/core/services/collecting-shelf.service';
|
||||
import { BranchSelectors } from 'apps/sales/src/app/core/store/selectors/branch.selector';
|
||||
import { takeUntil, take } from 'rxjs/operators';
|
||||
import { SetShelfSearch, ChangeCurrentRoute } from 'apps/sales/src/app/core/store/actions/process.actions';
|
||||
import { ShelfSearch } from 'apps/sales/src/app/core/models/shelf-search.modal';
|
||||
import { SHELF_SCROLL_INDEX } from 'apps/sales/src/app/core/utils/app.constants';
|
||||
import { AddBreadcrumb } from 'apps/sales/src/app/core/store/actions/breadcrumb.actions';
|
||||
import { Breadcrumb } from 'apps/sales/src/app/core/models/breadcrumb.model';
|
||||
import { OrderItemListItemDTO, ListResponseArgsOfOrderItemListItemDTO } from '@swagger/oms';
|
||||
|
||||
@Component({
|
||||
selector: 'app-shelf-barcode-search',
|
||||
templateUrl: 'barcode-search.component.html',
|
||||
styleUrls: ['barcode-search.component.scss'],
|
||||
})
|
||||
export class ShelfBarcodeSearchComponent implements OnInit, OnDestroy {
|
||||
@ViewChild('scanner', { static: false }) scanner: BarcodeScannerScanditComponent;
|
||||
scanningVisible = false;
|
||||
destroy$ = new Subject();
|
||||
|
||||
constructor(private store: Store, private router: Router, private collectingShelf: CollectingShelfService) { }
|
||||
|
||||
ngOnInit() { }
|
||||
|
||||
triggerSearch(barcode) {
|
||||
if (isNullOrUndefined(barcode) || barcode.length <= 1) {
|
||||
return;
|
||||
}
|
||||
barcode = barcode.replace('ORD:', '').trim();
|
||||
const branchNumber = this.store.selectSnapshot(BranchSelectors.getUserBranch);
|
||||
this.collectingShelf
|
||||
.searchShelfHasResultsWithResult(barcode, branchNumber)
|
||||
.pipe(take(1))
|
||||
.subscribe((reponse: ListResponseArgsOfOrderItemListItemDTO) => {
|
||||
if (reponse) {
|
||||
if (reponse.hits > 1) {
|
||||
this.store.dispatch(
|
||||
new SetShelfSearch(<ShelfSearch>{
|
||||
input: barcode,
|
||||
branchnumber: branchNumber,
|
||||
})
|
||||
);
|
||||
sessionStorage.removeItem(SHELF_SCROLL_INDEX);
|
||||
this.navigateToRoute('/shelf/results', `${barcode} (${reponse.hits} Ergebnisse)`);
|
||||
} else if (reponse.hits === 1) {
|
||||
this.details(reponse.result[0]);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
details(order: OrderItemListItemDTO) {
|
||||
if (order && (order.compartmentCode || order.orderId)) {
|
||||
const path = `/shelf/details/${order.compartmentCode ? order.compartmentCode : order.orderId}/${order.orderId}/${
|
||||
order.processingStatus
|
||||
}/${order.compartmentCode ? 'c' : 'o'}`;
|
||||
this.store.dispatch(
|
||||
new AddBreadcrumb(
|
||||
<Breadcrumb>{
|
||||
name: order.firstName + ' ' + order.lastName,
|
||||
path: path,
|
||||
},
|
||||
'shelf'
|
||||
)
|
||||
);
|
||||
this.store.dispatch(new ChangeCurrentRoute(path));
|
||||
this.router.navigate([path]);
|
||||
}
|
||||
}
|
||||
|
||||
private navigateToRoute(route: string, breadcrumbName: string) {
|
||||
this.store.dispatch(
|
||||
new AddBreadcrumb(
|
||||
<Breadcrumb>{
|
||||
name: breadcrumbName,
|
||||
path: route,
|
||||
},
|
||||
'shelf'
|
||||
)
|
||||
);
|
||||
this.store.dispatch(new ChangeCurrentRoute(route));
|
||||
this.router.navigate([route]);
|
||||
}
|
||||
|
||||
toggleScan() {
|
||||
this.scanningVisible = !this.scanningVisible;
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.destroy$.next();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
// start:ng42.barrel
|
||||
export * from './customer-order.component';
|
||||
// end:ng42.barrel
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
export * from './barcode-search/barcode-search.component';
|
||||
export * from './text-search/text-search.component';
|
||||
export * from './customer-order/customer-order.component';
|
||||
export * from './order-item/order-item.component';
|
||||
export * from './order-tag/order-tag.component';
|
||||
export * from './article-details/article-details.component';
|
||||
export * from './partial-collection-modal/partial-collection-modal.component';
|
||||
// start:ng42.barrel
|
||||
export * from './article-details';
|
||||
export * from './customer-order';
|
||||
export * from './order-item-edit';
|
||||
export * from './order-item';
|
||||
export * from './order-loading';
|
||||
export * from './order-overview-edit';
|
||||
export * from './order-tag';
|
||||
export * from './partial-collection-modal';
|
||||
export * from './searchbar';
|
||||
// end:ng42.barrel
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
// start:ng42.barrel
|
||||
export * from './order-item-edit.component';
|
||||
// end:ng42.barrel
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
// start:ng42.barrel
|
||||
export * from './order-item.component';
|
||||
// end:ng42.barrel
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
// start:ng42.barrel
|
||||
export * from './order-loading.component';
|
||||
// end:ng42.barrel
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
// start:ng42.barrel
|
||||
export * from './order-overview-edit.component';
|
||||
// end:ng42.barrel
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
// start:ng42.barrel
|
||||
export * from './order-tag.component';
|
||||
// end:ng42.barrel
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
// start:ng42.barrel
|
||||
export * from './partial-collection-modal.component';
|
||||
// end:ng42.barrel
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
// start:ng42.barrel
|
||||
export * from './searchbar.component';
|
||||
export * from './searchbar.module';
|
||||
// end:ng42.barrel
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
<div class="input-wrapper">
|
||||
<input
|
||||
focus
|
||||
autocomplete="off"
|
||||
class="isa-input isa-text-input"
|
||||
[class.error]="!!errorMessage.length"
|
||||
[placeholder]="placeholder | truncateText: 35"
|
||||
type="text"
|
||||
name="shelf-search"
|
||||
id="shelf-search-input"
|
||||
[formControl]="searchForm"
|
||||
(keyup.enter)="triggerSearch()"
|
||||
/>
|
||||
<span class="isa-input-error" *ngIf="!!errorMessage.length">{{
|
||||
errorMessage
|
||||
}}</span>
|
||||
<button
|
||||
class="isa-btn-close isa-input-reset"
|
||||
type="reset"
|
||||
*ngIf="
|
||||
(!isFetchingData && searchQuery$ | async | showSearchResetPipe) ||
|
||||
errorMessage
|
||||
"
|
||||
(click)="resetForm()"
|
||||
></button>
|
||||
<ng-container [ngSwitch]="isFetchingData">
|
||||
<div class="spinner isa-mt-16" *ngSwitchCase="true"></div>
|
||||
<button
|
||||
*ngSwitchDefault
|
||||
class="isa-input-submit"
|
||||
[class.scan]="!errorMessage && !(searchQuery$ | async)"
|
||||
type="submit"
|
||||
(click)="triggerSearch()"
|
||||
></button>
|
||||
</ng-container>
|
||||
<div
|
||||
class="autocomplete-results"
|
||||
*ngFor="let result of autocompleteResults$ | async"
|
||||
>
|
||||
<!-- Create own component using ListKey CDK -->
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,16 @@
|
||||
@import '../../../../../assets/scss/variables';
|
||||
|
||||
app-search {
|
||||
width: 80vw;
|
||||
max-width: 550px;
|
||||
}
|
||||
|
||||
.input-wrapper {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: 80vw;
|
||||
max-width: 550px;
|
||||
border-radius: 30px;
|
||||
box-shadow: 0px 6px 24px 0px rgba(214, 215, 217, 0.8);
|
||||
}
|
||||
@@ -0,0 +1,223 @@
|
||||
import {
|
||||
Component,
|
||||
Input,
|
||||
OnInit,
|
||||
OnDestroy,
|
||||
Output,
|
||||
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';
|
||||
|
||||
@Component({
|
||||
selector: 'app-shelf-searchbar',
|
||||
templateUrl: './searchbar.component.html',
|
||||
styleUrls: ['./searchbar.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class ShelfSearchbarComponent implements OnInit, OnDestroy {
|
||||
searchForm: FormControl;
|
||||
searchQuery$: Observable<string>;
|
||||
autocompleteResults$: Observable<any[]>;
|
||||
|
||||
@Input() isIPad: boolean;
|
||||
@Input() isFetchingData = false;
|
||||
@Input() errorMessage = '';
|
||||
@Input() placeholder =
|
||||
'Kundenname, Abholfach, Abholschein, Kundenkartennummer';
|
||||
@Output() search = new EventEmitter<{
|
||||
type: 'scan' | 'search';
|
||||
value: string;
|
||||
}>();
|
||||
|
||||
destroy$ = new Subject();
|
||||
|
||||
constructor(private store: Store) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.initForm();
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.destroy$.next();
|
||||
}
|
||||
|
||||
initForm() {
|
||||
this.searchForm = new FormControl(null);
|
||||
this.searchQuery$ = this.searchForm.valueChanges;
|
||||
}
|
||||
|
||||
resetForm() {
|
||||
this.searchForm.reset();
|
||||
this.resetError();
|
||||
}
|
||||
|
||||
setError(message: string) {
|
||||
this.errorMessage = message;
|
||||
}
|
||||
|
||||
triggerSearch() {
|
||||
const isValidInput = this.validateSearchInputBeforeSubmit(
|
||||
this.searchForm.value
|
||||
);
|
||||
|
||||
if (!isValidInput) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.search.emit({
|
||||
type: this.isSearch() ? 'search' : 'scan',
|
||||
value: this.searchForm.value,
|
||||
});
|
||||
}
|
||||
|
||||
private validateSearchInputBeforeSubmit(searchInput: string): boolean {
|
||||
return !isNullOrUndefined(searchInput) && searchInput.length >= 1;
|
||||
}
|
||||
|
||||
private isSearch(): boolean {
|
||||
return this.searchForm.value && this.searchForm.value.length;
|
||||
}
|
||||
|
||||
private resetError() {
|
||||
this.errorMessage = '';
|
||||
}
|
||||
|
||||
/* search2(searchParams: string) {
|
||||
const branchNumber = this.store.selectSnapshot(
|
||||
BranchSelectors.getUserBranch
|
||||
);
|
||||
this.collectingShelf
|
||||
.searchShelfHasResultsWithResult(searchParams, branchNumber)
|
||||
.pipe(take(1))
|
||||
.subscribe((reponse: ListResponseArgsOfOrderItemListItemDTO) => {
|
||||
if (reponse) {
|
||||
if (
|
||||
reponse.hits > 1 ||
|
||||
(reponse.result && reponse.result.length > 1)
|
||||
) {
|
||||
this.store.dispatch(
|
||||
new SetShelfSearch(<ShelfSearch>{
|
||||
input: searchParams,
|
||||
branchnumber: branchNumber,
|
||||
})
|
||||
);
|
||||
sessionStorage.removeItem(SHELF_SCROLL_INDEX);
|
||||
this.store
|
||||
.dispatch(
|
||||
new SetCachedResults({
|
||||
result: this.mapper.fromOrderItemListItemDTOArrayToCollectingShelfOrder(
|
||||
reponse.result,
|
||||
this.collectingShelf,
|
||||
true
|
||||
),
|
||||
hits: reponse.hits,
|
||||
})
|
||||
)
|
||||
.toPromise()
|
||||
.then(() => {
|
||||
// this.searchInput.stopLoading();
|
||||
this.store.dispatch(new SetCollectingShelfCacheState(true));
|
||||
this.navigateToRoute(
|
||||
'/shelf/results',
|
||||
`${searchParams} (${
|
||||
reponse.hits ? reponse.hits : reponse.result.length
|
||||
} Ergebnisse)`
|
||||
);
|
||||
});
|
||||
} else if (
|
||||
reponse.hits === 1 ||
|
||||
(reponse.result && reponse.result.length === 1)
|
||||
) {
|
||||
this.details(reponse.result[0]);
|
||||
this.store.dispatch(new ClearCachedResults());
|
||||
} else {
|
||||
// this.searchInput.stopLoading();
|
||||
this.store.dispatch(new ClearCachedResults());
|
||||
this.error = 'Ergibt keine Suchergebnisse';
|
||||
}
|
||||
} else {
|
||||
// this.searchInput.stopLoading();
|
||||
this.store.dispatch(new ClearCachedResults());
|
||||
this.error = 'Ergibt keine Suchergebnisse';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
details(order: OrderItemListItemDTO) {
|
||||
if (order && (order.compartmentCode || order.orderId)) {
|
||||
const path = `/shelf/details/${
|
||||
order.compartmentCode ? order.compartmentCode : order.orderId
|
||||
}/${order.orderId}/${order.processingStatus}/${
|
||||
order.compartmentCode ? 'c' : 'o'
|
||||
}`;
|
||||
this.store.dispatch(
|
||||
new AddBreadcrumb(
|
||||
<Breadcrumb>{
|
||||
name: order.firstName + ' ' + order.lastName,
|
||||
path: path,
|
||||
},
|
||||
'shelf'
|
||||
)
|
||||
);
|
||||
this.store.dispatch(new ChangeCurrentRoute(path));
|
||||
this.router.navigate([path]);
|
||||
}
|
||||
}
|
||||
|
||||
private navigateToRoute(route: string, breadcrumbName: string) {
|
||||
this.store.dispatch(
|
||||
new AddBreadcrumb(
|
||||
<Breadcrumb>{
|
||||
name: breadcrumbName,
|
||||
path: route,
|
||||
},
|
||||
'shelf'
|
||||
)
|
||||
);
|
||||
this.store.dispatch(new ChangeCurrentRoute(route));
|
||||
this.router.navigate([route]);
|
||||
}
|
||||
|
||||
createTab() {
|
||||
const processExists =
|
||||
this.store.selectSnapshot(ProcessSelectors.getProcessesCount) > 0;
|
||||
if (!processExists) {
|
||||
this.createProcess();
|
||||
}
|
||||
}
|
||||
|
||||
clear() {
|
||||
this.error = '';
|
||||
} */
|
||||
|
||||
private createProcess() {
|
||||
const newProcess = <Process>{
|
||||
id: 1,
|
||||
name: 'Vorgang 1',
|
||||
currentRoute: '/shelf/search',
|
||||
};
|
||||
|
||||
this.store.dispatch(new AddProcess(newProcess));
|
||||
this.store.dispatch(
|
||||
new AddBreadcrumb(
|
||||
<Breadcrumb>{
|
||||
name: 'Abholfach',
|
||||
path: '/shelf/search',
|
||||
},
|
||||
'shelf'
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { ReactiveFormsModule } from '@angular/forms';
|
||||
import { SearchInputModule } from '@libs/ui';
|
||||
import { FocusDirective } from '../../shared/directives';
|
||||
import { TruncateTextPipe, ShowSearchResetPipe } from '../../shared/pipes';
|
||||
import { ShelfSearchbarComponent } from './searchbar.component';
|
||||
|
||||
@NgModule({
|
||||
imports: [CommonModule, SearchInputModule, ReactiveFormsModule],
|
||||
exports: [
|
||||
ShelfSearchbarComponent,
|
||||
ShowSearchResetPipe,
|
||||
TruncateTextPipe,
|
||||
FocusDirective,
|
||||
],
|
||||
declarations: [
|
||||
ShelfSearchbarComponent,
|
||||
ShowSearchResetPipe,
|
||||
TruncateTextPipe,
|
||||
FocusDirective,
|
||||
],
|
||||
providers: [],
|
||||
})
|
||||
export class ShelfSearchBarModule {}
|
||||
@@ -1,26 +0,0 @@
|
||||
<div
|
||||
class="shelf-search-container"
|
||||
[ngClass]="{ 'shelf-search-container-mobile': isIPad }"
|
||||
>
|
||||
<div class="shelf-section shelf-search">
|
||||
<div class="align-center shelf-search-title-margin">
|
||||
<span class="shelf-search-title">Bestellpostensuche</span>
|
||||
</div>
|
||||
<div class="align-center">
|
||||
<span class="shelf-search-description">
|
||||
Suchen Sie den Bestellposten via Name, Abholfachnummer,
|
||||
Abholscheinnummer, Kundenkartennummer oder Vorgang-ID.
|
||||
</span>
|
||||
</div>
|
||||
<div class="align-center search-container">
|
||||
<app-search
|
||||
#searchInput
|
||||
(input)="createTab()"
|
||||
(search)="search($event)"
|
||||
[load]="true"
|
||||
placeholder="Name, Abholfach, Abholschein, Kundenkarte"
|
||||
error="{{ error }}"
|
||||
></app-search>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,100 +0,0 @@
|
||||
@import '../../../../../assets/scss/variables';
|
||||
|
||||
.shelf-search-container {
|
||||
background-image: linear-gradient(-180deg, #ffffff 0%, #ffffff 100%);
|
||||
box-shadow: 0px -2px 24px 0px #dce2e9;
|
||||
height: calc(100% + 75px);
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.shelf-search-container-mobile {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.shelf-section {
|
||||
box-shadow: 0px -2px 6px 0px $hima-content-shadow-color;
|
||||
-moz-box-shadow: 0px -2px 6px 0px $hima-content-shadow-color;
|
||||
-webkit-box-shadow: 0px -2px 6px 0px $hima-content-shadow-color;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.shelf-scan {
|
||||
display: grid;
|
||||
grid-template-columns: auto;
|
||||
height: 40px;
|
||||
padding-top: 28px;
|
||||
}
|
||||
|
||||
.shelf-scan-header {
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
color: #557596;
|
||||
opacity: 0.8;
|
||||
text-align: left;
|
||||
line-height: 21px;
|
||||
}
|
||||
|
||||
.shelf-scan-content {
|
||||
font-size: 10pt;
|
||||
}
|
||||
|
||||
.shelf-scan-content-div {
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
.shelf-search {
|
||||
padding-top: 30px;
|
||||
background-color: #fff;
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.shelf-search-title-margin {
|
||||
margin-top: 25px;
|
||||
}
|
||||
.shelf-search-title {
|
||||
font-size: 26px;
|
||||
color: #000000;
|
||||
font-weight: bold;
|
||||
}
|
||||
.shelf-search-description {
|
||||
font-size: 22px;
|
||||
width: 530px;
|
||||
margin: 0 auto;
|
||||
display: block;
|
||||
}
|
||||
.search-container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin-top: 30px;
|
||||
}
|
||||
|
||||
/*
|
||||
##Device = Big Desktops
|
||||
*/
|
||||
@media (min-width: 1281px) {
|
||||
app-search {
|
||||
width: 718px;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
##Device = Laptops, Desktops, Ipad pro
|
||||
*/
|
||||
@media (min-width: 1025px) and (max-width: 1280px) {
|
||||
app-search {
|
||||
width: 718px;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
##Device = Tablets, Ipads
|
||||
*/
|
||||
@media (min-width: 768px) and (max-width: 1024px) {
|
||||
app-search {
|
||||
width: 564px;
|
||||
}
|
||||
}
|
||||
@@ -1,191 +0,0 @@
|
||||
import { AfterViewInit, Component, Input, OnInit, ViewChild, OnDestroy } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
import { SearchInputComponent } from '@libs/ui';
|
||||
import { Store } from '@ngxs/store';
|
||||
import { Process } from 'apps/sales/src/app/core/models/process.model';
|
||||
import { AddProcess, SetShelfSearch, ChangeCurrentRoute } 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 { ProcessSelectors } from 'apps/sales/src/app/core/store/selectors/process.selectors';
|
||||
import { CollectingShelfService } from 'apps/sales/src/app/core/services/collecting-shelf.service';
|
||||
import { BranchSelectors } from 'apps/sales/src/app/core/store/selectors/branch.selector';
|
||||
import { Subject } from 'rxjs';
|
||||
import { takeUntil, take } from 'rxjs/operators';
|
||||
import { OrderItemListItemDTO, ListResponseArgsOfOrderItemListItemDTO, OrderDTO } from '@swagger/oms';
|
||||
import { ShelfSearch } from 'apps/sales/src/app/core/models/shelf-search.modal';
|
||||
import { isNullOrUndefined } from 'util';
|
||||
import { WindowRef } from 'apps/sales/src/app/core/services/window-ref.service';
|
||||
import { SHELF_SCROLL_INDEX } from 'apps/sales/src/app/core/utils/app.constants';
|
||||
import {
|
||||
ClearCachedResults,
|
||||
SetCachedResults,
|
||||
SetCollectingShelfCacheState,
|
||||
} from 'apps/sales/src/app/core/store/actions/collecting-shelf.action';
|
||||
import { ShelfMapping } from 'apps/sales/src/app/core/mappings/shelf.mapping';
|
||||
|
||||
@Component({
|
||||
selector: 'app-shelf-text-search',
|
||||
templateUrl: './text-search.component.html',
|
||||
styleUrls: ['./text-search.component.scss'],
|
||||
})
|
||||
export class ShelfTextSearchComponent implements OnInit, AfterViewInit, OnDestroy {
|
||||
timer: any;
|
||||
error = '';
|
||||
autoCompleteEnabled = true;
|
||||
isIPad: boolean;
|
||||
private iPadDetected = false;
|
||||
private iPadEventRecieved = false;
|
||||
|
||||
@ViewChild('searchInput', { static: true }) searchInput: SearchInputComponent;
|
||||
|
||||
destroy$ = new Subject();
|
||||
|
||||
constructor(
|
||||
private store: Store,
|
||||
private router: Router,
|
||||
private mapper: ShelfMapping,
|
||||
private collectingShelf: CollectingShelfService,
|
||||
private windowRef: WindowRef
|
||||
) { }
|
||||
|
||||
ngOnInit() {
|
||||
this.isIPad = this.isIPadEnv();
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.destroy$.next();
|
||||
}
|
||||
|
||||
ngAfterViewInit() {
|
||||
this.searchInput.inputChange.subscribe((data) => {
|
||||
if (!data && this.error) {
|
||||
this.error = '';
|
||||
}
|
||||
});
|
||||
this.searchInput.focus();
|
||||
}
|
||||
|
||||
search(searchParams: string) {
|
||||
searchParams = searchParams.trim();
|
||||
if (isNullOrUndefined(searchParams) || searchParams.length <= 1) {
|
||||
return;
|
||||
}
|
||||
const branchNumber = this.store.selectSnapshot(BranchSelectors.getUserBranch);
|
||||
this.collectingShelf
|
||||
.searchShelfHasResultsWithResult(searchParams, branchNumber)
|
||||
.pipe(take(1))
|
||||
.subscribe((reponse: ListResponseArgsOfOrderItemListItemDTO) => {
|
||||
if (reponse) {
|
||||
if (reponse.hits > 1 || (reponse.result && reponse.result.length > 1)) {
|
||||
this.store.dispatch(
|
||||
new SetShelfSearch(<ShelfSearch>{
|
||||
input: searchParams,
|
||||
branchnumber: branchNumber,
|
||||
})
|
||||
);
|
||||
sessionStorage.removeItem(SHELF_SCROLL_INDEX);
|
||||
this.store
|
||||
.dispatch(
|
||||
new SetCachedResults({
|
||||
result: this.mapper.fromOrderItemListItemDTOArrayToCollectingShelfOrder(reponse.result, this.collectingShelf, true),
|
||||
hits: reponse.hits,
|
||||
})
|
||||
)
|
||||
.toPromise()
|
||||
.then(() => {
|
||||
this.searchInput.stopLoading();
|
||||
this.store.dispatch(new SetCollectingShelfCacheState(true));
|
||||
this.navigateToRoute(
|
||||
'/shelf/results',
|
||||
`${searchParams} (${reponse.hits ? reponse.hits : reponse.result.length} Ergebnisse)`
|
||||
);
|
||||
});
|
||||
} else if (reponse.hits === 1 || (reponse.result && reponse.result.length === 1)) {
|
||||
this.details(reponse.result[0]);
|
||||
this.store.dispatch(new ClearCachedResults());
|
||||
} else {
|
||||
this.searchInput.stopLoading();
|
||||
this.store.dispatch(new ClearCachedResults());
|
||||
this.error = 'Ergibt keine Suchergebnisse';
|
||||
}
|
||||
} else {
|
||||
this.searchInput.stopLoading();
|
||||
this.store.dispatch(new ClearCachedResults());
|
||||
this.error = 'Ergibt keine Suchergebnisse';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
details(order: OrderItemListItemDTO) {
|
||||
if (order && (order.compartmentCode || order.orderId)) {
|
||||
const path = `/shelf/details/${order.compartmentCode ? order.compartmentCode : order.orderId}/${order.orderId}/${
|
||||
order.processingStatus
|
||||
}/${order.compartmentCode ? 'c' : 'o'}`;
|
||||
this.store.dispatch(
|
||||
new AddBreadcrumb(
|
||||
<Breadcrumb>{
|
||||
name: order.firstName + ' ' + order.lastName,
|
||||
path: path,
|
||||
},
|
||||
'shelf'
|
||||
)
|
||||
);
|
||||
this.store.dispatch(new ChangeCurrentRoute(path));
|
||||
this.router.navigate([path]);
|
||||
}
|
||||
}
|
||||
|
||||
private navigateToRoute(route: string, breadcrumbName: string) {
|
||||
this.store.dispatch(
|
||||
new AddBreadcrumb(
|
||||
<Breadcrumb>{
|
||||
name: breadcrumbName,
|
||||
path: route,
|
||||
},
|
||||
'shelf'
|
||||
)
|
||||
);
|
||||
this.store.dispatch(new ChangeCurrentRoute(route));
|
||||
this.router.navigate([route]);
|
||||
}
|
||||
|
||||
createTab() {
|
||||
const processExists = this.store.selectSnapshot(ProcessSelectors.getProcessesCount) > 0;
|
||||
if (!processExists) {
|
||||
this.createProcess();
|
||||
}
|
||||
}
|
||||
|
||||
clear() {
|
||||
this.error = '';
|
||||
}
|
||||
|
||||
private createProcess() {
|
||||
const newProcess = <Process>{
|
||||
id: 1,
|
||||
name: 'Vorgang 1',
|
||||
currentRoute: '/shelf/search',
|
||||
};
|
||||
|
||||
this.store.dispatch(new AddProcess(newProcess));
|
||||
this.store.dispatch(
|
||||
new AddBreadcrumb(
|
||||
<Breadcrumb>{
|
||||
name: 'Abholfach',
|
||||
path: '/shelf/search',
|
||||
},
|
||||
'shelf'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
isIPadEnv() {
|
||||
const navigator = this.windowRef.nativeWindow.navigator as Navigator;
|
||||
const standalone = (navigator as any).standalone,
|
||||
userAgent = navigator.userAgent.toLowerCase(),
|
||||
ios = /iphone|ipod|ipad/.test(userAgent);
|
||||
|
||||
this.iPadDetected = ios && !standalone;
|
||||
return this.iPadDetected || this.iPadEventRecieved;
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,25 @@
|
||||
import { Subject, of, Observable } from 'rxjs';
|
||||
|
||||
import { Component, OnDestroy, OnInit, ViewChild, ChangeDetectionStrategy, ChangeDetectorRef, AfterContentChecked, ViewRef } from '@angular/core';
|
||||
import {
|
||||
Component,
|
||||
OnDestroy,
|
||||
OnInit,
|
||||
ViewChild,
|
||||
ChangeDetectionStrategy,
|
||||
ChangeDetectorRef,
|
||||
AfterContentChecked,
|
||||
ViewRef,
|
||||
} from '@angular/core';
|
||||
import { Store } from '@ngxs/store';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { switchMap, takeUntil, take, catchError, concatMap, filter } from 'rxjs/operators';
|
||||
import {
|
||||
switchMap,
|
||||
takeUntil,
|
||||
take,
|
||||
catchError,
|
||||
concatMap,
|
||||
filter,
|
||||
} from 'rxjs/operators';
|
||||
import { CollectingShelfService } from 'apps/sales/src/app/core/services/collecting-shelf.service';
|
||||
import {
|
||||
OrderDTO,
|
||||
@@ -13,8 +29,11 @@ import {
|
||||
OrderItemSubsetDTO,
|
||||
EntityDTOContainerOfOrderItemDTO,
|
||||
} from '@swagger/oms';
|
||||
import { orderStatusMapper, orderPaymentType, OrderStatus } from 'apps/sales/src/app/core/mappings/shelf.mapping';
|
||||
import { ShelfPartialCollectionModalComponent } from '../../components';
|
||||
import {
|
||||
orderStatusMapper,
|
||||
orderPaymentType,
|
||||
OrderStatus,
|
||||
} from 'apps/sales/src/app/core/mappings/shelf.mapping';
|
||||
import { SetEditOrder } from 'apps/sales/src/app/core/store/actions/collecting-shelf.action';
|
||||
import {
|
||||
AddBreadcrumb,
|
||||
@@ -28,6 +47,7 @@ import { objectNotNull } from 'apps/sales/src/app/core/utils/app.utils';
|
||||
import { isNullOrUndefined } from 'util';
|
||||
import { CustomerService } from 'apps/sales/src/app/core/services/customer.service';
|
||||
import { User } from 'apps/sales/src/app/core/models/user.model';
|
||||
import { ShelfPartialCollectionModalComponent } from '../../components';
|
||||
|
||||
export const COLLECTED = 256;
|
||||
export const BACK_TO_STOCK = 262144;
|
||||
@@ -39,8 +59,10 @@ export const ARRIVED = 128;
|
||||
styleUrls: ['./shelf-order-details.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class ShelfOrderDetailsComponent implements OnInit, OnDestroy, AfterContentChecked {
|
||||
@ViewChild('partialModal', { static: false }) partialModal: ShelfPartialCollectionModalComponent;
|
||||
export class ShelfOrderDetailsComponent
|
||||
implements OnInit, OnDestroy, AfterContentChecked {
|
||||
@ViewChild('partialModal', { static: false })
|
||||
partialModal: ShelfPartialCollectionModalComponent;
|
||||
destroy$ = new Subject();
|
||||
|
||||
orderDTO: OrderDTO;
|
||||
@@ -65,7 +87,13 @@ export class ShelfOrderDetailsComponent implements OnInit, OnDestroy, AfterConte
|
||||
changedToArrived = false;
|
||||
notAvailableModel = {
|
||||
comment: { value: '', disabled: true, errors: undefined },
|
||||
message: { code: '', value: '', valid: false, disabled: true, errors: undefined },
|
||||
message: {
|
||||
code: '',
|
||||
value: '',
|
||||
valid: false,
|
||||
disabled: true,
|
||||
errors: undefined,
|
||||
},
|
||||
};
|
||||
features: string[];
|
||||
|
||||
@@ -82,7 +110,7 @@ export class ShelfOrderDetailsComponent implements OnInit, OnDestroy, AfterConte
|
||||
private cdrf: ChangeDetectorRef,
|
||||
private router: Router,
|
||||
private customerService: CustomerService
|
||||
) { }
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.loadOrder();
|
||||
@@ -100,7 +128,10 @@ export class ShelfOrderDetailsComponent implements OnInit, OnDestroy, AfterConte
|
||||
} else {
|
||||
const dateEl = document.getElementById('date-span');
|
||||
if (dateEl) {
|
||||
this.dateWidth = status.clientWidth && dateEl.clientWidth ? status.clientWidth - dateEl.clientWidth : 25;
|
||||
this.dateWidth =
|
||||
status.clientWidth && dateEl.clientWidth
|
||||
? status.clientWidth - dateEl.clientWidth
|
||||
: 25;
|
||||
}
|
||||
}
|
||||
this.detectChanges();
|
||||
@@ -109,7 +140,9 @@ export class ShelfOrderDetailsComponent implements OnInit, OnDestroy, AfterConte
|
||||
}
|
||||
|
||||
private loadOrder() {
|
||||
this.route.params.pipe(take(1), switchMap(this.orderParamSwitcher)).subscribe(this.orderSubscription$);
|
||||
this.route.params
|
||||
.pipe(take(1), switchMap(this.orderParamSwitcher))
|
||||
.subscribe(this.orderSubscription$);
|
||||
}
|
||||
|
||||
private orderSubscription$ = (result: OrderDTO) => {
|
||||
@@ -119,7 +152,11 @@ export class ShelfOrderDetailsComponent implements OnInit, OnDestroy, AfterConte
|
||||
this.loadCustomerData(result.buyer.source);
|
||||
}
|
||||
this.order = this.orderDisplayMapper(this.orderDTO);
|
||||
if (this.orderDTO && this.orderDTO.items && this.orderDTO.items.length < 1) {
|
||||
if (
|
||||
this.orderDTO &&
|
||||
this.orderDTO.items &&
|
||||
this.orderDTO.items.length < 1
|
||||
) {
|
||||
this.goToResults();
|
||||
}
|
||||
if (this.partialModal) {
|
||||
@@ -160,7 +197,11 @@ export class ShelfOrderDetailsComponent implements OnInit, OnDestroy, AfterConte
|
||||
};
|
||||
|
||||
hasMultipleItems() {
|
||||
if (this.orderDTO && this.orderDTO.items && this.orderDTO.items.length > 1) {
|
||||
if (
|
||||
this.orderDTO &&
|
||||
this.orderDTO.items &&
|
||||
this.orderDTO.items.length > 1
|
||||
) {
|
||||
return true;
|
||||
} else if (
|
||||
this.orderDTO &&
|
||||
@@ -170,7 +211,9 @@ export class ShelfOrderDetailsComponent implements OnInit, OnDestroy, AfterConte
|
||||
this.orderDTO.items[0].data.subsetItems.length > 0
|
||||
) {
|
||||
const quantity = this.orderDTO.items[0].data.subsetItems
|
||||
.filter((subItems) => subItems && subItems.data && subItems.data.quantity)
|
||||
.filter(
|
||||
(subItems) => subItems && subItems.data && subItems.data.quantity
|
||||
)
|
||||
.map((subItems) => subItems.data.quantity)
|
||||
.reduce((q1, q2) => q1 + q2);
|
||||
if (quantity > 1) {
|
||||
@@ -184,7 +227,12 @@ export class ShelfOrderDetailsComponent implements OnInit, OnDestroy, AfterConte
|
||||
}
|
||||
|
||||
private orderParamSwitcher = (params) => {
|
||||
if (params['id'] && params['orderid'] && params['status'] && params['type']) {
|
||||
if (
|
||||
params['id'] &&
|
||||
params['orderid'] &&
|
||||
params['status'] &&
|
||||
params['type']
|
||||
) {
|
||||
if (!this.isReload) {
|
||||
this.status = params['status'];
|
||||
}
|
||||
@@ -192,7 +240,10 @@ export class ShelfOrderDetailsComponent implements OnInit, OnDestroy, AfterConte
|
||||
if (!this.changedToArrived) {
|
||||
this.compartmentCode = params['id'];
|
||||
}
|
||||
return this.shelfService.getOrdersByCompartmentNumber([this.compartmentCode], params['orderid']);
|
||||
return this.shelfService.getOrdersByCompartmentNumber(
|
||||
[this.compartmentCode],
|
||||
params['orderid']
|
||||
);
|
||||
} else {
|
||||
this.orderId = params['id'];
|
||||
return this.shelfService.getOrderByOrderId(params['id']);
|
||||
@@ -241,7 +292,12 @@ export class ShelfOrderDetailsComponent implements OnInit, OnDestroy, AfterConte
|
||||
subsetItems: [
|
||||
...item.data.subsetItems
|
||||
.map((subitem) => {
|
||||
if (subitem && subitem.data && subitem.data.processingStatus.toString() === this.status) {
|
||||
if (
|
||||
subitem &&
|
||||
subitem.data &&
|
||||
subitem.data.processingStatus.toString() ===
|
||||
this.status
|
||||
) {
|
||||
return subitem;
|
||||
}
|
||||
})
|
||||
@@ -251,7 +307,13 @@ export class ShelfOrderDetailsComponent implements OnInit, OnDestroy, AfterConte
|
||||
};
|
||||
return subitems;
|
||||
})
|
||||
.filter((f) => f && f.data && f.data.subsetItems && f.data.subsetItems.length > 0),
|
||||
.filter(
|
||||
(f) =>
|
||||
f &&
|
||||
f.data &&
|
||||
f.data.subsetItems &&
|
||||
f.data.subsetItems.length > 0
|
||||
),
|
||||
],
|
||||
};
|
||||
}
|
||||
@@ -291,10 +353,20 @@ export class ShelfOrderDetailsComponent implements OnInit, OnDestroy, AfterConte
|
||||
let changed: Date;
|
||||
if (orderDto.items) {
|
||||
items = orderDto.items.map((itemContainer) => itemContainer.data);
|
||||
if (items[0] && items[0].subsetItems && items[0].subsetItems[0].data && items[0].subsetItems[0].data.compartmentStop) {
|
||||
if (
|
||||
items[0] &&
|
||||
items[0].subsetItems &&
|
||||
items[0].subsetItems[0].data &&
|
||||
items[0].subsetItems[0].data.compartmentStop
|
||||
) {
|
||||
pickUpDate = new Date(items[0].subsetItems[0].data.compartmentStop);
|
||||
}
|
||||
if (items[0] && items[0].subsetItems && items[0].subsetItems[0].data && items[0].subsetItems[0].data.processingStatus) {
|
||||
if (
|
||||
items[0] &&
|
||||
items[0].subsetItems &&
|
||||
items[0].subsetItems[0].data &&
|
||||
items[0].subsetItems[0].data.processingStatus
|
||||
) {
|
||||
statusCode = items[0].subsetItems[0].data.processingStatus;
|
||||
if (statusCode) {
|
||||
status = orderStatusMapper[statusCode];
|
||||
@@ -312,7 +384,8 @@ export class ShelfOrderDetailsComponent implements OnInit, OnDestroy, AfterConte
|
||||
items[0].subsetItems[0].data &&
|
||||
items[0].subsetItems[0].data.specialComment
|
||||
) {
|
||||
this.notAvailableModel.comment.value = items[0].subsetItems[0].data.specialComment;
|
||||
this.notAvailableModel.comment.value =
|
||||
items[0].subsetItems[0].data.specialComment;
|
||||
}
|
||||
|
||||
if (
|
||||
@@ -324,7 +397,8 @@ export class ShelfOrderDetailsComponent implements OnInit, OnDestroy, AfterConte
|
||||
items[0].subsetItems[0].data.sscText
|
||||
) {
|
||||
this.notAvailableModel.message.code = items[0].subsetItems[0].data.ssc;
|
||||
this.notAvailableModel.message.value = items[0].subsetItems[0].data.sscText;
|
||||
this.notAvailableModel.message.value =
|
||||
items[0].subsetItems[0].data.sscText;
|
||||
}
|
||||
|
||||
if (
|
||||
@@ -475,7 +549,11 @@ export class ShelfOrderDetailsComponent implements OnInit, OnDestroy, AfterConte
|
||||
this.collect(collection, true);
|
||||
}
|
||||
|
||||
collect(collection: { [key: string]: number } = {}, partial = false, newStatus = COLLECTED) {
|
||||
collect(
|
||||
collection: { [key: string]: number } = {},
|
||||
partial = false,
|
||||
newStatus = COLLECTED
|
||||
) {
|
||||
if (this.order && this.order.items) {
|
||||
const orderId = this.order.orderId;
|
||||
const items = this.order.items as OrderItemDTO[];
|
||||
@@ -496,8 +574,8 @@ export class ShelfOrderDetailsComponent implements OnInit, OnDestroy, AfterConte
|
||||
? collection[orderItem.orderItemNumber]
|
||||
: 0
|
||||
: orderItem && orderItem.quantity
|
||||
? orderItem.quantity
|
||||
: 0;
|
||||
? orderItem.quantity
|
||||
: 0;
|
||||
if (quantity > 0 && orderId && orderItemId && orderItemSubsetId) {
|
||||
observer.next({
|
||||
orderId: orderId,
|
||||
@@ -510,7 +588,13 @@ export class ShelfOrderDetailsComponent implements OnInit, OnDestroy, AfterConte
|
||||
}
|
||||
});
|
||||
});
|
||||
this.listenForNeddedChangesToBeDone(patchingSubsetItemSequentially$, partial, items.length, collection, newStatus);
|
||||
this.listenForNeddedChangesToBeDone(
|
||||
patchingSubsetItemSequentially$,
|
||||
partial,
|
||||
items.length,
|
||||
collection,
|
||||
newStatus
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -548,17 +632,34 @@ export class ShelfOrderDetailsComponent implements OnInit, OnDestroy, AfterConte
|
||||
.subscribe((response: any) => {
|
||||
itemsProcessed++;
|
||||
if (response) {
|
||||
if (newStatus === OrderStatus.Arrived && response && response.item1 && response.item1.compartmentCode) {
|
||||
if (
|
||||
newStatus === OrderStatus.Arrived &&
|
||||
response &&
|
||||
response.item1 &&
|
||||
response.item1.compartmentCode
|
||||
) {
|
||||
this.compartmentCode = response.item1.compartmentCode;
|
||||
this.changedToArrived = true;
|
||||
}
|
||||
this.isReload = true;
|
||||
this.realoadIfNeeded(partial, itemLength, itemsProcessed, collection, newStatus);
|
||||
this.realoadIfNeeded(
|
||||
partial,
|
||||
itemLength,
|
||||
itemsProcessed,
|
||||
collection,
|
||||
newStatus
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
realoadIfNeeded(partial: boolean, itemLength: number, itemsProcessed: number, collection: { [key: string]: number }, status: number) {
|
||||
realoadIfNeeded(
|
||||
partial: boolean,
|
||||
itemLength: number,
|
||||
itemsProcessed: number,
|
||||
collection: { [key: string]: number },
|
||||
status: number
|
||||
) {
|
||||
if (!partial) {
|
||||
if (itemsProcessed === itemLength) {
|
||||
this.status = status + '';
|
||||
@@ -626,7 +727,10 @@ export class ShelfOrderDetailsComponent implements OnInit, OnDestroy, AfterConte
|
||||
});
|
||||
});
|
||||
|
||||
this.listenForPickUpExtensions(extendingPickUpTimeSequentially$, items.length);
|
||||
this.listenForPickUpExtensions(
|
||||
extendingPickUpTimeSequentially$,
|
||||
items.length
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -644,7 +748,12 @@ export class ShelfOrderDetailsComponent implements OnInit, OnDestroy, AfterConte
|
||||
.pipe(
|
||||
takeUntil(this.destroy$),
|
||||
concatMap((data) => {
|
||||
return this.shelfService.extendPickUpPeriod(data.orderId, data.orderItemId, data.orderItemSubsetId, data.date);
|
||||
return this.shelfService.extendPickUpPeriod(
|
||||
data.orderId,
|
||||
data.orderItemId,
|
||||
data.orderItemSubsetId,
|
||||
data.date
|
||||
);
|
||||
}),
|
||||
catchError((error) => {
|
||||
console.error(error);
|
||||
@@ -664,11 +773,19 @@ export class ShelfOrderDetailsComponent implements OnInit, OnDestroy, AfterConte
|
||||
this.store.dispatch(new SetEditOrder(this.orderDTO));
|
||||
let breadcrumbName = '';
|
||||
if (this.orderDTO.buyer) {
|
||||
breadcrumbName = this.orderDTO.buyer.firstName + ' ' + this.orderDTO.buyer.lastName + ' Bearbeiten';
|
||||
breadcrumbName =
|
||||
this.orderDTO.buyer.firstName +
|
||||
' ' +
|
||||
this.orderDTO.buyer.lastName +
|
||||
' Bearbeiten';
|
||||
}
|
||||
const path = `/shelf/edit/${this.order.compartmentCode ? this.order.compartmentCode : this.order.orderId}/${this.order.orderId}/${
|
||||
this.status
|
||||
}/${this.order.compartmentCode ? 'c' : 'o'}/shelf/0/0`;
|
||||
const path = `/shelf/edit/${
|
||||
this.order.compartmentCode
|
||||
? this.order.compartmentCode
|
||||
: this.order.orderId
|
||||
}/${this.order.orderId}/${this.status}/${
|
||||
this.order.compartmentCode ? 'c' : 'o'
|
||||
}/shelf/0/0`;
|
||||
this.store.dispatch(
|
||||
new AddBreadcrumb(
|
||||
<Breadcrumb>{
|
||||
@@ -738,7 +855,11 @@ export class ShelfOrderDetailsComponent implements OnInit, OnDestroy, AfterConte
|
||||
|
||||
changeInputStatus(input: string, status: boolean) {
|
||||
this.notAvailableModel[input].disabled = status;
|
||||
if (input === 'message' && !isNullOrUndefined(this.notAvailableModel.message.code) && this.notAvailableModel.message.code !== '') {
|
||||
if (
|
||||
input === 'message' &&
|
||||
!isNullOrUndefined(this.notAvailableModel.message.code) &&
|
||||
this.notAvailableModel.message.code !== ''
|
||||
) {
|
||||
this.notAvailableModel.message.valid = true;
|
||||
}
|
||||
this.cdrf.detectChanges();
|
||||
@@ -768,9 +889,17 @@ export class ShelfOrderDetailsComponent implements OnInit, OnDestroy, AfterConte
|
||||
}
|
||||
this.timer = setTimeout(() => {
|
||||
orderItem.subsetItems.forEach((subsetItem) => {
|
||||
if (subsetItem && subsetItem.data && subsetItem.data.supplier && subsetItem.data.supplier.data) {
|
||||
if (
|
||||
subsetItem &&
|
||||
subsetItem.data &&
|
||||
subsetItem.data.supplier &&
|
||||
subsetItem.data.supplier.data
|
||||
) {
|
||||
this.shelfService
|
||||
.getMessageText(code, subsetItem.data.supplier && subsetItem.data.supplier.data.id)
|
||||
.getMessageText(
|
||||
code,
|
||||
subsetItem.data.supplier && subsetItem.data.supplier.data.id
|
||||
)
|
||||
.pipe(
|
||||
takeUntil(this.destroy$),
|
||||
catchError((error) => {
|
||||
@@ -794,7 +923,11 @@ export class ShelfOrderDetailsComponent implements OnInit, OnDestroy, AfterConte
|
||||
|
||||
detectChanges() {
|
||||
setTimeout(() => {
|
||||
if (this.cdrf !== null && this.cdrf !== undefined && !(this.cdrf as ViewRef).destroyed) {
|
||||
if (
|
||||
this.cdrf !== null &&
|
||||
this.cdrf !== undefined &&
|
||||
!(this.cdrf as ViewRef).destroyed
|
||||
) {
|
||||
this.cdrf.detectChanges();
|
||||
}
|
||||
}, 0);
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
// start:ng42.barrel
|
||||
export * from './shelf-search.component';
|
||||
export * from './shelf-search.module';
|
||||
export * from './stagger.animation';
|
||||
// end:ng42.barrel
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
// start:ng42.barrel
|
||||
export * from './shelf-search-desktop.component';
|
||||
// end:ng42.barrel
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-shelf-search-desktop',
|
||||
templateUrl: './shelf-search-desktop.component.html',
|
||||
styleUrls: ['./shelf-search-desktop.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class ShelfSearchDesktopComponent implements OnInit {
|
||||
constructor() {}
|
||||
|
||||
ngOnInit() {}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
// start:ng42.barrel
|
||||
export * from './shelf-search-ipad.component';
|
||||
export * from './shelf-search-ipad.module';
|
||||
// end:ng42.barrel
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
<div class="container">
|
||||
<app-shelf-searchbar
|
||||
[isFetchingData]="isFetchingData$ | async"
|
||||
[errorMessage]="errorMessage$ | async"
|
||||
(search)="triggerSearch($event)"
|
||||
></app-shelf-searchbar>
|
||||
|
||||
<lib-collecting-shelf-scanner
|
||||
#scanner
|
||||
(scan)="triggerBarcodeSearch($event)"
|
||||
></lib-collecting-shelf-scanner>
|
||||
</div>
|
||||
@@ -0,0 +1,14 @@
|
||||
.container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
user-select: none;
|
||||
margin-bottom: 90px;
|
||||
height: calc(100% - 55px);
|
||||
}
|
||||
|
||||
lib-barcode-scanner-scandit {
|
||||
width: 550px;
|
||||
height: 300px;
|
||||
border: #e1ebf5 2px solid;
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
import {
|
||||
Component,
|
||||
OnDestroy,
|
||||
ChangeDetectionStrategy,
|
||||
ViewChild,
|
||||
} from '@angular/core';
|
||||
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 {
|
||||
ShelfStoreFacadeService,
|
||||
ShelfNavigationService,
|
||||
} from '../../../shared/services';
|
||||
import { SHELF_SCROLL_INDEX } from 'apps/sales/src/app/core/utils/app.constants';
|
||||
|
||||
@Component({
|
||||
selector: 'app-shelf-search-ipad',
|
||||
templateUrl: 'shelf-search-ipad.component.html',
|
||||
styleUrls: ['./shelf-search-ipad.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class ShelfSearchIpadComponent implements OnDestroy {
|
||||
@ViewChild('scanner', { static: false })
|
||||
scanner: BarcodeScannerScanditComponent;
|
||||
destroy$ = new Subject();
|
||||
isFetchingData$ = new BehaviorSubject<boolean>(false);
|
||||
errorMessage$ = new BehaviorSubject<string>('');
|
||||
|
||||
constructor(
|
||||
private shelfSearchService: ShelfSearchFacadeService,
|
||||
private shelfStoreFacade: ShelfStoreFacadeService,
|
||||
private shelfNavigationService: ShelfNavigationService
|
||||
) {}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.destroy$.next();
|
||||
this.destroy$.complete();
|
||||
}
|
||||
|
||||
triggerBarcodeSearch(barcode: string) {
|
||||
this.triggerSearch({ type: 'scan', value: barcode });
|
||||
}
|
||||
|
||||
triggerSearch({ type, value }: { type: 'search' | 'scan'; value: string }) {
|
||||
let result$: Observable<ListResponseArgsOfOrderItemListItemDTO>;
|
||||
this.setIsFetchingData(true);
|
||||
if (type === 'search') {
|
||||
result$ = this.shelfSearchService.search(value);
|
||||
} else if (type === 'scan') {
|
||||
result$ = this.shelfSearchService.searchWithBarcode(value);
|
||||
}
|
||||
|
||||
result$
|
||||
.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 handleSearchResultError() {
|
||||
this.setErrorMessage('Ein Fehler ist aufgetreten');
|
||||
this.setIsFetchingData(false);
|
||||
}
|
||||
|
||||
private hasNoResult(result: ListResponseArgsOfOrderItemListItemDTO): boolean {
|
||||
return !!result.result && !result.result.length;
|
||||
}
|
||||
|
||||
private hasMultipleSearchResults(
|
||||
result: ListResponseArgsOfOrderItemListItemDTO
|
||||
): boolean {
|
||||
return !!result.result && !!result.result.length;
|
||||
}
|
||||
|
||||
private getDetails(result: ListResponseArgsOfOrderItemListItemDTO) {
|
||||
return result.result && result.result[0];
|
||||
}
|
||||
|
||||
private resetSessionStorage(key: string = SHELF_SCROLL_INDEX) {
|
||||
sessionStorage.removeItem(key);
|
||||
}
|
||||
|
||||
private setIsFetchingData(isFetching: boolean) {
|
||||
this.isFetchingData$.next(isFetching);
|
||||
}
|
||||
|
||||
private setErrorMessage(message: string) {
|
||||
this.errorMessage$.next(message);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { CollectingShelfScannerModule } from 'shared/public_api';
|
||||
import { ShelfSearchIpadComponent } from './shelf-search-ipad.component';
|
||||
import { ShelfSearchBarModule } from '../../../components';
|
||||
|
||||
@NgModule({
|
||||
imports: [CommonModule, CollectingShelfScannerModule, ShelfSearchBarModule],
|
||||
exports: [ShelfSearchIpadComponent],
|
||||
declarations: [ShelfSearchIpadComponent],
|
||||
providers: [],
|
||||
})
|
||||
export class ShelfSearchIpadModule {}
|
||||
@@ -1,18 +1,14 @@
|
||||
<div [@staggerAnimation]="active" class="headers" *ngIf="isIPad">
|
||||
<app-card *ngFor="let item of navigation" (click)="switch(item)" class="header">
|
||||
<span class="header-title">{{ titles[item] }}</span>
|
||||
</app-card>
|
||||
</div>
|
||||
<div class="content" [ngSwitch]="active" *ngIf="isIPad">
|
||||
<div *ngSwitchCase="'search'" [@fadeIn]="active">
|
||||
<app-shelf-text-search></app-shelf-text-search>
|
||||
<section class="isa-content-container mt-15">
|
||||
<div class="header pt-42 mb-45">
|
||||
<h2 class="isa-content-headline mt-0">Bestellpostensuche</h2>
|
||||
<h6 class="isa-content-subline">
|
||||
Suchen Sie den Bestellposten via Name, Abholfachnummer, Abholscheinnummer,
|
||||
Kundenkartennummer, Vorgang-ID oder scannen Sie den Artikel.
|
||||
</h6>
|
||||
</div>
|
||||
<div *ngSwitchCase="'scan'" [@fadeIn]="active">
|
||||
<app-shelf-barcode-search></app-shelf-barcode-search>
|
||||
|
||||
<div class="content">
|
||||
<app-shelf-search-ipad *ngIf="isIPad"></app-shelf-search-ipad>
|
||||
<app-shelf-search-desktop *ngIf="!isIPad"></app-shelf-search-desktop>
|
||||
</div>
|
||||
</div>
|
||||
<div class="content" [ngSwitch]="active" *ngIf="!isIPad">
|
||||
<div>
|
||||
<app-shelf-text-search></app-shelf-text-search>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
.headers {
|
||||
display: block;
|
||||
min-height: 60px;
|
||||
.header {
|
||||
}
|
||||
|
||||
.content {
|
||||
|
||||
@@ -14,29 +14,20 @@ import { ClearCachedResults } from 'apps/sales/src/app/core/store/actions/collec
|
||||
animations: [staggerAnimation, fadeInAnimation],
|
||||
})
|
||||
export class ShelfSearchComponent implements OnInit {
|
||||
titles = {
|
||||
search: 'Warenausgabe',
|
||||
scan: 'Abholschein oder Kundenkarte scannen',
|
||||
};
|
||||
navigation = ['scan'];
|
||||
active = 'search';
|
||||
isIPad: boolean;
|
||||
private iPadDetected = false;
|
||||
private iPadEventRecieved = false;
|
||||
constructor(private store: Store, private windowRef: WindowRef, private appService: AppService) {}
|
||||
private iPadEventReceived = false;
|
||||
constructor(
|
||||
private store: Store,
|
||||
private windowRef: WindowRef,
|
||||
private appService: AppService
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.isIPad = this.appService.isIPadEnv();
|
||||
this.store.dispatch(new ClearCachedResults());
|
||||
}
|
||||
|
||||
switch(newItem: string) {
|
||||
const index = this.navigation.indexOf(newItem);
|
||||
this.navigation[index] = this.active;
|
||||
this.active = newItem;
|
||||
this.store.dispatch(new UpdateCurrentBreadcrumbName(this.titles[this.active], 'shelf'));
|
||||
}
|
||||
|
||||
isIPadEnv() {
|
||||
const navigator = this.windowRef.nativeWindow.navigator as Navigator;
|
||||
const standalone = (navigator as any).standalone,
|
||||
@@ -44,6 +35,6 @@ export class ShelfSearchComponent implements OnInit {
|
||||
ios = /iphone|ipod|ipad/.test(userAgent);
|
||||
|
||||
this.iPadDetected = ios && !standalone;
|
||||
return this.iPadDetected || this.iPadEventRecieved;
|
||||
return this.iPadDetected || this.iPadEventReceived;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
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';
|
||||
|
||||
@NgModule({
|
||||
imports: [CommonModule, ShelfSearchIpadModule],
|
||||
exports: [ShelfSearchComponent, ShelfSearchDesktopComponent],
|
||||
declarations: [ShelfSearchComponent, ShelfSearchDesktopComponent],
|
||||
providers: [],
|
||||
})
|
||||
export class ShelfSearchModule {}
|
||||
@@ -0,0 +1,11 @@
|
||||
import { Directive, ElementRef, AfterViewInit } from '@angular/core';
|
||||
|
||||
// tslint:disable-next-line: directive-selector
|
||||
@Directive({ selector: 'input[focus]' })
|
||||
export class FocusDirective implements AfterViewInit {
|
||||
constructor(private elementRef: ElementRef<HTMLInputElement>) {}
|
||||
|
||||
ngAfterViewInit() {
|
||||
this.elementRef.nativeElement.focus();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
// start:ng42.barrel
|
||||
export * from './focus.directive';
|
||||
// end:ng42.barrel
|
||||
|
||||
5
apps/sales/src/app/modules/shelf/shared/pipes/index.ts
Normal file
5
apps/sales/src/app/modules/shelf/shared/pipes/index.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
// start:ng42.barrel
|
||||
export * from './show-search-reset.pipe';
|
||||
export * from './truncate.pipe';
|
||||
// end:ng42.barrel
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
import { Pipe, PipeTransform } from '@angular/core';
|
||||
|
||||
@Pipe({
|
||||
name: 'showSearchResetPipe',
|
||||
})
|
||||
export class ShowSearchResetPipe implements PipeTransform {
|
||||
transform(queryString: string, minimumNumberOfChars?: number): boolean {
|
||||
console.log({ queryString });
|
||||
return (
|
||||
!!queryString && !!(queryString.length > (minimumNumberOfChars || 0))
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
import { Pipe, PipeTransform } from '@angular/core';
|
||||
|
||||
@Pipe({
|
||||
name: 'truncateText',
|
||||
})
|
||||
export class TruncateTextPipe implements PipeTransform {
|
||||
transform(text: string, numberOfChars: number): string {
|
||||
return text.slice(0, numberOfChars || text.length) + '...';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
// start:ng42.barrel
|
||||
export * from './shelf-navigation.service';
|
||||
export * from './shelf-search.facade.service';
|
||||
export * from './shelf-store.facade.service';
|
||||
// end:ng42.barrel
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
import { Store } from '@ngxs/store';
|
||||
import { AddBreadcrumb } from 'apps/sales/src/app/core/store/actions/breadcrumb.actions';
|
||||
import { ChangeCurrentRoute } from 'apps/sales/src/app/core/store/actions/process.actions';
|
||||
import { Breadcrumb } from 'apps/sales/src/app/core/models/breadcrumb.model';
|
||||
import { OrderItemListItemDTO } from '@swagger/oms/lib';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class ShelfNavigationService {
|
||||
constructor(private store: Store, private router: Router) {}
|
||||
|
||||
navigateToDetails(order: OrderItemListItemDTO) {
|
||||
const path = this.getDetailsPath(order);
|
||||
const breadcrumb = this.getDetailsBreadcrumb(order);
|
||||
|
||||
this.navigateToRoute(path, breadcrumb);
|
||||
}
|
||||
|
||||
navigateToResultList({
|
||||
searchQuery,
|
||||
numberOfHits,
|
||||
}: {
|
||||
searchQuery: string;
|
||||
numberOfHits: number;
|
||||
}) {
|
||||
const path = '/shelf/results';
|
||||
const breadcrumb = this.getResultListBreadcrumb(searchQuery, numberOfHits);
|
||||
console.log('navigateo');
|
||||
this.navigateToRoute(path, breadcrumb);
|
||||
}
|
||||
|
||||
private navigateToRoute(route: string, breadcrumbName: string) {
|
||||
this.store.dispatch(
|
||||
new AddBreadcrumb(
|
||||
<Breadcrumb>{
|
||||
name: breadcrumbName,
|
||||
path: route,
|
||||
},
|
||||
'shelf'
|
||||
)
|
||||
);
|
||||
this.store.dispatch(new ChangeCurrentRoute(route));
|
||||
this.router.navigate([route]);
|
||||
}
|
||||
|
||||
private getResultListBreadcrumb(
|
||||
searchQuery: string,
|
||||
numberOfHits: number
|
||||
): string {
|
||||
return `${searchQuery} (${numberOfHits} Ergebnisse)`;
|
||||
}
|
||||
|
||||
getDetailsBreadcrumb(order: OrderItemListItemDTO): string {
|
||||
return `${order.firstName} ${order.lastName}`;
|
||||
}
|
||||
|
||||
private getDetailsPath(order: OrderItemListItemDTO): string {
|
||||
return `/shelf/details/${
|
||||
order.compartmentCode ? order.compartmentCode : order.orderId
|
||||
}/${order.orderId}/${order.processingStatus}/${
|
||||
order.compartmentCode ? 'c' : 'o'
|
||||
}`;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Store, Select } from '@ngxs/store';
|
||||
import { BranchSelectors } from 'apps/sales/src/app/core/store/selectors/branch.selector';
|
||||
import { Observable } from 'rxjs';
|
||||
import { filter, switchMap, map } from 'rxjs/operators';
|
||||
import { isNullOrUndefined } from 'util';
|
||||
import { CollectingShelfService } from 'apps/sales/src/app/core/services/collecting-shelf.service';
|
||||
import { ListResponseArgsOfOrderItemListItemDTO } from '@swagger/oms/lib';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class ShelfSearchFacadeService {
|
||||
@Select(BranchSelectors.getUserBranch) currentUserBranchId$: Observable<
|
||||
string
|
||||
>;
|
||||
|
||||
constructor(
|
||||
private store: Store,
|
||||
private collectingShelfService: CollectingShelfService
|
||||
) {}
|
||||
|
||||
search(queryString: string) {
|
||||
const searchParams = queryString.trim();
|
||||
|
||||
if (!this.isValidSearchQuery(searchParams)) {
|
||||
return;
|
||||
}
|
||||
|
||||
return this.requestSearch(searchParams).pipe(map(this.handleSearchResult));
|
||||
}
|
||||
|
||||
searchWithBarcode(barcode: string) {
|
||||
const searchParams = this.getBarcodeSearchParams(barcode);
|
||||
|
||||
if (!this.isValidSearchQuery(searchParams)) {
|
||||
return;
|
||||
}
|
||||
|
||||
return this.requestSearch(searchParams).pipe(map(this.handleSearchResult));
|
||||
}
|
||||
|
||||
private requestSearch(
|
||||
input: string
|
||||
): Observable<ListResponseArgsOfOrderItemListItemDTO> {
|
||||
return this.currentUserBranchId$.pipe(
|
||||
filter((branchNumber) => !isNullOrUndefined(branchNumber)),
|
||||
switchMap((branchNumber) =>
|
||||
this.collectingShelfService.searchShelfHasResultsWithResult(
|
||||
input,
|
||||
branchNumber
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
private handleSearchResult(result: ListResponseArgsOfOrderItemListItemDTO) {
|
||||
if (!result) {
|
||||
return {
|
||||
result: [],
|
||||
} as ListResponseArgsOfOrderItemListItemDTO;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private isValidSearchQuery(queryString: string): boolean {
|
||||
return !!queryString && !!queryString.length;
|
||||
}
|
||||
|
||||
private getBarcodeSearchParams(barcode: string) {
|
||||
return barcode.replace('ORD:', '').trim();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Store } from '@ngxs/store';
|
||||
import { SetShelfSearch } from 'apps/sales/src/app/core/store/actions/process.actions';
|
||||
import { ShelfSearch } from 'apps/sales/src/app/core/models/shelf-search.modal';
|
||||
import { BranchSelectors } from 'apps/sales/src/app/core/store/selectors/branch.selector';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class ShelfStoreFacadeService {
|
||||
constructor(private store: Store) {}
|
||||
|
||||
get branchnumber(): string {
|
||||
return this.store.selectSnapshot(BranchSelectors.getUserBranch);
|
||||
}
|
||||
|
||||
setShelfSearch(input: string) {
|
||||
this.store.dispatch(
|
||||
new SetShelfSearch(<ShelfSearch>{
|
||||
input,
|
||||
branchnumber: this.branchnumber,
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -6,20 +6,25 @@ import { CommonModule } from '@angular/common';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { ButtonModule, CardModule, IconModule, InputModule, LoadingModule, SearchInputModule, DropdownModule } from '@libs/ui';
|
||||
import {
|
||||
ButtonModule,
|
||||
CardModule,
|
||||
IconModule,
|
||||
InputModule,
|
||||
LoadingModule,
|
||||
SearchInputModule,
|
||||
DropdownModule,
|
||||
} from '@libs/ui';
|
||||
|
||||
import { SharedModule } from '../../shared/shared.module';
|
||||
import {
|
||||
ShelfBarcodeSearchComponent,
|
||||
ShelfArticleDetailsComponent,
|
||||
ShelfTextSearchComponent,
|
||||
ShelfOrderItemComponent,
|
||||
ShelfCustomerOrderComponent,
|
||||
ShelfOrderTagComponent,
|
||||
ShelfPartialCollectionModalComponent,
|
||||
} from './components';
|
||||
import { ShelfSearchResultsComponent } from './pages/shelf-search-results/shelf-search-results.component';
|
||||
import { ShelfSearchComponent } from './pages/shelf-search/shelf-search.component';
|
||||
import { ShelfRoutingModule } from './shelf-routing.module';
|
||||
import { ShelfOrderDetailsComponent } from './pages/shelf-order-details/shelf-order-details.component';
|
||||
import { OrderStatusPipe } from '../../pipes/order-status.pipe';
|
||||
@@ -28,12 +33,10 @@ import { ShelfEditOrderComponent } from './pages/shelf-edit-order/shelf-edit-ord
|
||||
import { OrderItemEditComponent } from './components/order-item-edit/order-item-edit.component';
|
||||
import { OrderOverviewEditComponent } from './components/order-overview-edit/order-overview-edit.component';
|
||||
import { PerfectScrollbarModule } from 'ngx-perfect-scrollbar';
|
||||
import { ShelfSearchModule } from './pages/shelf-search';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
ShelfSearchComponent,
|
||||
ShelfBarcodeSearchComponent,
|
||||
ShelfTextSearchComponent,
|
||||
ShelfSearchResultsComponent,
|
||||
ShelfOrderItemComponent,
|
||||
ShelfOrderTagComponent,
|
||||
@@ -51,6 +54,7 @@ import { PerfectScrollbarModule } from 'ngx-perfect-scrollbar';
|
||||
imports: [
|
||||
CommonModule,
|
||||
ShelfRoutingModule,
|
||||
ShelfSearchModule,
|
||||
FormsModule,
|
||||
ReactiveFormsModule,
|
||||
RouterModule,
|
||||
|
||||
12
apps/sales/src/assets/images/Search_Icon_Scan.svg
Normal file
12
apps/sales/src/assets/images/Search_Icon_Scan.svg
Normal file
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="58px" height="58px" viewBox="0 0 58 58" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>Group 2</title>
|
||||
<g id="277-/-Warenausgang---Filter" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="ISA_HIMA_Abholfach_Warenausgang_Filter_01" transform="translate(-600.000000, -467.000000)">
|
||||
<g id="Group-2" transform="translate(600.000000, 467.000000)">
|
||||
<rect id="CTA_BG-Copy" fill="#F70400" x="0" y="0" width="58" height="58" rx="29"></rect>
|
||||
<path d="M46,37.9268293 L46,43 L40.8981132,43 L40.8981132,41.097561 L44.0861132,41.098 L44.0867925,37.9268293 L46,37.9268293 Z M14.1132075,37.9268293 L14.1138868,41.098 L17.3018868,41.097561 L17.3018868,43 L12.2,43 L12.2,37.9268293 L14.1132075,37.9268293 Z M18.5773585,22.0731707 L18.5773585,37.9268293 L16.6641509,37.9268293 L16.6641509,22.0731707 L18.5773585,22.0731707 Z M31.9698113,22.0731707 L31.9698113,37.9268293 L30.0566038,37.9268293 L30.0566038,22.0731707 L31.9698113,22.0731707 Z M40.8981132,22.0731707 L40.8981132,37.9268293 L38.9849057,37.9268293 L38.9849057,22.0731707 L40.8981132,22.0731707 Z M23.0415094,35.3902439 L23.0415094,37.9268293 L21.1283019,37.9268293 L21.1283019,35.3902439 L23.0415094,35.3902439 Z M36.4339623,35.3902439 L36.4339623,37.9268293 L34.5207547,37.9268293 L34.5207547,35.3902439 L36.4339623,35.3902439 Z M27.5056604,35.3902439 L27.5056604,37.9268293 L25.5924528,37.9268293 L25.5924528,35.3902439 L27.5056604,35.3902439 Z M23.0415094,22.0731707 L23.0415094,32.2195122 L21.1283019,32.2195122 L21.1283019,22.0731707 L23.0415094,22.0731707 Z M36.4339623,22.0731707 L36.4339623,32.2195122 L34.5207547,32.2195122 L34.5207547,22.0731707 L36.4339623,22.0731707 Z M27.5056604,22.0731707 L27.5056604,32.2195122 L25.5924528,32.2195122 L25.5924528,22.0731707 L27.5056604,22.0731707 Z M46,17 L46,22.0731707 L44.0867925,22.0731707 L44.0861132,18.902 L40.8981132,18.902439 L40.8981132,17 L46,17 Z M17.3018868,17 L17.3018868,18.902439 L14.1138868,18.902 L14.1132075,22.0731707 L12.2,22.0731707 L12.2,17 L17.3018868,17 Z" id="Icon_Scan-Copy" stroke="#FFFFFF" stroke-width="0.5" fill="#FFFFFF"></path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.2 KiB |
@@ -6,7 +6,10 @@
|
||||
/* MODULES */
|
||||
@import 'modules/button';
|
||||
@import 'modules/card';
|
||||
@import 'modules/content';
|
||||
@import 'modules/forms';
|
||||
@import 'modules/headline';
|
||||
@import 'modules/input';
|
||||
|
||||
/* HELPERS */
|
||||
@import 'helpers/spacing';
|
||||
|
||||
@@ -22,6 +22,20 @@ $desktop: 1200px;
|
||||
$big-desktop: 1800px;
|
||||
|
||||
/* ***MODULES*** */
|
||||
|
||||
/* CONTENT */
|
||||
$content-background-color: #fff;
|
||||
$content-border-radius: 5px;
|
||||
|
||||
/* HEADLINE */
|
||||
$headline-font-size-l: 26px;
|
||||
$headline-font-size-m: 22px;
|
||||
|
||||
/* INPUT */
|
||||
$input-height-size-l: 60px;
|
||||
$input-font-size: 21px;
|
||||
$input-letter-spacing: -0.01rem;
|
||||
|
||||
/* BUTTON */
|
||||
$button-font-weight: bold;
|
||||
$button-font-size-l: 18px;
|
||||
|
||||
@@ -54,6 +54,14 @@
|
||||
box-shadow: 0 0 30px rgba(89, 100, 112, 0.5);
|
||||
}
|
||||
|
||||
.isa-btn-close {
|
||||
background: none;
|
||||
background-image: url('/assets/images/close.svg');
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
border: none;
|
||||
}
|
||||
|
||||
button:disabled.isa-btn {
|
||||
background: $button-disabled-color !important;
|
||||
}
|
||||
|
||||
6
apps/sales/src/scss/modules/_content.scss
Normal file
6
apps/sales/src/scss/modules/_content.scss
Normal file
@@ -0,0 +1,6 @@
|
||||
.isa-content-container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: $content-background-color;
|
||||
border-radius: $content-border-radius;
|
||||
}
|
||||
15
apps/sales/src/scss/modules/_headline.scss
Normal file
15
apps/sales/src/scss/modules/_headline.scss
Normal file
@@ -0,0 +1,15 @@
|
||||
.isa-content-headline {
|
||||
font-family: $font-family;
|
||||
font-weight: $font-weight-bold;
|
||||
font-size: $headline-font-size-l;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.isa-content-subline {
|
||||
font-family: $font-family;
|
||||
font-size: $headline-font-size-m;
|
||||
text-align: center;
|
||||
font-weight: $font-weight;
|
||||
max-width: 434px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
68
apps/sales/src/scss/modules/_input.scss
Normal file
68
apps/sales/src/scss/modules/_input.scss
Normal file
@@ -0,0 +1,68 @@
|
||||
.isa-input {
|
||||
height: $input-height-size-l;
|
||||
font-family: $font-family;
|
||||
font-size: $input-font-size;
|
||||
font-weight: $font-weight-bold;
|
||||
letter-spacing: $input-letter-spacing;
|
||||
}
|
||||
|
||||
.isa-text-input {
|
||||
border: inherit;
|
||||
border-radius: inherit;
|
||||
padding: 0 5%;
|
||||
overflow: hidden;
|
||||
width: 75%;
|
||||
outline: none;
|
||||
caret-color: $isa-red;
|
||||
|
||||
&:placeholder-shown {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
&::placeholder {
|
||||
color: rgba(90, 114, 138, 1);
|
||||
}
|
||||
|
||||
&.error {
|
||||
width: 35%;
|
||||
}
|
||||
}
|
||||
|
||||
.isa-input-submit {
|
||||
background: $content-background-color;
|
||||
background-image: url('assets/images/Search_Icon.svg');
|
||||
border: inherit;
|
||||
border-radius: inherit;
|
||||
position: absolute;
|
||||
outline: none;
|
||||
right: 20px;
|
||||
height: 27px;
|
||||
width: 27px;
|
||||
background-size: cover;
|
||||
top: 17px;
|
||||
|
||||
&.scan {
|
||||
top: 0;
|
||||
right: 0;
|
||||
height: 58px;
|
||||
width: 58px;
|
||||
background-image: url('assets/images/Search_Icon_Scan.svg');
|
||||
}
|
||||
}
|
||||
|
||||
.isa-input-reset {
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
right: 65px;
|
||||
top: 19px;
|
||||
outline: none;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.isa-input-error {
|
||||
color: $isa-red;
|
||||
font-size: 14px;
|
||||
font-weight: 700;
|
||||
}
|
||||
@@ -85,6 +85,10 @@ body {
|
||||
padding-top: 39px;
|
||||
}
|
||||
|
||||
.pt-42 {
|
||||
padding-top: 42px;
|
||||
}
|
||||
|
||||
.pr-4 {
|
||||
padding-right: 4px;
|
||||
}
|
||||
@@ -93,6 +97,14 @@ body {
|
||||
padding-bottom: 16px;
|
||||
}
|
||||
|
||||
.mt-0 {
|
||||
margin-top: 0px;
|
||||
}
|
||||
|
||||
.mt-15 {
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
.mx-8 {
|
||||
margin-left: 8px;
|
||||
margin-right: 8px;
|
||||
@@ -129,6 +141,10 @@ body {
|
||||
margin-left: 16px;
|
||||
}
|
||||
|
||||
.mb-45 {
|
||||
margin-bottom: 45px;
|
||||
}
|
||||
|
||||
.c-pointer {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
774
package-lock.json
generated
774
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user